Initial input
authorKilian Saffran <ksaffran@dks.lu>
Thu, 21 Feb 2019 09:12:39 +0000 (10:12 +0100)
committerKilian Saffran <ksaffran@dks.lu>
Thu, 21 Feb 2019 09:12:39 +0000 (10:12 +0100)
143 files changed:
.gitignore [new file with mode: 0644]
css/app.css [new file with mode: 0644]
css/calendar.css [new file with mode: 0644]
css/creorga.css [new file with mode: 0644]
css/creorga.epic.css [new file with mode: 0644]
css/style.css [new file with mode: 0644]
img/creorga.png [new file with mode: 0644]
img/dks_1000.png [new file with mode: 0644]
index.html [new file with mode: 0644]
js/app.js [new file with mode: 0644]
js/creorga.js [new file with mode: 0644]
js/database.js [new file with mode: 0644]
js/lang/summernote-fr-FR.js [new file with mode: 0644]
js/lang/summernote-fr-FR.min.js [new file with mode: 0644]
js/locale/datatable_de.json [new file with mode: 0644]
js/locale/datatable_fr.json [new file with mode: 0644]
js/moduleglobal.js [new file with mode: 0644]
js/old/data.js [new file with mode: 0644]
js/old/database.js [new file with mode: 0644]
js/old/encrypt.js [new file with mode: 0644]
js/old/init.js [new file with mode: 0644]
js/old/license.js [new file with mode: 0644]
js/old/navigation.js [new file with mode: 0644]
js/old/preferences.js [new file with mode: 0644]
js/old/sync.js [new file with mode: 0644]
js/old/system.js [new file with mode: 0644]
js/old/tools.js [new file with mode: 0644]
js/preferences.js [new file with mode: 0644]
js/webdatabase.js [new file with mode: 0644]
js/webpreferences.js [new file with mode: 0644]
main.js [new file with mode: 0644]
modules/accounting/accounting.html [new file with mode: 0644]
modules/accounting/accounting.xul [new file with mode: 0644]
modules/accounting/accountingchild.html [new file with mode: 0644]
modules/accounting/accountingopeninvoice.html [new file with mode: 0644]
modules/accounting/accountingyear.html [new file with mode: 0644]
modules/accounting/checkservice.html [new file with mode: 0644]
modules/accounting/img/accounting.png [new file with mode: 0644]
modules/accounting/js/accounting.js [new file with mode: 0644]
modules/accounting/js/accountingchild.js [new file with mode: 0644]
modules/accounting/js/accountingopeninvoice.js [new file with mode: 0644]
modules/accounting/js/accountingyear.js [new file with mode: 0644]
modules/accounting/js/checkservice.js [new file with mode: 0644]
modules/calendar/calactivity.html [new file with mode: 0644]
modules/calendar/calchilds.html [new file with mode: 0644]
modules/calendar/calendar.xul [new file with mode: 0644]
modules/calendar/calglobal.html [new file with mode: 0644]
modules/calendar/callunch.html [new file with mode: 0644]
modules/calendar/calvacancy.html [new file with mode: 0644]
modules/calendar/img/calendar.png [new file with mode: 0644]
modules/calendar/js/calactivity.js [new file with mode: 0644]
modules/calendar/js/calchilds.js [new file with mode: 0644]
modules/calendar/js/calglobal.js [new file with mode: 0644]
modules/calendar/js/callunch.js [new file with mode: 0644]
modules/calendar/js/calvacancy.js [new file with mode: 0644]
modules/calendar/js/nlp.js [new file with mode: 0644]
modules/calendar/js/rrule.js [new file with mode: 0644]
modules/childs/child.html [new file with mode: 0644]
modules/childs/child.js [new file with mode: 0644]
modules/childs/filters.js [new file with mode: 0644]
modules/childs/index.html [new file with mode: 0644]
modules/childs/index.js [new file with mode: 0644]
modules/creche/creche.html [new file with mode: 0644]
modules/creche/creche.js [new file with mode: 0644]
modules/dashboard/index.html [new file with mode: 0644]
modules/dashboard/index.js [new file with mode: 0644]
modules/forms/forms.html [new file with mode: 0644]
modules/forms/forms.xul [new file with mode: 0644]
modules/forms/img/doc.png [new file with mode: 0644]
modules/forms/img/form.png [new file with mode: 0644]
modules/forms/js/forms.js [new file with mode: 0644]
modules/logbook/img/logbook.png [new file with mode: 0644]
modules/logbook/js/logactivity.js [new file with mode: 0644]
modules/logbook/js/logactivity_basic.js [new file with mode: 0644]
modules/logbook/js/logchild.js [new file with mode: 0644]
modules/logbook/js/logcominterne.js [new file with mode: 0644]
modules/logbook/js/logcominterne_basic.js [new file with mode: 0644]
modules/logbook/js/logstaff.js [new file with mode: 0644]
modules/logbook/logactivity.html [new file with mode: 0644]
modules/logbook/logactivity_basic.html [new file with mode: 0644]
modules/logbook/logbook.xul [new file with mode: 0644]
modules/logbook/logbook_basic.xul [new file with mode: 0644]
modules/logbook/logchild.html [new file with mode: 0644]
modules/logbook/logcominterne.html [new file with mode: 0644]
modules/logbook/logcominterne_basic.html [new file with mode: 0644]
modules/logbook/logstaff.html [new file with mode: 0644]
modules/presences/dailypresences.html [new file with mode: 0644]
modules/presences/img/presence.png [new file with mode: 0644]
modules/presences/js/dailypresences.js [new file with mode: 0644]
modules/presences/js/weeklypresences.js [new file with mode: 0644]
modules/presences/presences.xul [new file with mode: 0644]
modules/presences/weeklypresences.html [new file with mode: 0644]
modules/reports/css/print.css [new file with mode: 0644]
modules/reports/dlg/dlgpdfviewer.xul [new file with mode: 0644]
modules/reports/dlg/dlgprint.xul [new file with mode: 0644]
modules/reports/img/logoprint.png [new file with mode: 0644]
modules/reports/img/print.png [new file with mode: 0644]
modules/reports/img/save.png [new file with mode: 0644]
modules/reports/img/settings.png [new file with mode: 0644]
modules/reports/js/print.js [new file with mode: 0644]
modules/reports/js/print_book.js [new file with mode: 0644]
modules/reports/js/print_calendar.js [new file with mode: 0644]
modules/reports/js/print_child.js [new file with mode: 0644]
modules/reports/js/print_loaddata.js [new file with mode: 0644]
modules/reports/js/print_logchild.js [new file with mode: 0644]
modules/reports/js/print_multilist.js [new file with mode: 0644]
modules/reports/js/print_table.js [new file with mode: 0644]
modules/reports/js/printpdf.js [new file with mode: 0644]
modules/reports/js/printutils.js [new file with mode: 0644]
modules/reports/print_book.html [new file with mode: 0644]
modules/reports/print_calendar.html [new file with mode: 0644]
modules/reports/print_child.html [new file with mode: 0644]
modules/reports/print_list.html [new file with mode: 0644]
modules/reports/print_logchild.html [new file with mode: 0644]
modules/reports/print_multilist.html [new file with mode: 0644]
modules/reports/print_table.html [new file with mode: 0644]
modules/reports/reports.xul [new file with mode: 0644]
modules/settings/db.html [new file with mode: 0644]
modules/settings/dbconfig.js [new file with mode: 0644]
modules/settings/index.html [new file with mode: 0644]
modules/settings/index.js [new file with mode: 0644]
modules/settings/js/multisite_reader.js [new file with mode: 0644]
modules/settings/multisite.xul [new file with mode: 0644]
modules/settings/support/js/multisite.js [new file with mode: 0644]
modules/settings/support/js/update.js [new file with mode: 0644]
modules/settings/support/multisite.html [new file with mode: 0644]
modules/settings/support/support.xul [new file with mode: 0644]
modules/settings/support/update.html [new file with mode: 0644]
modules/staff/coworker.html [new file with mode: 0644]
modules/staff/coworker_basic.html [new file with mode: 0644]
modules/staff/img/staff.png [new file with mode: 0644]
modules/staff/js/coworker.js [new file with mode: 0644]
modules/staff/js/coworker_basic.js [new file with mode: 0644]
modules/staff/js/staff.js [new file with mode: 0644]
modules/staff/js/staff_basic.js [new file with mode: 0644]
modules/staff/staff.html [new file with mode: 0644]
modules/staff/staff.xul [new file with mode: 0644]
modules/staff/staff_basic.html [new file with mode: 0644]
modules/staff/staff_basic.xul [new file with mode: 0644]
modules/waitlist/waitlist.html [new file with mode: 0644]
modules/waitlist/waitlist.js [new file with mode: 0644]
package-lock.json [new file with mode: 0644]
package.json [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..2709666
--- /dev/null
@@ -0,0 +1,2 @@
+node_modules/*
+.vscode/*
diff --git a/css/app.css b/css/app.css
new file mode 100644 (file)
index 0000000..d9b25df
--- /dev/null
@@ -0,0 +1,65 @@
+body {
+    overflow-x: hidden;
+    overflow-y: hidden;
+  }
+  
+  #sidebar-wrapper {
+    min-height: 97vh;
+    margin-left: -15rem;
+    -webkit-transition: margin .25s ease-out;
+    -moz-transition: margin .25s ease-out;
+    -o-transition: margin .25s ease-out;
+    transition: margin .25s ease-out;
+  }
+  
+  #sidebar-wrapper .sidebar-heading {
+    padding: 5px;
+    font-size: 15px;
+    font-weight: bold;
+    color: #fff;
+    text-align: center;
+  }
+  
+  #sidebar-wrapper .list-group {
+    width: 160px;
+  }
+  
+  #page-content-wrapper {
+    min-width: 100vw;
+  }
+  
+  #wrapper.toggled #sidebar-wrapper {
+    margin-left: 0;
+  }
+  
+  @media (min-width: 768px) {
+    #sidebar-wrapper {
+      margin-left: 0;
+    }
+  
+    #page-content-wrapper {
+      min-width: 0;
+      width: 100%;
+    }
+  
+    #wrapper.toggled #sidebar-wrapper {
+      margin-left: -15rem;
+    }
+  }
+select.form-control {
+    -webkit-appearance: none;
+    -webkit-border-radius: 0px;
+    background-image: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 24 24'><path fill='#444' d='M7.406 7.828l4.594 4.594 4.594-4.594 1.406 1.406-6 6-6-6z'></path></svg>");
+    background-position: 100% 50%;
+    background-repeat: no-repeat;
+}
+
+input.right {
+  text-align: right;
+}
+.table-hover tbody tr:hover {
+  background-color: rgb(58,89,177);
+  color: #fff;
+  
+  
+}
\ No newline at end of file
diff --git a/css/calendar.css b/css/calendar.css
new file mode 100644 (file)
index 0000000..fa7115e
--- /dev/null
@@ -0,0 +1,91 @@
+.panel-day {
+  width: 100%;
+  padding: 0px;
+  margin: 0px;
+}
+
+.panel-dayhead {
+  padding: 3px;
+  width: 100%;
+  text-align: right;
+  border-bottom: 1px solid lightgrey;
+}
+
+.panel-dayheadcurrent {
+  font-weight: bold;
+}
+
+.panel-dayweekend{
+  background-color: #d1d1d1;
+}
+
+.panel-dayother {
+  background-color: #969696;
+}
+
+
+
+.panel-daybody {
+  height: 10.5vh;
+  max-height: 10.5vh;
+  overflow-y: auto;
+  padding: 3px;
+}
+
+.calevent {
+  display: block;
+  width: 100%;
+  border: 1px solid black;
+  /*border-radius: 5px;*/
+  cursor: pointer;
+}
+
+.calactivity {
+  display: inline-block;
+  margin: 2px;
+  padding: 3px;
+  border: 1px solid black;
+  /*border-radius: 5px;*/
+  cursor: pointer;
+  mix-blend-mode: screen;
+}
+table#cal_month > tbody > tr > td {
+  width: calc(100vw/7);
+  max-width: calc(100vw/7);
+  padding: 0px;
+  margin: 0px;
+}
+
+.tdweek {
+  background-color: #d1d1d1;
+}
+
+.calvacrange {
+  background-color: #FF9C2A !important;
+  /*color: #fff !important;*/
+}
+
+.calvacancy {
+  background-color: #FF7145 !important;
+}
+
+.calvacheader {
+  text-align: left;
+  max-width: 80%;
+  float: left;
+  overflow: hidden;
+  white-space: nowrap;
+}
+
+.noprint2 {
+  width: 50px;
+  min-width: 50px;
+}
+
+@media print {
+  .noprint2 {
+    display: none;
+  }
+
+}
+
diff --git a/css/creorga.css b/css/creorga.css
new file mode 100644 (file)
index 0000000..410c780
--- /dev/null
@@ -0,0 +1,267 @@
+html,body {
+        /*padding-top: 60px;
+        padding-bottom: 40px;*/
+        /*background-color: #f5f5f5;*/
+        background-color: #fff;
+        -moz-user-select: none;
+        /*padding-top: 50px;*/
+      }
+
+.pagehead {
+        font-size: 18px;
+        font-weight: bold;
+}
+.main {
+  padding: 0px;
+}
+@media (min-width: 768px) {
+  .main {
+               padding: 0px;
+    padding-right: 10px;
+    padding-left: 10px;
+  }
+}
+.main .page-header {
+  margin-top: 0;
+}
+
+.action1btn {
+        min-width: 50px;
+}
+
+.infoweek {
+        width: 320px;
+}
+
+.modal .modal-body {
+    max-height: 420px;
+    overflow-y: auto;
+}
+/*.btn-primary {
+  margin-bottom: 10px;
+}*/
+
+
+/*.table-hover tbody tr:hover td {
+        background-color: #FCF8E3;
+} */
+
+/*@media (min-width: 768px) {
+  .main {
+    padding-right: 40px;
+    padding-left: 40px;
+  }
+}*/
+.main .page-header {
+  margin-top: 0;
+}
+
+/* hides the spin-button for firefox */
+input[type=number] {
+    -moz-appearance: textfield;
+}
+/* hides the spin-button for chrome*/
+/*input[type=number]::-webkit-outer-spin-button,
+input[type=number]::-webkit-inner-spin-button {
+    -webkit-appearance: none;
+    margin: 0;
+}*/
+
+.checkbox {
+        margin-left: 30px;
+        padding-top: 0px;
+}
+
+.field {
+    margin-bottom: 5px;
+  }
+  .field label {
+    float: left;
+    width:  160px;
+    
+    text-align: right;
+    padding-right: 10px;
+    margin: 5px 0px 5px 0px;
+  }
+  .field input {
+    width: 300px;
+    margin: 0px;
+  }
+
+  .field textarea {
+    width: 300px;
+    margin: 0px;
+  }
+
+  .field button {
+    margin: 0px;
+  }
+.date {
+        width: 145px;
+}
+.month , .week {
+        width: 180px;
+}
+.number {
+        width: 145px;
+}
+.time {
+        width: 120px;
+}
+.hidden {
+  visibility: hidden;
+}
+
+input[type="date"]:disabled, input[type="text"]:disabled {
+  background-color: #fff;
+} {
+  background-color: #fff;
+}
+.tab-pane {
+        margin-top: 20px;
+}
+
+select {
+  background-color: #fff;
+  border: 1px solid #cccccc;
+  border-radius: 3px;
+  font-size: 14px;
+  height: 34px;
+  line-height: 1.42857;
+  padding: 6px 12px;
+}
+
+
+.table td.align-right {
+  text-align: right;
+}
+
+.alignright{
+        text-align: right;
+}
+
+.alignleft {
+        text-align: left;
+}
+
+.aligntop {
+  vertical-align: top;  
+}
+
+.weekwidth {
+   width: 60px;
+}
+
+.totalwidth {
+   width: 90px;
+}
+
+.modal.modal-wide .modal-dialog {
+  width: 90%;
+}
+.modal-wide .modal-body {
+  overflow-y: auto;
+}
+
+#print-head {
+  display: none;
+}
+
+#print-foot {
+  display: none;
+}
+
+.colhidden {
+  display: none;
+  max-width: 0px;
+}
+
+.btn-default:hover {
+  background: #90c8f6;
+}
+
+.summernote, .note-editable, .panel-body {
+  -moz-user-select: text;
+}
+.input-group-addon {
+  background-color: #337ab7;
+  border-color: #2e6da4;
+  color: #fff;
+}
+
+.modal-header {
+  background-color: #4F4F4F;
+  color: #fff;
+}
+
+.modal-footer {
+  background-color: #4F4F4F;
+}
+
+.timepicker {
+        max-width: 65px;
+}
+
+.warning {
+       background-color: orange;
+}
+
+/*.note-editor .note-dropzone { opacity: 0 !important; }*/
+
+.btn-absent2 {
+  color: #fff;
+  background-color: #d96f4f;
+  border-color: #ac2925;
+}
+.btn-absent2:focus,
+.btn-absent2.focus {
+  color: #fff;
+  background-color: #d96f4f;
+  border-color: #761c19;
+}
+.btn-absent2:hover {
+  color: #fff;
+  background-color: #d96f4f;
+  border-color: #ac2925;
+}
+.btn-absent2:active,
+.btn-absent2.active,
+.open > .dropdown-toggle.btn-absent2 {
+  color: #fff;
+  background-color: #d96f4f;
+  border-color: #ac2925;
+}
+.btn-absent2:active:hover,
+.btn-absent2.active:hover,
+.open > .dropdown-toggle.btn-absent2:hover,
+.btn-absent2:active:focus,
+.btn-absent2.active:focus,
+.open > .dropdown-toggle.btn-absent2:focus,
+.btn-absent2:active.focus,
+.btn-absent2.active.focus,
+.open > .dropdown-toggle.btn-absent2.focus {
+  color: #fff;
+  background-color: #d96f4f;
+  border-color: #761c19;
+}
+.btn-absent2:active,
+.btn-absent2.active,
+.open > .dropdown-toggle.btn-absent2 {
+  background-image: none;
+}
+.btn-absent2.disabled:hover,
+.btn-absent2[disabled]:hover,
+fieldset[disabled] .btn-absent2:hover,
+.btn-absent2.disabled:focus,
+.btn-absent2[disabled]:focus,
+fieldset[disabled] .btn-absent2:focus,
+.btn-absent2.disabled.focus,
+.btn-absent2[disabled].focus,
+fieldset[disabled] .btn-absent2.focus {
+  background-color: #d96f4f;
+  border-color: #ac2925;
+}
+.btn-absent2 .badge {
+  color: #d96f4f;
+  background-color: #fff;
+}
\ No newline at end of file
diff --git a/css/creorga.epic.css b/css/creorga.epic.css
new file mode 100644 (file)
index 0000000..42ce262
--- /dev/null
@@ -0,0 +1,8814 @@
+/*----Fonts----*/
+
+@import url('https://fonts.googleapis.com/css?family=Roboto');
+
+
+/*----Bootstrap----*/
+
+:root {
+  --blue: #007bff;
+  --indigo: #6610f2;
+  --purple: #6f42c1;
+  --pink: #e83e8c;
+  --red: #dc3545;
+  --orange: #fd7e14;
+  --yellow: #ffc107;
+  --green: #28a745;
+  --teal: #20c997;
+  --cyan: #17a2b8;
+  --white: #fff;
+  --gray: #6c757d;
+  --gray-dark: #343a40;
+  --primary: #5a5758;
+  --secondary: #cccccc;
+  --success: #22b24c;
+  --info: #1c9af7;
+  --warning: #f7aa1c;
+  --danger: #fc3434;
+  --light: #dddddd;
+  --dark: #77a518;
+  --breakpoint-xs: 0;
+  --breakpoint-sm: 576px;
+  --breakpoint-md: 768px;
+  --breakpoint-lg: 992px;
+  --breakpoint-xl: 1200px;
+  --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+  --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+@media print {
+  *,
+  *::before,
+  *::after {
+    text-shadow: none !important;
+    box-shadow: none !important;
+  }
+  a:not(.btn) {
+    text-decoration: underline;
+  }
+  abbr[title]::after {
+    content: " (" attr(title) ")";
+  }
+  pre {
+    white-space: pre-wrap !important;
+  }
+  pre,
+  blockquote {
+    border: 1px solid #adb5bd;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  @page {
+    size: a3;
+  }
+  body {
+    min-width: 992px !important;
+  }
+  .container {
+    min-width: 992px !important;
+  }
+  .navbar {
+    display: none;
+  }
+  .badge {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #dee2e6 !important;
+  }
+  .table-dark {
+    color: inherit;
+  }
+  .table-dark th,
+  .table-dark td,
+  .table-dark thead th,
+  .table-dark tbody + tbody {
+    border-color: #dee2e6;
+  }
+  .table .thead-dark th {
+    color: inherit;
+    border-color: #dee2e6;
+  }
+}
+
+*,
+*::before,
+*::after {
+  box-sizing: border-box;
+}
+
+html {
+  font-family: sans-serif;
+  line-height: 1.15;
+  -webkit-text-size-adjust: 100%;
+  -ms-text-size-adjust: 100%;
+  -ms-overflow-style: scrollbar;
+  -webkit-tap-highlight-color: transparent;
+}
+
+@-ms-viewport {
+  width: device-width;
+}
+
+article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
+  display: block;
+}
+
+body {
+  margin: 0;
+  font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+  font-size: 0.81rem;
+  font-weight: 400;
+  line-height: 1.5;
+  color: #212529;
+  text-align: left;
+  background-color: #fff;
+}
+
+[tabindex="-1"]:focus {
+  outline: 0 !important;
+}
+
+hr {
+  box-sizing: content-box;
+  height: 0;
+  overflow: visible;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin-top: 0;
+  margin-bottom: 0.5rem;
+}
+
+p {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+abbr[title],
+abbr[data-original-title] {
+  text-decoration: underline;
+  -webkit-text-decoration: underline dotted;
+  text-decoration: underline dotted;
+  cursor: help;
+  border-bottom: 0;
+}
+
+address {
+  margin-bottom: 1rem;
+  font-style: normal;
+  line-height: inherit;
+}
+
+ol,
+ul,
+dl {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+  margin-bottom: 0;
+}
+
+dt {
+  font-weight: 700;
+}
+
+dd {
+  margin-bottom: .5rem;
+  margin-left: 0;
+}
+
+blockquote {
+  margin: 0 0 1rem;
+}
+
+dfn {
+  font-style: italic;
+}
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+small {
+  font-size: 80%;
+}
+
+sub,
+sup {
+  position: relative;
+  font-size: 75%;
+  line-height: 0;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -.25em;
+}
+
+sup {
+  top: -.5em;
+}
+
+a {
+  color: #5a5758;
+  text-decoration: none;
+  background-color: transparent;
+  -webkit-text-decoration-skip: objects;
+}
+
+a:hover {
+  color: #333132;
+  text-decoration: underline;
+}
+
+a:not([href]):not([tabindex]) {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus {
+  outline: 0;
+}
+
+pre,
+code,
+kbd,
+samp {
+  font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+  font-size: 1em;
+}
+
+pre {
+  margin-top: 0;
+  margin-bottom: 1rem;
+  overflow: auto;
+  -ms-overflow-style: scrollbar;
+}
+
+figure {
+  margin: 0 0 1rem;
+}
+
+img {
+  vertical-align: middle;
+  border-style: none;
+}
+
+svg {
+  overflow: hidden;
+  vertical-align: middle;
+}
+
+table {
+  border-collapse: collapse;
+}
+
+caption {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  color: #6c757d;
+  text-align: left;
+  caption-side: bottom;
+}
+
+th {
+  text-align: inherit;
+}
+
+label {
+  display: inline-block;
+  margin-bottom: 0.5rem;
+}
+
+button {
+  border-radius: 0;
+}
+
+button:focus {
+  outline: 1px dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+}
+
+input,
+button,
+select,
+optgroup,
+textarea {
+  margin: 0;
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+
+button,
+input {
+  overflow: visible;
+}
+
+button,
+select {
+  text-transform: none;
+}
+
+button,
+html [type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button;
+}
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  padding: 0;
+  border-style: none;
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+  box-sizing: border-box;
+  padding: 0;
+}
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  -webkit-appearance: listbox;
+}
+
+textarea {
+  overflow: auto;
+  resize: vertical;
+}
+
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  max-width: 100%;
+  padding: 0;
+  margin-bottom: .5rem;
+  font-size: 1.5rem;
+  line-height: inherit;
+  color: inherit;
+  white-space: normal;
+}
+
+progress {
+  vertical-align: baseline;
+}
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+[type="search"] {
+  outline-offset: -2px;
+  -webkit-appearance: none;
+}
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+::-webkit-file-upload-button {
+  font: inherit;
+  -webkit-appearance: button;
+}
+
+output {
+  display: inline-block;
+}
+
+summary {
+  display: list-item;
+  cursor: pointer;
+}
+
+template {
+  display: none;
+}
+
+[hidden] {
+  display: none !important;
+}
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+  margin-bottom: 0.5rem;
+  font-family: inherit;
+  font-weight: 200;
+  line-height: 1.1;
+  color: inherit;
+}
+
+h1, .h1 {
+  font-size: 1.5rem;
+}
+
+h2, .h2 {
+  font-size: 1.25rem;
+}
+
+h3, .h3 {
+  font-size: 1.4175rem;
+}
+
+h4, .h4 {
+  font-size: 1.215rem;
+}
+
+h5, .h5 {
+  font-size: 1.0125rem;
+}
+
+h6, .h6 {
+  font-size: 0.81rem;
+}
+
+.lead {
+  font-size: 1.0125rem;
+  font-weight: 300;
+}
+
+.display-1 {
+  font-size: 6rem;
+  font-weight: 300;
+  line-height: 1.1;
+}
+
+.display-2 {
+  font-size: 5.5rem;
+  font-weight: 300;
+  line-height: 1.1;
+}
+
+.display-3 {
+  font-size: 4.5rem;
+  font-weight: 300;
+  line-height: 1.1;
+}
+
+.display-4 {
+  font-size: 3.5rem;
+  font-weight: 300;
+  line-height: 1.1;
+}
+
+hr {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border: 0;
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+small,
+.small {
+  font-size: 80%;
+  font-weight: 400;
+}
+
+mark,
+.mark {
+  padding: 0.2em;
+  background-color: #fcf8e3;
+}
+
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline-item {
+  display: inline-block;
+}
+
+.list-inline-item:not(:last-child) {
+  margin-right: 0.5rem;
+}
+
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+.blockquote {
+  margin-bottom: 1rem;
+  font-size: 1.0125rem;
+}
+
+.blockquote-footer {
+  display: block;
+  font-size: 80%;
+  color: #6c757d;
+}
+
+.blockquote-footer::before {
+  content: "\2014 \00A0";
+}
+
+.img-fluid {
+  max-width: 100%;
+  height: auto;
+}
+
+.img-thumbnail {
+  padding: 0.25rem;
+  background-color: #fff;
+  border: 1px solid #dee2e6;
+  max-width: 100%;
+  height: auto;
+}
+
+.figure {
+  display: inline-block;
+}
+
+.figure-img {
+  margin-bottom: 0.5rem;
+  line-height: 1;
+}
+
+.figure-caption {
+  font-size: 90%;
+  color: #6c757d;
+}
+
+code {
+  font-size: 87.5%;
+  color: #e83e8c;
+  word-break: break-word;
+}
+
+a > code {
+  color: inherit;
+}
+
+kbd {
+  padding: 0.2rem 0.4rem;
+  font-size: 87.5%;
+  color: #fff;
+  background-color: #212529;
+}
+
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  font-weight: 700;
+}
+
+pre {
+  display: block;
+  font-size: 87.5%;
+  color: #212529;
+}
+
+pre code {
+  font-size: inherit;
+  color: inherit;
+  word-break: normal;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+.container {
+  width: 100%;
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+@media (min-width: 576px) {
+  .container {
+    max-width: 540px;
+  }
+}
+
+@media (min-width: 768px) {
+  .container {
+    max-width: 720px;
+  }
+}
+
+@media (min-width: 992px) {
+  .container {
+    max-width: 960px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .container {
+    max-width: 1140px;
+  }
+}
+
+.container-fluid {
+  width: 100%;
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+.row {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  margin-right: -15px;
+  margin-left: -15px;
+}
+
+.no-gutters {
+  margin-right: 0;
+  margin-left: 0;
+}
+
+.no-gutters > .col,
+.no-gutters > [class*="col-"] {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,
+.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,
+.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,
+.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,
+.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,
+.col-xl-auto {
+  position: relative;
+  width: 100%;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+
+.col {
+  -ms-flex-preferred-size: 0;
+  flex-basis: 0;
+  -ms-flex-positive: 1;
+  flex-grow: 1;
+  max-width: 100%;
+}
+
+.col-auto {
+  -ms-flex: 0 0 auto;
+  flex: 0 0 auto;
+  width: auto;
+  max-width: none;
+}
+
+.col-1 {
+  -ms-flex: 0 0 8.333333%;
+  flex: 0 0 8.333333%;
+  max-width: 8.333333%;
+}
+
+.col-2 {
+  -ms-flex: 0 0 16.666667%;
+  flex: 0 0 16.666667%;
+  max-width: 16.666667%;
+}
+
+.col-3 {
+  -ms-flex: 0 0 25%;
+  flex: 0 0 25%;
+  max-width: 25%;
+}
+
+.col-4 {
+  -ms-flex: 0 0 33.333333%;
+  flex: 0 0 33.333333%;
+  max-width: 33.333333%;
+}
+
+.col-5 {
+  -ms-flex: 0 0 41.666667%;
+  flex: 0 0 41.666667%;
+  max-width: 41.666667%;
+}
+
+.col-6 {
+  -ms-flex: 0 0 50%;
+  flex: 0 0 50%;
+  max-width: 50%;
+}
+
+.col-7 {
+  -ms-flex: 0 0 58.333333%;
+  flex: 0 0 58.333333%;
+  max-width: 58.333333%;
+}
+
+.col-8 {
+  -ms-flex: 0 0 66.666667%;
+  flex: 0 0 66.666667%;
+  max-width: 66.666667%;
+}
+
+.col-9 {
+  -ms-flex: 0 0 75%;
+  flex: 0 0 75%;
+  max-width: 75%;
+}
+
+.col-10 {
+  -ms-flex: 0 0 83.333333%;
+  flex: 0 0 83.333333%;
+  max-width: 83.333333%;
+}
+
+.col-11 {
+  -ms-flex: 0 0 91.666667%;
+  flex: 0 0 91.666667%;
+  max-width: 91.666667%;
+}
+
+.col-12 {
+  -ms-flex: 0 0 100%;
+  flex: 0 0 100%;
+  max-width: 100%;
+}
+
+.order-first {
+  -ms-flex-order: -1;
+  order: -1;
+}
+
+.order-last {
+  -ms-flex-order: 13;
+  order: 13;
+}
+
+.order-0 {
+  -ms-flex-order: 0;
+  order: 0;
+}
+
+.order-1 {
+  -ms-flex-order: 1;
+  order: 1;
+}
+
+.order-2 {
+  -ms-flex-order: 2;
+  order: 2;
+}
+
+.order-3 {
+  -ms-flex-order: 3;
+  order: 3;
+}
+
+.order-4 {
+  -ms-flex-order: 4;
+  order: 4;
+}
+
+.order-5 {
+  -ms-flex-order: 5;
+  order: 5;
+}
+
+.order-6 {
+  -ms-flex-order: 6;
+  order: 6;
+}
+
+.order-7 {
+  -ms-flex-order: 7;
+  order: 7;
+}
+
+.order-8 {
+  -ms-flex-order: 8;
+  order: 8;
+}
+
+.order-9 {
+  -ms-flex-order: 9;
+  order: 9;
+}
+
+.order-10 {
+  -ms-flex-order: 10;
+  order: 10;
+}
+
+.order-11 {
+  -ms-flex-order: 11;
+  order: 11;
+}
+
+.order-12 {
+  -ms-flex-order: 12;
+  order: 12;
+}
+
+.offset-1 {
+  margin-left: 8.333333%;
+}
+
+.offset-2 {
+  margin-left: 16.666667%;
+}
+
+.offset-3 {
+  margin-left: 25%;
+}
+
+.offset-4 {
+  margin-left: 33.333333%;
+}
+
+.offset-5 {
+  margin-left: 41.666667%;
+}
+
+.offset-6 {
+  margin-left: 50%;
+}
+
+.offset-7 {
+  margin-left: 58.333333%;
+}
+
+.offset-8 {
+  margin-left: 66.666667%;
+}
+
+.offset-9 {
+  margin-left: 75%;
+}
+
+.offset-10 {
+  margin-left: 83.333333%;
+}
+
+.offset-11 {
+  margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+  .col-sm {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+  }
+  .col-sm-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+  }
+  .col-sm-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+  }
+  .col-sm-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+  }
+  .col-sm-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+  }
+  .col-sm-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+  }
+  .col-sm-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+  }
+  .col-sm-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+  }
+  .col-sm-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+  }
+  .col-sm-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+  }
+  .col-sm-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+  }
+  .col-sm-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+  }
+  .col-sm-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+  }
+  .col-sm-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+  }
+  .order-sm-first {
+    -ms-flex-order: -1;
+    order: -1;
+  }
+  .order-sm-last {
+    -ms-flex-order: 13;
+    order: 13;
+  }
+  .order-sm-0 {
+    -ms-flex-order: 0;
+    order: 0;
+  }
+  .order-sm-1 {
+    -ms-flex-order: 1;
+    order: 1;
+  }
+  .order-sm-2 {
+    -ms-flex-order: 2;
+    order: 2;
+  }
+  .order-sm-3 {
+    -ms-flex-order: 3;
+    order: 3;
+  }
+  .order-sm-4 {
+    -ms-flex-order: 4;
+    order: 4;
+  }
+  .order-sm-5 {
+    -ms-flex-order: 5;
+    order: 5;
+  }
+  .order-sm-6 {
+    -ms-flex-order: 6;
+    order: 6;
+  }
+  .order-sm-7 {
+    -ms-flex-order: 7;
+    order: 7;
+  }
+  .order-sm-8 {
+    -ms-flex-order: 8;
+    order: 8;
+  }
+  .order-sm-9 {
+    -ms-flex-order: 9;
+    order: 9;
+  }
+  .order-sm-10 {
+    -ms-flex-order: 10;
+    order: 10;
+  }
+  .order-sm-11 {
+    -ms-flex-order: 11;
+    order: 11;
+  }
+  .order-sm-12 {
+    -ms-flex-order: 12;
+    order: 12;
+  }
+  .offset-sm-0 {
+    margin-left: 0;
+  }
+  .offset-sm-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-sm-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-sm-3 {
+    margin-left: 25%;
+  }
+  .offset-sm-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-sm-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-sm-6 {
+    margin-left: 50%;
+  }
+  .offset-sm-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-sm-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-sm-9 {
+    margin-left: 75%;
+  }
+  .offset-sm-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-sm-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-md {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+  }
+  .col-md-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+  }
+  .col-md-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+  }
+  .col-md-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+  }
+  .col-md-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+  }
+  .col-md-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+  }
+  .col-md-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+  }
+  .col-md-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+  }
+  .col-md-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+  }
+  .col-md-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+  }
+  .col-md-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+  }
+  .col-md-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+  }
+  .col-md-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+  }
+  .col-md-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+  }
+  .order-md-first {
+    -ms-flex-order: -1;
+    order: -1;
+  }
+  .order-md-last {
+    -ms-flex-order: 13;
+    order: 13;
+  }
+  .order-md-0 {
+    -ms-flex-order: 0;
+    order: 0;
+  }
+  .order-md-1 {
+    -ms-flex-order: 1;
+    order: 1;
+  }
+  .order-md-2 {
+    -ms-flex-order: 2;
+    order: 2;
+  }
+  .order-md-3 {
+    -ms-flex-order: 3;
+    order: 3;
+  }
+  .order-md-4 {
+    -ms-flex-order: 4;
+    order: 4;
+  }
+  .order-md-5 {
+    -ms-flex-order: 5;
+    order: 5;
+  }
+  .order-md-6 {
+    -ms-flex-order: 6;
+    order: 6;
+  }
+  .order-md-7 {
+    -ms-flex-order: 7;
+    order: 7;
+  }
+  .order-md-8 {
+    -ms-flex-order: 8;
+    order: 8;
+  }
+  .order-md-9 {
+    -ms-flex-order: 9;
+    order: 9;
+  }
+  .order-md-10 {
+    -ms-flex-order: 10;
+    order: 10;
+  }
+  .order-md-11 {
+    -ms-flex-order: 11;
+    order: 11;
+  }
+  .order-md-12 {
+    -ms-flex-order: 12;
+    order: 12;
+  }
+  .offset-md-0 {
+    margin-left: 0;
+  }
+  .offset-md-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-md-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-md-3 {
+    margin-left: 25%;
+  }
+  .offset-md-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-md-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-md-6 {
+    margin-left: 50%;
+  }
+  .offset-md-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-md-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-md-9 {
+    margin-left: 75%;
+  }
+  .offset-md-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-md-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-lg {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+  }
+  .col-lg-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+  }
+  .col-lg-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+  }
+  .col-lg-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+  }
+  .col-lg-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+  }
+  .col-lg-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+  }
+  .col-lg-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+  }
+  .col-lg-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+  }
+  .col-lg-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+  }
+  .col-lg-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+  }
+  .col-lg-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+  }
+  .col-lg-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+  }
+  .col-lg-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+  }
+  .col-lg-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+  }
+  .order-lg-first {
+    -ms-flex-order: -1;
+    order: -1;
+  }
+  .order-lg-last {
+    -ms-flex-order: 13;
+    order: 13;
+  }
+  .order-lg-0 {
+    -ms-flex-order: 0;
+    order: 0;
+  }
+  .order-lg-1 {
+    -ms-flex-order: 1;
+    order: 1;
+  }
+  .order-lg-2 {
+    -ms-flex-order: 2;
+    order: 2;
+  }
+  .order-lg-3 {
+    -ms-flex-order: 3;
+    order: 3;
+  }
+  .order-lg-4 {
+    -ms-flex-order: 4;
+    order: 4;
+  }
+  .order-lg-5 {
+    -ms-flex-order: 5;
+    order: 5;
+  }
+  .order-lg-6 {
+    -ms-flex-order: 6;
+    order: 6;
+  }
+  .order-lg-7 {
+    -ms-flex-order: 7;
+    order: 7;
+  }
+  .order-lg-8 {
+    -ms-flex-order: 8;
+    order: 8;
+  }
+  .order-lg-9 {
+    -ms-flex-order: 9;
+    order: 9;
+  }
+  .order-lg-10 {
+    -ms-flex-order: 10;
+    order: 10;
+  }
+  .order-lg-11 {
+    -ms-flex-order: 11;
+    order: 11;
+  }
+  .order-lg-12 {
+    -ms-flex-order: 12;
+    order: 12;
+  }
+  .offset-lg-0 {
+    margin-left: 0;
+  }
+  .offset-lg-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-lg-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-lg-3 {
+    margin-left: 25%;
+  }
+  .offset-lg-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-lg-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-lg-6 {
+    margin-left: 50%;
+  }
+  .offset-lg-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-lg-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-lg-9 {
+    margin-left: 75%;
+  }
+  .offset-lg-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-lg-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xl {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+  }
+  .col-xl-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+  }
+  .col-xl-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+  }
+  .col-xl-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+  }
+  .col-xl-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+  }
+  .col-xl-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+  }
+  .col-xl-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+  }
+  .col-xl-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+  }
+  .col-xl-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+  }
+  .col-xl-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+  }
+  .col-xl-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+  }
+  .col-xl-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+  }
+  .col-xl-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+  }
+  .col-xl-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+  }
+  .order-xl-first {
+    -ms-flex-order: -1;
+    order: -1;
+  }
+  .order-xl-last {
+    -ms-flex-order: 13;
+    order: 13;
+  }
+  .order-xl-0 {
+    -ms-flex-order: 0;
+    order: 0;
+  }
+  .order-xl-1 {
+    -ms-flex-order: 1;
+    order: 1;
+  }
+  .order-xl-2 {
+    -ms-flex-order: 2;
+    order: 2;
+  }
+  .order-xl-3 {
+    -ms-flex-order: 3;
+    order: 3;
+  }
+  .order-xl-4 {
+    -ms-flex-order: 4;
+    order: 4;
+  }
+  .order-xl-5 {
+    -ms-flex-order: 5;
+    order: 5;
+  }
+  .order-xl-6 {
+    -ms-flex-order: 6;
+    order: 6;
+  }
+  .order-xl-7 {
+    -ms-flex-order: 7;
+    order: 7;
+  }
+  .order-xl-8 {
+    -ms-flex-order: 8;
+    order: 8;
+  }
+  .order-xl-9 {
+    -ms-flex-order: 9;
+    order: 9;
+  }
+  .order-xl-10 {
+    -ms-flex-order: 10;
+    order: 10;
+  }
+  .order-xl-11 {
+    -ms-flex-order: 11;
+    order: 11;
+  }
+  .order-xl-12 {
+    -ms-flex-order: 12;
+    order: 12;
+  }
+  .offset-xl-0 {
+    margin-left: 0;
+  }
+  .offset-xl-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-xl-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-xl-3 {
+    margin-left: 25%;
+  }
+  .offset-xl-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-xl-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-xl-6 {
+    margin-left: 50%;
+  }
+  .offset-xl-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-xl-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-xl-9 {
+    margin-left: 75%;
+  }
+  .offset-xl-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-xl-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+.table {
+  width: 100%;
+  margin-bottom: 1rem;
+  background-color: transparent;
+}
+
+.table th,
+.table td {
+  padding: 0.5rem;
+  vertical-align: top;
+  border-top: 1px solid #dee2e6;
+}
+
+.table thead th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #dee2e6;
+}
+
+.table tbody + tbody {
+  border-top: 2px solid #dee2e6;
+}
+
+.table .table {
+  background-color: #fff;
+}
+
+.table-sm th,
+.table-sm td {
+  padding: 0.3rem;
+}
+
+.table-bordered {
+  border: 1px solid #dee2e6;
+}
+
+.table-bordered th,
+.table-bordered td {
+  border: 1px solid #dee2e6;
+}
+
+.table-bordered thead th,
+.table-bordered thead td {
+  border-bottom-width: 2px;
+}
+
+.table-borderless th,
+.table-borderless td,
+.table-borderless thead th,
+.table-borderless tbody + tbody {
+  border: 0;
+}
+
+.table-striped tbody tr:nth-of-type(odd) {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+
+.table-hover tbody tr:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-primary,
+.table-primary > th,
+.table-primary > td {
+  background-color: #d1d0d0;
+}
+
+.table-hover .table-primary:hover {
+  background-color: #c4c3c3;
+}
+
+.table-hover .table-primary:hover > td,
+.table-hover .table-primary:hover > th {
+  background-color: #c4c3c3;
+}
+
+.table-secondary,
+.table-secondary > th,
+.table-secondary > td {
+  background-color: #f1f1f1;
+}
+
+.table-hover .table-secondary:hover {
+  background-color: #e4e4e4;
+}
+
+.table-hover .table-secondary:hover > td,
+.table-hover .table-secondary:hover > th {
+  background-color: #e4e4e4;
+}
+
+.table-success,
+.table-success > th,
+.table-success > td {
+  background-color: #c1e9cd;
+}
+
+.table-hover .table-success:hover {
+  background-color: #aee2be;
+}
+
+.table-hover .table-success:hover > td,
+.table-hover .table-success:hover > th {
+  background-color: #aee2be;
+}
+
+.table-info,
+.table-info > th,
+.table-info > td {
+  background-color: #bfe3fd;
+}
+
+.table-hover .table-info:hover {
+  background-color: #a6d8fc;
+}
+
+.table-hover .table-info:hover > td,
+.table-hover .table-info:hover > th {
+  background-color: #a6d8fc;
+}
+
+.table-warning,
+.table-warning > th,
+.table-warning > td {
+  background-color: #fde7bf;
+}
+
+.table-hover .table-warning:hover {
+  background-color: #fcdea6;
+}
+
+.table-hover .table-warning:hover > td,
+.table-hover .table-warning:hover > th {
+  background-color: #fcdea6;
+}
+
+.table-danger,
+.table-danger > th,
+.table-danger > td {
+  background-color: #fec6c6;
+}
+
+.table-hover .table-danger:hover {
+  background-color: #feadad;
+}
+
+.table-hover .table-danger:hover > td,
+.table-hover .table-danger:hover > th {
+  background-color: #feadad;
+}
+
+.table-light,
+.table-light > th,
+.table-light > td {
+  background-color: whitesmoke;
+}
+
+.table-hover .table-light:hover {
+  background-color: #e8e8e8;
+}
+
+.table-hover .table-light:hover > td,
+.table-hover .table-light:hover > th {
+  background-color: #e8e8e8;
+}
+
+.table-dark,
+.table-dark > th,
+.table-dark > td {
+  background-color: #d9e6be;
+}
+
+.table-hover .table-dark:hover {
+  background-color: #cedfac;
+}
+
+.table-hover .table-dark:hover > td,
+.table-hover .table-dark:hover > th {
+  background-color: #cedfac;
+}
+
+.table-active,
+.table-active > th,
+.table-active > td {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover > td,
+.table-hover .table-active:hover > th {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table .thead-dark th {
+  color: #fff;
+  background-color: #212529;
+  border-color: #32383e;
+}
+
+.table .thead-light th {
+  color: #495057;
+  background-color: #e9ecef;
+  border-color: #dee2e6;
+}
+
+.table-dark {
+  color: #fff;
+  background-color: #212529;
+}
+
+.table-dark th,
+.table-dark td,
+.table-dark thead th {
+  border-color: #32383e;
+}
+
+.table-dark.table-bordered {
+  border: 0;
+}
+
+.table-dark.table-striped tbody tr:nth-of-type(odd) {
+  background-color: rgba(255, 255, 255, 0.05);
+}
+
+.table-dark.table-hover tbody tr:hover {
+  background-color: rgba(255, 255, 255, 0.075);
+}
+
+@media (max-width: 575.98px) {
+  .table-responsive-sm {
+    display: block;
+    width: 100%;
+    overflow-x: auto;
+    -webkit-overflow-scrolling: touch;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+  }
+  .table-responsive-sm > .table-bordered {
+    border: 0;
+  }
+}
+
+@media (max-width: 767.98px) {
+  .table-responsive-md {
+    display: block;
+    width: 100%;
+    overflow-x: auto;
+    -webkit-overflow-scrolling: touch;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+  }
+  .table-responsive-md > .table-bordered {
+    border: 0;
+  }
+}
+
+@media (max-width: 991.98px) {
+  .table-responsive-lg {
+    display: block;
+    width: 100%;
+    overflow-x: auto;
+    -webkit-overflow-scrolling: touch;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+  }
+  .table-responsive-lg > .table-bordered {
+    border: 0;
+  }
+}
+
+@media (max-width: 1199.98px) {
+  .table-responsive-xl {
+    display: block;
+    width: 100%;
+    overflow-x: auto;
+    -webkit-overflow-scrolling: touch;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+  }
+  .table-responsive-xl > .table-bordered {
+    border: 0;
+  }
+}
+
+.table-responsive {
+  display: block;
+  width: 100%;
+  overflow-x: auto;
+  -webkit-overflow-scrolling: touch;
+  -ms-overflow-style: -ms-autohiding-scrollbar;
+}
+
+.table-responsive > .table-bordered {
+  border: 0;
+}
+
+.form-control {
+  display: block;
+  width: 100%;
+  height: calc(1.965rem + 2px);
+  padding: 0.375rem 0.38rem;
+  font-size: 0.81rem;
+  line-height: 1.5;
+  color: #495057;
+  background-color: #fff;
+  background-clip: padding-box;
+  border: 1px solid #ced4da;
+  border-radius: 0;
+  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .form-control {
+    transition: none;
+  }
+}
+
+.form-control::-ms-expand {
+  background-color: transparent;
+  border: 0;
+}
+
+.form-control:focus {
+  color: #495057;
+  background-color: #fff;
+  border-color: #9a9798;
+  outline: 0;
+  box-shadow: 0 0 0 0.2rem rgba(90, 87, 88, 0.25);
+}
+
+.form-control::-webkit-input-placeholder {
+  color: #6c757d;
+  opacity: 1;
+}
+
+.form-control::-moz-placeholder {
+  color: #6c757d;
+  opacity: 1;
+}
+
+.form-control:-ms-input-placeholder {
+  color: #6c757d;
+  opacity: 1;
+}
+
+.form-control::-ms-input-placeholder {
+  color: #6c757d;
+  opacity: 1;
+}
+
+.form-control::placeholder {
+  color: #6c757d;
+  opacity: 1;
+}
+
+.form-control:disabled, .form-control[readonly] {
+  background-color: #e9ecef;
+  opacity: 1;
+}
+
+select.form-control:focus::-ms-value {
+  color: #495057;
+  background-color: #fff;
+}
+
+.form-control-file,
+.form-control-range {
+  display: block;
+  width: 100%;
+}
+
+.col-form-label {
+  padding-top: calc(0.375rem + 1px);
+  padding-bottom: calc(0.375rem + 1px);
+  margin-bottom: 0;
+  font-size: inherit;
+  line-height: 1.5;
+}
+
+.col-form-label-lg {
+  padding-top: calc(0.5rem + 1px);
+  padding-bottom: calc(0.5rem + 1px);
+  font-size: 1.0125rem;
+  line-height: 1.5;
+}
+
+.col-form-label-sm {
+  padding-top: calc(0.25rem + 1px);
+  padding-bottom: calc(0.25rem + 1px);
+  font-size: 0.70875rem;
+  line-height: 1.5;
+}
+
+.form-control-plaintext {
+  display: block;
+  width: 100%;
+  padding-top: 0.375rem;
+  padding-bottom: 0.375rem;
+  margin-bottom: 0;
+  line-height: 1.5;
+  color: #212529;
+  background-color: transparent;
+  border: solid transparent;
+  border-width: 1px 0;
+}
+
+.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.form-control-sm {
+  height: calc(1.563125rem + 2px);
+  padding: 0.25rem 0.5rem;
+  font-size: 0.70875rem;
+  line-height: 1.5;
+}
+
+.form-control-lg {
+  height: calc(2.51875rem + 2px);
+  padding: 0.5rem 1rem;
+  font-size: 1.0125rem;
+  line-height: 1.5;
+}
+
+select.form-control[size], select.form-control[multiple] {
+  height: auto;
+}
+
+textarea.form-control {
+  height: auto;
+}
+
+.form-group {
+  margin-bottom: 1rem;
+}
+
+.form-text {
+  display: block;
+  margin-top: 0.25rem;
+}
+
+.form-row {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  margin-right: -5px;
+  margin-left: -5px;
+}
+
+.form-row > .col,
+.form-row > [class*="col-"] {
+  padding-right: 5px;
+  padding-left: 5px;
+}
+
+.form-check {
+  position: relative;
+  display: block;
+  padding-left: 1.25rem;
+}
+
+.form-check-input {
+  position: absolute;
+  margin-top: 0.3rem;
+  margin-left: -1.25rem;
+}
+
+.form-check-input:disabled ~ .form-check-label {
+  color: #6c757d;
+}
+
+.form-check-label {
+  margin-bottom: 0;
+}
+
+.form-check-inline {
+  display: -ms-inline-flexbox;
+  display: inline-flex;
+  -ms-flex-align: center;
+  align-items: center;
+  padding-left: 0;
+  margin-right: 0.75rem;
+}
+
+.form-check-inline .form-check-input {
+  position: static;
+  margin-top: 0;
+  margin-right: 0.3125rem;
+  margin-left: 0;
+}
+
+.valid-feedback {
+  display: none;
+  width: 100%;
+  margin-top: 0.25rem;
+  font-size: 80%;
+  color: #22b24c;
+}
+
+.valid-tooltip {
+  position: absolute;
+  top: 100%;
+  z-index: 5;
+  display: none;
+  max-width: 100%;
+  padding: 0.25rem 0.5rem;
+  margin-top: .1rem;
+  font-size: 0.70875rem;
+  line-height: 1.5;
+  color: #fff;
+  background-color: rgba(34, 178, 76, 0.9);
+}
+
+.was-validated .form-control:valid, .form-control.is-valid, .was-validated
+.custom-select:valid,
+.custom-select.is-valid {
+  border-color: #22b24c;
+}
+
+.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated
+.custom-select:valid:focus,
+.custom-select.is-valid:focus {
+  border-color: #22b24c;
+  box-shadow: 0 0 0 0.2rem rgba(34, 178, 76, 0.25);
+}
+
+.was-validated .form-control:valid ~ .valid-feedback,
+.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,
+.form-control.is-valid ~ .valid-tooltip, .was-validated
+.custom-select:valid ~ .valid-feedback,
+.was-validated
+.custom-select:valid ~ .valid-tooltip,
+.custom-select.is-valid ~ .valid-feedback,
+.custom-select.is-valid ~ .valid-tooltip {
+  display: block;
+}
+
+.was-validated .form-control-file:valid ~ .valid-feedback,
+.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback,
+.form-control-file.is-valid ~ .valid-tooltip {
+  display: block;
+}
+
+.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {
+  color: #22b24c;
+}
+
+.was-validated .form-check-input:valid ~ .valid-feedback,
+.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback,
+.form-check-input.is-valid ~ .valid-tooltip {
+  display: block;
+}
+
+.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label {
+  color: #22b24c;
+}
+
+.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before {
+  background-color: #70e492;
+}
+
+.was-validated .custom-control-input:valid ~ .valid-feedback,
+.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback,
+.custom-control-input.is-valid ~ .valid-tooltip {
+  display: block;
+}
+
+.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {
+  background-color: #30d761;
+}
+
+.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before {
+  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(34, 178, 76, 0.25);
+}
+
+.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label {
+  border-color: #22b24c;
+}
+
+.was-validated .custom-file-input:valid ~ .custom-file-label::after, .custom-file-input.is-valid ~ .custom-file-label::after {
+  border-color: inherit;
+}
+
+.was-validated .custom-file-input:valid ~ .valid-feedback,
+.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback,
+.custom-file-input.is-valid ~ .valid-tooltip {
+  display: block;
+}
+
+.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {
+  box-shadow: 0 0 0 0.2rem rgba(34, 178, 76, 0.25);
+}
+
+.invalid-feedback {
+  display: none;
+  width: 100%;
+  margin-top: 0.25rem;
+  font-size: 80%;
+  color: #fc3434;
+}
+
+.invalid-tooltip {
+  position: absolute;
+  top: 100%;
+  z-index: 5;
+  display: none;
+  max-width: 100%;
+  padding: 0.25rem 0.5rem;
+  margin-top: .1rem;
+  font-size: 0.70875rem;
+  line-height: 1.5;
+  color: #fff;
+  background-color: rgba(252, 52, 52, 0.9);
+}
+
+.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated
+.custom-select:invalid,
+.custom-select.is-invalid {
+  border-color: #fc3434;
+}
+
+.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated
+.custom-select:invalid:focus,
+.custom-select.is-invalid:focus {
+  border-color: #fc3434;
+  box-shadow: 0 0 0 0.2rem rgba(252, 52, 52, 0.25);
+}
+
+.was-validated .form-control:invalid ~ .invalid-feedback,
+.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,
+.form-control.is-invalid ~ .invalid-tooltip, .was-validated
+.custom-select:invalid ~ .invalid-feedback,
+.was-validated
+.custom-select:invalid ~ .invalid-tooltip,
+.custom-select.is-invalid ~ .invalid-feedback,
+.custom-select.is-invalid ~ .invalid-tooltip {
+  display: block;
+}
+
+.was-validated .form-control-file:invalid ~ .invalid-feedback,
+.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback,
+.form-control-file.is-invalid ~ .invalid-tooltip {
+  display: block;
+}
+
+.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {
+  color: #fc3434;
+}
+
+.was-validated .form-check-input:invalid ~ .invalid-feedback,
+.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback,
+.form-check-input.is-invalid ~ .invalid-tooltip {
+  display: block;
+}
+
+.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label {
+  color: #fc3434;
+}
+
+.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before {
+  background-color: #feb2b2;
+}
+
+.was-validated .custom-control-input:invalid ~ .invalid-feedback,
+.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback,
+.custom-control-input.is-invalid ~ .invalid-tooltip {
+  display: block;
+}
+
+.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {
+  background-color: #fd6666;
+}
+
+.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before {
+  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(252, 52, 52, 0.25);
+}
+
+.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {
+  border-color: #fc3434;
+}
+
+.was-validated .custom-file-input:invalid ~ .custom-file-label::after, .custom-file-input.is-invalid ~ .custom-file-label::after {
+  border-color: inherit;
+}
+
+.was-validated .custom-file-input:invalid ~ .invalid-feedback,
+.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback,
+.custom-file-input.is-invalid ~ .invalid-tooltip {
+  display: block;
+}
+
+.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {
+  box-shadow: 0 0 0 0.2rem rgba(252, 52, 52, 0.25);
+}
+
+.form-inline {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-flow: row wrap;
+  flex-flow: row wrap;
+  -ms-flex-align: center;
+  align-items: center;
+}
+
+.form-inline .form-check {
+  width: 100%;
+}
+
+@media (min-width: 576px) {
+  .form-inline label {
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex-align: center;
+    align-items: center;
+    -ms-flex-pack: center;
+    justify-content: center;
+    margin-bottom: 0;
+  }
+  .form-inline .form-group {
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    -ms-flex-flow: row wrap;
+    flex-flow: row wrap;
+    -ms-flex-align: center;
+    align-items: center;
+    margin-bottom: 0;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .form-control-plaintext {
+    display: inline-block;
+  }
+  .form-inline .input-group,
+  .form-inline .custom-select {
+    width: auto;
+  }
+  .form-inline .form-check {
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex-align: center;
+    align-items: center;
+    -ms-flex-pack: center;
+    justify-content: center;
+    width: auto;
+    padding-left: 0;
+  }
+  .form-inline .form-check-input {
+    position: relative;
+    margin-top: 0;
+    margin-right: 0.25rem;
+    margin-left: 0;
+  }
+  .form-inline .custom-control {
+    -ms-flex-align: center;
+    align-items: center;
+    -ms-flex-pack: center;
+    justify-content: center;
+  }
+  .form-inline .custom-control-label {
+    margin-bottom: 0;
+  }
+}
+
+.btn {
+  display: inline-block;
+  font-weight: 400;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  border: 1px solid transparent;
+  padding: 0.375rem 1rem;
+  font-size: 0.81rem;
+  line-height: 1.5;
+  border-radius: 0;
+  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .btn {
+    transition: none;
+  }
+}
+
+.btn:hover, .btn:focus {
+  text-decoration: none;
+}
+
+.btn:focus, .btn.focus {
+  outline: 0;
+  box-shadow: 0 0 0 0.2rem rgba(90, 87, 88, 0.25);
+}
+
+.btn.disabled, .btn:disabled {
+  opacity: 0.65;
+}
+
+.btn:not(:disabled):not(.disabled) {
+  cursor: pointer;
+}
+
+a.btn.disabled,
+fieldset:disabled a.btn {
+  pointer-events: none;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #5a5758;
+  border-color: #5a5758;
+}
+
+.btn-primary:hover {
+  color: #fff;
+  background-color: #474445;
+  border-color: #403e3f;
+}
+
+.btn-primary:focus, .btn-primary.focus {
+  box-shadow: 0 0 0 0.2rem rgba(90, 87, 88, 0.5);
+}
+
+.btn-primary.disabled, .btn-primary:disabled {
+  color: #fff;
+  background-color: #5a5758;
+  border-color: #5a5758;
+}
+
+.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active,
+.show > .btn-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #403e3f;
+  border-color: #3a3838;
+}
+
+.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus,
+.show > .btn-primary.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(90, 87, 88, 0.5);
+}
+
+.btn-secondary {
+  color: #212529;
+  background-color: #cccccc;
+  border-color: #cccccc;
+}
+
+.btn-secondary:hover {
+  color: #212529;
+  background-color: #b9b9b9;
+  border-color: #b3b3b3;
+}
+
+.btn-secondary:focus, .btn-secondary.focus {
+  box-shadow: 0 0 0 0.2rem rgba(204, 204, 204, 0.5);
+}
+
+.btn-secondary.disabled, .btn-secondary:disabled {
+  color: #212529;
+  background-color: #cccccc;
+  border-color: #cccccc;
+}
+
+.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active,
+.show > .btn-secondary.dropdown-toggle {
+  color: #212529;
+  background-color: #b3b3b3;
+  border-color: #acacac;
+}
+
+.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus,
+.show > .btn-secondary.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(204, 204, 204, 0.5);
+}
+
+.btn-success {
+  color: #fff;
+  background-color: #22b24c;
+  border-color: #22b24c;
+}
+
+.btn-success:hover {
+  color: #fff;
+  background-color: #1c923e;
+  border-color: #1a873a;
+}
+
+.btn-success:focus, .btn-success.focus {
+  box-shadow: 0 0 0 0.2rem rgba(34, 178, 76, 0.5);
+}
+
+.btn-success.disabled, .btn-success:disabled {
+  color: #fff;
+  background-color: #22b24c;
+  border-color: #22b24c;
+}
+
+.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,
+.show > .btn-success.dropdown-toggle {
+  color: #fff;
+  background-color: #1a873a;
+  border-color: #187c35;
+}
+
+.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus,
+.show > .btn-success.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(34, 178, 76, 0.5);
+}
+
+.btn-info {
+  color: #fff;
+  background-color: #1c9af7;
+  border-color: #1c9af7;
+}
+
+.btn-info:hover {
+  color: #fff;
+  background-color: #0887e5;
+  border-color: #0880d8;
+}
+
+.btn-info:focus, .btn-info.focus {
+  box-shadow: 0 0 0 0.2rem rgba(28, 154, 247, 0.5);
+}
+
+.btn-info.disabled, .btn-info:disabled {
+  color: #fff;
+  background-color: #1c9af7;
+  border-color: #1c9af7;
+}
+
+.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active,
+.show > .btn-info.dropdown-toggle {
+  color: #fff;
+  background-color: #0880d8;
+  border-color: #0778cc;
+}
+
+.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus,
+.show > .btn-info.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(28, 154, 247, 0.5);
+}
+
+.btn-warning {
+  color: #212529;
+  background-color: #f7aa1c;
+  border-color: #f7aa1c;
+}
+
+.btn-warning:hover {
+  color: #212529;
+  background-color: #e59708;
+  border-color: #d88f08;
+}
+
+.btn-warning:focus, .btn-warning.focus {
+  box-shadow: 0 0 0 0.2rem rgba(247, 170, 28, 0.5);
+}
+
+.btn-warning.disabled, .btn-warning:disabled {
+  color: #212529;
+  background-color: #f7aa1c;
+  border-color: #f7aa1c;
+}
+
+.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active,
+.show > .btn-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #d88f08;
+  border-color: #cc8707;
+}
+
+.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus,
+.show > .btn-warning.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(247, 170, 28, 0.5);
+}
+
+.btn-danger {
+  color: #fff;
+  background-color: #fc3434;
+  border-color: #fc3434;
+}
+
+.btn-danger:hover {
+  color: #fff;
+  background-color: #fb0e0e;
+  border-color: #f90404;
+}
+
+.btn-danger:focus, .btn-danger.focus {
+  box-shadow: 0 0 0 0.2rem rgba(252, 52, 52, 0.5);
+}
+
+.btn-danger.disabled, .btn-danger:disabled {
+  color: #fff;
+  background-color: #fc3434;
+  border-color: #fc3434;
+}
+
+.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active,
+.show > .btn-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #f90404;
+  border-color: #ed0303;
+}
+
+.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus,
+.show > .btn-danger.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(252, 52, 52, 0.5);
+}
+
+.btn-light {
+  color: #212529;
+  background-color: #dddddd;
+  border-color: #dddddd;
+}
+
+.btn-light:hover {
+  color: #212529;
+  background-color: #cacaca;
+  border-color: #c4c4c4;
+}
+
+.btn-light:focus, .btn-light.focus {
+  box-shadow: 0 0 0 0.2rem rgba(221, 221, 221, 0.5);
+}
+
+.btn-light.disabled, .btn-light:disabled {
+  color: #212529;
+  background-color: #dddddd;
+  border-color: #dddddd;
+}
+
+.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active,
+.show > .btn-light.dropdown-toggle {
+  color: #212529;
+  background-color: #c4c4c4;
+  border-color: #bdbdbd;
+}
+
+.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus,
+.show > .btn-light.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(221, 221, 221, 0.5);
+}
+
+.btn-dark {
+  color: #fff;
+  background-color: #77a518;
+  border-color: #77a518;
+}
+
+.btn-dark:hover {
+  color: #fff;
+  background-color: #5f8413;
+  border-color: #577812;
+}
+
+.btn-dark:focus, .btn-dark.focus {
+  box-shadow: 0 0 0 0.2rem rgba(119, 165, 24, 0.5);
+}
+
+.btn-dark.disabled, .btn-dark:disabled {
+  color: #fff;
+  background-color: #77a518;
+  border-color: #77a518;
+}
+
+.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active,
+.show > .btn-dark.dropdown-toggle {
+  color: #fff;
+  background-color: #577812;
+  border-color: #4f6d10;
+}
+
+.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus,
+.show > .btn-dark.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(119, 165, 24, 0.5);
+}
+
+.btn-outline-primary {
+  color: #5a5758;
+  background-color: transparent;
+  background-image: none;
+  border-color: #5a5758;
+}
+
+.btn-outline-primary:hover {
+  color: #fff;
+  background-color: #5a5758;
+  border-color: #5a5758;
+}
+
+.btn-outline-primary:focus, .btn-outline-primary.focus {
+  box-shadow: 0 0 0 0.2rem rgba(90, 87, 88, 0.5);
+}
+
+.btn-outline-primary.disabled, .btn-outline-primary:disabled {
+  color: #5a5758;
+  background-color: transparent;
+}
+
+.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active,
+.show > .btn-outline-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #5a5758;
+  border-color: #5a5758;
+}
+
+.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus,
+.show > .btn-outline-primary.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(90, 87, 88, 0.5);
+}
+
+.btn-outline-secondary {
+  color: #cccccc;
+  background-color: transparent;
+  background-image: none;
+  border-color: #cccccc;
+}
+
+.btn-outline-secondary:hover {
+  color: #212529;
+  background-color: #cccccc;
+  border-color: #cccccc;
+}
+
+.btn-outline-secondary:focus, .btn-outline-secondary.focus {
+  box-shadow: 0 0 0 0.2rem rgba(204, 204, 204, 0.5);
+}
+
+.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {
+  color: #cccccc;
+  background-color: transparent;
+}
+
+.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active,
+.show > .btn-outline-secondary.dropdown-toggle {
+  color: #212529;
+  background-color: #cccccc;
+  border-color: #cccccc;
+}
+
+.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,
+.show > .btn-outline-secondary.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(204, 204, 204, 0.5);
+}
+
+.btn-outline-success {
+  color: #22b24c;
+  background-color: transparent;
+  background-image: none;
+  border-color: #22b24c;
+}
+
+.btn-outline-success:hover {
+  color: #fff;
+  background-color: #22b24c;
+  border-color: #22b24c;
+}
+
+.btn-outline-success:focus, .btn-outline-success.focus {
+  box-shadow: 0 0 0 0.2rem rgba(34, 178, 76, 0.5);
+}
+
+.btn-outline-success.disabled, .btn-outline-success:disabled {
+  color: #22b24c;
+  background-color: transparent;
+}
+
+.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active,
+.show > .btn-outline-success.dropdown-toggle {
+  color: #fff;
+  background-color: #22b24c;
+  border-color: #22b24c;
+}
+
+.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus,
+.show > .btn-outline-success.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(34, 178, 76, 0.5);
+}
+
+.btn-outline-info {
+  color: #1c9af7;
+  background-color: transparent;
+  background-image: none;
+  border-color: #1c9af7;
+}
+
+.btn-outline-info:hover {
+  color: #fff;
+  background-color: #1c9af7;
+  border-color: #1c9af7;
+}
+
+.btn-outline-info:focus, .btn-outline-info.focus {
+  box-shadow: 0 0 0 0.2rem rgba(28, 154, 247, 0.5);
+}
+
+.btn-outline-info.disabled, .btn-outline-info:disabled {
+  color: #1c9af7;
+  background-color: transparent;
+}
+
+.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active,
+.show > .btn-outline-info.dropdown-toggle {
+  color: #fff;
+  background-color: #1c9af7;
+  border-color: #1c9af7;
+}
+
+.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus,
+.show > .btn-outline-info.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(28, 154, 247, 0.5);
+}
+
+.btn-outline-warning {
+  color: #f7aa1c;
+  background-color: transparent;
+  background-image: none;
+  border-color: #f7aa1c;
+}
+
+.btn-outline-warning:hover {
+  color: #212529;
+  background-color: #f7aa1c;
+  border-color: #f7aa1c;
+}
+
+.btn-outline-warning:focus, .btn-outline-warning.focus {
+  box-shadow: 0 0 0 0.2rem rgba(247, 170, 28, 0.5);
+}
+
+.btn-outline-warning.disabled, .btn-outline-warning:disabled {
+  color: #f7aa1c;
+  background-color: transparent;
+}
+
+.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active,
+.show > .btn-outline-warning.dropdown-toggle {
+  color: #212529;
+  background-color: #f7aa1c;
+  border-color: #f7aa1c;
+}
+
+.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus,
+.show > .btn-outline-warning.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(247, 170, 28, 0.5);
+}
+
+.btn-outline-danger {
+  color: #fc3434;
+  background-color: transparent;
+  background-image: none;
+  border-color: #fc3434;
+}
+
+.btn-outline-danger:hover {
+  color: #fff;
+  background-color: #fc3434;
+  border-color: #fc3434;
+}
+
+.btn-outline-danger:focus, .btn-outline-danger.focus {
+  box-shadow: 0 0 0 0.2rem rgba(252, 52, 52, 0.5);
+}
+
+.btn-outline-danger.disabled, .btn-outline-danger:disabled {
+  color: #fc3434;
+  background-color: transparent;
+}
+
+.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active,
+.show > .btn-outline-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #fc3434;
+  border-color: #fc3434;
+}
+
+.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus,
+.show > .btn-outline-danger.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(252, 52, 52, 0.5);
+}
+
+.btn-outline-light {
+  color: #dddddd;
+  background-color: transparent;
+  background-image: none;
+  border-color: #dddddd;
+}
+
+.btn-outline-light:hover {
+  color: #212529;
+  background-color: #dddddd;
+  border-color: #dddddd;
+}
+
+.btn-outline-light:focus, .btn-outline-light.focus {
+  box-shadow: 0 0 0 0.2rem rgba(221, 221, 221, 0.5);
+}
+
+.btn-outline-light.disabled, .btn-outline-light:disabled {
+  color: #dddddd;
+  background-color: transparent;
+}
+
+.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active,
+.show > .btn-outline-light.dropdown-toggle {
+  color: #212529;
+  background-color: #dddddd;
+  border-color: #dddddd;
+}
+
+.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus,
+.show > .btn-outline-light.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(221, 221, 221, 0.5);
+}
+
+.btn-outline-dark {
+  color: #77a518;
+  background-color: transparent;
+  background-image: none;
+  border-color: #77a518;
+}
+
+.btn-outline-dark:hover {
+  color: #fff;
+  background-color: #77a518;
+  border-color: #77a518;
+}
+
+.btn-outline-dark:focus, .btn-outline-dark.focus {
+  box-shadow: 0 0 0 0.2rem rgba(119, 165, 24, 0.5);
+}
+
+.btn-outline-dark.disabled, .btn-outline-dark:disabled {
+  color: #77a518;
+  background-color: transparent;
+}
+
+.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active,
+.show > .btn-outline-dark.dropdown-toggle {
+  color: #fff;
+  background-color: #77a518;
+  border-color: #77a518;
+}
+
+.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus,
+.show > .btn-outline-dark.dropdown-toggle:focus {
+  box-shadow: 0 0 0 0.2rem rgba(119, 165, 24, 0.5);
+}
+
+.btn-link {
+  font-weight: 400;
+  color: #5a5758;
+  background-color: transparent;
+}
+
+.btn-link:hover {
+  color: #333132;
+  text-decoration: underline;
+  background-color: transparent;
+  border-color: transparent;
+}
+
+.btn-link:focus, .btn-link.focus {
+  text-decoration: underline;
+  border-color: transparent;
+  box-shadow: none;
+}
+
+.btn-link:disabled, .btn-link.disabled {
+  color: #6c757d;
+  pointer-events: none;
+}
+
+.btn-lg, .btn-group-lg > .btn {
+  padding: 0.5rem 1rem;
+  font-size: 1.0125rem;
+  line-height: 1.5;
+  border-radius: 0;
+}
+
+.btn-sm, .btn-group-sm > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.70875rem;
+  line-height: 1.5;
+  border-radius: 0;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+}
+
+.btn-block + .btn-block {
+  margin-top: 0.5rem;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.fade {
+  transition: opacity 0.15s linear;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .fade {
+    transition: none;
+  }
+}
+
+.fade:not(.show) {
+  opacity: 0;
+}
+
+.collapse:not(.show) {
+  display: none;
+}
+
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  transition: height 0.35s ease;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .collapsing {
+    transition: none;
+  }
+}
+
+.dropup,
+.dropright,
+.dropdown,
+.dropleft {
+  position: relative;
+}
+
+.dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.255em;
+  vertical-align: 0.255em;
+  content: "";
+  border-top: 0.3em solid;
+  border-right: 0.3em solid transparent;
+  border-bottom: 0;
+  border-left: 0.3em solid transparent;
+}
+
+.dropdown-toggle:empty::after {
+  margin-left: 0;
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 10rem;
+  padding: 0.5rem 0;
+  margin: 0.125rem 0 0;
+  font-size: 0.81rem;
+  color: #212529;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+}
+
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+
+.dropup .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-top: 0;
+  margin-bottom: 0.125rem;
+}
+
+.dropup .dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.255em;
+  vertical-align: 0.255em;
+  content: "";
+  border-top: 0;
+  border-right: 0.3em solid transparent;
+  border-bottom: 0.3em solid;
+  border-left: 0.3em solid transparent;
+}
+
+.dropup .dropdown-toggle:empty::after {
+  margin-left: 0;
+}
+
+.dropright .dropdown-menu {
+  top: 0;
+  right: auto;
+  left: 100%;
+  margin-top: 0;
+  margin-left: 0.125rem;
+}
+
+.dropright .dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.255em;
+  vertical-align: 0.255em;
+  content: "";
+  border-top: 0.3em solid transparent;
+  border-right: 0;
+  border-bottom: 0.3em solid transparent;
+  border-left: 0.3em solid;
+}
+
+.dropright .dropdown-toggle:empty::after {
+  margin-left: 0;
+}
+
+.dropright .dropdown-toggle::after {
+  vertical-align: 0;
+}
+
+.dropleft .dropdown-menu {
+  top: 0;
+  right: 100%;
+  left: auto;
+  margin-top: 0;
+  margin-right: 0.125rem;
+}
+
+.dropleft .dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.255em;
+  vertical-align: 0.255em;
+  content: "";
+}
+
+.dropleft .dropdown-toggle::after {
+  display: none;
+}
+
+.dropleft .dropdown-toggle::before {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-right: 0.255em;
+  vertical-align: 0.255em;
+  content: "";
+  border-top: 0.3em solid transparent;
+  border-right: 0.3em solid;
+  border-bottom: 0.3em solid transparent;
+}
+
+.dropleft .dropdown-toggle:empty::after {
+  margin-left: 0;
+}
+
+.dropleft .dropdown-toggle::before {
+  vertical-align: 0;
+}
+
+.dropdown-menu[x-placement^="top"], .dropdown-menu[x-placement^="right"], .dropdown-menu[x-placement^="bottom"], .dropdown-menu[x-placement^="left"] {
+  right: auto;
+  bottom: auto;
+}
+
+.dropdown-divider {
+  height: 0;
+  margin: 0.5rem 0;
+  overflow: hidden;
+  border-top: 1px solid #e9ecef;
+}
+
+.dropdown-item {
+  display: block;
+  width: 100%;
+  padding: 0.25rem 1.5rem;
+  clear: both;
+  font-weight: 400;
+  color: #212529;
+  text-align: inherit;
+  white-space: nowrap;
+  background-color: transparent;
+  border: 0;
+}
+
+.dropdown-item:hover, .dropdown-item:focus {
+  color: #16181b;
+  text-decoration: none;
+  background-color: #f8f9fa;
+}
+
+.dropdown-item.active, .dropdown-item:active {
+  color: #fff;
+  text-decoration: none;
+  background-color: #5a5758;
+}
+
+.dropdown-item.disabled, .dropdown-item:disabled {
+  color: #6c757d;
+  background-color: transparent;
+}
+
+.dropdown-menu.show {
+  display: block;
+}
+
+.dropdown-header {
+  display: block;
+  padding: 0.5rem 1.5rem;
+  margin-bottom: 0;
+  font-size: 0.70875rem;
+  color: #6c757d;
+  white-space: nowrap;
+}
+
+.dropdown-item-text {
+  display: block;
+  padding: 0.25rem 1.5rem;
+  color: #212529;
+}
+
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: -ms-inline-flexbox;
+  display: inline-flex;
+  vertical-align: middle;
+}
+
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  -ms-flex: 0 1 auto;
+  flex: 0 1 auto;
+}
+
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover {
+  z-index: 1;
+}
+
+.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
+.btn-group-vertical > .btn:focus,
+.btn-group-vertical > .btn:active,
+.btn-group-vertical > .btn.active {
+  z-index: 1;
+}
+
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group,
+.btn-group-vertical .btn + .btn,
+.btn-group-vertical .btn + .btn-group,
+.btn-group-vertical .btn-group + .btn,
+.btn-group-vertical .btn-group + .btn-group {
+  margin-left: -1px;
+}
+
+.btn-toolbar {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  -ms-flex-pack: start;
+  justify-content: flex-start;
+}
+
+.btn-toolbar .input-group {
+  width: auto;
+}
+
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+
+.dropdown-toggle-split {
+  padding-right: 0.75rem;
+  padding-left: 0.75rem;
+}
+
+.dropdown-toggle-split::after,
+.dropup .dropdown-toggle-split::after,
+.dropright .dropdown-toggle-split::after {
+  margin-left: 0;
+}
+
+.dropleft .dropdown-toggle-split::before {
+  margin-right: 0;
+}
+
+.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
+  padding-right: 0.375rem;
+  padding-left: 0.375rem;
+}
+
+.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
+  padding-right: 0.75rem;
+  padding-left: 0.75rem;
+}
+
+.btn-group-vertical {
+  -ms-flex-direction: column;
+  flex-direction: column;
+  -ms-flex-align: start;
+  align-items: flex-start;
+  -ms-flex-pack: center;
+  justify-content: center;
+}
+
+.btn-group-vertical .btn,
+.btn-group-vertical .btn-group {
+  width: 100%;
+}
+
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+
+.btn-group-toggle > .btn,
+.btn-group-toggle > .btn-group > .btn {
+  margin-bottom: 0;
+}
+
+.btn-group-toggle > .btn input[type="radio"],
+.btn-group-toggle > .btn input[type="checkbox"],
+.btn-group-toggle > .btn-group > .btn input[type="radio"],
+.btn-group-toggle > .btn-group > .btn input[type="checkbox"] {
+  position: absolute;
+  clip: rect(0, 0, 0, 0);
+  pointer-events: none;
+}
+
+.input-group {
+  position: relative;
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  -ms-flex-align: stretch;
+  align-items: stretch;
+  width: 100%;
+}
+
+.input-group > .form-control,
+.input-group > .custom-select,
+.input-group > .custom-file {
+  position: relative;
+  -ms-flex: 1 1 auto;
+  flex: 1 1 auto;
+  width: 1%;
+  margin-bottom: 0;
+}
+
+.input-group > .form-control + .form-control,
+.input-group > .form-control + .custom-select,
+.input-group > .form-control + .custom-file,
+.input-group > .custom-select + .form-control,
+.input-group > .custom-select + .custom-select,
+.input-group > .custom-select + .custom-file,
+.input-group > .custom-file + .form-control,
+.input-group > .custom-file + .custom-select,
+.input-group > .custom-file + .custom-file {
+  margin-left: -1px;
+}
+
+.input-group > .form-control:focus,
+.input-group > .custom-select:focus,
+.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label {
+  z-index: 3;
+}
+
+.input-group > .custom-file .custom-file-input:focus {
+  z-index: 4;
+}
+
+.input-group > .custom-file {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: center;
+  align-items: center;
+}
+
+.input-group-prepend,
+.input-group-append {
+  display: -ms-flexbox;
+  display: flex;
+}
+
+.input-group-prepend .btn,
+.input-group-append .btn {
+  position: relative;
+  z-index: 2;
+}
+
+.input-group-prepend .btn + .btn,
+.input-group-prepend .btn + .input-group-text,
+.input-group-prepend .input-group-text + .input-group-text,
+.input-group-prepend .input-group-text + .btn,
+.input-group-append .btn + .btn,
+.input-group-append .btn + .input-group-text,
+.input-group-append .input-group-text + .input-group-text,
+.input-group-append .input-group-text + .btn {
+  margin-left: -1px;
+}
+
+.input-group-prepend {
+  margin-right: -1px;
+}
+
+.input-group-append {
+  margin-left: -1px;
+}
+
+.input-group-text {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: center;
+  align-items: center;
+  padding: 0.375rem 0.38rem;
+  margin-bottom: 0;
+  font-size: 0.81rem;
+  font-weight: 400;
+  line-height: 1.5;
+  color: #495057;
+  text-align: center;
+  white-space: nowrap;
+  background-color: #e9ecef;
+  border: 1px solid #ced4da;
+}
+
+.input-group-text input[type="radio"],
+.input-group-text input[type="checkbox"] {
+  margin-top: 0;
+}
+
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-prepend > .input-group-text,
+.input-group-lg > .input-group-append > .input-group-text,
+.input-group-lg > .input-group-prepend > .btn,
+.input-group-lg > .input-group-append > .btn {
+  height: calc(2.51875rem + 2px);
+  padding: 0.5rem 1rem;
+  font-size: 1.0125rem;
+  line-height: 1.5;
+}
+
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-prepend > .input-group-text,
+.input-group-sm > .input-group-append > .input-group-text,
+.input-group-sm > .input-group-prepend > .btn,
+.input-group-sm > .input-group-append > .btn {
+  height: calc(1.563125rem + 2px);
+  padding: 0.25rem 0.5rem;
+  font-size: 0.70875rem;
+  line-height: 1.5;
+}
+
+.custom-control {
+  position: relative;
+  display: block;
+  min-height: 1.215rem;
+  padding-left: 1.5rem;
+}
+
+.custom-control-inline {
+  display: -ms-inline-flexbox;
+  display: inline-flex;
+  margin-right: 1rem;
+}
+
+.custom-control-input {
+  position: absolute;
+  z-index: -1;
+  opacity: 0;
+}
+
+.custom-control-input:checked ~ .custom-control-label::before {
+  color: #fff;
+  background-color: #5a5758;
+}
+
+.custom-control-input:focus ~ .custom-control-label::before {
+  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(90, 87, 88, 0.25);
+}
+
+.custom-control-input:active ~ .custom-control-label::before {
+  color: #fff;
+  background-color: #b3b0b1;
+}
+
+.custom-control-input:disabled ~ .custom-control-label {
+  color: #6c757d;
+}
+
+.custom-control-input:disabled ~ .custom-control-label::before {
+  background-color: #e9ecef;
+}
+
+.custom-control-label {
+  position: relative;
+  margin-bottom: 0;
+}
+
+.custom-control-label::before {
+  position: absolute;
+  top: 0.1075rem;
+  left: -1.5rem;
+  display: block;
+  width: 1rem;
+  height: 1rem;
+  pointer-events: none;
+  content: "";
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  background-color: #dee2e6;
+}
+
+.custom-control-label::after {
+  position: absolute;
+  top: 0.1075rem;
+  left: -1.5rem;
+  display: block;
+  width: 1rem;
+  height: 1rem;
+  content: "";
+  background-repeat: no-repeat;
+  background-position: center center;
+  background-size: 50% 50%;
+}
+
+.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before {
+  background-color: #5a5758;
+}
+
+.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
+}
+
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {
+  background-color: #5a5758;
+}
+
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E");
+}
+
+.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {
+  background-color: rgba(90, 87, 88, 0.5);
+}
+
+.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {
+  background-color: rgba(90, 87, 88, 0.5);
+}
+
+.custom-radio .custom-control-label::before {
+  border-radius: 50%;
+}
+
+.custom-radio .custom-control-input:checked ~ .custom-control-label::before {
+  background-color: #5a5758;
+}
+
+.custom-radio .custom-control-input:checked ~ .custom-control-label::after {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E");
+}
+
+.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {
+  background-color: rgba(90, 87, 88, 0.5);
+}
+
+.custom-select {
+  display: inline-block;
+  width: 100%;
+  height: calc(1.965rem + 2px);
+  padding: 0.375rem 1.75rem 0.375rem 0.75rem;
+  line-height: 1.5;
+  color: #495057;
+  vertical-align: middle;
+  background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center;
+  background-size: 8px 10px;
+  border: 1px solid #ced4da;
+  border-radius: 0;
+  -webkit-appearance: none;
+  -moz-appearance: none;
+  appearance: none;
+}
+
+.custom-select:focus {
+  border-color: #9a9798;
+  outline: 0;
+  box-shadow: 0 0 0 0.2rem rgba(154, 151, 152, 0.5);
+}
+
+.custom-select:focus::-ms-value {
+  color: #495057;
+  background-color: #fff;
+}
+
+.custom-select[multiple], .custom-select[size]:not([size="1"]) {
+  height: auto;
+  padding-right: 0.75rem;
+  background-image: none;
+}
+
+.custom-select:disabled {
+  color: #6c757d;
+  background-color: #e9ecef;
+}
+
+.custom-select::-ms-expand {
+  opacity: 0;
+}
+
+.custom-select-sm {
+  height: calc(1.563125rem + 2px);
+  padding-top: 0.375rem;
+  padding-bottom: 0.375rem;
+  font-size: 75%;
+}
+
+.custom-select-lg {
+  height: calc(2.51875rem + 2px);
+  padding-top: 0.375rem;
+  padding-bottom: 0.375rem;
+  font-size: 125%;
+}
+
+.custom-file {
+  position: relative;
+  display: inline-block;
+  width: 100%;
+  height: calc(1.965rem + 2px);
+  margin-bottom: 0;
+}
+
+.custom-file-input {
+  position: relative;
+  z-index: 2;
+  width: 100%;
+  height: calc(1.965rem + 2px);
+  margin: 0;
+  opacity: 0;
+}
+
+.custom-file-input:focus ~ .custom-file-label {
+  border-color: #9a9798;
+  box-shadow: 0 0 0 0.2rem rgba(90, 87, 88, 0.25);
+}
+
+.custom-file-input:focus ~ .custom-file-label::after {
+  border-color: #9a9798;
+}
+
+.custom-file-input:disabled ~ .custom-file-label {
+  background-color: #e9ecef;
+}
+
+.custom-file-input:lang(en) ~ .custom-file-label::after {
+  content: "Browse";
+}
+
+.custom-file-label {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1;
+  height: calc(1.965rem + 2px);
+  padding: 0.375rem 0.75rem;
+  line-height: 1.5;
+  color: #495057;
+  background-color: #fff;
+  border: 1px solid #ced4da;
+}
+
+.custom-file-label::after {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 3;
+  display: block;
+  height: 1.965rem;
+  padding: 0.375rem 0.75rem;
+  line-height: 1.5;
+  color: #495057;
+  content: "Browse";
+  background-color: #e9ecef;
+  border-left: 1px solid #ced4da;
+}
+
+.custom-range {
+  width: 100%;
+  padding-left: 0;
+  background-color: transparent;
+  -webkit-appearance: none;
+  -moz-appearance: none;
+  appearance: none;
+}
+
+.custom-range:focus {
+  outline: none;
+}
+
+.custom-range:focus::-webkit-slider-thumb {
+  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(90, 87, 88, 0.25);
+}
+
+.custom-range:focus::-moz-range-thumb {
+  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(90, 87, 88, 0.25);
+}
+
+.custom-range:focus::-ms-thumb {
+  box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(90, 87, 88, 0.25);
+}
+
+.custom-range::-moz-focus-outer {
+  border: 0;
+}
+
+.custom-range::-webkit-slider-thumb {
+  width: 1rem;
+  height: 1rem;
+  margin-top: -0.25rem;
+  background-color: #5a5758;
+  border: 0;
+  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+  -webkit-appearance: none;
+  appearance: none;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .custom-range::-webkit-slider-thumb {
+    transition: none;
+  }
+}
+
+.custom-range::-webkit-slider-thumb:active {
+  background-color: #b3b0b1;
+}
+
+.custom-range::-webkit-slider-runnable-track {
+  width: 100%;
+  height: 0.5rem;
+  color: transparent;
+  cursor: pointer;
+  background-color: #dee2e6;
+  border-color: transparent;
+}
+
+.custom-range::-moz-range-thumb {
+  width: 1rem;
+  height: 1rem;
+  background-color: #5a5758;
+  border: 0;
+  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+  -moz-appearance: none;
+  appearance: none;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .custom-range::-moz-range-thumb {
+    transition: none;
+  }
+}
+
+.custom-range::-moz-range-thumb:active {
+  background-color: #b3b0b1;
+}
+
+.custom-range::-moz-range-track {
+  width: 100%;
+  height: 0.5rem;
+  color: transparent;
+  cursor: pointer;
+  background-color: #dee2e6;
+  border-color: transparent;
+}
+
+.custom-range::-ms-thumb {
+  width: 1rem;
+  height: 1rem;
+  margin-top: 0;
+  margin-right: 0.2rem;
+  margin-left: 0.2rem;
+  background-color: #5a5758;
+  border: 0;
+  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+  appearance: none;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .custom-range::-ms-thumb {
+    transition: none;
+  }
+}
+
+.custom-range::-ms-thumb:active {
+  background-color: #b3b0b1;
+}
+
+.custom-range::-ms-track {
+  width: 100%;
+  height: 0.5rem;
+  color: transparent;
+  cursor: pointer;
+  background-color: transparent;
+  border-color: transparent;
+  border-width: 0.5rem;
+}
+
+.custom-range::-ms-fill-lower {
+  background-color: #dee2e6;
+}
+
+.custom-range::-ms-fill-upper {
+  margin-right: 15px;
+  background-color: #dee2e6;
+}
+
+.custom-control-label::before,
+.custom-file-label,
+.custom-select {
+  transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .custom-control-label::before,
+  .custom-file-label,
+  .custom-select {
+    transition: none;
+  }
+}
+
+.nav {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+
+.nav-link {
+  display: block;
+  padding: 0.5rem 1rem;
+}
+
+.nav-link:hover, .nav-link:focus {
+  text-decoration: none;
+}
+
+.nav-link.disabled {
+  color: #6c757d;
+}
+
+.nav-tabs {
+  border-bottom: 1px solid #dee2e6;
+}
+
+.nav-tabs .nav-item {
+  margin-bottom: -1px;
+}
+
+.nav-tabs .nav-link {
+  border: 1px solid transparent;
+}
+
+.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {
+  border-color: #e9ecef #e9ecef #dee2e6;
+}
+
+.nav-tabs .nav-link.disabled {
+  color: #6c757d;
+  background-color: transparent;
+  border-color: transparent;
+}
+
+.nav-tabs .nav-link.active,
+.nav-tabs .nav-item.show .nav-link {
+  color: #495057;
+  background-color: #fff;
+  border-color: #dee2e6 #dee2e6 #fff;
+}
+
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+}
+
+.nav-pills .nav-link.active,
+.nav-pills .show > .nav-link {
+  color: #fff;
+  background-color: #5a5758;
+}
+
+.nav-fill .nav-item {
+  -ms-flex: 1 1 auto;
+  flex: 1 1 auto;
+  text-align: center;
+}
+
+.nav-justified .nav-item {
+  -ms-flex-preferred-size: 0;
+  flex-basis: 0;
+  -ms-flex-positive: 1;
+  flex-grow: 1;
+  text-align: center;
+}
+
+.tab-content > .tab-pane {
+  display: none;
+}
+
+.tab-content > .active {
+  display: block;
+}
+
+.navbar {
+  position: relative;
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  -ms-flex-align: center;
+  align-items: center;
+  -ms-flex-pack: justify;
+  justify-content: space-between;
+  padding: 0rem 0rem;
+}
+
+.navbar > .container,
+.navbar > .container-fluid {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  -ms-flex-align: center;
+  align-items: center;
+  -ms-flex-pack: justify;
+  justify-content: space-between;
+}
+
+.navbar-brand {
+  display: inline-block;
+  padding-top: 0.348125rem;
+  padding-bottom: 0.348125rem;
+  margin-right: 0rem;
+  font-size: 1.0125rem;
+  line-height: inherit;
+  white-space: nowrap;
+}
+
+.navbar-brand:hover, .navbar-brand:focus {
+  text-decoration: none;
+}
+
+.navbar-nav {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-direction: column;
+  flex-direction: column;
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+
+.navbar-nav .nav-link {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.navbar-nav .dropdown-menu {
+  position: static;
+  float: none;
+}
+
+.navbar-text {
+  display: inline-block;
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+}
+
+.navbar-collapse {
+  -ms-flex-preferred-size: 100%;
+  flex-basis: 100%;
+  -ms-flex-positive: 1;
+  flex-grow: 1;
+  -ms-flex-align: center;
+  align-items: center;
+}
+
+.navbar-toggler {
+  padding: 0.25rem 0.75rem;
+  font-size: 1.0125rem;
+  line-height: 1;
+  background-color: transparent;
+  border: 1px solid transparent;
+}
+
+.navbar-toggler:hover, .navbar-toggler:focus {
+  text-decoration: none;
+}
+
+.navbar-toggler:not(:disabled):not(.disabled) {
+  cursor: pointer;
+}
+
+.navbar-toggler-icon {
+  display: inline-block;
+  width: 1.5em;
+  height: 1.5em;
+  vertical-align: middle;
+  content: "";
+  background: no-repeat center center;
+  background-size: 100% 100%;
+}
+
+@media (max-width: 575.98px) {
+  .navbar-expand-sm > .container,
+  .navbar-expand-sm > .container-fluid {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-expand-sm {
+    -ms-flex-flow: row nowrap;
+    flex-flow: row nowrap;
+    -ms-flex-pack: start;
+    justify-content: flex-start;
+  }
+  .navbar-expand-sm .navbar-nav {
+    -ms-flex-direction: row;
+    flex-direction: row;
+  }
+  .navbar-expand-sm .navbar-nav .dropdown-menu {
+    position: absolute;
+  }
+  .navbar-expand-sm .navbar-nav .nav-link {
+    padding-right: 0.5rem;
+    padding-left: 0.5rem;
+  }
+  .navbar-expand-sm > .container,
+  .navbar-expand-sm > .container-fluid {
+    -ms-flex-wrap: nowrap;
+    flex-wrap: nowrap;
+  }
+  .navbar-expand-sm .navbar-collapse {
+    display: -ms-flexbox !important;
+    display: flex !important;
+    -ms-flex-preferred-size: auto;
+    flex-basis: auto;
+  }
+  .navbar-expand-sm .navbar-toggler {
+    display: none;
+  }
+}
+
+@media (max-width: 767.98px) {
+  .navbar-expand-md > .container,
+  .navbar-expand-md > .container-fluid {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-expand-md {
+    -ms-flex-flow: row nowrap;
+    flex-flow: row nowrap;
+    -ms-flex-pack: start;
+    justify-content: flex-start;
+  }
+  .navbar-expand-md .navbar-nav {
+    -ms-flex-direction: row;
+    flex-direction: row;
+  }
+  .navbar-expand-md .navbar-nav .dropdown-menu {
+    position: absolute;
+  }
+  .navbar-expand-md .navbar-nav .nav-link {
+    padding-right: 0.5rem;
+    padding-left: 0.5rem;
+  }
+  .navbar-expand-md > .container,
+  .navbar-expand-md > .container-fluid {
+    -ms-flex-wrap: nowrap;
+    flex-wrap: nowrap;
+  }
+  .navbar-expand-md .navbar-collapse {
+    display: -ms-flexbox !important;
+    display: flex !important;
+    -ms-flex-preferred-size: auto;
+    flex-basis: auto;
+  }
+  .navbar-expand-md .navbar-toggler {
+    display: none;
+  }
+}
+
+@media (max-width: 991.98px) {
+  .navbar-expand-lg > .container,
+  .navbar-expand-lg > .container-fluid {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-expand-lg {
+    -ms-flex-flow: row nowrap;
+    flex-flow: row nowrap;
+    -ms-flex-pack: start;
+    justify-content: flex-start;
+  }
+  .navbar-expand-lg .navbar-nav {
+    -ms-flex-direction: row;
+    flex-direction: row;
+  }
+  .navbar-expand-lg .navbar-nav .dropdown-menu {
+    position: absolute;
+  }
+  .navbar-expand-lg .navbar-nav .nav-link {
+    padding-right: 0.5rem;
+    padding-left: 0.5rem;
+  }
+  .navbar-expand-lg > .container,
+  .navbar-expand-lg > .container-fluid {
+    -ms-flex-wrap: nowrap;
+    flex-wrap: nowrap;
+  }
+  .navbar-expand-lg .navbar-collapse {
+    display: -ms-flexbox !important;
+    display: flex !important;
+    -ms-flex-preferred-size: auto;
+    flex-basis: auto;
+  }
+  .navbar-expand-lg .navbar-toggler {
+    display: none;
+  }
+}
+
+@media (max-width: 1199.98px) {
+  .navbar-expand-xl > .container,
+  .navbar-expand-xl > .container-fluid {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+
+@media (min-width: 1200px) {
+  .navbar-expand-xl {
+    -ms-flex-flow: row nowrap;
+    flex-flow: row nowrap;
+    -ms-flex-pack: start;
+    justify-content: flex-start;
+  }
+  .navbar-expand-xl .navbar-nav {
+    -ms-flex-direction: row;
+    flex-direction: row;
+  }
+  .navbar-expand-xl .navbar-nav .dropdown-menu {
+    position: absolute;
+  }
+  .navbar-expand-xl .navbar-nav .nav-link {
+    padding-right: 0.5rem;
+    padding-left: 0.5rem;
+  }
+  .navbar-expand-xl > .container,
+  .navbar-expand-xl > .container-fluid {
+    -ms-flex-wrap: nowrap;
+    flex-wrap: nowrap;
+  }
+  .navbar-expand-xl .navbar-collapse {
+    display: -ms-flexbox !important;
+    display: flex !important;
+    -ms-flex-preferred-size: auto;
+    flex-basis: auto;
+  }
+  .navbar-expand-xl .navbar-toggler {
+    display: none;
+  }
+}
+
+.navbar-expand {
+  -ms-flex-flow: row nowrap;
+  flex-flow: row nowrap;
+  -ms-flex-pack: start;
+  justify-content: flex-start;
+}
+
+.navbar-expand > .container,
+.navbar-expand > .container-fluid {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.navbar-expand .navbar-nav {
+  -ms-flex-direction: row;
+  flex-direction: row;
+}
+
+.navbar-expand .navbar-nav .dropdown-menu {
+  position: absolute;
+}
+
+.navbar-expand .navbar-nav .nav-link {
+  padding-right: 0.5rem;
+  padding-left: 0.5rem;
+}
+
+.navbar-expand > .container,
+.navbar-expand > .container-fluid {
+  -ms-flex-wrap: nowrap;
+  flex-wrap: nowrap;
+}
+
+.navbar-expand .navbar-collapse {
+  display: -ms-flexbox !important;
+  display: flex !important;
+  -ms-flex-preferred-size: auto;
+  flex-basis: auto;
+}
+
+.navbar-expand .navbar-toggler {
+  display: none;
+}
+
+.navbar-light .navbar-brand {
+  color: #000;
+}
+
+.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {
+  color: #000;
+}
+
+.navbar-light .navbar-nav .nav-link {
+  color: rgba(0, 0, 0, 0.7);
+}
+
+.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {
+  color: #000;
+}
+
+.navbar-light .navbar-nav .nav-link.disabled {
+  color: rgba(0, 0, 0, 0.3);
+}
+
+.navbar-light .navbar-nav .show > .nav-link,
+.navbar-light .navbar-nav .active > .nav-link,
+.navbar-light .navbar-nav .nav-link.show,
+.navbar-light .navbar-nav .nav-link.active {
+  color: #000;
+}
+
+.navbar-light .navbar-toggler {
+  color: rgba(0, 0, 0, 0.7);
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.navbar-light .navbar-toggler-icon {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.7)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");
+}
+
+.navbar-light .navbar-text {
+  color: rgba(0, 0, 0, 0.7);
+}
+
+.navbar-light .navbar-text a {
+  color: #000;
+}
+
+.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus {
+  color: #000;
+}
+
+.navbar-dark .navbar-brand {
+  color: #fff;
+}
+
+.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {
+  color: #fff;
+}
+
+.navbar-dark .navbar-nav .nav-link {
+  color: rgba(255, 255, 255, 0.5);
+}
+
+.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.navbar-dark .navbar-nav .nav-link.disabled {
+  color: rgba(255, 255, 255, 0.25);
+}
+
+.navbar-dark .navbar-nav .show > .nav-link,
+.navbar-dark .navbar-nav .active > .nav-link,
+.navbar-dark .navbar-nav .nav-link.show,
+.navbar-dark .navbar-nav .nav-link.active {
+  color: #fff;
+}
+
+.navbar-dark .navbar-toggler {
+  color: rgba(255, 255, 255, 0.5);
+  border-color: rgba(255, 255, 255, 0.1);
+}
+
+.navbar-dark .navbar-toggler-icon {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");
+}
+
+.navbar-dark .navbar-text {
+  color: rgba(255, 255, 255, 0.5);
+}
+
+.navbar-dark .navbar-text a {
+  color: #fff;
+}
+
+.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus {
+  color: #fff;
+}
+
+.card {
+  position: relative;
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-direction: column;
+  flex-direction: column;
+  min-width: 0;
+  word-wrap: break-word;
+  background-color: #fff;
+  background-clip: border-box;
+  border: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card > hr {
+  margin-right: 0;
+  margin-left: 0;
+}
+
+.card-body {
+  -ms-flex: 1 1 auto;
+  flex: 1 1 auto;
+  padding: 1.25rem;
+}
+
+.card-title {
+  margin-bottom: 8px;
+}
+
+.card-subtitle {
+  margin-top: -4px;
+  margin-bottom: 0;
+}
+
+.card-text:last-child {
+  margin-bottom: 0;
+}
+
+.card-link:hover {
+  text-decoration: none;
+}
+
+.card-link + .card-link {
+  margin-left: 1.25rem;
+}
+
+.card-header {
+  padding: 8px 1.25rem;
+  margin-bottom: 0;
+  background-color: rgba(0, 0, 0, 0.03);
+  border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-header + .list-group .list-group-item:first-child {
+  border-top: 0;
+}
+
+.card-footer {
+  padding: 8px 1.25rem;
+  background-color: rgba(0, 0, 0, 0.03);
+  border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-header-tabs {
+  margin-right: -0.625rem;
+  margin-bottom: -8px;
+  margin-left: -0.625rem;
+  border-bottom: 0;
+}
+
+.card-header-pills {
+  margin-right: -0.625rem;
+  margin-left: -0.625rem;
+}
+
+.card-img-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1.25rem;
+}
+
+.card-img {
+  width: 100%;
+}
+
+.card-img-top {
+  width: 100%;
+}
+
+.card-img-bottom {
+  width: 100%;
+}
+
+.card-deck {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-direction: column;
+  flex-direction: column;
+}
+
+.card-deck .card {
+  margin-bottom: 15px;
+}
+
+@media (min-width: 576px) {
+  .card-deck {
+    -ms-flex-flow: row wrap;
+    flex-flow: row wrap;
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+  .card-deck .card {
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex: 1 0 0%;
+    flex: 1 0 0%;
+    -ms-flex-direction: column;
+    flex-direction: column;
+    margin-right: 15px;
+    margin-bottom: 0;
+    margin-left: 15px;
+  }
+}
+
+.card-group {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-direction: column;
+  flex-direction: column;
+}
+
+.card-group > .card {
+  margin-bottom: 15px;
+}
+
+@media (min-width: 576px) {
+  .card-group {
+    -ms-flex-flow: row wrap;
+    flex-flow: row wrap;
+  }
+  .card-group > .card {
+    -ms-flex: 1 0 0%;
+    flex: 1 0 0%;
+    margin-bottom: 0;
+  }
+  .card-group > .card + .card {
+    margin-left: 0;
+    border-left: 0;
+  }
+}
+
+.card-columns .card {
+  margin-bottom: 8px;
+}
+
+@media (min-width: 576px) {
+  .card-columns {
+    -webkit-column-count: 3;
+    -moz-column-count: 3;
+    column-count: 3;
+    -webkit-column-gap: 1.25rem;
+    -moz-column-gap: 1.25rem;
+    column-gap: 1.25rem;
+    orphans: 1;
+    widows: 1;
+  }
+  .card-columns .card {
+    display: inline-block;
+    width: 100%;
+  }
+}
+
+.accordion .card:not(:first-of-type):not(:last-of-type) {
+  border-bottom: 0;
+  border-radius: 0;
+}
+
+.accordion .card:not(:first-of-type) .card-header:first-child {
+  border-radius: 0;
+}
+
+.accordion .card:first-of-type {
+  border-bottom: 0;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.accordion .card:last-of-type {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.breadcrumb {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  padding: 0.75rem 0.5rem;
+  margin-bottom: 1rem;
+  list-style: none;
+  background-color: #e9ecef;
+}
+
+.breadcrumb-item + .breadcrumb-item {
+  padding-left: 0.5rem;
+}
+
+.breadcrumb-item + .breadcrumb-item::before {
+  display: inline-block;
+  padding-right: 0.5rem;
+  color: #6c757d;
+  content: "/";
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: underline;
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: none;
+}
+
+.breadcrumb-item.active {
+  color: #6c757d;
+}
+
+.pagination {
+  display: -ms-flexbox;
+  display: flex;
+  padding-left: 0;
+  list-style: none;
+}
+
+.page-link {
+  position: relative;
+  display: block;
+  padding: 0.5rem 0.75rem;
+  margin-left: -1px;
+  line-height: 1.25;
+  color: #5a5758;
+  background-color: #fff;
+  border: 1px solid #EB6864;
+}
+
+.page-link:hover {
+  z-index: 2;
+  color: #fff;
+  text-decoration: none;
+  background-color: #EB6864;
+  border-color: #dee2e6;
+}
+
+.page-link:focus {
+  z-index: 2;
+  outline: 0;
+  box-shadow: 0 0 0 0.2rem rgba(90, 87, 88, 0.25);
+}
+
+.page-link:not(:disabled):not(.disabled) {
+  cursor: pointer;
+}
+
+.page-item:first-child .page-link {
+  margin-left: 0;
+}
+
+.page-item.active .page-link {
+  z-index: 1;
+  color: #fff;
+  background-color: #5a5758;
+  border-color: #5a5758;
+}
+
+.page-item.disabled .page-link {
+  color: #6c757d;
+  pointer-events: none;
+  cursor: auto;
+  background-color: #fff;
+  border-color: #dee2e6;
+}
+
+.pagination-lg .page-link {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.0125rem;
+  line-height: 1.5;
+}
+
+.pagination-sm .page-link {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.70875rem;
+  line-height: 1.5;
+}
+
+.badge {
+  display: inline-block;
+  padding: 0.25rem 0.4em;
+  font-size: 75%;
+  font-weight: 700;
+  line-height: 1;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+}
+
+.badge:empty {
+  display: none;
+}
+
+.btn .badge {
+  position: relative;
+  top: -1px;
+}
+
+.badge-pill {
+  padding-right: 0.6em;
+  padding-left: 0.6em;
+}
+
+.badge-primary {
+  color: #fff;
+  background-color: #5a5758;
+}
+
+.badge-primary[href]:hover, .badge-primary[href]:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #403e3f;
+}
+
+.badge-secondary {
+  color: #212529;
+  background-color: #cccccc;
+}
+
+.badge-secondary[href]:hover, .badge-secondary[href]:focus {
+  color: #212529;
+  text-decoration: none;
+  background-color: #b3b3b3;
+}
+
+.badge-success {
+  color: #fff;
+  background-color: #22b24c;
+}
+
+.badge-success[href]:hover, .badge-success[href]:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #1a873a;
+}
+
+.badge-info {
+  color: #fff;
+  background-color: #1c9af7;
+}
+
+.badge-info[href]:hover, .badge-info[href]:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #0880d8;
+}
+
+.badge-warning {
+  color: #212529;
+  background-color: #f7aa1c;
+}
+
+.badge-warning[href]:hover, .badge-warning[href]:focus {
+  color: #212529;
+  text-decoration: none;
+  background-color: #d88f08;
+}
+
+.badge-danger {
+  color: #fff;
+  background-color: #fc3434;
+}
+
+.badge-danger[href]:hover, .badge-danger[href]:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #f90404;
+}
+
+.badge-light {
+  color: #212529;
+  background-color: #dddddd;
+}
+
+.badge-light[href]:hover, .badge-light[href]:focus {
+  color: #212529;
+  text-decoration: none;
+  background-color: #c4c4c4;
+}
+
+.badge-dark {
+  color: #fff;
+  background-color: #77a518;
+}
+
+.badge-dark[href]:hover, .badge-dark[href]:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #577812;
+}
+
+.jumbotron {
+  padding: 1.44rem 0.72rem;
+  margin-bottom: 1.44rem;
+  background-color: #e9ecef;
+}
+
+@media (min-width: 576px) {
+  .jumbotron {
+    padding: 2.88rem 1.44rem;
+  }
+}
+
+.jumbotron-fluid {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.alert {
+  position: relative;
+  padding: 0.5rem 1.25rem;
+  margin-bottom: 1rem;
+  border: 1px solid transparent;
+}
+
+.alert-heading {
+  color: inherit;
+}
+
+.alert-link {
+  font-weight: 700;
+}
+
+.alert-dismissible {
+  padding-right: 3.715rem;
+}
+
+.alert-dismissible .close {
+  position: absolute;
+  top: 0;
+  right: 0;
+  padding: 0.5rem 1.25rem;
+  color: inherit;
+}
+
+.alert-primary {
+  color: #2f2d2e;
+  background-color: #deddde;
+  border-color: #d1d0d0;
+}
+
+.alert-primary hr {
+  border-top-color: #c4c3c3;
+}
+
+.alert-primary .alert-link {
+  color: #151415;
+}
+
+.alert-secondary {
+  color: #6a6a6a;
+  background-color: whitesmoke;
+  border-color: #f1f1f1;
+}
+
+.alert-secondary hr {
+  border-top-color: #e4e4e4;
+}
+
+.alert-secondary .alert-link {
+  color: #515151;
+}
+
+.alert-success {
+  color: #125d28;
+  background-color: #d3f0db;
+  border-color: #c1e9cd;
+}
+
+.alert-success hr {
+  border-top-color: #aee2be;
+}
+
+.alert-success .alert-link {
+  color: #0a3216;
+}
+
+.alert-info {
+  color: #0f5080;
+  background-color: #d2ebfd;
+  border-color: #bfe3fd;
+}
+
+.alert-info hr {
+  border-top-color: #a6d8fc;
+}
+
+.alert-info .alert-link {
+  color: #0a3352;
+}
+
+.alert-warning {
+  color: #80580f;
+  background-color: #fdeed2;
+  border-color: #fde7bf;
+}
+
+.alert-warning hr {
+  border-top-color: #fcdea6;
+}
+
+.alert-warning .alert-link {
+  color: #52390a;
+}
+
+.alert-danger {
+  color: #831b1b;
+  background-color: #fed6d6;
+  border-color: #fec6c6;
+}
+
+.alert-danger hr {
+  border-top-color: #feadad;
+}
+
+.alert-danger .alert-link {
+  color: #591212;
+}
+
+.alert-light {
+  color: #737373;
+  background-color: #f8f8f8;
+  border-color: whitesmoke;
+}
+
+.alert-light hr {
+  border-top-color: #e8e8e8;
+}
+
+.alert-light .alert-link {
+  color: #5a5a5a;
+}
+
+.alert-dark {
+  color: #3e560c;
+  background-color: #e4edd1;
+  border-color: #d9e6be;
+}
+
+.alert-dark hr {
+  border-top-color: #cedfac;
+}
+
+.alert-dark .alert-link {
+  color: #1e2906;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+.progress {
+  display: -ms-flexbox;
+  display: flex;
+  height: 1rem;
+  overflow: hidden;
+  font-size: 0.6075rem;
+  background-color: #e9ecef;
+}
+
+.progress-bar {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-direction: column;
+  flex-direction: column;
+  -ms-flex-pack: center;
+  justify-content: center;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  background-color: #5a5758;
+  transition: width 0.6s ease;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .progress-bar {
+    transition: none;
+  }
+}
+
+.progress-bar-striped {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+.progress-bar-animated {
+  -webkit-animation: progress-bar-stripes 1s linear infinite;
+  animation: progress-bar-stripes 1s linear infinite;
+}
+
+.media {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: start;
+  align-items: flex-start;
+}
+
+.media-body {
+  -ms-flex: 1;
+  flex: 1;
+}
+
+.list-group {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-direction: column;
+  flex-direction: column;
+  padding-left: 0;
+  margin-bottom: 0;
+}
+
+.list-group-item-action {
+  width: 100%;
+  color: #495057;
+  text-align: inherit;
+}
+
+.list-group-item-action:hover, .list-group-item-action:focus {
+  color: #495057;
+  text-decoration: none;
+  background-color: #f8f9fa;
+}
+
+.list-group-item-action:active {
+  color: #212529;
+  background-color: #e9ecef;
+}
+
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 0.5rem 0.5rem;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.list-group-item:last-child {
+  margin-bottom: 0;
+}
+
+.list-group-item:hover, .list-group-item:focus {
+  z-index: 1;
+  text-decoration: none;
+}
+
+.list-group-item.disabled, .list-group-item:disabled {
+  color: #6c757d;
+  background-color: #fff;
+}
+
+.list-group-item.active {
+  z-index: 2;
+  color: #fff;
+  background-color: #5a5758;
+  border-color: #5a5758;
+}
+
+.list-group-flush .list-group-item {
+  border-right: 0;
+  border-left: 0;
+}
+
+.list-group-flush:first-child .list-group-item:first-child {
+  border-top: 0;
+}
+
+.list-group-flush:last-child .list-group-item:last-child {
+  border-bottom: 0;
+}
+
+.list-group-item-primary {
+  color: #2f2d2e;
+  background-color: #d1d0d0;
+}
+
+.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {
+  color: #2f2d2e;
+  background-color: #c4c3c3;
+}
+
+.list-group-item-primary.list-group-item-action.active {
+  color: #fff;
+  background-color: #2f2d2e;
+  border-color: #2f2d2e;
+}
+
+.list-group-item-secondary {
+  color: #6a6a6a;
+  background-color: #f1f1f1;
+}
+
+.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {
+  color: #6a6a6a;
+  background-color: #e4e4e4;
+}
+
+.list-group-item-secondary.list-group-item-action.active {
+  color: #fff;
+  background-color: #6a6a6a;
+  border-color: #6a6a6a;
+}
+
+.list-group-item-success {
+  color: #125d28;
+  background-color: #c1e9cd;
+}
+
+.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {
+  color: #125d28;
+  background-color: #aee2be;
+}
+
+.list-group-item-success.list-group-item-action.active {
+  color: #fff;
+  background-color: #125d28;
+  border-color: #125d28;
+}
+
+.list-group-item-info {
+  color: #0f5080;
+  background-color: #bfe3fd;
+}
+
+.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {
+  color: #0f5080;
+  background-color: #a6d8fc;
+}
+
+.list-group-item-info.list-group-item-action.active {
+  color: #fff;
+  background-color: #0f5080;
+  border-color: #0f5080;
+}
+
+.list-group-item-warning {
+  color: #80580f;
+  background-color: #fde7bf;
+}
+
+.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {
+  color: #80580f;
+  background-color: #fcdea6;
+}
+
+.list-group-item-warning.list-group-item-action.active {
+  color: #fff;
+  background-color: #80580f;
+  border-color: #80580f;
+}
+
+.list-group-item-danger {
+  color: #831b1b;
+  background-color: #fec6c6;
+}
+
+.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {
+  color: #831b1b;
+  background-color: #feadad;
+}
+
+.list-group-item-danger.list-group-item-action.active {
+  color: #fff;
+  background-color: #831b1b;
+  border-color: #831b1b;
+}
+
+.list-group-item-light {
+  color: #737373;
+  background-color: whitesmoke;
+}
+
+.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {
+  color: #737373;
+  background-color: #e8e8e8;
+}
+
+.list-group-item-light.list-group-item-action.active {
+  color: #fff;
+  background-color: #737373;
+  border-color: #737373;
+}
+
+.list-group-item-dark {
+  color: #3e560c;
+  background-color: #d9e6be;
+}
+
+.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {
+  color: #3e560c;
+  background-color: #cedfac;
+}
+
+.list-group-item-dark.list-group-item-action.active {
+  color: #fff;
+  background-color: #3e560c;
+  border-color: #3e560c;
+}
+
+.close {
+  float: right;
+  font-size: 1.215rem;
+  font-weight: 700;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  opacity: .5;
+}
+
+.close:not(:disabled):not(.disabled) {
+  cursor: pointer;
+}
+
+.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus {
+  color: #000;
+  text-decoration: none;
+  opacity: .75;
+}
+
+button.close {
+  padding: 0;
+  background-color: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+
+.modal-open {
+  overflow: hidden;
+}
+
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  outline: 0;
+}
+
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 0.5rem;
+  pointer-events: none;
+}
+
+.modal.fade .modal-dialog {
+  transition: -webkit-transform 0.3s ease-out;
+  transition: transform 0.3s ease-out;
+  transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out;
+  -webkit-transform: translate(0, -25%);
+  transform: translate(0, -25%);
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .modal.fade .modal-dialog {
+    transition: none;
+  }
+}
+
+.modal.show .modal-dialog {
+  -webkit-transform: translate(0, 0);
+  transform: translate(0, 0);
+}
+
+.modal-dialog-centered {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: center;
+  align-items: center;
+  min-height: calc(100% - (0.5rem * 2));
+}
+
+.modal-dialog-centered::before {
+  display: block;
+  height: calc(100vh - (0.5rem * 2));
+  content: "";
+}
+
+.modal-content {
+  position: relative;
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-direction: column;
+  flex-direction: column;
+  width: 100%;
+  pointer-events: auto;
+  background-color: #fff;
+  background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  outline: 0;
+}
+
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+
+.modal-backdrop.fade {
+  opacity: 0;
+}
+
+.modal-backdrop.show {
+  opacity: 0.5;
+}
+
+.modal-header {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: start;
+  align-items: flex-start;
+  -ms-flex-pack: justify;
+  justify-content: space-between;
+  padding: 1rem;
+  border-bottom: 1px solid #e9ecef;
+}
+
+.modal-header .close {
+  padding: 1rem;
+  margin: -1rem -1rem -1rem auto;
+}
+
+.modal-title {
+  margin-bottom: 0;
+  line-height: 1.5;
+}
+
+.modal-body {
+  position: relative;
+  -ms-flex: 1 1 auto;
+  flex: 1 1 auto;
+  padding: 1rem;
+}
+
+.modal-footer {
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: center;
+  align-items: center;
+  -ms-flex-pack: end;
+  justify-content: flex-end;
+  padding: 1rem;
+  border-top: 1px solid #e9ecef;
+}
+
+.modal-footer > :not(:first-child) {
+  margin-left: .25rem;
+}
+
+.modal-footer > :not(:last-child) {
+  margin-right: .25rem;
+}
+
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+
+@media (min-width: 576px) {
+  .modal-dialog {
+    max-width: 500px;
+    margin: 1.75rem auto;
+  }
+  .modal-dialog-centered {
+    min-height: calc(100% - (1.75rem * 2));
+  }
+  .modal-dialog-centered::before {
+    height: calc(100vh - (1.75rem * 2));
+  }
+  .modal-sm {
+    max-width: 300px;
+  }
+}
+
+@media (min-width: 992px) {
+  .modal-lg {
+    max-width: 800px;
+  }
+}
+
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  margin: 0;
+  font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+  font-style: normal;
+  font-weight: 400;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  letter-spacing: normal;
+  word-break: normal;
+  word-spacing: normal;
+  white-space: normal;
+  line-break: auto;
+  font-size: 0.70875rem;
+  word-wrap: break-word;
+  opacity: 0;
+}
+
+.tooltip.show {
+  opacity: 0.9;
+}
+
+.tooltip .arrow {
+  position: absolute;
+  display: block;
+  width: 0.8rem;
+  height: 0.4rem;
+}
+
+.tooltip .arrow::before {
+  position: absolute;
+  content: "";
+  border-color: transparent;
+  border-style: solid;
+}
+
+.bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] {
+  padding: 0.4rem 0;
+}
+
+.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow {
+  bottom: 0;
+}
+
+.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before {
+  top: 0;
+  border-width: 0.4rem 0.4rem 0;
+  border-top-color: #000;
+}
+
+.bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] {
+  padding: 0 0.4rem;
+}
+
+.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow {
+  left: 0;
+  width: 0.4rem;
+  height: 0.8rem;
+}
+
+.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before {
+  right: 0;
+  border-width: 0.4rem 0.4rem 0.4rem 0;
+  border-right-color: #000;
+}
+
+.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] {
+  padding: 0.4rem 0;
+}
+
+.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow {
+  top: 0;
+}
+
+.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before {
+  bottom: 0;
+  border-width: 0 0.4rem 0.4rem;
+  border-bottom-color: #000;
+}
+
+.bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] {
+  padding: 0 0.4rem;
+}
+
+.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow {
+  right: 0;
+  width: 0.4rem;
+  height: 0.8rem;
+}
+
+.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before {
+  left: 0;
+  border-width: 0.4rem 0 0.4rem 0.4rem;
+  border-left-color: #000;
+}
+
+.tooltip-inner {
+  max-width: 200px;
+  padding: 0.25rem 0.5rem;
+  color: #fff;
+  text-align: center;
+  background-color: #000;
+}
+
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: block;
+  max-width: 276px;
+  font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+  font-style: normal;
+  font-weight: 400;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  letter-spacing: normal;
+  word-break: normal;
+  word-spacing: normal;
+  white-space: normal;
+  line-break: auto;
+  font-size: 0.70875rem;
+  word-wrap: break-word;
+  background-color: #fff;
+  background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+}
+
+.popover .arrow {
+  position: absolute;
+  display: block;
+  width: 1rem;
+  height: 0.5rem;
+  margin: 0 0.3rem;
+}
+
+.popover .arrow::before, .popover .arrow::after {
+  position: absolute;
+  display: block;
+  content: "";
+  border-color: transparent;
+  border-style: solid;
+}
+
+.bs-popover-top, .bs-popover-auto[x-placement^="top"] {
+  margin-bottom: 0.5rem;
+}
+
+.bs-popover-top .arrow, .bs-popover-auto[x-placement^="top"] .arrow {
+  bottom: calc((0.5rem + 1px) * -1);
+}
+
+.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before,
+.bs-popover-top .arrow::after,
+.bs-popover-auto[x-placement^="top"] .arrow::after {
+  border-width: 0.5rem 0.5rem 0;
+}
+
+.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before {
+  bottom: 0;
+  border-top-color: rgba(0, 0, 0, 0.25);
+}
+
+
+.bs-popover-top .arrow::after,
+.bs-popover-auto[x-placement^="top"] .arrow::after {
+  bottom: 1px;
+  border-top-color: #fff;
+}
+
+.bs-popover-right, .bs-popover-auto[x-placement^="right"] {
+  margin-left: 0.5rem;
+}
+
+.bs-popover-right .arrow, .bs-popover-auto[x-placement^="right"] .arrow {
+  left: calc((0.5rem + 1px) * -1);
+  width: 0.5rem;
+  height: 1rem;
+  margin: 0.3rem 0;
+}
+
+.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before,
+.bs-popover-right .arrow::after,
+.bs-popover-auto[x-placement^="right"] .arrow::after {
+  border-width: 0.5rem 0.5rem 0.5rem 0;
+}
+
+.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before {
+  left: 0;
+  border-right-color: rgba(0, 0, 0, 0.25);
+}
+
+
+.bs-popover-right .arrow::after,
+.bs-popover-auto[x-placement^="right"] .arrow::after {
+  left: 1px;
+  border-right-color: #fff;
+}
+
+.bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] {
+  margin-top: 0.5rem;
+}
+
+.bs-popover-bottom .arrow, .bs-popover-auto[x-placement^="bottom"] .arrow {
+  top: calc((0.5rem + 1px) * -1);
+}
+
+.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before,
+.bs-popover-bottom .arrow::after,
+.bs-popover-auto[x-placement^="bottom"] .arrow::after {
+  border-width: 0 0.5rem 0.5rem 0.5rem;
+}
+
+.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before {
+  top: 0;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+}
+
+
+.bs-popover-bottom .arrow::after,
+.bs-popover-auto[x-placement^="bottom"] .arrow::after {
+  top: 1px;
+  border-bottom-color: #fff;
+}
+
+.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before {
+  position: absolute;
+  top: 0;
+  left: 50%;
+  display: block;
+  width: 1rem;
+  margin-left: -0.5rem;
+  content: "";
+  border-bottom: 1px solid #f7f7f7;
+}
+
+.bs-popover-left, .bs-popover-auto[x-placement^="left"] {
+  margin-right: 0.5rem;
+}
+
+.bs-popover-left .arrow, .bs-popover-auto[x-placement^="left"] .arrow {
+  right: calc((0.5rem + 1px) * -1);
+  width: 0.5rem;
+  height: 1rem;
+  margin: 0.3rem 0;
+}
+
+.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before,
+.bs-popover-left .arrow::after,
+.bs-popover-auto[x-placement^="left"] .arrow::after {
+  border-width: 0.5rem 0 0.5rem 0.5rem;
+}
+
+.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before {
+  right: 0;
+  border-left-color: rgba(0, 0, 0, 0.25);
+}
+
+
+.bs-popover-left .arrow::after,
+.bs-popover-auto[x-placement^="left"] .arrow::after {
+  right: 1px;
+  border-left-color: #fff;
+}
+
+.popover-header {
+  padding: 0.5rem 0.75rem;
+  margin-bottom: 0;
+  font-size: 0.81rem;
+  color: inherit;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+}
+
+.popover-header:empty {
+  display: none;
+}
+
+.popover-body {
+  padding: 0.5rem 0.75rem;
+  color: #212529;
+}
+
+.carousel {
+  position: relative;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-item {
+  position: relative;
+  display: none;
+  -ms-flex-align: center;
+  align-items: center;
+  width: 100%;
+  -webkit-backface-visibility: hidden;
+  backface-visibility: hidden;
+  -webkit-perspective: 1000px;
+  perspective: 1000px;
+}
+
+.carousel-item.active,
+.carousel-item-next,
+.carousel-item-prev {
+  display: block;
+  transition: -webkit-transform 0.6s ease;
+  transition: transform 0.6s ease;
+  transition: transform 0.6s ease, -webkit-transform 0.6s ease;
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+  .carousel-item.active,
+  .carousel-item-next,
+  .carousel-item-prev {
+    transition: none;
+  }
+}
+
+.carousel-item-next,
+.carousel-item-prev {
+  position: absolute;
+  top: 0;
+}
+
+.carousel-item-next.carousel-item-left,
+.carousel-item-prev.carousel-item-right {
+  -webkit-transform: translateX(0);
+  transform: translateX(0);
+}
+
+@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {
+  .carousel-item-next.carousel-item-left,
+  .carousel-item-prev.carousel-item-right {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.carousel-item-next,
+.active.carousel-item-right {
+  -webkit-transform: translateX(100%);
+  transform: translateX(100%);
+}
+
+@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {
+  .carousel-item-next,
+  .active.carousel-item-right {
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+  }
+}
+
+.carousel-item-prev,
+.active.carousel-item-left {
+  -webkit-transform: translateX(-100%);
+  transform: translateX(-100%);
+}
+
+@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {
+  .carousel-item-prev,
+  .active.carousel-item-left {
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+.carousel-fade .carousel-item {
+  opacity: 0;
+  transition-duration: .6s;
+  transition-property: opacity;
+}
+
+.carousel-fade .carousel-item.active,
+.carousel-fade .carousel-item-next.carousel-item-left,
+.carousel-fade .carousel-item-prev.carousel-item-right {
+  opacity: 1;
+}
+
+.carousel-fade .active.carousel-item-left,
+.carousel-fade .active.carousel-item-right {
+  opacity: 0;
+}
+
+.carousel-fade .carousel-item-next,
+.carousel-fade .carousel-item-prev,
+.carousel-fade .carousel-item.active,
+.carousel-fade .active.carousel-item-left,
+.carousel-fade .active.carousel-item-prev {
+  -webkit-transform: translateX(0);
+  transform: translateX(0);
+}
+
+@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) {
+  .carousel-fade .carousel-item-next,
+  .carousel-fade .carousel-item-prev,
+  .carousel-fade .carousel-item.active,
+  .carousel-fade .active.carousel-item-left,
+  .carousel-fade .active.carousel-item-prev {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.carousel-control-prev,
+.carousel-control-next {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: center;
+  align-items: center;
+  -ms-flex-pack: center;
+  justify-content: center;
+  width: 15%;
+  color: #fff;
+  text-align: center;
+  opacity: 0.5;
+}
+
+.carousel-control-prev:hover, .carousel-control-prev:focus,
+.carousel-control-next:hover,
+.carousel-control-next:focus {
+  color: #fff;
+  text-decoration: none;
+  outline: 0;
+  opacity: .9;
+}
+
+.carousel-control-prev {
+  left: 0;
+}
+
+.carousel-control-next {
+  right: 0;
+}
+
+.carousel-control-prev-icon,
+.carousel-control-next-icon {
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  background: transparent no-repeat center center;
+  background-size: 100% 100%;
+}
+
+.carousel-control-prev-icon {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E");
+}
+
+.carousel-control-next-icon {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E");
+}
+
+.carousel-indicators {
+  position: absolute;
+  right: 0;
+  bottom: 10px;
+  left: 0;
+  z-index: 15;
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-pack: center;
+  justify-content: center;
+  padding-left: 0;
+  margin-right: 15%;
+  margin-left: 15%;
+  list-style: none;
+}
+
+.carousel-indicators li {
+  position: relative;
+  -ms-flex: 0 1 auto;
+  flex: 0 1 auto;
+  width: 30px;
+  height: 3px;
+  margin-right: 3px;
+  margin-left: 3px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: rgba(255, 255, 255, 0.5);
+}
+
+.carousel-indicators li::before {
+  position: absolute;
+  top: -10px;
+  left: 0;
+  display: inline-block;
+  width: 100%;
+  height: 10px;
+  content: "";
+}
+
+.carousel-indicators li::after {
+  position: absolute;
+  bottom: -10px;
+  left: 0;
+  display: inline-block;
+  width: 100%;
+  height: 10px;
+  content: "";
+}
+
+.carousel-indicators .active {
+  background-color: #fff;
+}
+
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+}
+
+.align-baseline {
+  vertical-align: baseline !important;
+}
+
+.align-top {
+  vertical-align: top !important;
+}
+
+.align-middle {
+  vertical-align: middle !important;
+}
+
+.align-bottom {
+  vertical-align: bottom !important;
+}
+
+.align-text-bottom {
+  vertical-align: text-bottom !important;
+}
+
+.align-text-top {
+  vertical-align: text-top !important;
+}
+
+.bg-primary {
+  background-color: #5a5758 !important;
+}
+
+a.bg-primary:hover, a.bg-primary:focus,
+button.bg-primary:hover,
+button.bg-primary:focus {
+  background-color: #403e3f !important;
+}
+
+.bg-secondary {
+  background-color: #cccccc !important;
+}
+
+a.bg-secondary:hover, a.bg-secondary:focus,
+button.bg-secondary:hover,
+button.bg-secondary:focus {
+  background-color: #b3b3b3 !important;
+}
+
+.bg-success {
+  background-color: #22b24c !important;
+}
+
+a.bg-success:hover, a.bg-success:focus,
+button.bg-success:hover,
+button.bg-success:focus {
+  background-color: #1a873a !important;
+}
+
+.bg-info {
+  background-color: #1c9af7 !important;
+}
+
+a.bg-info:hover, a.bg-info:focus,
+button.bg-info:hover,
+button.bg-info:focus {
+  background-color: #0880d8 !important;
+}
+
+.bg-warning {
+  background-color: #f7aa1c !important;
+}
+
+a.bg-warning:hover, a.bg-warning:focus,
+button.bg-warning:hover,
+button.bg-warning:focus {
+  background-color: #d88f08 !important;
+}
+
+.bg-danger {
+  background-color: #fc3434 !important;
+}
+
+a.bg-danger:hover, a.bg-danger:focus,
+button.bg-danger:hover,
+button.bg-danger:focus {
+  background-color: #f90404 !important;
+}
+
+.bg-light {
+  background-color: #dddddd !important;
+}
+
+a.bg-light:hover, a.bg-light:focus,
+button.bg-light:hover,
+button.bg-light:focus {
+  background-color: #c4c4c4 !important;
+}
+
+.bg-dark {
+  background-color: #77a518 !important;
+}
+
+a.bg-dark:hover, a.bg-dark:focus,
+button.bg-dark:hover,
+button.bg-dark:focus {
+  background-color: #577812 !important;
+}
+
+.bg-white {
+  background-color: #fff !important;
+}
+
+.bg-transparent {
+  background-color: transparent !important;
+}
+
+.border {
+  border: 1px solid #dee2e6 !important;
+}
+
+.border-top {
+  border-top: 1px solid #dee2e6 !important;
+}
+
+.border-right {
+  border-right: 1px solid #dee2e6 !important;
+}
+
+.border-bottom {
+  border-bottom: 1px solid #dee2e6 !important;
+}
+
+.border-left {
+  border-left: 1px solid #dee2e6 !important;
+}
+
+.border-0 {
+  border: 0 !important;
+}
+
+.border-top-0 {
+  border-top: 0 !important;
+}
+
+.border-right-0 {
+  border-right: 0 !important;
+}
+
+.border-bottom-0 {
+  border-bottom: 0 !important;
+}
+
+.border-left-0 {
+  border-left: 0 !important;
+}
+
+.border-primary {
+  border-color: #5a5758 !important;
+}
+
+.border-secondary {
+  border-color: #cccccc !important;
+}
+
+.border-success {
+  border-color: #22b24c !important;
+}
+
+.border-info {
+  border-color: #1c9af7 !important;
+}
+
+.border-warning {
+  border-color: #f7aa1c !important;
+}
+
+.border-danger {
+  border-color: #fc3434 !important;
+}
+
+.border-light {
+  border-color: #dddddd !important;
+}
+
+.border-dark {
+  border-color: #77a518 !important;
+}
+
+.border-white {
+  border-color: #fff !important;
+}
+
+.rounded {
+  border-radius: 0.25rem !important;
+}
+
+.rounded-top {
+  border-top-left-radius: 0.25rem !important;
+  border-top-right-radius: 0.25rem !important;
+}
+
+.rounded-right {
+  border-top-right-radius: 0.25rem !important;
+  border-bottom-right-radius: 0.25rem !important;
+}
+
+.rounded-bottom {
+  border-bottom-right-radius: 0.25rem !important;
+  border-bottom-left-radius: 0.25rem !important;
+}
+
+.rounded-left {
+  border-top-left-radius: 0.25rem !important;
+  border-bottom-left-radius: 0.25rem !important;
+}
+
+.rounded-circle {
+  border-radius: 50% !important;
+}
+
+.rounded-0 {
+  border-radius: 0 !important;
+}
+
+.clearfix::after {
+  display: block;
+  clear: both;
+  content: "";
+}
+
+.d-none {
+  display: none !important;
+}
+
+.d-inline {
+  display: inline !important;
+}
+
+.d-inline-block {
+  display: inline-block !important;
+}
+
+.d-block {
+  display: block !important;
+}
+
+.d-table {
+  display: table !important;
+}
+
+.d-table-row {
+  display: table-row !important;
+}
+
+.d-table-cell {
+  display: table-cell !important;
+}
+
+.d-flex {
+  display: -ms-flexbox !important;
+  display: flex !important;
+}
+
+.d-inline-flex {
+  display: -ms-inline-flexbox !important;
+  display: inline-flex !important;
+}
+
+@media (min-width: 576px) {
+  .d-sm-none {
+    display: none !important;
+  }
+  .d-sm-inline {
+    display: inline !important;
+  }
+  .d-sm-inline-block {
+    display: inline-block !important;
+  }
+  .d-sm-block {
+    display: block !important;
+  }
+  .d-sm-table {
+    display: table !important;
+  }
+  .d-sm-table-row {
+    display: table-row !important;
+  }
+  .d-sm-table-cell {
+    display: table-cell !important;
+  }
+  .d-sm-flex {
+    display: -ms-flexbox !important;
+    display: flex !important;
+  }
+  .d-sm-inline-flex {
+    display: -ms-inline-flexbox !important;
+    display: inline-flex !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .d-md-none {
+    display: none !important;
+  }
+  .d-md-inline {
+    display: inline !important;
+  }
+  .d-md-inline-block {
+    display: inline-block !important;
+  }
+  .d-md-block {
+    display: block !important;
+  }
+  .d-md-table {
+    display: table !important;
+  }
+  .d-md-table-row {
+    display: table-row !important;
+  }
+  .d-md-table-cell {
+    display: table-cell !important;
+  }
+  .d-md-flex {
+    display: -ms-flexbox !important;
+    display: flex !important;
+  }
+  .d-md-inline-flex {
+    display: -ms-inline-flexbox !important;
+    display: inline-flex !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .d-lg-none {
+    display: none !important;
+  }
+  .d-lg-inline {
+    display: inline !important;
+  }
+  .d-lg-inline-block {
+    display: inline-block !important;
+  }
+  .d-lg-block {
+    display: block !important;
+  }
+  .d-lg-table {
+    display: table !important;
+  }
+  .d-lg-table-row {
+    display: table-row !important;
+  }
+  .d-lg-table-cell {
+    display: table-cell !important;
+  }
+  .d-lg-flex {
+    display: -ms-flexbox !important;
+    display: flex !important;
+  }
+  .d-lg-inline-flex {
+    display: -ms-inline-flexbox !important;
+    display: inline-flex !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .d-xl-none {
+    display: none !important;
+  }
+  .d-xl-inline {
+    display: inline !important;
+  }
+  .d-xl-inline-block {
+    display: inline-block !important;
+  }
+  .d-xl-block {
+    display: block !important;
+  }
+  .d-xl-table {
+    display: table !important;
+  }
+  .d-xl-table-row {
+    display: table-row !important;
+  }
+  .d-xl-table-cell {
+    display: table-cell !important;
+  }
+  .d-xl-flex {
+    display: -ms-flexbox !important;
+    display: flex !important;
+  }
+  .d-xl-inline-flex {
+    display: -ms-inline-flexbox !important;
+    display: inline-flex !important;
+  }
+}
+
+@media print {
+  .d-print-none {
+    display: none !important;
+  }
+  .d-print-inline {
+    display: inline !important;
+  }
+  .d-print-inline-block {
+    display: inline-block !important;
+  }
+  .d-print-block {
+    display: block !important;
+  }
+  .d-print-table {
+    display: table !important;
+  }
+  .d-print-table-row {
+    display: table-row !important;
+  }
+  .d-print-table-cell {
+    display: table-cell !important;
+  }
+  .d-print-flex {
+    display: -ms-flexbox !important;
+    display: flex !important;
+  }
+  .d-print-inline-flex {
+    display: -ms-inline-flexbox !important;
+    display: inline-flex !important;
+  }
+}
+
+.embed-responsive {
+  position: relative;
+  display: block;
+  width: 100%;
+  padding: 0;
+  overflow: hidden;
+}
+
+.embed-responsive::before {
+  display: block;
+  content: "";
+}
+
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+.embed-responsive-21by9::before {
+  padding-top: 42.857143%;
+}
+
+.embed-responsive-16by9::before {
+  padding-top: 56.25%;
+}
+
+.embed-responsive-4by3::before {
+  padding-top: 75%;
+}
+
+.embed-responsive-1by1::before {
+  padding-top: 100%;
+}
+
+.flex-row {
+  -ms-flex-direction: row !important;
+  flex-direction: row !important;
+}
+
+.flex-column {
+  -ms-flex-direction: column !important;
+  flex-direction: column !important;
+}
+
+.flex-row-reverse {
+  -ms-flex-direction: row-reverse !important;
+  flex-direction: row-reverse !important;
+}
+
+.flex-column-reverse {
+  -ms-flex-direction: column-reverse !important;
+  flex-direction: column-reverse !important;
+}
+
+.flex-wrap {
+  -ms-flex-wrap: wrap !important;
+  flex-wrap: wrap !important;
+}
+
+.flex-nowrap {
+  -ms-flex-wrap: nowrap !important;
+  flex-wrap: nowrap !important;
+}
+
+.flex-wrap-reverse {
+  -ms-flex-wrap: wrap-reverse !important;
+  flex-wrap: wrap-reverse !important;
+}
+
+.flex-fill {
+  -ms-flex: 1 1 auto !important;
+  flex: 1 1 auto !important;
+}
+
+.flex-grow-0 {
+  -ms-flex-positive: 0 !important;
+  flex-grow: 0 !important;
+}
+
+.flex-grow-1 {
+  -ms-flex-positive: 1 !important;
+  flex-grow: 1 !important;
+}
+
+.flex-shrink-0 {
+  -ms-flex-negative: 0 !important;
+  flex-shrink: 0 !important;
+}
+
+.flex-shrink-1 {
+  -ms-flex-negative: 1 !important;
+  flex-shrink: 1 !important;
+}
+
+.justify-content-start {
+  -ms-flex-pack: start !important;
+  justify-content: flex-start !important;
+}
+
+.justify-content-end {
+  -ms-flex-pack: end !important;
+  justify-content: flex-end !important;
+}
+
+.justify-content-center {
+  -ms-flex-pack: center !important;
+  justify-content: center !important;
+}
+
+.justify-content-between {
+  -ms-flex-pack: justify !important;
+  justify-content: space-between !important;
+}
+
+.justify-content-around {
+  -ms-flex-pack: distribute !important;
+  justify-content: space-around !important;
+}
+
+.align-items-start {
+  -ms-flex-align: start !important;
+  align-items: flex-start !important;
+}
+
+.align-items-end {
+  -ms-flex-align: end !important;
+  align-items: flex-end !important;
+}
+
+.align-items-center {
+  -ms-flex-align: center !important;
+  align-items: center !important;
+}
+
+.align-items-baseline {
+  -ms-flex-align: baseline !important;
+  align-items: baseline !important;
+}
+
+.align-items-stretch {
+  -ms-flex-align: stretch !important;
+  align-items: stretch !important;
+}
+
+.align-content-start {
+  -ms-flex-line-pack: start !important;
+  align-content: flex-start !important;
+}
+
+.align-content-end {
+  -ms-flex-line-pack: end !important;
+  align-content: flex-end !important;
+}
+
+.align-content-center {
+  -ms-flex-line-pack: center !important;
+  align-content: center !important;
+}
+
+.align-content-between {
+  -ms-flex-line-pack: justify !important;
+  align-content: space-between !important;
+}
+
+.align-content-around {
+  -ms-flex-line-pack: distribute !important;
+  align-content: space-around !important;
+}
+
+.align-content-stretch {
+  -ms-flex-line-pack: stretch !important;
+  align-content: stretch !important;
+}
+
+.align-self-auto {
+  -ms-flex-item-align: auto !important;
+  align-self: auto !important;
+}
+
+.align-self-start {
+  -ms-flex-item-align: start !important;
+  align-self: flex-start !important;
+}
+
+.align-self-end {
+  -ms-flex-item-align: end !important;
+  align-self: flex-end !important;
+}
+
+.align-self-center {
+  -ms-flex-item-align: center !important;
+  align-self: center !important;
+}
+
+.align-self-baseline {
+  -ms-flex-item-align: baseline !important;
+  align-self: baseline !important;
+}
+
+.align-self-stretch {
+  -ms-flex-item-align: stretch !important;
+  align-self: stretch !important;
+}
+
+@media (min-width: 576px) {
+  .flex-sm-row {
+    -ms-flex-direction: row !important;
+    flex-direction: row !important;
+  }
+  .flex-sm-column {
+    -ms-flex-direction: column !important;
+    flex-direction: column !important;
+  }
+  .flex-sm-row-reverse {
+    -ms-flex-direction: row-reverse !important;
+    flex-direction: row-reverse !important;
+  }
+  .flex-sm-column-reverse {
+    -ms-flex-direction: column-reverse !important;
+    flex-direction: column-reverse !important;
+  }
+  .flex-sm-wrap {
+    -ms-flex-wrap: wrap !important;
+    flex-wrap: wrap !important;
+  }
+  .flex-sm-nowrap {
+    -ms-flex-wrap: nowrap !important;
+    flex-wrap: nowrap !important;
+  }
+  .flex-sm-wrap-reverse {
+    -ms-flex-wrap: wrap-reverse !important;
+    flex-wrap: wrap-reverse !important;
+  }
+  .flex-sm-fill {
+    -ms-flex: 1 1 auto !important;
+    flex: 1 1 auto !important;
+  }
+  .flex-sm-grow-0 {
+    -ms-flex-positive: 0 !important;
+    flex-grow: 0 !important;
+  }
+  .flex-sm-grow-1 {
+    -ms-flex-positive: 1 !important;
+    flex-grow: 1 !important;
+  }
+  .flex-sm-shrink-0 {
+    -ms-flex-negative: 0 !important;
+    flex-shrink: 0 !important;
+  }
+  .flex-sm-shrink-1 {
+    -ms-flex-negative: 1 !important;
+    flex-shrink: 1 !important;
+  }
+  .justify-content-sm-start {
+    -ms-flex-pack: start !important;
+    justify-content: flex-start !important;
+  }
+  .justify-content-sm-end {
+    -ms-flex-pack: end !important;
+    justify-content: flex-end !important;
+  }
+  .justify-content-sm-center {
+    -ms-flex-pack: center !important;
+    justify-content: center !important;
+  }
+  .justify-content-sm-between {
+    -ms-flex-pack: justify !important;
+    justify-content: space-between !important;
+  }
+  .justify-content-sm-around {
+    -ms-flex-pack: distribute !important;
+    justify-content: space-around !important;
+  }
+  .align-items-sm-start {
+    -ms-flex-align: start !important;
+    align-items: flex-start !important;
+  }
+  .align-items-sm-end {
+    -ms-flex-align: end !important;
+    align-items: flex-end !important;
+  }
+  .align-items-sm-center {
+    -ms-flex-align: center !important;
+    align-items: center !important;
+  }
+  .align-items-sm-baseline {
+    -ms-flex-align: baseline !important;
+    align-items: baseline !important;
+  }
+  .align-items-sm-stretch {
+    -ms-flex-align: stretch !important;
+    align-items: stretch !important;
+  }
+  .align-content-sm-start {
+    -ms-flex-line-pack: start !important;
+    align-content: flex-start !important;
+  }
+  .align-content-sm-end {
+    -ms-flex-line-pack: end !important;
+    align-content: flex-end !important;
+  }
+  .align-content-sm-center {
+    -ms-flex-line-pack: center !important;
+    align-content: center !important;
+  }
+  .align-content-sm-between {
+    -ms-flex-line-pack: justify !important;
+    align-content: space-between !important;
+  }
+  .align-content-sm-around {
+    -ms-flex-line-pack: distribute !important;
+    align-content: space-around !important;
+  }
+  .align-content-sm-stretch {
+    -ms-flex-line-pack: stretch !important;
+    align-content: stretch !important;
+  }
+  .align-self-sm-auto {
+    -ms-flex-item-align: auto !important;
+    align-self: auto !important;
+  }
+  .align-self-sm-start {
+    -ms-flex-item-align: start !important;
+    align-self: flex-start !important;
+  }
+  .align-self-sm-end {
+    -ms-flex-item-align: end !important;
+    align-self: flex-end !important;
+  }
+  .align-self-sm-center {
+    -ms-flex-item-align: center !important;
+    align-self: center !important;
+  }
+  .align-self-sm-baseline {
+    -ms-flex-item-align: baseline !important;
+    align-self: baseline !important;
+  }
+  .align-self-sm-stretch {
+    -ms-flex-item-align: stretch !important;
+    align-self: stretch !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .flex-md-row {
+    -ms-flex-direction: row !important;
+    flex-direction: row !important;
+  }
+  .flex-md-column {
+    -ms-flex-direction: column !important;
+    flex-direction: column !important;
+  }
+  .flex-md-row-reverse {
+    -ms-flex-direction: row-reverse !important;
+    flex-direction: row-reverse !important;
+  }
+  .flex-md-column-reverse {
+    -ms-flex-direction: column-reverse !important;
+    flex-direction: column-reverse !important;
+  }
+  .flex-md-wrap {
+    -ms-flex-wrap: wrap !important;
+    flex-wrap: wrap !important;
+  }
+  .flex-md-nowrap {
+    -ms-flex-wrap: nowrap !important;
+    flex-wrap: nowrap !important;
+  }
+  .flex-md-wrap-reverse {
+    -ms-flex-wrap: wrap-reverse !important;
+    flex-wrap: wrap-reverse !important;
+  }
+  .flex-md-fill {
+    -ms-flex: 1 1 auto !important;
+    flex: 1 1 auto !important;
+  }
+  .flex-md-grow-0 {
+    -ms-flex-positive: 0 !important;
+    flex-grow: 0 !important;
+  }
+  .flex-md-grow-1 {
+    -ms-flex-positive: 1 !important;
+    flex-grow: 1 !important;
+  }
+  .flex-md-shrink-0 {
+    -ms-flex-negative: 0 !important;
+    flex-shrink: 0 !important;
+  }
+  .flex-md-shrink-1 {
+    -ms-flex-negative: 1 !important;
+    flex-shrink: 1 !important;
+  }
+  .justify-content-md-start {
+    -ms-flex-pack: start !important;
+    justify-content: flex-start !important;
+  }
+  .justify-content-md-end {
+    -ms-flex-pack: end !important;
+    justify-content: flex-end !important;
+  }
+  .justify-content-md-center {
+    -ms-flex-pack: center !important;
+    justify-content: center !important;
+  }
+  .justify-content-md-between {
+    -ms-flex-pack: justify !important;
+    justify-content: space-between !important;
+  }
+  .justify-content-md-around {
+    -ms-flex-pack: distribute !important;
+    justify-content: space-around !important;
+  }
+  .align-items-md-start {
+    -ms-flex-align: start !important;
+    align-items: flex-start !important;
+  }
+  .align-items-md-end {
+    -ms-flex-align: end !important;
+    align-items: flex-end !important;
+  }
+  .align-items-md-center {
+    -ms-flex-align: center !important;
+    align-items: center !important;
+  }
+  .align-items-md-baseline {
+    -ms-flex-align: baseline !important;
+    align-items: baseline !important;
+  }
+  .align-items-md-stretch {
+    -ms-flex-align: stretch !important;
+    align-items: stretch !important;
+  }
+  .align-content-md-start {
+    -ms-flex-line-pack: start !important;
+    align-content: flex-start !important;
+  }
+  .align-content-md-end {
+    -ms-flex-line-pack: end !important;
+    align-content: flex-end !important;
+  }
+  .align-content-md-center {
+    -ms-flex-line-pack: center !important;
+    align-content: center !important;
+  }
+  .align-content-md-between {
+    -ms-flex-line-pack: justify !important;
+    align-content: space-between !important;
+  }
+  .align-content-md-around {
+    -ms-flex-line-pack: distribute !important;
+    align-content: space-around !important;
+  }
+  .align-content-md-stretch {
+    -ms-flex-line-pack: stretch !important;
+    align-content: stretch !important;
+  }
+  .align-self-md-auto {
+    -ms-flex-item-align: auto !important;
+    align-self: auto !important;
+  }
+  .align-self-md-start {
+    -ms-flex-item-align: start !important;
+    align-self: flex-start !important;
+  }
+  .align-self-md-end {
+    -ms-flex-item-align: end !important;
+    align-self: flex-end !important;
+  }
+  .align-self-md-center {
+    -ms-flex-item-align: center !important;
+    align-self: center !important;
+  }
+  .align-self-md-baseline {
+    -ms-flex-item-align: baseline !important;
+    align-self: baseline !important;
+  }
+  .align-self-md-stretch {
+    -ms-flex-item-align: stretch !important;
+    align-self: stretch !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .flex-lg-row {
+    -ms-flex-direction: row !important;
+    flex-direction: row !important;
+  }
+  .flex-lg-column {
+    -ms-flex-direction: column !important;
+    flex-direction: column !important;
+  }
+  .flex-lg-row-reverse {
+    -ms-flex-direction: row-reverse !important;
+    flex-direction: row-reverse !important;
+  }
+  .flex-lg-column-reverse {
+    -ms-flex-direction: column-reverse !important;
+    flex-direction: column-reverse !important;
+  }
+  .flex-lg-wrap {
+    -ms-flex-wrap: wrap !important;
+    flex-wrap: wrap !important;
+  }
+  .flex-lg-nowrap {
+    -ms-flex-wrap: nowrap !important;
+    flex-wrap: nowrap !important;
+  }
+  .flex-lg-wrap-reverse {
+    -ms-flex-wrap: wrap-reverse !important;
+    flex-wrap: wrap-reverse !important;
+  }
+  .flex-lg-fill {
+    -ms-flex: 1 1 auto !important;
+    flex: 1 1 auto !important;
+  }
+  .flex-lg-grow-0 {
+    -ms-flex-positive: 0 !important;
+    flex-grow: 0 !important;
+  }
+  .flex-lg-grow-1 {
+    -ms-flex-positive: 1 !important;
+    flex-grow: 1 !important;
+  }
+  .flex-lg-shrink-0 {
+    -ms-flex-negative: 0 !important;
+    flex-shrink: 0 !important;
+  }
+  .flex-lg-shrink-1 {
+    -ms-flex-negative: 1 !important;
+    flex-shrink: 1 !important;
+  }
+  .justify-content-lg-start {
+    -ms-flex-pack: start !important;
+    justify-content: flex-start !important;
+  }
+  .justify-content-lg-end {
+    -ms-flex-pack: end !important;
+    justify-content: flex-end !important;
+  }
+  .justify-content-lg-center {
+    -ms-flex-pack: center !important;
+    justify-content: center !important;
+  }
+  .justify-content-lg-between {
+    -ms-flex-pack: justify !important;
+    justify-content: space-between !important;
+  }
+  .justify-content-lg-around {
+    -ms-flex-pack: distribute !important;
+    justify-content: space-around !important;
+  }
+  .align-items-lg-start {
+    -ms-flex-align: start !important;
+    align-items: flex-start !important;
+  }
+  .align-items-lg-end {
+    -ms-flex-align: end !important;
+    align-items: flex-end !important;
+  }
+  .align-items-lg-center {
+    -ms-flex-align: center !important;
+    align-items: center !important;
+  }
+  .align-items-lg-baseline {
+    -ms-flex-align: baseline !important;
+    align-items: baseline !important;
+  }
+  .align-items-lg-stretch {
+    -ms-flex-align: stretch !important;
+    align-items: stretch !important;
+  }
+  .align-content-lg-start {
+    -ms-flex-line-pack: start !important;
+    align-content: flex-start !important;
+  }
+  .align-content-lg-end {
+    -ms-flex-line-pack: end !important;
+    align-content: flex-end !important;
+  }
+  .align-content-lg-center {
+    -ms-flex-line-pack: center !important;
+    align-content: center !important;
+  }
+  .align-content-lg-between {
+    -ms-flex-line-pack: justify !important;
+    align-content: space-between !important;
+  }
+  .align-content-lg-around {
+    -ms-flex-line-pack: distribute !important;
+    align-content: space-around !important;
+  }
+  .align-content-lg-stretch {
+    -ms-flex-line-pack: stretch !important;
+    align-content: stretch !important;
+  }
+  .align-self-lg-auto {
+    -ms-flex-item-align: auto !important;
+    align-self: auto !important;
+  }
+  .align-self-lg-start {
+    -ms-flex-item-align: start !important;
+    align-self: flex-start !important;
+  }
+  .align-self-lg-end {
+    -ms-flex-item-align: end !important;
+    align-self: flex-end !important;
+  }
+  .align-self-lg-center {
+    -ms-flex-item-align: center !important;
+    align-self: center !important;
+  }
+  .align-self-lg-baseline {
+    -ms-flex-item-align: baseline !important;
+    align-self: baseline !important;
+  }
+  .align-self-lg-stretch {
+    -ms-flex-item-align: stretch !important;
+    align-self: stretch !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .flex-xl-row {
+    -ms-flex-direction: row !important;
+    flex-direction: row !important;
+  }
+  .flex-xl-column {
+    -ms-flex-direction: column !important;
+    flex-direction: column !important;
+  }
+  .flex-xl-row-reverse {
+    -ms-flex-direction: row-reverse !important;
+    flex-direction: row-reverse !important;
+  }
+  .flex-xl-column-reverse {
+    -ms-flex-direction: column-reverse !important;
+    flex-direction: column-reverse !important;
+  }
+  .flex-xl-wrap {
+    -ms-flex-wrap: wrap !important;
+    flex-wrap: wrap !important;
+  }
+  .flex-xl-nowrap {
+    -ms-flex-wrap: nowrap !important;
+    flex-wrap: nowrap !important;
+  }
+  .flex-xl-wrap-reverse {
+    -ms-flex-wrap: wrap-reverse !important;
+    flex-wrap: wrap-reverse !important;
+  }
+  .flex-xl-fill {
+    -ms-flex: 1 1 auto !important;
+    flex: 1 1 auto !important;
+  }
+  .flex-xl-grow-0 {
+    -ms-flex-positive: 0 !important;
+    flex-grow: 0 !important;
+  }
+  .flex-xl-grow-1 {
+    -ms-flex-positive: 1 !important;
+    flex-grow: 1 !important;
+  }
+  .flex-xl-shrink-0 {
+    -ms-flex-negative: 0 !important;
+    flex-shrink: 0 !important;
+  }
+  .flex-xl-shrink-1 {
+    -ms-flex-negative: 1 !important;
+    flex-shrink: 1 !important;
+  }
+  .justify-content-xl-start {
+    -ms-flex-pack: start !important;
+    justify-content: flex-start !important;
+  }
+  .justify-content-xl-end {
+    -ms-flex-pack: end !important;
+    justify-content: flex-end !important;
+  }
+  .justify-content-xl-center {
+    -ms-flex-pack: center !important;
+    justify-content: center !important;
+  }
+  .justify-content-xl-between {
+    -ms-flex-pack: justify !important;
+    justify-content: space-between !important;
+  }
+  .justify-content-xl-around {
+    -ms-flex-pack: distribute !important;
+    justify-content: space-around !important;
+  }
+  .align-items-xl-start {
+    -ms-flex-align: start !important;
+    align-items: flex-start !important;
+  }
+  .align-items-xl-end {
+    -ms-flex-align: end !important;
+    align-items: flex-end !important;
+  }
+  .align-items-xl-center {
+    -ms-flex-align: center !important;
+    align-items: center !important;
+  }
+  .align-items-xl-baseline {
+    -ms-flex-align: baseline !important;
+    align-items: baseline !important;
+  }
+  .align-items-xl-stretch {
+    -ms-flex-align: stretch !important;
+    align-items: stretch !important;
+  }
+  .align-content-xl-start {
+    -ms-flex-line-pack: start !important;
+    align-content: flex-start !important;
+  }
+  .align-content-xl-end {
+    -ms-flex-line-pack: end !important;
+    align-content: flex-end !important;
+  }
+  .align-content-xl-center {
+    -ms-flex-line-pack: center !important;
+    align-content: center !important;
+  }
+  .align-content-xl-between {
+    -ms-flex-line-pack: justify !important;
+    align-content: space-between !important;
+  }
+  .align-content-xl-around {
+    -ms-flex-line-pack: distribute !important;
+    align-content: space-around !important;
+  }
+  .align-content-xl-stretch {
+    -ms-flex-line-pack: stretch !important;
+    align-content: stretch !important;
+  }
+  .align-self-xl-auto {
+    -ms-flex-item-align: auto !important;
+    align-self: auto !important;
+  }
+  .align-self-xl-start {
+    -ms-flex-item-align: start !important;
+    align-self: flex-start !important;
+  }
+  .align-self-xl-end {
+    -ms-flex-item-align: end !important;
+    align-self: flex-end !important;
+  }
+  .align-self-xl-center {
+    -ms-flex-item-align: center !important;
+    align-self: center !important;
+  }
+  .align-self-xl-baseline {
+    -ms-flex-item-align: baseline !important;
+    align-self: baseline !important;
+  }
+  .align-self-xl-stretch {
+    -ms-flex-item-align: stretch !important;
+    align-self: stretch !important;
+  }
+}
+
+.float-left {
+  float: left !important;
+}
+
+.float-right {
+  float: right !important;
+}
+
+.float-none {
+  float: none !important;
+}
+
+@media (min-width: 576px) {
+  .float-sm-left {
+    float: left !important;
+  }
+  .float-sm-right {
+    float: right !important;
+  }
+  .float-sm-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .float-md-left {
+    float: left !important;
+  }
+  .float-md-right {
+    float: right !important;
+  }
+  .float-md-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .float-lg-left {
+    float: left !important;
+  }
+  .float-lg-right {
+    float: right !important;
+  }
+  .float-lg-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .float-xl-left {
+    float: left !important;
+  }
+  .float-xl-right {
+    float: right !important;
+  }
+  .float-xl-none {
+    float: none !important;
+  }
+}
+
+.position-static {
+  position: static !important;
+}
+
+.position-relative {
+  position: relative !important;
+}
+
+.position-absolute {
+  position: absolute !important;
+}
+
+.position-fixed {
+  position: fixed !important;
+}
+
+.position-sticky {
+  position: -webkit-sticky !important;
+  position: sticky !important;
+}
+
+.fixed-top {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+.fixed-bottom {
+  position: fixed;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+@supports ((position: -webkit-sticky) or (position: sticky)) {
+  .sticky-top {
+    position: -webkit-sticky;
+    position: sticky;
+    top: 0;
+    z-index: 1020;
+  }
+}
+
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  white-space: nowrap;
+  border: 0;
+}
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  overflow: visible;
+  clip: auto;
+  white-space: normal;
+}
+
+.shadow-sm {
+  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;
+}
+
+.shadow {
+  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
+}
+
+.shadow-lg {
+  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;
+}
+
+.shadow-none {
+  box-shadow: none !important;
+}
+
+.w-25 {
+  width: 25% !important;
+}
+
+.w-50 {
+  width: 50% !important;
+}
+
+.w-75 {
+  width: 75% !important;
+}
+
+.w-100 {
+  width: 100% !important;
+}
+
+.w-auto {
+  width: auto !important;
+}
+
+.h-25 {
+  height: 25% !important;
+}
+
+.h-50 {
+  height: 50% !important;
+}
+
+.h-75 {
+  height: 75% !important;
+}
+
+.h-100 {
+  height: 100% !important;
+}
+
+.h-auto {
+  height: auto !important;
+}
+
+.mw-100 {
+  max-width: 100% !important;
+}
+
+.mh-100 {
+  max-height: 100% !important;
+}
+
+.m-0 {
+  margin: 0 !important;
+}
+
+.mt-0,
+.my-0 {
+  margin-top: 0 !important;
+}
+
+.mr-0,
+.mx-0 {
+  margin-right: 0 !important;
+}
+
+.mb-0,
+.my-0 {
+  margin-bottom: 0 !important;
+}
+
+.ml-0,
+.mx-0 {
+  margin-left: 0 !important;
+}
+
+.m-1 {
+  margin: 0.25rem !important;
+}
+
+.mt-1,
+.my-1 {
+  margin-top: 0.25rem !important;
+}
+
+.mr-1,
+.mx-1 {
+  margin-right: 0.25rem !important;
+}
+
+.mb-1,
+.my-1 {
+  margin-bottom: 0.25rem !important;
+}
+
+.ml-1,
+.mx-1 {
+  margin-left: 0.25rem !important;
+}
+
+.m-2 {
+  margin: 0.5rem !important;
+}
+
+.mt-2,
+.my-2 {
+  margin-top: 0.5rem !important;
+}
+
+.mr-2,
+.mx-2 {
+  margin-right: 0.5rem !important;
+}
+
+.mb-2,
+.my-2 {
+  margin-bottom: 0.5rem !important;
+}
+
+.ml-2,
+.mx-2 {
+  margin-left: 0.5rem !important;
+}
+
+.m-3 {
+  margin: 1rem !important;
+}
+
+.mt-3,
+.my-3 {
+  margin-top: 1rem !important;
+}
+
+.mr-3,
+.mx-3 {
+  margin-right: 1rem !important;
+}
+
+.mb-3,
+.my-3 {
+  margin-bottom: 1rem !important;
+}
+
+.ml-3,
+.mx-3 {
+  margin-left: 1rem !important;
+}
+
+.m-4 {
+  margin: 1.5rem !important;
+}
+
+.mt-4,
+.my-4 {
+  margin-top: 1.5rem !important;
+}
+
+.mr-4,
+.mx-4 {
+  margin-right: 1.5rem !important;
+}
+
+.mb-4,
+.my-4 {
+  margin-bottom: 1.5rem !important;
+}
+
+.ml-4,
+.mx-4 {
+  margin-left: 1.5rem !important;
+}
+
+.m-5 {
+  margin: 3rem !important;
+}
+
+.mt-5,
+.my-5 {
+  margin-top: 3rem !important;
+}
+
+.mr-5,
+.mx-5 {
+  margin-right: 3rem !important;
+}
+
+.mb-5,
+.my-5 {
+  margin-bottom: 3rem !important;
+}
+
+.ml-5,
+.mx-5 {
+  margin-left: 3rem !important;
+}
+
+.p-0 {
+  padding: 0 !important;
+}
+
+.pt-0,
+.py-0 {
+  padding-top: 0 !important;
+}
+
+.pr-0,
+.px-0 {
+  padding-right: 0 !important;
+}
+
+.pb-0,
+.py-0 {
+  padding-bottom: 0 !important;
+}
+
+.pl-0,
+.px-0 {
+  padding-left: 0 !important;
+}
+
+.p-1 {
+  padding: 0.25rem !important;
+}
+
+.pt-1,
+.py-1 {
+  padding-top: 0.25rem !important;
+}
+
+.pr-1,
+.px-1 {
+  padding-right: 0.25rem !important;
+}
+
+.pb-1,
+.py-1 {
+  padding-bottom: 0.25rem !important;
+}
+
+.pl-1,
+.px-1 {
+  padding-left: 0.25rem !important;
+}
+
+.p-2 {
+  padding: 0.5rem !important;
+}
+
+.pt-2,
+.py-2 {
+  padding-top: 0.5rem !important;
+}
+
+.pr-2,
+.px-2 {
+  padding-right: 0.5rem !important;
+}
+
+.pb-2,
+.py-2 {
+  padding-bottom: 0.5rem !important;
+}
+
+.pl-2,
+.px-2 {
+  padding-left: 0.5rem !important;
+}
+
+.p-3 {
+  padding: 1rem !important;
+}
+
+.pt-3,
+.py-3 {
+  padding-top: 1rem !important;
+}
+
+.pr-3,
+.px-3 {
+  padding-right: 1rem !important;
+}
+
+.pb-3,
+.py-3 {
+  padding-bottom: 1rem !important;
+}
+
+.pl-3,
+.px-3 {
+  padding-left: 1rem !important;
+}
+
+.p-4 {
+  padding: 1.5rem !important;
+}
+
+.pt-4,
+.py-4 {
+  padding-top: 1.5rem !important;
+}
+
+.pr-4,
+.px-4 {
+  padding-right: 1.5rem !important;
+}
+
+.pb-4,
+.py-4 {
+  padding-bottom: 1.5rem !important;
+}
+
+.pl-4,
+.px-4 {
+  padding-left: 1.5rem !important;
+}
+
+.p-5 {
+  padding: 3rem !important;
+}
+
+.pt-5,
+.py-5 {
+  padding-top: 3rem !important;
+}
+
+.pr-5,
+.px-5 {
+  padding-right: 3rem !important;
+}
+
+.pb-5,
+.py-5 {
+  padding-bottom: 3rem !important;
+}
+
+.pl-5,
+.px-5 {
+  padding-left: 3rem !important;
+}
+
+.m-auto {
+  margin: auto !important;
+}
+
+.mt-auto,
+.my-auto {
+  margin-top: auto !important;
+}
+
+.mr-auto,
+.mx-auto {
+  margin-right: auto !important;
+}
+
+.mb-auto,
+.my-auto {
+  margin-bottom: auto !important;
+}
+
+.ml-auto,
+.mx-auto {
+  margin-left: auto !important;
+}
+
+@media (min-width: 576px) {
+  .m-sm-0 {
+    margin: 0 !important;
+  }
+  .mt-sm-0,
+  .my-sm-0 {
+    margin-top: 0 !important;
+  }
+  .mr-sm-0,
+  .mx-sm-0 {
+    margin-right: 0 !important;
+  }
+  .mb-sm-0,
+  .my-sm-0 {
+    margin-bottom: 0 !important;
+  }
+  .ml-sm-0,
+  .mx-sm-0 {
+    margin-left: 0 !important;
+  }
+  .m-sm-1 {
+    margin: 0.25rem !important;
+  }
+  .mt-sm-1,
+  .my-sm-1 {
+    margin-top: 0.25rem !important;
+  }
+  .mr-sm-1,
+  .mx-sm-1 {
+    margin-right: 0.25rem !important;
+  }
+  .mb-sm-1,
+  .my-sm-1 {
+    margin-bottom: 0.25rem !important;
+  }
+  .ml-sm-1,
+  .mx-sm-1 {
+    margin-left: 0.25rem !important;
+  }
+  .m-sm-2 {
+    margin: 0.5rem !important;
+  }
+  .mt-sm-2,
+  .my-sm-2 {
+    margin-top: 0.5rem !important;
+  }
+  .mr-sm-2,
+  .mx-sm-2 {
+    margin-right: 0.5rem !important;
+  }
+  .mb-sm-2,
+  .my-sm-2 {
+    margin-bottom: 0.5rem !important;
+  }
+  .ml-sm-2,
+  .mx-sm-2 {
+    margin-left: 0.5rem !important;
+  }
+  .m-sm-3 {
+    margin: 1rem !important;
+  }
+  .mt-sm-3,
+  .my-sm-3 {
+    margin-top: 1rem !important;
+  }
+  .mr-sm-3,
+  .mx-sm-3 {
+    margin-right: 1rem !important;
+  }
+  .mb-sm-3,
+  .my-sm-3 {
+    margin-bottom: 1rem !important;
+  }
+  .ml-sm-3,
+  .mx-sm-3 {
+    margin-left: 1rem !important;
+  }
+  .m-sm-4 {
+    margin: 1.5rem !important;
+  }
+  .mt-sm-4,
+  .my-sm-4 {
+    margin-top: 1.5rem !important;
+  }
+  .mr-sm-4,
+  .mx-sm-4 {
+    margin-right: 1.5rem !important;
+  }
+  .mb-sm-4,
+  .my-sm-4 {
+    margin-bottom: 1.5rem !important;
+  }
+  .ml-sm-4,
+  .mx-sm-4 {
+    margin-left: 1.5rem !important;
+  }
+  .m-sm-5 {
+    margin: 3rem !important;
+  }
+  .mt-sm-5,
+  .my-sm-5 {
+    margin-top: 3rem !important;
+  }
+  .mr-sm-5,
+  .mx-sm-5 {
+    margin-right: 3rem !important;
+  }
+  .mb-sm-5,
+  .my-sm-5 {
+    margin-bottom: 3rem !important;
+  }
+  .ml-sm-5,
+  .mx-sm-5 {
+    margin-left: 3rem !important;
+  }
+  .p-sm-0 {
+    padding: 0 !important;
+  }
+  .pt-sm-0,
+  .py-sm-0 {
+    padding-top: 0 !important;
+  }
+  .pr-sm-0,
+  .px-sm-0 {
+    padding-right: 0 !important;
+  }
+  .pb-sm-0,
+  .py-sm-0 {
+    padding-bottom: 0 !important;
+  }
+  .pl-sm-0,
+  .px-sm-0 {
+    padding-left: 0 !important;
+  }
+  .p-sm-1 {
+    padding: 0.25rem !important;
+  }
+  .pt-sm-1,
+  .py-sm-1 {
+    padding-top: 0.25rem !important;
+  }
+  .pr-sm-1,
+  .px-sm-1 {
+    padding-right: 0.25rem !important;
+  }
+  .pb-sm-1,
+  .py-sm-1 {
+    padding-bottom: 0.25rem !important;
+  }
+  .pl-sm-1,
+  .px-sm-1 {
+    padding-left: 0.25rem !important;
+  }
+  .p-sm-2 {
+    padding: 0.5rem !important;
+  }
+  .pt-sm-2,
+  .py-sm-2 {
+    padding-top: 0.5rem !important;
+  }
+  .pr-sm-2,
+  .px-sm-2 {
+    padding-right: 0.5rem !important;
+  }
+  .pb-sm-2,
+  .py-sm-2 {
+    padding-bottom: 0.5rem !important;
+  }
+  .pl-sm-2,
+  .px-sm-2 {
+    padding-left: 0.5rem !important;
+  }
+  .p-sm-3 {
+    padding: 1rem !important;
+  }
+  .pt-sm-3,
+  .py-sm-3 {
+    padding-top: 1rem !important;
+  }
+  .pr-sm-3,
+  .px-sm-3 {
+    padding-right: 1rem !important;
+  }
+  .pb-sm-3,
+  .py-sm-3 {
+    padding-bottom: 1rem !important;
+  }
+  .pl-sm-3,
+  .px-sm-3 {
+    padding-left: 1rem !important;
+  }
+  .p-sm-4 {
+    padding: 1.5rem !important;
+  }
+  .pt-sm-4,
+  .py-sm-4 {
+    padding-top: 1.5rem !important;
+  }
+  .pr-sm-4,
+  .px-sm-4 {
+    padding-right: 1.5rem !important;
+  }
+  .pb-sm-4,
+  .py-sm-4 {
+    padding-bottom: 1.5rem !important;
+  }
+  .pl-sm-4,
+  .px-sm-4 {
+    padding-left: 1.5rem !important;
+  }
+  .p-sm-5 {
+    padding: 3rem !important;
+  }
+  .pt-sm-5,
+  .py-sm-5 {
+    padding-top: 3rem !important;
+  }
+  .pr-sm-5,
+  .px-sm-5 {
+    padding-right: 3rem !important;
+  }
+  .pb-sm-5,
+  .py-sm-5 {
+    padding-bottom: 3rem !important;
+  }
+  .pl-sm-5,
+  .px-sm-5 {
+    padding-left: 3rem !important;
+  }
+  .m-sm-auto {
+    margin: auto !important;
+  }
+  .mt-sm-auto,
+  .my-sm-auto {
+    margin-top: auto !important;
+  }
+  .mr-sm-auto,
+  .mx-sm-auto {
+    margin-right: auto !important;
+  }
+  .mb-sm-auto,
+  .my-sm-auto {
+    margin-bottom: auto !important;
+  }
+  .ml-sm-auto,
+  .mx-sm-auto {
+    margin-left: auto !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .m-md-0 {
+    margin: 0 !important;
+  }
+  .mt-md-0,
+  .my-md-0 {
+    margin-top: 0 !important;
+  }
+  .mr-md-0,
+  .mx-md-0 {
+    margin-right: 0 !important;
+  }
+  .mb-md-0,
+  .my-md-0 {
+    margin-bottom: 0 !important;
+  }
+  .ml-md-0,
+  .mx-md-0 {
+    margin-left: 0 !important;
+  }
+  .m-md-1 {
+    margin: 0.25rem !important;
+  }
+  .mt-md-1,
+  .my-md-1 {
+    margin-top: 0.25rem !important;
+  }
+  .mr-md-1,
+  .mx-md-1 {
+    margin-right: 0.25rem !important;
+  }
+  .mb-md-1,
+  .my-md-1 {
+    margin-bottom: 0.25rem !important;
+  }
+  .ml-md-1,
+  .mx-md-1 {
+    margin-left: 0.25rem !important;
+  }
+  .m-md-2 {
+    margin: 0.5rem !important;
+  }
+  .mt-md-2,
+  .my-md-2 {
+    margin-top: 0.5rem !important;
+  }
+  .mr-md-2,
+  .mx-md-2 {
+    margin-right: 0.5rem !important;
+  }
+  .mb-md-2,
+  .my-md-2 {
+    margin-bottom: 0.5rem !important;
+  }
+  .ml-md-2,
+  .mx-md-2 {
+    margin-left: 0.5rem !important;
+  }
+  .m-md-3 {
+    margin: 1rem !important;
+  }
+  .mt-md-3,
+  .my-md-3 {
+    margin-top: 1rem !important;
+  }
+  .mr-md-3,
+  .mx-md-3 {
+    margin-right: 1rem !important;
+  }
+  .mb-md-3,
+  .my-md-3 {
+    margin-bottom: 1rem !important;
+  }
+  .ml-md-3,
+  .mx-md-3 {
+    margin-left: 1rem !important;
+  }
+  .m-md-4 {
+    margin: 1.5rem !important;
+  }
+  .mt-md-4,
+  .my-md-4 {
+    margin-top: 1.5rem !important;
+  }
+  .mr-md-4,
+  .mx-md-4 {
+    margin-right: 1.5rem !important;
+  }
+  .mb-md-4,
+  .my-md-4 {
+    margin-bottom: 1.5rem !important;
+  }
+  .ml-md-4,
+  .mx-md-4 {
+    margin-left: 1.5rem !important;
+  }
+  .m-md-5 {
+    margin: 3rem !important;
+  }
+  .mt-md-5,
+  .my-md-5 {
+    margin-top: 3rem !important;
+  }
+  .mr-md-5,
+  .mx-md-5 {
+    margin-right: 3rem !important;
+  }
+  .mb-md-5,
+  .my-md-5 {
+    margin-bottom: 3rem !important;
+  }
+  .ml-md-5,
+  .mx-md-5 {
+    margin-left: 3rem !important;
+  }
+  .p-md-0 {
+    padding: 0 !important;
+  }
+  .pt-md-0,
+  .py-md-0 {
+    padding-top: 0 !important;
+  }
+  .pr-md-0,
+  .px-md-0 {
+    padding-right: 0 !important;
+  }
+  .pb-md-0,
+  .py-md-0 {
+    padding-bottom: 0 !important;
+  }
+  .pl-md-0,
+  .px-md-0 {
+    padding-left: 0 !important;
+  }
+  .p-md-1 {
+    padding: 0.25rem !important;
+  }
+  .pt-md-1,
+  .py-md-1 {
+    padding-top: 0.25rem !important;
+  }
+  .pr-md-1,
+  .px-md-1 {
+    padding-right: 0.25rem !important;
+  }
+  .pb-md-1,
+  .py-md-1 {
+    padding-bottom: 0.25rem !important;
+  }
+  .pl-md-1,
+  .px-md-1 {
+    padding-left: 0.25rem !important;
+  }
+  .p-md-2 {
+    padding: 0.5rem !important;
+  }
+  .pt-md-2,
+  .py-md-2 {
+    padding-top: 0.5rem !important;
+  }
+  .pr-md-2,
+  .px-md-2 {
+    padding-right: 0.5rem !important;
+  }
+  .pb-md-2,
+  .py-md-2 {
+    padding-bottom: 0.5rem !important;
+  }
+  .pl-md-2,
+  .px-md-2 {
+    padding-left: 0.5rem !important;
+  }
+  .p-md-3 {
+    padding: 1rem !important;
+  }
+  .pt-md-3,
+  .py-md-3 {
+    padding-top: 1rem !important;
+  }
+  .pr-md-3,
+  .px-md-3 {
+    padding-right: 1rem !important;
+  }
+  .pb-md-3,
+  .py-md-3 {
+    padding-bottom: 1rem !important;
+  }
+  .pl-md-3,
+  .px-md-3 {
+    padding-left: 1rem !important;
+  }
+  .p-md-4 {
+    padding: 1.5rem !important;
+  }
+  .pt-md-4,
+  .py-md-4 {
+    padding-top: 1.5rem !important;
+  }
+  .pr-md-4,
+  .px-md-4 {
+    padding-right: 1.5rem !important;
+  }
+  .pb-md-4,
+  .py-md-4 {
+    padding-bottom: 1.5rem !important;
+  }
+  .pl-md-4,
+  .px-md-4 {
+    padding-left: 1.5rem !important;
+  }
+  .p-md-5 {
+    padding: 3rem !important;
+  }
+  .pt-md-5,
+  .py-md-5 {
+    padding-top: 3rem !important;
+  }
+  .pr-md-5,
+  .px-md-5 {
+    padding-right: 3rem !important;
+  }
+  .pb-md-5,
+  .py-md-5 {
+    padding-bottom: 3rem !important;
+  }
+  .pl-md-5,
+  .px-md-5 {
+    padding-left: 3rem !important;
+  }
+  .m-md-auto {
+    margin: auto !important;
+  }
+  .mt-md-auto,
+  .my-md-auto {
+    margin-top: auto !important;
+  }
+  .mr-md-auto,
+  .mx-md-auto {
+    margin-right: auto !important;
+  }
+  .mb-md-auto,
+  .my-md-auto {
+    margin-bottom: auto !important;
+  }
+  .ml-md-auto,
+  .mx-md-auto {
+    margin-left: auto !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .m-lg-0 {
+    margin: 0 !important;
+  }
+  .mt-lg-0,
+  .my-lg-0 {
+    margin-top: 0 !important;
+  }
+  .mr-lg-0,
+  .mx-lg-0 {
+    margin-right: 0 !important;
+  }
+  .mb-lg-0,
+  .my-lg-0 {
+    margin-bottom: 0 !important;
+  }
+  .ml-lg-0,
+  .mx-lg-0 {
+    margin-left: 0 !important;
+  }
+  .m-lg-1 {
+    margin: 0.25rem !important;
+  }
+  .mt-lg-1,
+  .my-lg-1 {
+    margin-top: 0.25rem !important;
+  }
+  .mr-lg-1,
+  .mx-lg-1 {
+    margin-right: 0.25rem !important;
+  }
+  .mb-lg-1,
+  .my-lg-1 {
+    margin-bottom: 0.25rem !important;
+  }
+  .ml-lg-1,
+  .mx-lg-1 {
+    margin-left: 0.25rem !important;
+  }
+  .m-lg-2 {
+    margin: 0.5rem !important;
+  }
+  .mt-lg-2,
+  .my-lg-2 {
+    margin-top: 0.5rem !important;
+  }
+  .mr-lg-2,
+  .mx-lg-2 {
+    margin-right: 0.5rem !important;
+  }
+  .mb-lg-2,
+  .my-lg-2 {
+    margin-bottom: 0.5rem !important;
+  }
+  .ml-lg-2,
+  .mx-lg-2 {
+    margin-left: 0.5rem !important;
+  }
+  .m-lg-3 {
+    margin: 1rem !important;
+  }
+  .mt-lg-3,
+  .my-lg-3 {
+    margin-top: 1rem !important;
+  }
+  .mr-lg-3,
+  .mx-lg-3 {
+    margin-right: 1rem !important;
+  }
+  .mb-lg-3,
+  .my-lg-3 {
+    margin-bottom: 1rem !important;
+  }
+  .ml-lg-3,
+  .mx-lg-3 {
+    margin-left: 1rem !important;
+  }
+  .m-lg-4 {
+    margin: 1.5rem !important;
+  }
+  .mt-lg-4,
+  .my-lg-4 {
+    margin-top: 1.5rem !important;
+  }
+  .mr-lg-4,
+  .mx-lg-4 {
+    margin-right: 1.5rem !important;
+  }
+  .mb-lg-4,
+  .my-lg-4 {
+    margin-bottom: 1.5rem !important;
+  }
+  .ml-lg-4,
+  .mx-lg-4 {
+    margin-left: 1.5rem !important;
+  }
+  .m-lg-5 {
+    margin: 3rem !important;
+  }
+  .mt-lg-5,
+  .my-lg-5 {
+    margin-top: 3rem !important;
+  }
+  .mr-lg-5,
+  .mx-lg-5 {
+    margin-right: 3rem !important;
+  }
+  .mb-lg-5,
+  .my-lg-5 {
+    margin-bottom: 3rem !important;
+  }
+  .ml-lg-5,
+  .mx-lg-5 {
+    margin-left: 3rem !important;
+  }
+  .p-lg-0 {
+    padding: 0 !important;
+  }
+  .pt-lg-0,
+  .py-lg-0 {
+    padding-top: 0 !important;
+  }
+  .pr-lg-0,
+  .px-lg-0 {
+    padding-right: 0 !important;
+  }
+  .pb-lg-0,
+  .py-lg-0 {
+    padding-bottom: 0 !important;
+  }
+  .pl-lg-0,
+  .px-lg-0 {
+    padding-left: 0 !important;
+  }
+  .p-lg-1 {
+    padding: 0.25rem !important;
+  }
+  .pt-lg-1,
+  .py-lg-1 {
+    padding-top: 0.25rem !important;
+  }
+  .pr-lg-1,
+  .px-lg-1 {
+    padding-right: 0.25rem !important;
+  }
+  .pb-lg-1,
+  .py-lg-1 {
+    padding-bottom: 0.25rem !important;
+  }
+  .pl-lg-1,
+  .px-lg-1 {
+    padding-left: 0.25rem !important;
+  }
+  .p-lg-2 {
+    padding: 0.5rem !important;
+  }
+  .pt-lg-2,
+  .py-lg-2 {
+    padding-top: 0.5rem !important;
+  }
+  .pr-lg-2,
+  .px-lg-2 {
+    padding-right: 0.5rem !important;
+  }
+  .pb-lg-2,
+  .py-lg-2 {
+    padding-bottom: 0.5rem !important;
+  }
+  .pl-lg-2,
+  .px-lg-2 {
+    padding-left: 0.5rem !important;
+  }
+  .p-lg-3 {
+    padding: 1rem !important;
+  }
+  .pt-lg-3,
+  .py-lg-3 {
+    padding-top: 1rem !important;
+  }
+  .pr-lg-3,
+  .px-lg-3 {
+    padding-right: 1rem !important;
+  }
+  .pb-lg-3,
+  .py-lg-3 {
+    padding-bottom: 1rem !important;
+  }
+  .pl-lg-3,
+  .px-lg-3 {
+    padding-left: 1rem !important;
+  }
+  .p-lg-4 {
+    padding: 1.5rem !important;
+  }
+  .pt-lg-4,
+  .py-lg-4 {
+    padding-top: 1.5rem !important;
+  }
+  .pr-lg-4,
+  .px-lg-4 {
+    padding-right: 1.5rem !important;
+  }
+  .pb-lg-4,
+  .py-lg-4 {
+    padding-bottom: 1.5rem !important;
+  }
+  .pl-lg-4,
+  .px-lg-4 {
+    padding-left: 1.5rem !important;
+  }
+  .p-lg-5 {
+    padding: 3rem !important;
+  }
+  .pt-lg-5,
+  .py-lg-5 {
+    padding-top: 3rem !important;
+  }
+  .pr-lg-5,
+  .px-lg-5 {
+    padding-right: 3rem !important;
+  }
+  .pb-lg-5,
+  .py-lg-5 {
+    padding-bottom: 3rem !important;
+  }
+  .pl-lg-5,
+  .px-lg-5 {
+    padding-left: 3rem !important;
+  }
+  .m-lg-auto {
+    margin: auto !important;
+  }
+  .mt-lg-auto,
+  .my-lg-auto {
+    margin-top: auto !important;
+  }
+  .mr-lg-auto,
+  .mx-lg-auto {
+    margin-right: auto !important;
+  }
+  .mb-lg-auto,
+  .my-lg-auto {
+    margin-bottom: auto !important;
+  }
+  .ml-lg-auto,
+  .mx-lg-auto {
+    margin-left: auto !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .m-xl-0 {
+    margin: 0 !important;
+  }
+  .mt-xl-0,
+  .my-xl-0 {
+    margin-top: 0 !important;
+  }
+  .mr-xl-0,
+  .mx-xl-0 {
+    margin-right: 0 !important;
+  }
+  .mb-xl-0,
+  .my-xl-0 {
+    margin-bottom: 0 !important;
+  }
+  .ml-xl-0,
+  .mx-xl-0 {
+    margin-left: 0 !important;
+  }
+  .m-xl-1 {
+    margin: 0.25rem !important;
+  }
+  .mt-xl-1,
+  .my-xl-1 {
+    margin-top: 0.25rem !important;
+  }
+  .mr-xl-1,
+  .mx-xl-1 {
+    margin-right: 0.25rem !important;
+  }
+  .mb-xl-1,
+  .my-xl-1 {
+    margin-bottom: 0.25rem !important;
+  }
+  .ml-xl-1,
+  .mx-xl-1 {
+    margin-left: 0.25rem !important;
+  }
+  .m-xl-2 {
+    margin: 0.5rem !important;
+  }
+  .mt-xl-2,
+  .my-xl-2 {
+    margin-top: 0.5rem !important;
+  }
+  .mr-xl-2,
+  .mx-xl-2 {
+    margin-right: 0.5rem !important;
+  }
+  .mb-xl-2,
+  .my-xl-2 {
+    margin-bottom: 0.5rem !important;
+  }
+  .ml-xl-2,
+  .mx-xl-2 {
+    margin-left: 0.5rem !important;
+  }
+  .m-xl-3 {
+    margin: 1rem !important;
+  }
+  .mt-xl-3,
+  .my-xl-3 {
+    margin-top: 1rem !important;
+  }
+  .mr-xl-3,
+  .mx-xl-3 {
+    margin-right: 1rem !important;
+  }
+  .mb-xl-3,
+  .my-xl-3 {
+    margin-bottom: 1rem !important;
+  }
+  .ml-xl-3,
+  .mx-xl-3 {
+    margin-left: 1rem !important;
+  }
+  .m-xl-4 {
+    margin: 1.5rem !important;
+  }
+  .mt-xl-4,
+  .my-xl-4 {
+    margin-top: 1.5rem !important;
+  }
+  .mr-xl-4,
+  .mx-xl-4 {
+    margin-right: 1.5rem !important;
+  }
+  .mb-xl-4,
+  .my-xl-4 {
+    margin-bottom: 1.5rem !important;
+  }
+  .ml-xl-4,
+  .mx-xl-4 {
+    margin-left: 1.5rem !important;
+  }
+  .m-xl-5 {
+    margin: 3rem !important;
+  }
+  .mt-xl-5,
+  .my-xl-5 {
+    margin-top: 3rem !important;
+  }
+  .mr-xl-5,
+  .mx-xl-5 {
+    margin-right: 3rem !important;
+  }
+  .mb-xl-5,
+  .my-xl-5 {
+    margin-bottom: 3rem !important;
+  }
+  .ml-xl-5,
+  .mx-xl-5 {
+    margin-left: 3rem !important;
+  }
+  .p-xl-0 {
+    padding: 0 !important;
+  }
+  .pt-xl-0,
+  .py-xl-0 {
+    padding-top: 0 !important;
+  }
+  .pr-xl-0,
+  .px-xl-0 {
+    padding-right: 0 !important;
+  }
+  .pb-xl-0,
+  .py-xl-0 {
+    padding-bottom: 0 !important;
+  }
+  .pl-xl-0,
+  .px-xl-0 {
+    padding-left: 0 !important;
+  }
+  .p-xl-1 {
+    padding: 0.25rem !important;
+  }
+  .pt-xl-1,
+  .py-xl-1 {
+    padding-top: 0.25rem !important;
+  }
+  .pr-xl-1,
+  .px-xl-1 {
+    padding-right: 0.25rem !important;
+  }
+  .pb-xl-1,
+  .py-xl-1 {
+    padding-bottom: 0.25rem !important;
+  }
+  .pl-xl-1,
+  .px-xl-1 {
+    padding-left: 0.25rem !important;
+  }
+  .p-xl-2 {
+    padding: 0.5rem !important;
+  }
+  .pt-xl-2,
+  .py-xl-2 {
+    padding-top: 0.5rem !important;
+  }
+  .pr-xl-2,
+  .px-xl-2 {
+    padding-right: 0.5rem !important;
+  }
+  .pb-xl-2,
+  .py-xl-2 {
+    padding-bottom: 0.5rem !important;
+  }
+  .pl-xl-2,
+  .px-xl-2 {
+    padding-left: 0.5rem !important;
+  }
+  .p-xl-3 {
+    padding: 1rem !important;
+  }
+  .pt-xl-3,
+  .py-xl-3 {
+    padding-top: 1rem !important;
+  }
+  .pr-xl-3,
+  .px-xl-3 {
+    padding-right: 1rem !important;
+  }
+  .pb-xl-3,
+  .py-xl-3 {
+    padding-bottom: 1rem !important;
+  }
+  .pl-xl-3,
+  .px-xl-3 {
+    padding-left: 1rem !important;
+  }
+  .p-xl-4 {
+    padding: 1.5rem !important;
+  }
+  .pt-xl-4,
+  .py-xl-4 {
+    padding-top: 1.5rem !important;
+  }
+  .pr-xl-4,
+  .px-xl-4 {
+    padding-right: 1.5rem !important;
+  }
+  .pb-xl-4,
+  .py-xl-4 {
+    padding-bottom: 1.5rem !important;
+  }
+  .pl-xl-4,
+  .px-xl-4 {
+    padding-left: 1.5rem !important;
+  }
+  .p-xl-5 {
+    padding: 3rem !important;
+  }
+  .pt-xl-5,
+  .py-xl-5 {
+    padding-top: 3rem !important;
+  }
+  .pr-xl-5,
+  .px-xl-5 {
+    padding-right: 3rem !important;
+  }
+  .pb-xl-5,
+  .py-xl-5 {
+    padding-bottom: 3rem !important;
+  }
+  .pl-xl-5,
+  .px-xl-5 {
+    padding-left: 3rem !important;
+  }
+  .m-xl-auto {
+    margin: auto !important;
+  }
+  .mt-xl-auto,
+  .my-xl-auto {
+    margin-top: auto !important;
+  }
+  .mr-xl-auto,
+  .mx-xl-auto {
+    margin-right: auto !important;
+  }
+  .mb-xl-auto,
+  .my-xl-auto {
+    margin-bottom: auto !important;
+  }
+  .ml-xl-auto,
+  .mx-xl-auto {
+    margin-left: auto !important;
+  }
+}
+
+.text-monospace {
+  font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+.text-justify {
+  text-align: justify !important;
+}
+
+.text-nowrap {
+  white-space: nowrap !important;
+}
+
+.text-truncate {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.text-left {
+  text-align: left !important;
+}
+
+.text-right {
+  text-align: right !important;
+}
+
+.text-center {
+  text-align: center !important;
+}
+
+@media (min-width: 576px) {
+  .text-sm-left {
+    text-align: left !important;
+  }
+  .text-sm-right {
+    text-align: right !important;
+  }
+  .text-sm-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .text-md-left {
+    text-align: left !important;
+  }
+  .text-md-right {
+    text-align: right !important;
+  }
+  .text-md-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .text-lg-left {
+    text-align: left !important;
+  }
+  .text-lg-right {
+    text-align: right !important;
+  }
+  .text-lg-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .text-xl-left {
+    text-align: left !important;
+  }
+  .text-xl-right {
+    text-align: right !important;
+  }
+  .text-xl-center {
+    text-align: center !important;
+  }
+}
+
+.text-lowercase {
+  text-transform: lowercase !important;
+}
+
+.text-uppercase {
+  text-transform: uppercase !important;
+}
+
+.text-capitalize {
+  text-transform: capitalize !important;
+}
+
+.font-weight-light {
+  font-weight: 300 !important;
+}
+
+.font-weight-normal {
+  font-weight: 400 !important;
+}
+
+.font-weight-bold {
+  font-weight: 700 !important;
+}
+
+.font-italic {
+  font-style: italic !important;
+}
+
+.text-white {
+  color: #fff !important;
+}
+
+.text-primary {
+  color: #5a5758 !important;
+}
+
+a.text-primary:hover, a.text-primary:focus {
+  color: #403e3f !important;
+}
+
+.text-secondary {
+  color: #cccccc !important;
+}
+
+a.text-secondary:hover, a.text-secondary:focus {
+  color: #b3b3b3 !important;
+}
+
+.text-success {
+  color: #22b24c !important;
+}
+
+a.text-success:hover, a.text-success:focus {
+  color: #1a873a !important;
+}
+
+.text-info {
+  color: #1c9af7 !important;
+}
+
+a.text-info:hover, a.text-info:focus {
+  color: #0880d8 !important;
+}
+
+.text-warning {
+  color: #f7aa1c !important;
+}
+
+a.text-warning:hover, a.text-warning:focus {
+  color: #d88f08 !important;
+}
+
+.text-danger {
+  color: #fc3434 !important;
+}
+
+a.text-danger:hover, a.text-danger:focus {
+  color: #f90404 !important;
+}
+
+.text-light {
+  color: #dddddd !important;
+}
+
+a.text-light:hover, a.text-light:focus {
+  color: #c4c4c4 !important;
+}
+
+.text-dark {
+  color: #77a518 !important;
+}
+
+a.text-dark:hover, a.text-dark:focus {
+  color: #577812 !important;
+}
+
+.text-body {
+  color: #212529 !important;
+}
+
+.text-muted {
+  color: #6c757d !important;
+}
+
+.text-black-50 {
+  color: rgba(0, 0, 0, 0.5) !important;
+}
+
+.text-white-50 {
+  color: rgba(255, 255, 255, 0.5) !important;
+}
+
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.visible {
+  visibility: visible !important;
+}
+
+.invisible {
+  visibility: hidden !important;
+}
+
+/*----Custom CSS----*/
+
diff --git a/css/style.css b/css/style.css
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/img/creorga.png b/img/creorga.png
new file mode 100644 (file)
index 0000000..15689f8
Binary files /dev/null and b/img/creorga.png differ
diff --git a/img/dks_1000.png b/img/dks_1000.png
new file mode 100644 (file)
index 0000000..87b44eb
Binary files /dev/null and b/img/dks_1000.png differ
diff --git a/index.html b/index.html
new file mode 100644 (file)
index 0000000..73159b2
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
+<link rel="stylesheet" href="node_modules/bootstrap-table/dist/bootstrap-table.min.css">
+<link rel="stylesheet" href="css/creorga.epic.css">
+<link rel="stylesheet" href="css/app.css">
+<title>Creorga</title>
+</head>
+<body>
+    <!--New Start-->
+    <div class="d-flex" id="wrapper">
+
+            <!-- Sidebar -->
+            <div class="bg-dark border-right" id="sidebar-wrapper">
+              <div class="sidebar-heading"><a href="javascript:location.href='index.html';"><img src="img/creorga.png" style="width: 140px;"><br/>Creorga</a></div>
+              <div class="list-group list-group-flush">
+                    <a  class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('dashboard');">Dashboard</a>
+                    <a  class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('childs');">Enfants</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('presences');">Présences</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('persons');">Personnes de références</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('accounting');">Décompte</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('staff');">Staff</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('vacancy');">Congés</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('waitlist');">Liste d'attente</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('calendar');">Calendriers</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('forms');">Formulaires</a>
+                    <a class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('logbook');">Livrets</a>
+                    <a  class="list-group-item list-group-item-action bg-light" href="javascript:userapp.loadmodule('settings');">Configuration</a></li>
+              </div>
+            </div>
+            <!-- /#sidebar-wrapper -->
+        
+            <!-- Page Content -->
+            <div id="page-content-wrapper">
+              <iframe id="moduleframe" src="modules/dashboard/index.html" style="width: 100%;height: 100vh; border: 0px;">
+              </iframe> 
+            </div>
+            <!-- /#page-content-wrapper -->
+        
+          </div>
+    <!--New End-->
+
+<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
+<script src="node_modules/jquery/dist/jquery.min.js"></script>
+<script src="node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
+<script src="node_modules/store2/dist/store2.min.js"></script>
+<script src="js/app.js"></script>
+<script>if (window.module) module = window.module;</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/js/app.js b/js/app.js
new file mode 100644 (file)
index 0000000..fdb6710
--- /dev/null
+++ b/js/app.js
@@ -0,0 +1,75 @@
+
+// $("#menu-toggle").click(function(e) {
+//   e.preventDefault();
+//   $("#wrapper").toggleClass("toggled");
+// });
+
+
+$( document ).ready(function() {
+  console.log( "Main ready!" );
+  userapp.loadmodule("dashboard");
+  console.log("After module load!");
+});
+//console.log(navigator);
+console.log(location.protocol);
+var userapp = {
+  loadmodule: function(modulename){
+    var appdata = [];
+    if (modulename != 'settings'){
+      appdata = userapp.getconfig();  
+    }
+    if (!appdata){
+      $("#moduleframe").attr("src","modules/settings/index.html");
+      return;
+    }
+    //var appdata = userapp.getconfig();
+    var params = "?";
+    for (var i in appdata){
+      params += "&" + i +"=" + encodeURIComponent(appdata[i]);
+    }
+    console.log("modules/"+modulename+"/index.html"+params);
+    $("#moduleframe").attr("src","modules/"+modulename+"/index.html"+ params);
+  },
+  loadmodulepage: function(modulename,page,pageparams = null){
+    var appdata = userapp.getconfig();
+    var params = "?";
+    for (var i in appdata){
+      params += "&" + i +"=" + encodeURIComponent(appdata[i]);
+    }
+    if (pageparams){
+      for (var i in pageparams){
+        params += "&" + i +"=" + encodeURIComponent(pageparams[i]);
+      }
+    }
+    //console.log("modules/"+modulename+"/index.html"+params);
+    $("#moduleframe").attr("src","modules/"+modulename+"/"+ page +".html"+ params);
+  },
+  getconfig:function (key=null){
+    var ret = {};
+    if (!key){
+      ret = userpref.getpref("currentglobal");
+      // console.log("current global");
+      // console.log(ret);
+      // if (ret == null){
+      //   $("#moduleframe").attr("src","modules/settings/index.html");
+      // }  
+    }else {
+      ret = userpref.getpref(key);
+      //{dbfile:"creorga",serviceurl:"http://localhost:6060/"}
+    }
+    //var currentdb = userpref.getpref("currentdb");
+    
+    return ret;
+  }
+}
+
+var userpref ={
+  setpref: function(key,datavalue){
+    var x = store(key, datavalue);
+    return x;
+  },
+  getpref: function(key){
+    var datavalue = store(key);
+    return datavalue;
+  }
+}
\ No newline at end of file
diff --git a/js/creorga.js b/js/creorga.js
new file mode 100644 (file)
index 0000000..053747c
--- /dev/null
@@ -0,0 +1,434 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+function check_birthdate_valid(){
+   var dx = new Array;
+   if ($("#childs_birthday").val() == "") {
+        dx.push("la date de naissance"); 
+   }
+   if ($("#childs_entrydate").val() == "") {
+        dx.push("la date d'entrée"); 
+    }
+   if ($("#childs_leavedate").val() == ""){
+        dx.push("la date de sortie");
+   }
+   if (dx.length > 0) {
+        alert("Vous n'avez pas encore ajouté " + dx.join(", ")+" du enfant.\n"+ ((dx.length > 1)?"Ces dates sont requis":"cette date est requis")+ " pour la planification!");
+        return false;
+   }
+   
+  return true;
+}
+
+function daysBetween(first, second) {
+
+    // Copy date parts of the timestamps, discarding the time parts.
+    var one = new Date(first.getFullYear(), first.getMonth(), first.getDate());
+    var two = new Date(second.getFullYear(), second.getMonth(), second.getDate());
+
+    // Do the math.
+    var millisecondsPerDay = 1000 * 60 * 60 * 24;
+    var millisBetween = two.getTime() - one.getTime();
+    var days = millisBetween / millisecondsPerDay;
+
+    // Round down.
+    return Math.floor(days);
+}
+
+function saveonfocusout(objname){
+  if (($('#' + objname).attr('type') == "date") && ($('#' + objname).val() != '')){
+      if (checkdateformat(objname) == false){
+        return false;  
+      }
+      
+      if (objname == "childs_entrydate") {
+        var ed = encodeparam($('#childs_entrydate').val(),'date').replace(/'/g,'');
+        var bd = encodeparam($('#childs_birthday').val(),'date').replace(/'/g,'');
+        if (ed < bd) {
+          errormsg("ERREUR","La date d'entrée ne peut pas Ãªtre inferieur Ã  la date de naissance!");
+          return false;
+        }
+      }
+      if (objname == "childs_leavedate") {
+        var ed = encodeparam($('#childs_entrydate').val(),'date').replace(/'/g,'');
+        var ld = encodeparam($('#childs_leavedate').val(),'date').replace(/'/g,'');
+        if (ld < ed) {
+          errormsg("ERREUR","La date de sortie ne peut pas Ãªtre inferieur Ã  la date d'entrée!");
+          return false;
+        }
+      }
+      
+      //if (objname == "childs_birthday") {
+      //  //$("#dt_childs_entrydate").datetimepicker('setStartDate',$('#' + objname).val());
+      //  //$("#dt_childs_leavedate").datepicker('setStartDate',$('#' + objname).val());
+      //}
+      //if (objname == "childs_entrydate") {
+      //  //$("#dt_childs_leavedate").datepicker('setStartDate',$('#' + objname).val());
+      //}
+  }
+  if (objname == "staff_password"){
+         var pwd = $('#' + objname).val();
+         if (pwd.length < 4){
+                 alert("Le mot de passe est trop court!");
+                 return false;
+         } 
+         if(!confirm("Êtes vous sûre de changer le mot de passe?")){
+                 $('#' + objname).val("");
+                 return false;
+         }
+  }
+  if (objname == "creche_crechename") {
+    var num = apppref.getpreference("support.database.currentdb.num");
+    var scfg = apppref.getpreference("support.database." + num);
+    var sitecfg = JSON.parse(scfg);
+    sitecfg.name=$('#' + objname).val();
+    apppref.setpreference("support.database." + num,sitecfg);
+    globelreq.send_request({page:'updatesiteslist',data:{curname:sitecfg.name}});
+  }
+  
+  if ((objname) && $('#' + objname).hasClass("dailypresence")){
+      return false; 
+  }
+  if ((objname) && ($('#' + objname).attr('id').indexOf("_") != -1) && $('#' + objname).attr('id').indexOf("chart_") == -1) {
+        var data = $('#' + objname).attr('id').split("_");
+        //dump("OBJNAME: " + objname + "\n");
+//        if (objname == "staff_password" ){
+//             var dval=MD5($('#' + objname).val());
+//            var ty = $('#' + objname).attr('type');
+//            var sql = "UPDATE "+data[0]+" SET "+data[1]+"="+encodeparam(dval,ty)+" where '"+$data[4]+"'='"+ data[2] +"';";
+//            //dump("SQL PWD:" + sql + "\n");
+//            appdb.dbexec(sql);
+//        } else 
+        if (data.length==2) {
+          var tagtype = $('#' + objname).attr('type');
+          //dump("TAGTYPE: " + tagtype + "\n");
+          if ($('#' + objname).prop("tagName") === "TEXTAREA"){
+           tagtype =  'richtextarea';
+          }
+          var sql = "UPDATE "+data[0]+" SET "+data[1]+"="+encodeparam($('#' + objname).val(),tagtype)+" where uuid='"+ document.getElementById(data[0] + '_uuid').value +"';";
+          //dump("updatesql: " + sql + "\n"); 
+          appdb.dbexec(sql);
+        }else if (data.length==4) {
+          var dval=$('#' + objname).val();
+          var ty = $('#' + objname).attr('type');
+          var sql = "UPDATE "+data[0]+" SET "+data[1]+"="+encodeparam(dval,ty)+" where '"+$data[4]+"'='"+ data[2] +"';";
+          appdb.dbexec(sql);
+        }else {
+          return false;
+        }  
+    }
+    return false;
+}
+
+function encodeparam(string,type){
+    if (type == "text") {
+        if (string == "") {
+            string = 'null';
+        }else {
+            string = string.replace(/</g,'&lt;');
+            string = string.replace(/>/g,'&gt;');
+            string = string.replace(/&/g,'&amp;');
+            string = string.replace(/"/g,'&quot');
+            string = string.replace(/'/g,"''");
+            string = "'"+ string+"'";
+        }
+    }
+    else if(type == "richtextarea"){
+      string = string.replace(/'/g,"''");
+      string = "'"+ string+"'";
+    }
+    else if(type == "password"){
+       if (string == "") {
+            string = 'null';
+        }else {
+            //string.replace(',','.');
+               string = "'"+ MD5(string)+"'";
+        }
+        
+    }
+    else if(type == "date"){
+      var re = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/i;
+        if (!string.match(re)) {
+            string = 'null';
+        }else{
+           var dspl=string.split('.');
+            string = "'"+dspl[2]+'-'+dspl[1]+'-'+dspl[0]+"'";
+        }
+    }
+    else if(type == "year"){
+      var re = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/i;
+        if (!string.match(re)) {
+            string = 'null';
+        }else{
+           var dspl=string.split('.');
+            string = "'"+dspl[2]+"'";
+        }
+    }
+    else if(type == "number"){
+        if (string == "") {
+            string = 'null';
+        }else {
+            string.replace(',','.');
+            string = parseFloat(string);
+        }
+    }else if(type == "boolean"){
+        if (string == "") {
+          string = 'null';
+        }
+        string= string.replace('true',"'1'");
+        string= string.replace('false',"'0'");
+    }else if(type == "month"){
+      var re = /^(\d{1,2})\.(\d{4})$/i;
+        if (!string.match(re)) {
+            string = 'null';
+        }else{
+           var dspl=string.split('.');
+            string = "'"+dspl[1]+'-'+dspl[0]+"-01'"
+        }
+    }else if(type == "file"){
+      string = system.getFileName(string);
+      string = string.replace("'","''",'g');
+      string = string = "'"+ string+"'";
+    }
+    else {
+      if (typeof(string) == "object") {
+        string = JSON.stringify(string);
+      }
+        string = string.replace(/</g,'&lt;');
+        string = string.replace(/>/g,'&gt;');
+        string = string.replace(/&/g,'&amp;');
+        string = string.replace(/'/g,"''");
+        string = "'"+ string+"'";
+    }
+    
+    return string;
+}
+
+function checkdateformat(fieldname){
+  var re = null;
+  var plh = $('#' + fieldname).attr("placeholder");
+  var val = $('#' + fieldname).val();
+  if (plh == 'dd.mm.yyyy') {
+    re = /^\d{1,2}\.\d{1,2}\.\d{4}$/;
+  }else if (plh == 'mm.yyyy') {
+    re = /^\d{1,2}\.\d{4}$/;
+  }else {
+    return true;
+  }
+  if (!val.match(re)) {
+    errormsg("ERREUR format date!","Le format de la date n'est pas correcte!<br/>il doit Ãªtre " + plh);
+    return false;
+  }
+  return true;
+}
+
+
+function errormsg(title,msg){
+  $("#errtitle").html(title);
+  $("#errmsg").html(msg);
+  $("#dlgerror").modal('show');
+}
+
+//function sqlerrormsg(sqlquery){
+//  //dump("Load Resend:" + sqlquery + "\n");
+//  $("#sqlquery").val(sqlquery);
+//  $("#dlgsqlerror").modal('show');
+//}
+//
+//function resendsql(){
+//   $("#dlgsqlerror").modal('hide');
+//
+//   //dump("Resend: "+$("#sqlquery").val()+"\n");
+//   var r = appdb.dbexec($("#sqlquery").val());
+//   if (!r){
+//      sqlerrormsg($("#sqlquery").val());
+//   }else {
+//      $("#sqlquery").val("");
+//      $("#dlgsqlerror").modal('hide');
+//   }
+//}
+
+function loadtextareas(eheight=200){
+   
+   $('.summernote').summernote({
+        lang: 'fr-FR',
+        toolbar: [
+    ['style', ['bold', 'italic', 'underline']],
+    ['font', ['strikethrough', 'superscript', 'subscript']],
+    ['fontsize', ['fontsize'],['color']],
+    ['color', ['color']],
+    ['para', ['ul', 'ol', 'paragraph']],
+    ['reset',['clear']]
+    ],
+    height: eheight,
+    minHeight: eheight,
+    maxHeight: eheight,
+    shortcuts: false,
+    disableResizeEditor: true,
+    disableDragAndDrop: true,
+    callbacks: {
+      onBlur: function() {
+         saveonfocusout($(this).attr('id'));
+      }
+     }
+      });
+}
+
+
+function load_helpers(){
+    $('input').focusout(function(){
+      
+      if ($(this).attr('type') == 'number') {
+        //alert('number');
+        if ($(this).attr('nullable') && $(this).attr('nullable') === 'false' && $(this).val() === "") {
+          $(this).val($(this).attr('min'));
+        }
+      }
+      saveonfocusout($(this).attr('id'));
+    });
+    $('input').on("click", function () {
+      $(this).select();
+    });
+    $("input[type='number']").on('keypress', function(ev){
+
+      var keycode = window.event ? ev.keyCode : ev.which;
+      if (keycode < 48 || keycode > 57){
+        if (keycode !== 0 && keycode !== 8 && keycode !== 13 && !ev.ctrlKey && keycode !== 46 && keycode !== 44) {
+          ev.preventDefault();
+        }
+      }
+    });
+    
+    
+    $(".input-group.date input[type='date']").each(function(){
+       //dump("init dtp " + this.id + "\n");
+        var dateobjid =  this.id;
+        if ($('#' + dateobjid).attr('limits') == '1'){
+            $('#' + dateobjid).datetimepicker({
+                locale: 'fr',
+                format: "DD.MM.YYYY",
+                daysOfWeekDisabled: [0]
+            });
+        } else if ($('#' + dateobjid).attr('widgetpos')){
+          $('#' + dateobjid).datetimepicker({
+                locale: 'fr',
+                format: "DD.MM.YYYY",
+                widgetPositioning:{
+                   horizontal: 'auto',
+                   vertical: $('#' + dateobjid).attr('widgetpos')
+                }
+            });
+          
+          }else {
+            $('#' + dateobjid).datetimepicker({
+                locale: 'fr',
+                format: "DD.MM.YYYY",
+            });
+        }
+        
+    });
+    //dump("load month helper\n");
+    $(".input-group.month input[type='date']").datetimepicker({
+      locale: 'fr',
+      format: 'MM.YYYY',
+      viewMode:'months'
+    });
+    //dump("load week helper\n");
+    $(".input-group.week input[type='date']").datetimepicker({
+    locale: 'fr',
+    format: "DD.MM.YYYY",
+    calendarWeeks: true,
+    daysOfWeekDisabled: [0,2,3,4,5,6],
+    });
+
+    // $('.timepicker').timepicker({
+    //     showSeconds: false,
+    //     showMeridian: false,
+    //     defaultTime: '00:00',
+    // });
+    $('.timepicker').attr("style","width: 70px;");
+
+    $.fn.dataTableExt.sErrMode='throw';
+}
+
+function set_infoheader(strinfoheader) {
+  globelreq.send_request({page:'infoheader',header:strinfoheader});
+}
+
+var globelreq = {
+        send_request: function(data, callback) { // analogue of chrome.extension.sendRequest
+          var request = document.createTextNode(JSON.stringify(data));
+
+          request.addEventListener("creorga-response", function(event) {
+            request.parentNode.removeChild(request);
+
+            if (callback) {
+              var response = JSON.parse(request.nodeValue);
+              callback(response);
+            }
+          }, false);
+
+          document.head.appendChild(request);
+
+          var event = document.createEvent("HTMLEvents");
+          event.initEvent("creorga-query", true, false);
+          request.dispatchEvent(event);
+        },
+
+        callback: function(response) {
+          return alert("response: " + (response ? response.toSource() : response));
+        }
+      }
+
+$(document).ready(function() {
+
+    initdata();
+    $('body').append('<div class="modal fade" id="dlgerror">'+
+  '<div class="modal-dialog">' +
+    '<div class="modal-content">' +
+      '<div class="modal-header">' +
+        '<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>' +
+        '<h4 class="modal-title" id="errtitle">ERREUR!</h4>' +
+      '</div>' +
+      '<div class="modal-body">' +
+        '<p id="errmsg"></p>' +
+      '</div>' +
+      '<div class="modal-footer">' +
+        '<button type="button" class="btn btn-default" data-dismiss="modal">OK</button>' +
+      '</div>' +
+    '</div>' +
+  '</div>' +
+'</div>');
+//    $('body').append('<div class="modal fade" id="dlgsqlerror">'+
+//  '<div class="modal-dialog">' +
+//    '<div class="modal-content">' +
+//      '<div class="modal-header">' +
+//        '<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>' +
+//        '<h4 class="modal-title">ERREUR de sauvegarde!</h4>' +
+//      '</div>' +
+//      '<div class="modal-body">' +
+//        '<input type="hidden" value="" id="sqlquery"/>' +
+//        '<p id="sqlerrmsg">ERREUR de sauvegarde du contenu!</p>' +
+//      '</div>' +
+//      '<div class="modal-footer">' +
+//        '<button type="button" class="btn btn-default" onclick="resendsql();" data-dismiss="modal">Reessayer de sauvegarder</button>' +
+//      '</div>' +
+//    '</div>' +
+//  '</div>' +
+//'</div>');
+});
+
+
+function htmlUnescape(str){
+   var nstr = str
+        .replace(/&amp;/g, '&')
+        .replace(/&quot;/g, '"')
+        .replace(/&quot/g, '"')
+        .replace(/&#39;/g, "'")
+        .replace(/&lt;/g, '<')
+        .replace(/&gt;/g, '>');
+   return nstr;
+}
+
+jQuery.fn.exists = function(){ return this.length > 0; }
+
+
diff --git a/js/database.js b/js/database.js
new file mode 100644 (file)
index 0000000..c94a3c9
--- /dev/null
@@ -0,0 +1,86 @@
+var appdb = {
+               //dbfile: null,
+               url: null,
+               dbquery: function(sQuery){
+                       var type='querysorted';
+                       var result= {sqldata:[]};
+                       //console.log(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery));
+                       //dump(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) + "\n");
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:this.url,
+                               crossDomain: true,
+                               method: "POST",
+                               data: 'type=' + type + '&sql=' +encodeURIComponent(sQuery),
+                               success: function (data){
+                                       //dump(data + "\n");
+                                               result=data.result;
+                                       },
+                                       error: function(data){
+                                               alert("Error:" + JSON.stringify(data));
+                                               console.log("Error:" + JSON.stringify(data));
+                                       },
+                               async:false
+                       });
+                       return result;
+               },
+               dbqueryarray: function(sQuery){
+                       var type='queryarray';
+                       var result= {sqldata:[]};
+                       //console.log(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery));
+                       //alert(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) + "\n");
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:this.url,
+                               crossDomain: true,
+                               method: "POST",
+                               data: 'type=' + type + '&sql=' +encodeURIComponent(sQuery),
+                               success: function (data){
+                                               result=data.result;
+                                       },
+                               error: function(data){
+                                       alert("Error:" + JSON.stringify(data));
+                                       console.log("Error:" + JSON.stringify(data));
+                               },
+                               async:false
+                       });
+                       return result;
+               },
+               dbexec: function(sQuery){
+                       var type='exec';
+                       var result= {sqldata:[]};
+                       //dump(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) + "\n");
+                       //console.log(this.url + '&db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) );
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:this.url,
+                               crossDomain: true,
+                               method: "POST",
+                               data: 'type=' + type + '&sql=' +encodeURIComponent(sQuery),
+                               success: function (data){
+                                               result=data.result;
+                                       },
+                                       error: function(data){
+                                               alert("Error:" + JSON.stringify(data));
+                                               console.log("Error:" + JSON.stringify(data));
+                                       },
+                               async:false
+                       });
+                       return result;
+               },
+//             b64EncodeUnicode: function (str) {
+//                 // first we use encodeURIComponent to get percent-encoded UTF-8,
+//                 // then we convert the percent encodings into raw bytes which
+//                 // can be fed into btoa.
+//                 return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
+//                     function toSolidBytes(match, p1) {
+//                         return String.fromCharCode('0x' + p1);
+//                 }));
+//             },
+               generate_uuid: function(){
+                       return this.s4() + this.s4() + '-' + this.s4() + '-' + this.s4() + '-' + this.s4() + '-' + this.s4() + this.s4() + this.s4();
+               },
+               s4: function(){
+                       return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
+               }
+}
\ No newline at end of file
diff --git a/js/lang/summernote-fr-FR.js b/js/lang/summernote-fr-FR.js
new file mode 100644 (file)
index 0000000..5247e7c
--- /dev/null
@@ -0,0 +1,144 @@
+(function ($) {
+  $.extend($.summernote.lang, {
+    'fr-FR': {
+      font: {
+        bold: 'Gras',
+        italic: 'Italique',
+        underline: 'Souligné',
+        clear: 'Effacer la mise en forme',
+        height: 'Interligne',
+        name: 'Famille de police',
+        strikethrough: 'Barré',
+        superscript: 'Exposant',
+        subscript: 'Indice',
+        size: 'Taille de police'
+      },
+      image: {
+        image: 'Image',
+        insert: 'Insérer une image',
+        resizeFull: 'Taille originale',
+        resizeHalf: 'Redimensionner Ã  50 %',
+        resizeQuarter: 'Redimensionner Ã  25 %',
+        floatLeft: 'Aligné Ã  gauche',
+        floatRight: 'Aligné Ã  droite',
+        floatNone: 'Pas d\'alignement',
+        shapeRounded: 'Forme: Rectangle arrondie',
+        shapeCircle: 'Forme: Cercle',
+        shapeThumbnail: 'Forme: Vignette',
+        shapeNone: 'Forme: Aucune',
+        dragImageHere: 'Faites glisser une image ou un texte dans ce cadre',
+        dropImage: 'Lachez l\'image ou le texte',
+        selectFromFiles: 'Choisir un fichier',
+        maximumFileSize: 'Taille de fichier maximale',
+        maximumFileSizeError: 'Taille maximale du fichier dépassée',
+        url: 'URL de l\'image',
+        remove: 'Supprimer l\'image'
+      },
+      video: {
+        video: 'Vidéo',
+        videoLink: 'Lien vidéo',
+        insert: 'Insérer une vidéo',
+        url: 'URL de la vidéo',
+        providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion ou Youku)'
+      },
+      link: {
+        link: 'Lien',
+        insert: 'Insérer un lien',
+        unlink: 'Supprimer un lien',
+        edit: 'Modifier',
+        textToDisplay: 'Texte Ã  afficher',
+        url: 'URL du lien',
+        openInNewWindow: 'Ouvrir dans une nouvelle fenêtre'
+      },
+      table: {
+        table: 'Tableau'
+      },
+      hr: {
+        insert: 'Insérer une ligne horizontale'
+      },
+      style: {
+        style: 'Style',
+        p: 'Normal',
+        blockquote: 'Citation',
+        pre: 'Code source',
+        h1: 'Titre 1',
+        h2: 'Titre 2',
+        h3: 'Titre 3',
+        h4: 'Titre 4',
+        h5: 'Titre 5',
+        h6: 'Titre 6'
+      },
+      lists: {
+        unordered: 'Liste Ã  puces',
+        ordered: 'Liste numérotée'
+      },
+      options: {
+        help: 'Aide',
+        fullscreen: 'Plein Ã©cran',
+        codeview: 'Afficher le code HTML'
+      },
+      paragraph: {
+        paragraph: 'Paragraphe',
+        outdent: 'Diminuer le retrait',
+        indent: 'Augmenter le retrait',
+        left: 'Aligner Ã  gauche',
+        center: 'Centrer',
+        right: 'Aligner Ã  droite',
+        justify: 'Justifier'
+      },
+      color: {
+        recent: 'Dernière couleur sélectionnée',
+        more: 'Plus de couleurs',
+        background: 'Couleur de fond',
+        foreground: 'Couleur de police',
+        transparent: 'Transparent',
+        setTransparent: 'Définir la transparence',
+        reset: 'Restaurer',
+        resetToDefault: 'Restaurer la couleur par défaut'
+      },
+      shortcut: {
+        shortcuts: 'Raccourcis',
+        close: 'Fermer',
+        textFormatting: 'Mise en forme du texte',
+        action: 'Action',
+        paragraphFormatting: 'Mise en forme des paragraphes',
+        documentStyle: 'Style du document',
+        extraKeys: 'Touches supplémentaires'
+      },
+      help: {
+        'insertParagraph': 'Insérer paragraphe',
+        'undo': 'Défaire la dernière commande',
+        'redo': 'Refaire la dernière commande',
+        'tab': 'Tabulation',
+        'untab': 'Tabulation arrière',
+        'bold': 'Mettre en caractère gras',
+        'italic': 'Mettre en italique',
+        'underline': 'Mettre en souligné',
+        'strikethrough': 'Mettre en texte barré',
+        'removeFormat': 'Nettoyer les styles',
+        'justifyLeft': 'Aligner Ã  gauche',
+        'justifyCenter': 'Centrer',
+        'justifyRight': 'Aligner Ã  droite',
+        'justifyFull': 'Justifier Ã  gauche et Ã  droite',
+        'insertUnorderedList': 'Basculer liste Ã  puces',
+        'insertOrderedList': 'Basculer liste ordonnée',
+        'outdent': 'Diminuer le retrait du paragraphe',
+        'indent': 'Augmenter le retrait du paragraphe',
+        'formatPara': 'Changer le paragraphe en cours en normal (P)',
+        'formatH1': 'Changer le paragraphe en cours en entête H1',
+        'formatH2': 'Change current block\'s format as entête H2',
+        'formatH3': 'Change current block\'s format as entête H3',
+        'formatH4': 'Change current block\'s format as entête H4',
+        'formatH5': 'Change current block\'s format as entête H5',
+        'formatH6': 'Change current block\'s format as entête H6',
+        'insertHorizontalRule': 'Insérer ligne horizontale',
+        'linkDialog.show': 'Afficher fenêtre d\'hyperlien'
+      },
+      history: {
+        undo: 'Annuler la dernière action',
+        redo: 'Restaurer la dernière action annulée'
+      }
+
+    }
+  });
+})(jQuery);
diff --git a/js/lang/summernote-fr-FR.min.js b/js/lang/summernote-fr-FR.min.js
new file mode 100644 (file)
index 0000000..d21ff1c
--- /dev/null
@@ -0,0 +1,2 @@
+/*! Summernote v0.8.3 | (c) 2013-2015 Alan Hong and other contributors | MIT license */
+!function(a){a.extend(a.summernote.lang,{"fr-FR":{font:{bold:"Gras",italic:"Italique",underline:"Souligné",clear:"Effacer la mise en forme",height:"Interligne",name:"Famille de police",strikethrough:"Barré",superscript:"Exposant",subscript:"Indice",size:"Taille de police"},image:{image:"Image",insert:"Insérer une image",resizeFull:"Taille originale",resizeHalf:"Redimensionner Ã  50 %",resizeQuarter:"Redimensionner Ã  25 %",floatLeft:"Aligné Ã  gauche",floatRight:"Aligné Ã  droite",floatNone:"Pas d'alignement",shapeRounded:"Forme: Rectangle arrondie",shapeCircle:"Forme: Cercle",shapeThumbnail:"Forme: Vignette",shapeNone:"Forme: Aucune",dragImageHere:"Faites glisser une image ou un texte dans ce cadre",dropImage:"Lachez l'image ou le texte",selectFromFiles:"Choisir un fichier",maximumFileSize:"Taille de fichier maximale",maximumFileSizeError:"Taille maximale du fichier dépassée",url:"URL de l'image",remove:"Supprimer l'image"},video:{video:"Vidéo",videoLink:"Lien vidéo",insert:"Insérer une vidéo",url:"URL de la vidéo",providers:"(YouTube, Vimeo, Vine, Instagram, DailyMotion ou Youku)"},link:{link:"Lien",insert:"Insérer un lien",unlink:"Supprimer un lien",edit:"Modifier",textToDisplay:"Texte Ã  afficher",url:"URL du lien",openInNewWindow:"Ouvrir dans une nouvelle fenêtre"},table:{table:"Tableau"},hr:{insert:"Insérer une ligne horizontale"},style:{style:"Style",p:"Normal",blockquote:"Citation",pre:"Code source",h1:"Titre 1",h2:"Titre 2",h3:"Titre 3",h4:"Titre 4",h5:"Titre 5",h6:"Titre 6"},lists:{unordered:"Liste Ã  puces",ordered:"Liste numérotée"},options:{help:"Aide",fullscreen:"Plein Ã©cran",codeview:"Afficher le code HTML"},paragraph:{paragraph:"Paragraphe",outdent:"Diminuer le retrait",indent:"Augmenter le retrait",left:"Aligner Ã  gauche",center:"Centrer",right:"Aligner Ã  droite",justify:"Justifier"},color:{recent:"Dernière couleur sélectionnée",more:"Plus de couleurs",background:"Couleur de fond",foreground:"Couleur de police",transparent:"Transparent",setTransparent:"Définir la transparence",reset:"Restaurer",resetToDefault:"Restaurer la couleur par défaut"},shortcut:{shortcuts:"Raccourcis",close:"Fermer",textFormatting:"Mise en forme du texte",action:"Action",paragraphFormatting:"Mise en forme des paragraphes",documentStyle:"Style du document",extraKeys:"Touches supplémentaires"},help:{insertParagraph:"Insérer paragraphe",undo:"Défaire la dernière commande",redo:"Refaire la dernière commande",tab:"Tabulation",untab:"Tabulation arrière",bold:"Mettre en caractère gras",italic:"Mettre en italique",underline:"Mettre en souligné",strikethrough:"Mettre en texte barré",removeFormat:"Nettoyer les styles",justifyLeft:"Aligner Ã  gauche",justifyCenter:"Centrer",justifyRight:"Aligner Ã  droite",justifyFull:"Justifier Ã  gauche et Ã  droite",insertUnorderedList:"Basculer liste Ã  puces",insertOrderedList:"Basculer liste ordonnée",outdent:"Diminuer le retrait du paragraphe",indent:"Augmenter le retrait du paragraphe",formatPara:"Changer le paragraphe en cours en normal (P)",formatH1:"Changer le paragraphe en cours en entête H1",formatH2:"Change current block's format as entête H2",formatH3:"Change current block's format as entête H3",formatH4:"Change current block's format as entête H4",formatH5:"Change current block's format as entête H5",formatH6:"Change current block's format as entête H6",insertHorizontalRule:"Insérer ligne horizontale","linkDialog.show":"Afficher fenêtre d'hyperlien"},history:{undo:"Annuler la dernière action",redo:"Restaurer la dernière action annulée"}}})}(jQuery);
\ No newline at end of file
diff --git a/js/locale/datatable_de.json b/js/locale/datatable_de.json
new file mode 100644 (file)
index 0000000..d6a113d
--- /dev/null
@@ -0,0 +1,23 @@
+{
+       "sEmptyTable":          "Keine Daten in der Tabelle vorhanden",
+       "sInfo":                "_START_ bis _END_ von _TOTAL_ Einträgen",
+       "sInfoEmpty":           "0 bis 0 von 0 Einträgen",
+       "sInfoFiltered":        "(gefiltert von _MAX_ Einträgen)",
+       "sInfoPostFix":         "",
+       "sInfoThousands":       ".",
+       "sLengthMenu":          "_MENU_ Einträge anzeigen",
+       "sLoadingRecords":      "Wird geladen...",
+       "sProcessing":          "Bitte warten...",
+       "sSearch":              "Suchen",
+       "sZeroRecords":         "Keine Einträge vorhanden.",
+       "oPaginate": {
+               "sFirst":       "Erste",
+               "sPrevious":    "Zurück",
+               "sNext":        "Nächste",
+               "sLast":        "Letzte"
+       },
+       "oAria": {
+               "sSortAscending":  ": aktivieren, um Spalte aufsteigend zu sortieren",
+               "sSortDescending": ": aktivieren, um Spalte absteigend zu sortieren"
+       }
+}
diff --git a/js/locale/datatable_fr.json b/js/locale/datatable_fr.json
new file mode 100644 (file)
index 0000000..23edc99
--- /dev/null
@@ -0,0 +1,22 @@
+{
+       "sProcessing":     "Traitement en cours...",
+       "sSearch":         "Rechercher&nbsp;:",
+    "sLengthMenu":     "Afficher _MENU_ &eacute;l&eacute;ments",
+       "sInfo":           "Affichage de l'&eacute;l&eacute;ment _START_ &agrave; _END_ sur _TOTAL_ &eacute;l&eacute;ments",
+       "sInfoEmpty":      "Affichage de l'&eacute;l&eacute;ment 0 &agrave; 0 sur 0 &eacute;l&eacute;ments",
+       "sInfoFiltered":   "(filtr&eacute; de _MAX_ &eacute;l&eacute;ments au total)",
+       "sInfoPostFix":    "",
+       "sLoadingRecords": "Chargement en cours...",
+    "sZeroRecords":    "Aucun &eacute;l&eacute;ment &agrave; afficher",
+       "sEmptyTable":     "Aucune donn&eacute;e disponible dans le tableau",
+       "oPaginate": {
+               "sFirst":      "Premier",
+               "sPrevious":   "Pr&eacute;c&eacute;dent",
+               "sNext":       "Suivant",
+               "sLast":       "Dernier"
+       },
+       "oAria": {
+               "sSortAscending":  ": activer pour trier la colonne par ordre croissant",
+               "sSortDescending": ": activer pour trier la colonne par ordre d&eacute;croissant"
+       }
+}
diff --git a/js/moduleglobal.js b/js/moduleglobal.js
new file mode 100644 (file)
index 0000000..cf1c62b
--- /dev/null
@@ -0,0 +1,26 @@
+$( document ).ready(function() {
+  //console.log( "Iframe "+ location.pathname.substring(location.pathname.lastIndexOf("/")) +" ready!" );
+  mpref.loadconfig();
+  initpage();
+});
+
+var mpref ={
+  cfg: null,
+  getSearchParams: function (k){
+    //alert(location.href);
+    var p={};
+    console.log("params =>" + location.search);
+    location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(s,k,v){p[k]=v});
+    return k?p[k]:p;
+  },
+  loadconfig: function(){
+    this.cfg = this.getSearchParams();
+    //var page = location.pathname.substring(location.pathname.lastIndexOf("/"));
+    //page = page.replace(/\.html/,'');
+    //apppref.getpreference(page);
+    //appdb.dbfile = this.cfg.dbfile; 
+    if (typeof appdb !== "undefined"){
+      appdb.url = decodeURIComponent(this.cfg.serviceurl) + 'sqlite/' + decodeURIComponent(this.cfg.dbfile);
+    }
+  }
+}
\ No newline at end of file
diff --git a/js/old/data.js b/js/old/data.js
new file mode 100644 (file)
index 0000000..7b9c4aa
--- /dev/null
@@ -0,0 +1,54 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+var globalreq = {
+  listen_request: function(callback) { 
+    document.addEventListener("creorga-query", function(event) {
+      var node = event.target;
+      if (!node || node.nodeType != Node.TEXT_NODE)
+        return;
+
+      var doc = node.ownerDocument;
+      callback(JSON.parse(node.nodeValue), doc, function(response) {
+        node.nodeValue = JSON.stringify(response);
+
+        var event = doc.createEvent("HTMLEvents");
+        event.initEvent("creorga-response", true, false);
+        return node.dispatchEvent(event);
+      });
+    }, false, true);
+  },
+  callback: function(request, sender, callback) {
+    if (request.page) {
+      if (!request.module) {
+        request.module =null;
+      }
+      if (request.page=='preview') {
+        printmanager.onprint(request.data);
+      }else if (request.page=='updatesiteslist') {
+        try {
+          if (multisite_reader){
+            multisite_reader.getsites();
+          }else {
+              document.getElementById("curcreche").value = "";
+          }
+          } catch (Exception) {
+            if (request.data.curname){
+              document.getElementById("curcreche").value = request.data.curname;
+            }
+          }
+      }else if (request.page=='infoheader') {
+        navigation.set_infoheader(request.header);
+      }
+      else {
+        navigation.load_appview(request.page,request.module,request.data,request.header);
+      }
+        
+      return "";
+    }
+  
+    return callback(null);
+  }
+}
+
+globalreq.listen_request(globalreq.callback);
diff --git a/js/old/database.js b/js/old/database.js
new file mode 100644 (file)
index 0000000..88e9df7
--- /dev/null
@@ -0,0 +1,324 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+Components.utils["import"]("resource://gre/modules/Sqlite.jsm");
+Components.utils["import"]("resource://gre/modules/Services.jsm");
+Components.utils["import"]("resource://gre/modules/FileUtils.jsm");
+
+var appdb = {
+  dbFile: ((apppref.getpreference("support.database.currentdb.db"))?FileUtils.File(apppref.getpreference("support.database.currentdb.db")):null),
+  dbConn: null,
+  aTableData: null,   
+  aTableType: null,
+  aColumns: null,
+  keywords: ['ABORT','ACTION','ADD','AFTER','ALL','ALTER','ANALYZE','AND','AS','ASC','ATTACH','AUTOINCREMENT','BEFORE','BEGIN','BETWEEN','BY','CASCADE','CASE','CAST','CHECK','COLLATE','COLUMN','COMMIT','CONFLICT','CONSTRAINT','CREATE','CROSS','CURRENT_DATE','CURRENT_TIME','CURRENT_TIMESTAMP','DATABASE','DEFAULT','DEFERRABLE','DEFERRED','DELETE','DESC','DETACH','DISTINCT','DROP','EACH','ELSE','END','ESCAPE','EXCEPT','EXCLUSIVE','EXISTS','EXPLAIN','FAIL','FOR','FOREIGN','FROM','FULL','GLOB','GROUP','HAVING','IF','IGNORE','IMMEDIATE','IN','INDEX','INDEXED','INITIALLY','INNER','INSERT','INSTEAD','INTERSECT','INTO','IS','ISNULL','JOIN','KEY','LEFT','LIKE','LIMIT','MATCH','NATURAL','NO','NOT','not','null','NOTNULL','NULL','OF','OFFSET','ON','OR','ORDER','OUTER','PLAN','PRAGMA','PRIMARY','QUERY','RAISE','RECURSIVE','REFERENCES','REGEXP','REINDEX','RELEASE','RENAME','REPLACE','RESTRICT','RIGHT','ROLLBACK','ROW','SAVEPOINT','SELECT','SET','TABLE','TEMP','TEMPORARY','THEN','TO','TRANSACTION','TRIGGER','UNION','UNIQUE','UPDATE','USING','VACUUM','VALUES','VIEW','VIRTUAL','WHEN','WHERE','WITH','WITHOUT'],
+  setdbFile: function(fname){
+         this.dbFile=FileUtils.File(fname);
+  },
+  openDatabase: function() {
+    this.closeConnection();
+    try {
+      this.dbConn = Services.storage.openDatabase(this.dbFile);
+      
+    }
+    catch (e) {
+      //dump("Connection Failed: " +e.message + '-'+ curcfg.dbfile.local + " - "+ this.dbFile.path + "\n");
+      return false;
+    }
+    if(this.dbConn == null) return false;
+    return true;
+  },
+  closeConnection: function() {
+    if (this.dbConn != null) {
+      try {
+        this.dbConn.close();
+      } catch (e) {
+        this.dbConn = null;
+      }
+    }
+    this.dbConn = null;
+    this.aTableData = null;
+    this.aTableType = null;
+    this.aColumns = null;
+  },
+  dbexec: function(sql){
+         //dump("EXEC sql: " + sql + "\n");
+    if (this.dbConn == null) {
+      this.openDatabase();
+    }
+    try{
+        var statement = this.dbConn.createStatement(sql);
+        statement.executeAsync({
+         handleError: function(aError) {
+               if (sql != ""){
+                       //dump("Error:" + aError.message + "\nFailed SQL: " + sql + "\n");
+                       var params = { in : {msg:aError.message + "\nFailed SQL: " + sql},out: null};
+                       var dlg = window.openDialog("chrome://creorga/content/dlg/dlgsqlerror.xul", "dlgsqlerror","chrome,centerscreen,modal", params).focus();
+                       if (params.out) {
+                               appdb.dbexec( sql);
+                       }
+              }
+         },
+         handleCompletion: function(aReason) {
+           //if (aReason != Components.interfaces.mozIStorageStatementCallback.REASON_FINISHED)
+             //dump("Query canceled or aborted!");
+         }
+       });
+        if (curcfg.sync){
+                       sync.up(sql);
+        }
+        
+      } catch(e){
+          if (sql != ""){
+                       //dump("Error:" + e.message + "\nFailed SQL: " + sql + "\n");
+                       var params = { in : {msg:e.message + "\nFailed SQL: " + sql},out: null};
+                       var dlg = window.openDialog("chrome://creorga/content/dlg/dlgsqlerror.xul", "dlgsqlerror","chrome,centerscreen,modal", params).focus();
+                       if (params.out) {
+                               appdb.dbexec( sql);
+                       }
+          }
+        return false;
+      }
+      return true;
+  },
+  dbquery: function(sQuery) {
+    if (this.dbConn == null) {
+      var r = this.openDatabase();
+    }
+    
+    var xdata = {
+      sqldata : []
+    };
+    this.aTableData = new Array();
+    this.aTableType = new Array();
+    this.aColumns = null;        
+    var bResult = false;
+    try { 
+      var stmt = this.dbConn.createStatement(sQuery);
+    }
+    catch (e) {
+     
+      //dump("ERROR " + e.message + " " + sQuery +" - Statement ERROR!\n");
+      return false;
+    }
+    var iCols = 0;
+    var iType, colName;
+    try {
+      iCols = stmt.columnCount;
+      this.aColumns = new Array();
+      var aTemp;
+      for (var i = 0; i < iCols; i++) {
+        colName = stmt.getColumnName(i);
+        aTemp = [colName];
+        this.aColumns.push(aTemp);  
+      }
+    } catch (e) {
+      stmt.finalize();
+      //dump("Column ERROR!\n");
+      return false;
+    }
+
+    var cell;
+    var bFirstRow = true;
+    try {
+      var r = 0;
+      while (stmt.executeStep()) {
+        var rowdata = {};
+        for (i = 0; i < iCols; i++) {
+          iType = stmt.getTypeOfIndex(i);
+          switch (iType) {
+            case stmt.VALUE_TYPE_NULL: 
+              rowdata[this.aColumns[i]] = '';
+              break;
+            case stmt.VALUE_TYPE_INTEGER:
+              rowdata[this.aColumns[i]] = stmt.getInt64(i);
+              break;
+            case stmt.VALUE_TYPE_FLOAT:
+              rowdata[this.aColumns[i]] = stmt.getDouble(i);
+              break;
+            case stmt.VALUE_TYPE_TEXT:
+              rowdata[this.aColumns[i]] = stmt.getString(i);
+              break;
+            default: sData = "<unknown>"; 
+          }
+          r = r+1;
+        }
+        xdata.sqldata.push(rowdata);
+        r = r+1;
+      }
+    } catch (e) {
+      stmt.finalize();
+      //dump("Statement Result ERROR!\n");
+      return false;
+    }
+    stmt.finalize();
+    return xdata;
+  },
+  dbqueryarray: function(sQuery) {
+    if (this.dbConn == null) {
+      this.openDatabase();
+    }
+    var xdata = {
+      sqldata : [],
+      sqlhead : []
+    };
+
+    this.aTableData = new Array();
+    this.aTableType = new Array();
+    this.aColumns = null;        
+    var bResult = false;
+    try { 
+      var stmt = this.dbConn.createStatement(sQuery);
+    }
+    catch (e) {
+      return false;
+    }
+    
+    var iCols = 0;
+    var iType, colName;
+    try {
+      iCols = stmt.columnCount;
+      this.aColumns = new Array();
+      var aTemp;
+      for (var i = 0; i < iCols; i++) {
+        colName = stmt.getColumnName(i);
+        this.aColumns.push(colName);  
+      }
+    } catch (e) {
+      stmt.finalize();
+      return false;
+    }
+
+    var cell;
+    var bFirstRow = true;
+    try {
+      var r = 0;
+      while (stmt.executeStep()) {
+        var rowdata = new Array();
+        for (i = 0; i < iCols; i++) {
+          iType = stmt.getTypeOfIndex(i);
+          switch (iType) {
+            case stmt.VALUE_TYPE_NULL: 
+              rowdata.push('');
+              break;
+            case stmt.VALUE_TYPE_INTEGER:
+              rowdata.push(stmt.getInt64(i));
+              break;
+            case stmt.VALUE_TYPE_FLOAT:
+              rowdata.push(stmt.getDouble(i));
+              break;
+            case stmt.VALUE_TYPE_TEXT:
+              rowdata.push(stmt.getString(i));
+              break;
+            default: sData = "<unknown>"; 
+          }
+          r = r+1;
+        }
+        xdata.sqldata.push(rowdata);
+        
+        r = r+1;
+      }
+      xdata.sqlhead = this.aColumns;
+    } catch (e) {
+      stmt.finalize();
+      //dump("Query 2: " + sQuery + " - executeStep failed");
+      return false;
+    }
+    stmt.finalize();
+    return xdata;
+  },
+  strreplace: function(mytext){
+    mytext = mytext.toString().replace("'","''",'g');
+    return mytext;
+  },
+  generate_uuid: function(){
+    var uuidGenerator = Components.classes["@mozilla.org/uuid-generator;1"]
+                    .getService(Components.interfaces.nsIUUIDGenerator);
+    var uuid = uuidGenerator.generateUUID();
+    var xuuid = uuid.toString();
+    xuuid = xuuid.replace('}','');
+    xuuid = xuuid.replace('{','');
+    return xuuid;
+  },
+  getdatabases: function(){
+    var childnames = apppref.branch.getChildList("",{});
+    var curdbfiles = new Array();
+    for (var i in childnames){
+      if ((childnames[i].substring(0,16) == 'support.database')  && (childnames[i].indexOf("currentdb") == -1) && (childnames[i].indexOf("currentsite") == -1)) {
+        var sitecfg = JSON.parse(apppref.getpreference(childnames[i]));
+        curdbfiles.push(sitecfg.path.local + system.sep() + sitecfg.uuid + ".sqlite");
+      }
+    }
+    return curdbfiles;
+  },
+  getaccessibledatabases: function(){
+           var childnames = apppref.branch.getChildList("",{});
+           var curdbfiles = {};
+           for (var i in childnames){
+             if ((childnames[i].substring(0,16) == 'support.database')  && (childnames[i].indexOf("currentdb") == -1) && (childnames[i].indexOf("currentsite") == -1)) {
+               var sitecfg = JSON.parse(apppref.getpreference(childnames[i]));
+               if (system.fileexists(sitecfg.path.local + system.sep() + sitecfg.uuid + ".sqlite")){
+
+                       curdbfiles[sitecfg.dbnum] = sitecfg;
+               }
+               
+             }
+           }
+           return curdbfiles;
+         },
+
+  check_schema: function(dbid){
+    //alert("TEST");
+    var dbconf = apppref.getpreference("support.database." + dbid);
+    var sitecfg = JSON.parse(dbconf);
+    var dbpath = sitecfg.path.local + system.sep() + sitecfg.uuid + ".sqlite";
+    var defdb = system.appdir() + system.sep() + 'defaults'+ system.sep() + 'profile' + system.sep() + 'creorga.sqlite';
+
+    // var dbfiles = appdb.getdatabases();
+    //alert(JSON.stringify(sitecfg));
+    // for (var cdb in dbfiles){
+       if (system.fileexists(dbpath)){
+               
+               var args = ["-db",dbpath,"-t",defdb];
+                 
+               var bincheck = system.toolsdir() + system.sep() + "creorgadb.exe";
+               if (system.os != "WINNT") {
+                 bincheck = system.toolsdir() + system.sep() + "creorgadb";
+               }
+               system.runcmdline(bincheck,args,null);
+
+       }
+    // }
+    // OS.File.remove(system.profilerootdir() + system.sep() + '/checkschema.txt',{ignoreAbsent:true});
+
+  }//,
+
+}
+
+// var sync = {
+//             //TODO: dynamic url and dynamic (curcfg) schema -> ident
+               
+//             //url: "http://localhost:6060/localsyncup",
+//             up: function(ddlquery){
+//                     //dump("dbfile" +  + "\n");
+//                     /*var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
+//                     request.onload = function(aEvent) {
+//                               //dump("Response Text: " + aEvent.target.responseText + "\n");
+//                             };
+//                     request.onerror = function(aEvent) {
+//                             //dump("Error Msg:" + aEvent.target.responseText + "\n");
+//                             //dump("Error Status: " + aEvent.target.status + "\n");
+//                     };
+//                     request.open("POST", sync.url, true);
+//                     request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");*/
+//                     var cts = new Date();
+//                     var milli = cts.getMilliseconds();
+//                     if (milli < 10){
+//                             milli = "00" + milli;
+//                     } else if (milli < 100){
+//                             milli = "0" + milli;
+//                     } 
+//                     var dbident = system.getFileName(appdb.dbFile.path).replace(/\.sqlite/,'');
+//                 dump("SQL;;"+ cts.toLocaleFormat('%Y%m%d%H%M%S')+ milli +";;" + dbident +";;"+ddlquery+ "\n");
+//                     //request.send("ts="+ cts.toLocaleFormat('%Y-%m-%d %H:%M:%S') +"&q=" +encodeURIComponent(ddlquery)+ "&ident="+dbident+"&rh="+ system.hostname());
+//             }
+// }
diff --git a/js/old/encrypt.js b/js/old/encrypt.js
new file mode 100644 (file)
index 0000000..37ab16b
--- /dev/null
@@ -0,0 +1,200 @@
+var MD5 = function (string) {
+
+   function RotateLeft(lValue, iShiftBits) {
+           return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
+   }
+
+   function AddUnsigned(lX,lY) {
+           var lX4,lY4,lX8,lY8,lResult;
+           lX8 = (lX & 0x80000000);
+           lY8 = (lY & 0x80000000);
+           lX4 = (lX & 0x40000000);
+           lY4 = (lY & 0x40000000);
+           lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
+           if (lX4 & lY4) {
+                   return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+           }
+           if (lX4 | lY4) {
+                   if (lResult & 0x40000000) {
+                           return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+                   } else {
+                           return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+                   }
+           } else {
+                   return (lResult ^ lX8 ^ lY8);
+           }
+   }
+
+   function F(x,y,z) { return (x & y) | ((~x) & z); }
+   function G(x,y,z) { return (x & z) | (y & (~z)); }
+   function H(x,y,z) { return (x ^ y ^ z); }
+   function I(x,y,z) { return (y ^ (x | (~z))); }
+
+   function FF(a,b,c,d,x,s,ac) {
+           a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
+           return AddUnsigned(RotateLeft(a, s), b);
+   };
+
+   function GG(a,b,c,d,x,s,ac) {
+           a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
+           return AddUnsigned(RotateLeft(a, s), b);
+   };
+
+   function HH(a,b,c,d,x,s,ac) {
+           a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
+           return AddUnsigned(RotateLeft(a, s), b);
+   };
+
+   function II(a,b,c,d,x,s,ac) {
+           a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
+           return AddUnsigned(RotateLeft(a, s), b);
+   };
+
+   function ConvertToWordArray(string) {
+           var lWordCount;
+           var lMessageLength = string.length;
+           var lNumberOfWords_temp1=lMessageLength + 8;
+           var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
+           var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
+           var lWordArray=Array(lNumberOfWords-1);
+           var lBytePosition = 0;
+           var lByteCount = 0;
+           while ( lByteCount < lMessageLength ) {
+                   lWordCount = (lByteCount-(lByteCount % 4))/4;
+                   lBytePosition = (lByteCount % 4)*8;
+                   lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
+                   lByteCount++;
+           }
+           lWordCount = (lByteCount-(lByteCount % 4))/4;
+           lBytePosition = (lByteCount % 4)*8;
+           lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
+           lWordArray[lNumberOfWords-2] = lMessageLength<<3;
+           lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
+           return lWordArray;
+   };
+
+   function WordToHex(lValue) {
+           var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
+           for (lCount = 0;lCount<=3;lCount++) {
+                   lByte = (lValue>>>(lCount*8)) & 255;
+                   WordToHexValue_temp = "0" + lByte.toString(16);
+                   WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
+           }
+           return WordToHexValue;
+   };
+
+   function Utf8Encode(string) {
+           string = string.replace(/\r\n/g,"\n");
+           var utftext = "";
+
+           for (var n = 0; n < string.length; n++) {
+
+                   var c = string.charCodeAt(n);
+
+                   if (c < 128) {
+                           utftext += String.fromCharCode(c);
+                   }
+                   else if((c > 127) && (c < 2048)) {
+                           utftext += String.fromCharCode((c >> 6) | 192);
+                           utftext += String.fromCharCode((c & 63) | 128);
+                   }
+                   else {
+                           utftext += String.fromCharCode((c >> 12) | 224);
+                           utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+                           utftext += String.fromCharCode((c & 63) | 128);
+                   }
+
+           }
+
+           return utftext;
+   };
+
+   var x=Array();
+   var k,AA,BB,CC,DD,a,b,c,d;
+   var S11=7, S12=12, S13=17, S14=22;
+   var S21=5, S22=9 , S23=14, S24=20;
+   var S31=4, S32=11, S33=16, S34=23;
+   var S41=6, S42=10, S43=15, S44=21;
+
+   string = Utf8Encode(string);
+
+   x = ConvertToWordArray(string);
+
+   a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
+
+   for (k=0;k<x.length;k+=16) {
+           AA=a; BB=b; CC=c; DD=d;
+           a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
+           d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
+           c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
+           b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
+           a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
+           d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
+           c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
+           b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
+           a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
+           d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
+           c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
+           b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
+           a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
+           d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
+           c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
+           b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
+           a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
+           d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
+           c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
+           b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
+           a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
+           d=GG(d,a,b,c,x[k+10],S22,0x2441453);
+           c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
+           b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
+           a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
+           d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
+           c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
+           b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
+           a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
+           d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
+           c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
+           b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
+           a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
+           d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
+           c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
+           b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
+           a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
+           d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
+           c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
+           b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
+           a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
+           d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
+           c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
+           b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
+           a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
+           d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
+           c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
+           b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
+           a=II(a,b,c,d,x[k+0], S41,0xF4292244);
+           d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
+           c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
+           b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
+           a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
+           d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
+           c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
+           b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
+           a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
+           d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
+           c=II(c,d,a,b,x[k+6], S43,0xA3014314);
+           b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
+           a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
+           d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
+           c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
+           b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
+           a=AddUnsigned(a,AA);
+           b=AddUnsigned(b,BB);
+           c=AddUnsigned(c,CC);
+           d=AddUnsigned(d,DD);
+               }
+
+       var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
+
+       return temp.toLowerCase();
+}
\ No newline at end of file
diff --git a/js/old/init.js b/js/old/init.js
new file mode 100644 (file)
index 0000000..d9be102
--- /dev/null
@@ -0,0 +1,59 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+var loadtimeout = apppref.getpreference("support.loadtimeout");
+Components.utils["import"]("resource://gre/modules/osfile.jsm");
+var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
+                 .getService(Components.interfaces.nsIXULRuntime);
+xulRuntime.invalidateCachesOnRestart();
+var todaydate = new Date();
+//var lic = apppref.getpreference("support.license");
+//var expiration = apppref.getpreference("support.expiration");
+var today = new Date();
+
+// var licmatch = /(\w{4,})\-(\w{4,})\-(\w{4,})\-(\w{4,})\-(\w{4,})/;
+// var test = today.toLocaleFormat("%Y-%m-%d");
+// if ((expiration) && (test > expiration)){
+//     //dump("License expired\n");
+//     navigation.load_deck(1);
+// } else 
+if (!apppref.getpreference("support.database.currentdb.num")) {
+       
+  navigation.load_deck(1);
+  //dump("No Database configuration\n");
+} 
+// else if ( !lic || !expiration ||  !lic.match(licmatch)){
+//     //dump("no License Key\n");
+//     navigation.load_deck(1);
+// }
+else {
+       // if (system.fileexists(system.profilerootdir() + "/checkschema.txt")){
+       //      appdb.check_schema();
+       // }
+  if (system.fileexists(system.profilerootdir() + "/vpncfg.txt")){
+               //dump("current loadtimeout:" + loadtimeout + "\n");
+         if (system.os == "WINNT") {
+                 
+                 system.runcmdline(system.toolsdir() + system.sep() + "ovpn.exe",["--connect"],function(data){
+                 system.popup("Info","démarrage VPN!\n");
+               });
+         }
+               var r = system.loadconfig(loadtimeout);
+               if (r === false){
+                       var nx = { "view":"multisite","module":"support","header":"Configuration Sites"};
+                   apppref.setpreference("pageconfig.lastpage", nx);
+
+               }
+  } else {
+         var r = curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+         if (r === false){
+
+                   var nx = { "view":"multisite","module":"support","header":"Configuration Sites"};
+                   apppref.setpreference("pageconfig.lastpage", nx);
+
+         }
+         //license.checklicense(lic,license.setactiveview);
+         navigation.load_deck(2);
+  }
+
+}
+
+
diff --git a/js/old/license.js b/js/old/license.js
new file mode 100644 (file)
index 0000000..74810c1
--- /dev/null
@@ -0,0 +1,142 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+Components.utils["import"]("resource://gre/modules/NetUtil.jsm");
+Components.utils["import"]("resource://gre/modules/FileUtils.jsm");
+
+var license = {
+       url: "https://www.dks.lu/creorga/license.cgi",
+       activate:  function(){
+      document.getElementById("licerror").setAttribute("hidden",true);
+      var reglid = /(\w{4,})\-(\w{4,})\-(\w{4,})\-(\w{4,})\-(\w{4,})/;
+      var licensekey = document.getElementById("txtlicensekey").value;
+      if (!licensekey.match(reglid)){
+         document.getElementById("licerror").value="License pas valide!";
+         document.getElementById("licerror").setAttribute("hidden",false);
+        return;
+      }
+      
+      //verify licensse
+      this.checklicense(licensekey,this.setactiveview);
+      
+//      
+//      if (!chkcrpart){
+//        var cruuid = appdb.generate_uuid();
+//        var dbname = system.profiledir() + system.sep() + cruuid +".sqlite"; 
+//     var dbclone = system.appdir() + system.sep() +"defaults"+system.sep()+"profile"+system.sep()+"creorga.sqlite";
+//     OS.File.copy(dbclone, dbname);
+        
+    },
+    
+    setcreche: function(){
+      var chk = document.getElementById("chk_setcreche").checked;
+      //"Is checked" + chk + "\n");
+      if (chk === true){
+        document.getElementById("vbox_liccreche").style.removeProperty("display");
+      } else {
+        document.getElementById("vbox_liccreche").style.setProperty("display","none");
+      }
+    },
+//    browsecreche(lastdir,wmsg){
+//     var nsIFilePicker = Components.interfaces.nsIFilePicker;
+//        var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+//        fp.init(window, wmsg, nsIFilePicker.modeOpen);
+//        fp.appendFilter("Database Files", "*.sqlite");
+//        var selfile = null;
+//        if  ((lastdir) && (lastdir != '')) {
+//     var nsILocalFile= Components.interfaces.nsILocalFile;
+//     var f = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+//     f.initWithPath(lastdir);
+//     fp.displayDirectory = f;
+//        }
+//        var res = fp.show();
+//        if (res != nsIFilePicker.returnCancel) {
+//       selfile = fp.file;
+//        }
+//        return selfile;
+//    },
+    checklicense: function(lickey,callback){
+       var data = null;
+       
+        var appinfo = system.b64EncodeUnicode(JSON.stringify(system.appinfo()));
+        //dump(this.url + '?lic=' + lickey + ';appinfo=' + appinfo +"\n !!!!!\n");
+        NetUtil.asyncFetch(this.url + '?lic=' + lickey + ';appinfo=' + appinfo, function(inputStream, status) {
+          
+          if (!Components.isSuccessCode(status)) {
+               document.getElementById("licerror").value="Impossible de verifier la license!";
+                       document.getElementById("licerror").setAttribute("hidden",false);
+                       document.getElementById("apploadmsg").value="Serveur de DKS pas accessible! Contacter le support!";
+          } else {
+            var strdata = NetUtil.readInputStreamToString(inputStream, inputStream.available());
+           
+            //dump("Data returned:" + strdata + "\n");
+            try {
+               data = JSON.parse(strdata);
+            } catch(e){
+               document.getElementById("apploadmsg").value="Impossible de valider la license! Connection internet requis!";
+//             var expiration = apppref.getpreference("support.expiration");
+//             var today = new Date();
+//             var test = today.toLocaleFormat("%Y-%m-%d");
+//             var reglid = /(\w{4,})\-(\w{4,})\-(\w{4,})\-(\w{4,})\-(\w{4,})/;
+//             if (lickey.match(reglid) != "" && (expiration) && (test <= expiration)){
+//                     navigation.load_deck(2);
+//             }
+               //dump(e.message);
+               return data;
+            }
+            
+            if (callback != null){
+               callback(data)
+            }
+//            if (data.valid) && (data.valid == 1) {
+//              //apppref.setpreference("support.license",data.license);
+//              //apppref.setpreference("support.expiration",data.expiration);
+//              navigation.load_deck(2);
+//            }else {
+//               document.getElementById("licerror").value="license pas valide!";
+//               document.getElementById("licerror").setAttribute("hidden",false);
+//            }
+            
+          }
+        });
+        return data;
+    },
+    setactiveview: function(ldata){
+       //dump("Data returned:" + JSON.stringify(ldata) + "\n");
+       //dump("database returned:" + this.dbname + "\n");
+               if ((ldata.valid) && (ldata.valid == 1)) {
+                       apppref.setpreference("support.license",ldata.license);
+                       apppref.setpreference("support.expiration",ldata.expiration);
+                       //dump("Clone Database!\n");
+                       if (!apppref.getpreference("support.database.currentdb.db")){
+                               var cruuid = appdb.generate_uuid();
+                         var dbname = system.profiledir() + system.sep() + cruuid +".sqlite"; 
+                         var dbclone = system.appdir() + system.sep() +"defaults"+system.sep()+"profile"+system.sep()+"creorga.sqlite";
+                         //dump("DB to clone: " + dbclone);
+                         OS.File.copy(dbclone, dbname);
+                               apppref.setpreference("support.database.currentdb.num", 1);
+                               apppref.setpreference("support.database.currentdb.db",dbname);
+                               appdb.dbFile=FileUtils.File(apppref.getpreference("support.database.currentdb.db"));
+                               var nb = {name:'Crèche',uuid:cruuid,dbnum:1,path:{local:system.profiledir(),remote:null},lastsync:null};
+                               //dump("Database set:" + JSON.stringify(nb) + "\n");
+                               apppref.setpreference("support.database.1", nb);
+                               curcfg.loadconfig(1);
+                               //dump(appdb.dbFile.path + "\n");
+                               appdb.openDatabase();
+                               apppref.setpreference("pageconfig.creche",{"activetab":"groups"});
+                               
+                           navigation.load_appview("creche",null,null,"Crèche");
+                       }
+                       system.setappdata();  
+                       navigation.load_deck(2);
+                       //document.getElementById("deckglobal").selectedIndex=2;
+               }else {
+         document.getElementById("licerror").value="license pas valide!";
+         document.getElementById("licerror").setAttribute("hidden",false);
+               }
+               return;
+
+  
+       
+       }
+
+}
\ No newline at end of file
diff --git a/js/old/navigation.js b/js/old/navigation.js
new file mode 100644 (file)
index 0000000..c583d0c
--- /dev/null
@@ -0,0 +1,61 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+var navigation =
+{
+  print_disabled: ['home','creche','backup','multisite','forms','update'],
+  lastpanelid: null,
+  load_panel: function(panelname){
+    var idxpanel=-1;
+    var chn = document.getElementById("views").childNodes;
+    for (var i=0;i<chn.length; i++){
+      if (chn[i].getAttribute("id") == panelname) {
+        idxpanel = i;
+        break;
+      }
+    }
+    document.getElementById("views").selectedIndex = idxpanel;
+    this.lastpanelid = panelname;
+    return true;
+  },
+  update_dbname: function(dbname){
+      if (!dbname){
+         dbname = "";
+      }
+    document.getElementById("curcreche").value=dbname;
+  },
+  set_infoheader: function(infoheader){
+    document.getElementById("infoheader").value=infoheader;
+  },
+  load_appview: function(viewname,module,data,header){
+    if (header) {
+      document.getElementById("curpage").value=header;
+    }else {
+      document.getElementById("curpage").value='';
+    }
+    if (data) {
+      apppref.setpreference("pageconfig." + viewname,data);
+    }
+    var lpage = {view:viewname,module:module,header:header};
+    apppref.setpreference("pageconfig.lastpage",lpage);
+    if (this.lastpanelid != 'vw_application') {
+      this.load_panel('vw_application');
+    }
+    if (navigation.print_disabled.indexOf(viewname) >= 0) {
+      document.getElementById("tbb_print").setAttribute("disabled",true);
+    }else {
+      document.getElementById("tbb_print").removeAttribute("disabled");
+    }
+    var url = "chrome://creorga/content/web/"+viewname+".html";
+    if (module) {
+      url = "chrome://creorga/content/modules/"+module+"/"+viewname+".html";
+    }
+    document.getElementById("brw_application").loadURI(url,null,"UTF-8");
+  },
+  load_deck: function(num){
+    if (document.getElementById("deckglobal")){
+      document.getElementById("deckglobal").selectedIndex = num;
+    }else {
+      setTimeout(function(){ navigation.load_deck(num); }, 3000);
+    }
+  }
+}
diff --git a/js/old/preferences.js b/js/old/preferences.js
new file mode 100644 (file)
index 0000000..b0b9e40
--- /dev/null
@@ -0,0 +1,168 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+var curcfg = {
+  name: null,
+  uuid: null,
+  dbnum: null,
+  path: {local:null,remote:null},
+  dbfile: {local:null,remote:null},
+  lastsync:{},
+  local:{importpath:null,reportpath:null},
+  remote:{importpath:null,reportpath:null},
+  
+  loadconfig: function(num){
+    if (!num) {
+      num = 1;
+    }
+    var tcfg = JSON.parse(apppref.getpreference("support.database." + num));
+    curcfg.name = tcfg.name;
+    curcfg.path.local = tcfg.path.local;
+    curcfg.uuid = tcfg.uuid;
+    curcfg.dbnum = tcfg.dbnum;
+    curcfg.dbfile.local = curcfg.path.local + system.sep() + curcfg.uuid + ".sqlite";
+    if (!system.fileexists(curcfg.dbfile.local)){
+      return false;
+    }
+    apppref.setpreference("support.database.currentdb.db",curcfg.dbfile.local);
+       if (system.fileexists(system.profilerootdir() + system.sep() + "sync.conf")){
+               curcfg.sync = true;
+               var syncdir = FileUtils.File(system.profilerootdir() + system.sep() + 'syncup');
+               if (!system.fileexists(syncdir.path)){
+                       syncdir.create(1,0755);
+               }
+               var syncdirdb = FileUtils.File(system.profilerootdir() + system.sep() + 'syncup' + system.sep() + curcfg.uuid);
+               if (!system.fileexists(syncdirdb.path)){
+                       syncdirdb.create(1,0755);
+               }
+               var syncdirdb2 = FileUtils.File(system.profilerootdir() + system.sep() + 'syncdown' + system.sep() + curcfg.uuid);
+               if (!system.fileexists(syncdirdb2.path)){
+                       syncdirdb2.create(1,0755);
+               }
+               var todaydate = new Date();
+               var milli = todaydate.getMilliseconds();
+               if (milli < 10){
+                       milli = "00" + milli;
+               } else if (milli < 100){
+                       milli = "0" + milli;
+               } 
+               apppref.setbrowserpreference("dom.window.dump.file", syncdirdb.path + system.sep() + system.hostname()+ "_" + todaydate.toLocaleFormat('%Y%m%d%H%M%S') + milli +".log");
+    }
+    appdb.dbFile=FileUtils.File(curcfg.dbfile.local);
+    curcfg.local.importpath = curcfg.path.local + system.sep() + 'imports' +  system.sep() + curcfg.uuid;
+    curcfg.local.reportpath = curcfg.path.local + system.sep() + 'reports' +  system.sep() + curcfg.uuid;
+    curcfg.lastsync = null;
+    if (tcfg.path.remote) {
+      curcfg.path.remote = tcfg.path.remote;
+      curcfg.dbfile.remote = curcfg.path.remote + system.sep() + curcfg.uuid + ".sqlite";
+      curcfg.remote.importpath = curcfg.path.remote + system.sep() + 'imports' + system.sep() + curcfg.uuid;
+      curcfg.remote.reportpath = curcfg.path.remote + system.sep() + 'reports' + system.sep() +curcfg.uuid;
+      curcfg.lastsync = tcfg.lastsync;
+    }
+    
+    return true;
+  },
+  addsite: function(name,siteclone){
+    if (!siteclone) {
+      var cfg = {name:"Nouvelle Crèche",uuid:appdb.generate_uuid(),dbnum:1,ldbpath:curcfg.dbfile,rdbpath:curcfg.rdbfile,lastsync:curcfg.lastsync};
+      apppref.setpreference("support.database." + curcfg.dbnum,cfg);  
+    } else {
+      //TODO: 
+    }
+    
+  },
+  saveconfig: function(data){
+    if (data) {
+      apppref.setpreference("support.database." + data.dbnum,data);
+    }else{
+      var cfg = {name:curcfg.name,uuid:curcfg.uuid,dbnum:curcfg.dbnum,path:{local:curcfg.path.local,remote:curcfg.path.remote},lastsync:curcfg.lastsync};
+      apppref.setpreference("support.database." + curcfg.dbnum,cfg);  
+    }
+  },
+  updateconfigs: function(){
+    var childnames = apppref.branch.getChildList("",{});
+    for (var i in childnames){
+      var re = /support.database_\d+.db/;
+      if (childnames[i].match(re)) {
+        var num = childnames[i].substring(childnames[i].indexOf('_')+1).replace(/.db/,'').replace(/.name/,'');
+        var appx = apppref.getpreference("support.database." + num);
+        
+        if (!appx) {
+          var nobj = {name:null,uuid:null,dbnum:null,path:{local:null,remote:null},lastsync:null};
+          nobj.name = apppref.getpreference('support.database_'+num+'.name');
+          nobj.dbnum = num;
+          nobj.path.local = system.getDirectory(apppref.getpreference('support.database_'+num+'.db'));
+          appdb.closeConnection();
+          appdb.dbFile = FileUtils.File(apppref.getpreference('support.database_'+num+'.db'));
+          var cuuid = appdb.dbquery("select uuid from creche LIMIT 1;");
+          nobj.uuid = cuuid.sqldata[0].uuid;
+          var cfname = system.getFileName(appdb.dbFile.path);
+          if (cfname != nobj.uuid + ".sqlite") {
+            appdb.closeConnection();
+            if (cfname == 'creorga.sqlite') {
+              system.renamefile(appdb.dbFile.path,nobj.path.local,nobj.uuid + ".sqlite");
+            }else{
+              system.renamefile(appdb.dbFile.path,nobj.path.local,nobj.uuid + ".sqlite");
+            }
+          }
+
+          curcfg.saveconfig(nobj);
+          apppref.deletepreference('support.database_'+num+'.name');
+          apppref.deletepreference('support.database_'+num+'.db');
+          
+        }
+      }
+    }
+    appdb.closeConnection();
+    appdb.dbFile = null;
+  }
+}
+
+var apppref = {
+  branch: Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("creorga."),
+  browser: Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("browser."),
+  getpreference: function(keyname){
+    //dump(keyname + "\n");
+    var ptype = this.branch.getPrefType(keyname);
+    var keyvalue = null;
+    if (ptype == 32) {
+      keyvalue = this.branch.getCharPref(keyname);
+    } else if (ptype == 64) {
+      keyvalue = this.branch.getIntPref(keyname);
+    } else if (ptype == 128) {
+      keyvalue = this.branch.getBoolPref(keyname);
+    }
+    return keyvalue; 
+  },
+  setpreference: function(keyname,keyvalue){
+    if (typeof keyvalue == "string") {
+      this.branch.setCharPref(keyname,keyvalue);
+    } else if (typeof keyvalue == "number") {
+      this.branch.setIntPref(keyname,keyvalue);
+    } else if (typeof keyvalue == "boolean") {
+      this.branch.setBoolPref(keyname,keyvalue);
+    } else {
+      this.branch.setCharPref(keyname,JSON.stringify(keyvalue));
+    }
+    
+  },
+  setbrowserpreference: function(keyname,keyvalue){
+           //if (typeof keyvalue == "string") {
+             this.browser.setCharPref(keyname,keyvalue);
+           /*} else if (typeof keyvalue == "number") {
+             this.branch.setIntPref(keyname,keyvalue);
+           } else if (typeof keyvalue == "boolean") {
+             this.branch.setBoolPref(keyname,keyvalue);
+           } else {
+             this.branch.setCharPref(keyname,JSON.stringify(keyvalue));
+           }*/
+           
+         },
+  deletepreference: function(keyname){
+               this.branch.clearUserPref(keyname);
+       },
+       savepreferences: function(){
+               var prefService = Components.classes["@mozilla.org/preferences-service;1"]
+                               .getService(Components.interfaces.nsIPrefService);
+               prefService.savePrefFile(null);
+       }
+}
diff --git a/js/old/sync.js b/js/old/sync.js
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/js/old/system.js b/js/old/system.js
new file mode 100644 (file)
index 0000000..8a29924
--- /dev/null
@@ -0,0 +1,421 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+ function jsdump(str) {
+   Components.classes['@mozilla.org/consoleservice;1']
+             .getService(Components.interfaces.nsIConsoleService)
+             .logStringMessage(str);
+ }
+
+Components.utils["import"]("resource://gre/modules/FileUtils.jsm");
+Components.utils["import"]("resource://gre/modules/Services.jsm");
+Components.utils["import"]("resource://gre/modules/NetUtil.jsm");
+Components.utils["import"]("resource://gre/modules/osfile.jsm");
+Components.utils["import"]("resource://gre/modules/Downloads.jsm");
+var system = {
+  os: Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS,
+  sep: function() {
+    if (this.os == 'WINNT') {
+      return '\\';
+    } else {
+      return "/";
+    }
+  },
+  appdir: function() {
+    var mypath = Components.classes["@mozilla.org/file/directory_service;1"].
+    getService(Components.interfaces.nsIProperties).
+    get("CurProcD", Components.interfaces.nsIFile).path;
+
+
+    return mypath;
+  },
+  tmpdir: function(){
+    var mypath = Components.classes["@mozilla.org/file/directory_service;1"].
+    getService(Components.interfaces.nsIProperties).
+    get("TmpD", Components.interfaces.nsIFile).path;
+    return mypath;
+  },
+  homedir: function(){
+           var mypath = Components.classes["@mozilla.org/file/directory_service;1"].
+           getService(Components.interfaces.nsIProperties).
+           get("Home", Components.interfaces.nsIFile).path;
+           return mypath;
+  },
+  toolsdir: function() {
+    var mypath = Components.classes["@mozilla.org/file/directory_service;1"].
+    getService(Components.interfaces.nsIProperties).
+    get("CurProcD", Components.interfaces.nsIFile).path;
+
+  
+    return mypath + this.sep() + 'Tools';
+  },
+  commondir: function(){
+    if (this.os == 'WINNT') {
+      return "C:" + system.sep() + 'ProgramData' + system.sep() + 'Creorga';
+    } else {
+      return '/Library/Application Support/Creorga';
+    }
+  },
+  profiledir: function() {
+    var mypath = Components.classes["@mozilla.org/file/directory_service;1"].
+    getService(Components.interfaces.nsIProperties).
+    get("ProfD", Components.interfaces.nsIFile).path;
+    return mypath;
+  },
+  profilerootdir: function(){
+    var mypath = Components.classes["@mozilla.org/file/directory_service;1"].
+    getService(Components.interfaces.nsIProperties).
+    get("DefProfRt", Components.interfaces.nsIFile).path;
+    return mypath;
+    
+  },
+  getFileName: function (filePath) {
+    if (filePath.indexOf('http') == 0 ) {
+      return filePath.substring(filePath.lastIndexOf('/')+1);
+    }
+    else if (this.os == 'WINNT') { // windows
+      return filePath.substring(filePath.lastIndexOf('\\')+1);
+    } 
+    else { // unix
+      return filePath.substring(filePath.lastIndexOf('/')+1);
+    }
+  },
+  getDirectory: function(filePath){
+    if (this.os == 'WINNT') { // windows
+      return filePath.substring(0,filePath.lastIndexOf('\\'));
+    } 
+    else { // unix
+      return filePath.substring(0,filePath.lastIndexOf('/'));
+    }
+  },
+  
+  gotoUrl: function(url) {
+    var nsioservice = Components.classes["@mozilla.org/network/io-service;1"]
+      .getService(Components.interfaces.nsIIOService);
+
+    var uri = nsioservice.newURI(url, null, null);
+
+    var eps = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
+      .getService(Components.interfaces.nsIExternalProtocolService);
+
+    eps.loadURI(uri, null);
+  },
+  openFile: function(filepath) {
+    if (system.os == "WINNT") {
+      system.runcmdline(filepath,[],null);
+    } else {
+      system.runcmdline("/usr/bin/open",[filepath],null);
+    }
+  },
+  showdlgabout: function() {
+    window.openDialog('chrome://creorga/content/dlg/dlgabout.xul', 'dlgabout', 'chrome,modal,centerscreen,close=0');
+  },
+//  dlgupdate: function() {
+//    window.openDialog('chrome://creorga/content/modules/support/dlg/dlgupdate.xul', 'dlgupdate', 'chrome,modal,centerscreen');
+//  },
+  fileexists: function(filefrom) {
+    if (!filefrom) {
+      return false;
+    }
+    if (this.os == 'WINNT') {
+      filefrom = filefrom.replace('/', '\\');
+    }
+    var file = new FileUtils.File(filefrom);
+    if (file.exists()) {
+      file = null;
+      return true;
+    }
+    file=null;
+    return false;
+  },
+  renamefile: function(filefrom,pathto,fileto){
+    var file = new FileUtils.File(filefrom);
+    if (file.exists()) {
+      var dir = FileUtils.File(pathto);
+      file.renameTo(dir,fileto);
+    }
+    return true;
+  },
+  readLocalTextFile: function(aURL) {
+    var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+      .getService(Components.interfaces.nsIIOService);
+    var scriptableStream = Components
+      .classes["@mozilla.org/scriptableinputstream;1"]
+      .getService(Components.interfaces.nsIScriptableInputStream);
+
+    var channel = ioService.newChannel("file://" + aURL, null, null);
+    var input = channel.open();
+    scriptableStream.init(input);
+    var str = scriptableStream.read(input.available());
+    
+    scriptableStream.close();
+    input.close();
+    var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
+                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+    converter.charset = "UTF-8";
+    str = converter.ConvertToUnicode(str);
+    return str;
+  },
+  WriteTextFile: function(xdata, outfile) {
+        dump(outfile + "\n");
+    var nsifile   = new FileUtils.File( outfile );
+    var ostream = FileUtils.openSafeFileOutputStream(nsifile);
+    var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+    converter.charset = "UTF-8";
+    var istream = converter.convertToInputStream(xdata);
+    NetUtil.asyncCopy(istream, ostream,function(status) {
+    if (!Components.isSuccessCode(status)) {
+      // Handle error!
+      return;
+    }
+
+    });
+  },
+  WriteTextFile2: function(file,data){
+       dump(file.path);
+    OS.File.remove(file.path,{ignoreAbsent:true});
+    var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
+    foStream.init(file, 0x02 | 0x08 | 0x20, foStream.PR_IRWXU, 0); 
+    var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
+    converter.init(foStream, "UTF-8", 0, 0);
+    converter.writeString(data);
+    converter.close();
+  },
+  b64EncodeUnicode: function(str) {
+    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
+        return String.fromCharCode('0x' + p1);
+    }));
+  },
+  appinfo: function() {
+    var xulAppInfo = Components.classes["@mozilla.org/xre/app-info;1"]
+      .getService(Components.interfaces.nsIXULAppInfo);
+    var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
+      .getService(Components.interfaces.nsIXULRuntime);
+    var profileident = system.profiledir().substring(system.profilerootdir().length+1);
+    var appinfo = {
+      appBuildID: xulAppInfo.appBuildID,
+      ID: xulAppInfo.ID,
+      name: xulAppInfo.name,
+      platformBuildID: xulAppInfo.platformBuildID,
+      platformVersion: xulAppInfo.platformVersion,
+      vendor: xulAppInfo.vendor,
+      version: xulAppInfo.version,
+      OS: xulRuntime.OS,
+      profile: profileident
+    }
+    return appinfo;
+  },
+  hostname: function(){
+         var dnsComp = Components.classes["@mozilla.org/network/dns-service;1"]; 
+         var dnsSvc = dnsComp.getService(Components.interfaces.nsIDNSService);
+         var compName = dnsSvc.myHostName;
+         return compName;
+  },
+  setappdata: function() {
+    var appdata = this.appinfo();
+    //var lic = apppref.getpreference("support.license");
+    //var expiration = apppref.getpreference("support.expiration");
+    document.getElementById("stbversion").setAttribute('label', "Version " + appdata.version);
+    //dump(JSON.stringify(appdata) + "\n");
+    if (curcfg.name) {
+       document.getElementById("curcreche").value=curcfg.name;
+    } else {
+       document.getElementById("curcreche").value="";
+    }
+    
+  },
+  getBackups:function(){
+
+    var dir = new FileUtils.File(curcfg.path.local + system.sep() + 'backup');
+    var entries = dir.directoryEntries;
+    var array = [];
+    while(entries.hasMoreElements()) {
+      var entry = entries.getNext();
+      entry.QueryInterface(Components.interfaces.nsIFile);
+      if (entry.path.indexOf(curcfg.uuid) > 0){
+        array.push(entry);  
+      }
+    }
+    return array;
+  },
+  getReports:function(cruuid){
+
+    var dir =  new FileUtils.File(curcfg.path.local  + system.sep() + 'reports' + system.sep() +cruuid);
+    if (!system.fileexists(dir.path)){
+      dir.create(1,0755);
+    }
+    var entries = dir.directoryEntries;
+    var array = [];
+    while(entries.hasMoreElements()) {
+      var entry = entries.getNext();
+      entry.QueryInterface(Components.interfaces.nsIFile);
+         array.push(entry);
+    }
+    return array;
+  },
+  getOpenVPNConfig:function(){
+         //dump(system.homedir()  + system.sep() + 'OpenVPN' + system.sep() +'config'+ "\n");
+           var dir =  new FileUtils.File(system.homedir()  + system.sep() + 'OpenVPN' + system.sep() +'config');
+//         if (!system.fileexists(dir.path)){
+//           dir.create(1,0755);
+//         }
+           var entries = dir.directoryEntries;
+           var array = [];
+           while(entries.hasMoreElements()) {
+             var entry = entries.getNext();
+             entry.QueryInterface(Components.interfaces.nsIFile);
+                 if (entry.path.indexOf(".ovpn") != -1){
+                       var ovpn = system.getFileName(entry.path);
+                       array.push(ovpn.substring(0,ovpn.length - 5));
+                 }
+                 
+           }
+           return array;
+         },
+  getChildFiles:function(cruuid,chuuid){
+
+    var dir =  new FileUtils.File(curcfg.path.local  + system.sep() + 'childs' + system.sep() +cruuid + system.sep() + chuuid);
+    if (!system.fileexists(dir.path)){
+      dir.create(1,0755);
+    }
+    var entries = dir.directoryEntries;
+    var array = [];
+    while(entries.hasMoreElements()) {
+      var entry = entries.getNext();
+      entry.QueryInterface(Components.interfaces.nsIFile);
+      //dump("Push to Array:" + entry);
+      //if (!entry.path.startsWith('.')){
+         array.push(entry);
+      //}
+    }
+    return array;
+  },
+  getModtime: function(somePath){
+    var file = new FileUtils.File(somePath);
+    return new Date(file.lastModifiedTime).toLocaleFormat("%Y-%m-%d %H:%M:%S");
+  },
+  closecreorga: function(){
+    var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup);
+          appStartup.quit(Components.interfaces.nsIAppStartup.eForceQuit );
+  },
+  //restartapp: function(text) {
+  //
+  //    if (window.confirm(text + "\nRedémarrer maintenant?")){
+  //      var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup);
+  //      appStartup.quit(Components.interfaces.nsIAppStartup.eRestart | Components.interfaces.nsIAppStartup.eAttemptQuit);
+  //  }
+  //},
+  popup: function(title, msg) {
+  var image = null;
+  var win = Components.classes['@mozilla.org/embedcomp/window-watcher;1'].
+                      getService(Components.interfaces.nsIWindowWatcher).
+                      openWindow(null, 'chrome://global/content/alerts/alert.xul',
+                                  '_blank', 'chrome,titlebar=no,popup=yes', null);
+  win.arguments = [image, title, msg, false, ''];
+  return true;
+  },
+  runcmdline: function(cmdlapp,args,callback){
+    var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+    var process = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
+    //dump(cmdlapp + " "+ JSON.stringify(args) + "\n");
+    file.initWithPath(cmdlapp);
+    process.init(file);
+    //dump(cmdlapp + " "+ JSON.stringify(args) + "\n");
+    process.runwAsync( args, args.length,callback);
+    return true;
+  },
+  selectfile: function(lastdir,wmsg){
+      var nsIFilePicker = Components.interfaces.nsIFilePicker;
+      var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+      fp.init(window, wmsg, nsIFilePicker.modeOpen);
+      fp.appendFilter("Database Files", "*.sqlite");
+      var selfile = null;
+      if  ((lastdir) && (lastdir != '')) {
+       var nsILocalFile= Components.interfaces.nsILocalFile;
+       var f = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+       f.initWithPath(lastdir);
+       fp.displayDirectory = f;
+      }
+      var res = fp.show();
+      if (res != nsIFilePicker.returnCancel) {
+         selfile = fp.file;
+      }
+      return selfile;  
+  },
+  closeapp(){
+         if (system.fileexists(system.profilerootdir() + system.sep() + 'vpncfg.txt')){
+                 if (system.os == "Darwin" && system.fileexists(system.toolsdir() + system.sep() + "vpnclose.sh")){
+                         system.runcmdline("/bin/bash",[system.toolsdir() + system.sep() + "vpnclose.sh",system.profilerootdir() + system.sep() + 'vpncfg.txt']);
+                 } else {
+                         system.runcmdline(system.toolsdir() + system.sep() + "ovpn.exe",["--disconnect"],null);
+                 }
+         }
+         
+         
+  },
+  selectvpnfile: function(lastdir,wmsg){
+      var nsIFilePicker = Components.interfaces.nsIFilePicker;
+      var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+      fp.init(window, wmsg, nsIFilePicker.modeOpen);
+      fp.appendFilter("Private Key-File", "*.key");
+      var selfile = null;
+      if  ((lastdir) && (lastdir != '')) {
+       var nsILocalFile= Components.interfaces.nsILocalFile;
+       var f = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+       f.initWithPath(lastdir);
+       fp.displayDirectory = f;
+      }
+      var res = fp.show();
+      if (res != nsIFilePicker.returnCancel) {
+         selfile = fp.file;
+      }
+      return selfile;  
+  },
+  loadconfig:function(tout){
+         //dump("lc: timeout " + tout + "\n");
+         
+         if (tout <= 0){
+                 //dump("set site cfg sites!\n")
+                 var nx = { "view":"multisite","module":"support","header":"Configuration Sites"};
+                 apppref.setpreference("pageconfig.lastpage", nx);
+                 navigation.load_deck(2);
+                 return false;
+         }
+         tout = tout - 2000;
+         var r=curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+         if (r === false){
+                 
+                 setTimeout(function(){r = system.loadconfig(tout);},2000);
+         }else {
+                 setTimeout(function(){navigation.load_deck(2);},2000);
+         }
+         return r;
+  },
+  selectdirectory: function(lastdir,wmsg){
+    try {
+      //var lastdir = apppref.getpreference("support.lastfiledir");
+      var nsIFilePicker = Components.interfaces.nsIFilePicker;
+      var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+      fp.init(window, wmsg, nsIFilePicker.modeGetFolder);
+      //fp.appendFilter("PDF", "*.pdf");
+      if  ((lastdir) && (lastdir != '')) {
+        var nsILocalFile= Components.interfaces.nsILocalFile;
+        var f = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+        f.initWithPath(lastdir);
+        fp.displayDirectory = f;
+      }
+      var seldir = null;
+      var res = fp.show();
+      if (res != nsIFilePicker.returnCancel) {
+        seldir = fp.file;
+      } 
+    }catch(ex){
+      system.popup("Erreur d'selct dir!","Une erreur s'est produite!\n");
+      //"Error selecting folder! " + ex + "\n");
+    }
+    return seldir;
+  },
+  changelicense:function(){
+    navigation.load_deck(1);
+  }
+  
+}
\ No newline at end of file
diff --git a/js/old/tools.js b/js/old/tools.js
new file mode 100644 (file)
index 0000000..8309684
--- /dev/null
@@ -0,0 +1,189 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+Components.utils["import"]("resource://gre/modules/NetUtil.jsm");
+Components.utils["import"]("resource://gre/modules/FileUtils.jsm");
+var tools = {
+  waitdlg: null,
+  movecreche: function(oldfolder,newfolder,cuuid,dbnum){
+    //"Move Form: " + oldfolder + "\nTO: " + newfolder + "\nuuid:" + cuuid + "\ndbnum: " + dbnum + "\n");
+    try {
+        var repdir = new FileUtils.File(oldfolder + system.sep() + 'reports' + system.sep() + cuuid);
+        //"Reports: " + repdir.path + "\n");
+        var filearray = [];
+        var expdirarray = [];
+        expdirarray.push("reports");
+        expdirarray.push("reports" +  system.sep() + cuuid);
+        //get all reports
+        if (system.fileexists(repdir.path)){
+          
+        //for (var d in dirarray){
+        //dir = FileUtils.getDir("ProfD", ["reports",dirarray[d]], true);
+        
+          entries = repdir.directoryEntries;
+          //expdirarray.push("reports" + system.sep() + dirarray[d]);  
+            while(entries.hasMoreElements()) {
+              var entry = entries.getNext().QueryInterface(Components.interfaces.nsIFile);
+             
+              if (entry.isFile()) {
+                filearray.push(entry.path);
+              }
+            }
+        }
+        //}
+        //get all imports
+        var impdir = new FileUtils.File(oldfolder + system.sep() + 'imports' + system.sep() + cuuid);
+        //"Imports: " + impdir.path + "\n");
+        expdirarray.push("imports");
+        expdirarray.push("imports" +  system.sep() + cuuid);
+        if (system.fileexists(impdir.path)){
+        //for (var d in dirarray){
+        //  dir = FileUtils.getDir("ProfD", ["imports",dirarray[d]], true);
+          entries = impdir.directoryEntries;
+        //expdirarray.push("imports" + system.sep() + dirarray[d]);  
+          while(entries.hasMoreElements()) {
+            var entry = entries.getNext().QueryInterface(Components.interfaces.nsIFile);
+    
+              if (entry.isFile()) {
+                filearray.push(entry.path);
+              }
+            }
+        }
+        //create dirs in exportpath
+        var exportdir = new FileUtils.File(newfolder);
+        var fromdir = new FileUtils.File(oldfolder);
+        for (var ed in expdirarray){
+          var cexpdir = new FileUtils.File( exportdir.path + system.sep() + expdirarray[ed]);
+          //cexpdir.path + "\n");
+          if (!cexpdir.exists()) {
+            cexpdir.create(1,0755);
+          }
+          if (system.os != "WINNT") {
+            
+          }
+        }
+        //copy files
+        var filex= [];
+        //dump(JSON.stringify(filearray) + "\n");
+        for (var f in filearray){
+          var expfile = filearray[f];
+          //dump("EXP FILE: " + expfile + "\n");
+          var nfile = expfile.substring(fromdir.path.length);
+          //"n-file: " + nfile + "\n");
+          var fname = system.getFileName(nfile);
+          
+          var dname = exportdir.path +system.getDirectory(nfile);
+     
+          var ef =  new FileUtils.File(expfile);
+          var de = new FileUtils.File(dname);
+          //dump("from: "+ ef.path + " to folder: " + de.path  +" fname: " + fname + "\n");
+          ef.copyTo(de,fname);
+          //filex.push(nfile);
+        }
+        
+        var sqlfdb = FileUtils.File(fromdir.path + system.sep() + cuuid + ".sqlite");
+        if (system.fileexists(sqlfdb.path)){
+          //"Copy DB: " + sqlfdb.path + "\n");
+          sqlfdb.copyTo(exportdir,cuuid + ".sqlite");
+        }//var nzipfile = tools.backup(exportdir);
+        var strsitecfg = apppref.getpreference("support.database." + dbnum);
+        var jsitecfg = JSON.parse(strsitecfg);
+        jsitecfg.path.local=exportdir.path;
+        apppref.setpreference("support.database." + dbnum,jsitecfg);
+        if (curcfg.dbnum == dbnum){
+          
+          curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+        }
+        //
+        //
+        //var expdata = {"db":system.getFileName(nzipfile.path),"dir":expdirarray,"files":filex};
+        //
+        //expfname = system.getFileName(nzipfile.path);
+        //expfname = expfname.substring(0,expfname.length-3) + "def";
+        //system.WriteTextFile(JSON.stringify(expdata),exportdir.path + system.sep() + expfname);
+        system.popup("Export des données!","Les données ont Ã©té exportées vers "+ exportdir.path +"\n");
+    }catch(ex){
+      system.popup("Erreur d'Export!","L'export des données n'a pas completement fonctionné !\n");
+    }
+  },
+  readinvoicepdf: function(){
+           try {  
+             var lastdir = apppref.getpreference("support.lastfiledir");
+             var nsIFilePicker = Components.interfaces.nsIFilePicker;
+             var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+             fp.init(window, "selectionner fichier PDF", nsIFilePicker.modeOpen);
+             fp.appendFilter("PDF", "*.pdf");
+             if (lastdir != '') {
+               var nsILocalFile= Components.interfaces.nsILocalFile;
+               var f = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+               f.initWithPath(lastdir);
+               fp.displayDirectory = f;
+             }
+             var res = fp.show();
+             if (res != nsIFilePicker.returnCancel) {
+               var pdffile = fp.file;
+               apppref.setpreference("support.lastfiledir",system.getDirectory(pdffile.path));
+
+               var cname = appdb.dbquery("select uuid from creche LIMIT 1;");
+               cruuid = cname.sqldata[0].uuid;
+               var importpath = FileUtils.File(curcfg.path.local  + system.sep() +"imports" + system.sep() + cruuid);
+               var args = ["-db",'"' + appdb.dbFile.path + '"',"-p",'"' +pdffile.path + '"',"-o",'"' + importpath.path + '"',"-t",'"' + system.toolsdir() + '"',"-x","inv","-l", '"' + system.profiledir() + system.sep() + 'importerror.log"'];
+               
+               var binpdf = system.toolsdir() + system.sep() + "pdfextract.exe";
+               if (system.os != "WINNT") {
+                 binpdf = system.toolsdir() + system.sep() + "pdfextract";
+               }
+               //dump(binpdf + " " +JSON.stringify(args) + "\n");
+               system.popup("Import Factures!","Import du PDF '"+ pdffile.path +"' en cours!\n");
+               system.runcmdline(binpdf,args,function(data){
+                 var strx = apppref.getpreference("pageconfig.lastpage");
+                 var x = JSON.parse(strx);
+                 
+                 if (x.module == 'accounting') {
+                   navigation.load_appview(x.view,x.module,null,x.header);
+                 }
+                 system.popup("Import Factures!","Les factures ont Ã©té importées!\n");
+               });
+               
+             }
+           } catch(ex){
+             system.popup("Erreur d'import!","Une Erreur s'est produite pendant l'import des factures!\n");
+             //dump("Error importing invoice PDF! " + ex + "\n");
+           }
+         },
+         readbenefitstatement: function(){
+           try {
+             var lastdir = apppref.getpreference("support.lastfiledir");
+             var nsIFilePicker = Components.interfaces.nsIFilePicker;
+             var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+             fp.init(window, "selectionner fichier PDF", nsIFilePicker.modeOpen);
+             fp.appendFilter("PDF", "*.pdf");
+             if (lastdir != '') {
+               var nsILocalFile= Components.interfaces.nsILocalFile;
+               var f = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+               f.initWithPath(lastdir);
+               fp.displayDirectory = f;
+             }
+             var res = fp.show();
+             if (res != nsIFilePicker.returnCancel) {
+               var pdffile = fp.file;
+               apppref.setpreference("support.lastfiledir",system.getDirectory(pdffile.path));
+
+               var cname = appdb.dbquery("select uuid from creche LIMIT 1;");
+               cruuid = cname.sqldata[0].uuid;
+               var importpath = FileUtils.File(curcfg.path.local  + system.sep() +"imports" + system.sep() + cruuid);
+               var args = ["-db",'"' + appdb.dbFile.path + '"',"-p",'"' + pdffile.path + '"',"-o",'"' + importpath.path +'"',"-t",'"' +  system.toolsdir() + '"',"-x","stmt","-l",'"' + system.profiledir() + system.sep() + 'importerror.log"'];
+               var binpdf = system.toolsdir() + system.sep() + "pdfextract.exe";
+               if (system.os != "WINNT") {
+                 binpdf = system.toolsdir() + system.sep() + "pdfextract";
+               }
+               system.runcmdline(binpdf,args,function(data){
+                 system.popup("Import Prestations!","Les Prestations ont Ã©té importées!\n");
+               });
+             }
+           } catch(ex){
+             system.popup("Erreur d'import!","Une erreur s'est produite pendant l'import des prestations!\n");
+             //dump("Error importing statement PDF! " + ex + "\n");
+           }
+         }
+  
+};
diff --git a/js/preferences.js b/js/preferences.js
new file mode 100644 (file)
index 0000000..2823830
--- /dev/null
@@ -0,0 +1,144 @@
+// var globalreq = {
+//             send_request: function(data){
+
+//                     if (data.page){
+//                             if (data.data){
+//                                     console.log(window.location.pathname);
+//                                     var page = data.page.substring(data.page.lastIndexOf("/") + 1);
+//                                     page = page.replace(/\.html/,'');
+//                                     console.log(page);
+//                                     $.ajax({
+//                                             encoding:"UTF-8",
+//                                             url:'http://localhost:6060/app/preferences?page=' + page + '&set=' +encodeURIComponent('{"data":' + JSON.stringify(data.data) +'}') ,
+//                                             crossDomain: true,
+//                                             success: function (data){
+//                                                     var result=data.result;
+//                                             },
+//                                             error: function(data){
+//                                                     alert("Error:" + JSON.stringify(data));
+//                                                     console.log("Error:" + JSON.stringify(data));
+//                                             },
+//                                             async:false
+//                                     });
+//                             }
+
+//                             var path = "file://" +window.location.pathname.substring(0,window.location.pathname.indexOf('app') + 4); 
+//                             path = path + data.page + '?';
+//                             path += 'dbhosturl=' + apppref.curcfg.dbhosturl;
+//                             path += '&dbpath=' + apppref.curcfg.dbpath;
+//                             path += '&db=' + apppref.curcfg.db;
+//                             path += '&hostname=' + apppref.curcfg.hostname;
+//                             path += '&sitename=' + apppref.curcfg.sitename;
+//                             window.location = path;
+//                     }
+//             }
+// }
+
+// var mpref ={
+//             cfg: null,
+//             getSearchParams: function (k){
+//                     //alert(location.href);
+//                     var p={};
+//                     console.log("params =>" + location.search);
+//                     location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(s,k,v){p[k]=v});
+//                     return k?p[k]:p;
+//             },
+//             loadconfig: function(){
+//                     this.cfg = this.getSearchParams();
+//                     console.log(this.cfg);
+//                     //var page = location.pathname.substring(location.pathname.lastIndexOf("/"));
+//                     //page = page.replace(/\.html/,'');
+//                     //apppref.getpreference(page);
+//                     appdb.dbfile = this.cfg.dbfile; 
+//                     appdb.serviceurl = this.cfg.serviceurl;
+//                     //$("#current_site").html(decodeURI(this.curcfg.sitename));
+//             },
+//             // loadprintconfig: function(){
+//             //      this.curcfg = this.getSearchParams();
+                       
+//             //      var page = location.pathname.substring(location.pathname.lastIndexOf("/"));
+//             //      page = page.replace(/\.html/,'');
+//             //      page = page.replace(/report_/,'');
+//             //      console.log("current Config!");
+//             //      console.log(this.curcfg);
+//             //      apppref.getpreference(page);
+//             //      appdb.dbfile = ((this.curcfg.dbpath)?this.curcfg.dbpath + "/":"")  + this.curcfg.db;
+//             //      appdb.url = "http://localhost:6060/sqlite?";
+//             //      $("#current_site").html(decodeURI(this.curcfg.sitename));
+//             // },
+//             // setpreference:function(section,key,value){
+//             //      if (!apppref.curcfg.pageconfig[section]){
+//             //              apppref.curcfg.pageconfig[section] = {};
+//             //      }
+//             //      apppref.curcfg.pageconfig[section][key] = value;
+
+//             //      var page = location.pathname.substring(location.pathname.lastIndexOf("/"));
+//             //      page = page.replace(/\.html/,'');
+//             //      $.ajax({
+//             //              encoding:"UTF-8",
+//             //              url:'http://localhost:6060/app/preferences?page=' + page + '&set=' +encodeURIComponent(JSON.stringify(apppref.curcfg.pageconfig)) ,
+//             //              crossDomain: true,
+//             //              success: function (data){
+//             //                      var result=data.result;
+//             //              },
+//             //              error: function(data){
+//             //                      alert("Error:" + JSON.stringify(data));
+//             //                      console.log("Error:" + JSON.stringify(data));
+//             //              }
+//             //      });
+//             // },
+//             // getpreference: function(key){
+//             //      apppref.curcfg['pageconfig'] = {};
+//             //      $.ajax({
+//             //              encoding:"UTF-8",
+//             //              url:'http://localhost:6060/app/preferences?page=' + key ,
+//             //              crossDomain: true,
+//             //              success: function (data){
+//             //                      if (data.result){
+//             //                              apppref.curcfg.pageconfig = data.result;
+//             //                      }
+
+//             //              },
+//             //              error: function(data){
+//             //                      alert("Error:" + JSON.stringify(data));
+//             //                      console.log("Error:" + JSON.stringify(data));
+//             //              },
+//             //              async:false
+//             //      });
+
+//             // }, 
+//             // getforeignpreference: function(key){
+//             //      var ret = null;
+//             //      $.ajax({
+//             //              encoding:"UTF-8",
+//             //              url:'http://localhost:6060/app/preferences?page=' + key ,
+//             //              crossDomain: true,
+//             //              success: function (data){
+//             //                      if (data.result){
+//             //                              ret = data.result;
+//             //                      }
+
+//             //              },
+//             //              error: function(data){
+//             //                      alert("Error:" + JSON.stringify(data));
+//             //                      console.log("Error:" + JSON.stringify(data));
+//             //              },
+//             //              async:false
+//             //      });
+//             //      return ret
+//             // },
+//             // getCookie: function(cname) {
+//             //      var name = cname + "=";
+//             //      var ca = document.cookie.split(';');
+//             //      for(var i = 0; i < ca.length; i++) {
+//             //              var c = ca[i];
+//             //              while (c.charAt(0) == ' ') {
+//             //                      c = c.substring(1);
+//             //              }
+//             //              if (c.indexOf(name) == 0) {
+//             //                      return c.substring(name.length, c.length);
+//             //              }
+//             //      }
+//             //      return "";
+//             // }
+// }
diff --git a/js/webdatabase.js b/js/webdatabase.js
new file mode 100644 (file)
index 0000000..4dfc7bc
--- /dev/null
@@ -0,0 +1,80 @@
+var appdb = {
+               dbfile: null,
+               url: null,
+               dbquery: function(sQuery){
+                       var type='querysorted';
+                       var result= {sqldata:[]};
+                       //console.log(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery));
+                       //dump(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) + "\n");
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:this.url + '&db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) ,
+                               crossDomain: true,
+                               success: function (data){
+                                       //dump(data + "\n");
+                                               result=data.result;
+                                       },
+                                       error: function(data){
+                                               alert("Error:" + JSON.stringify(data));
+                                               console.log("Error:" + JSON.stringify(data));
+                                       },
+                               async:false
+                       });
+                       return result;
+               },
+               dbqueryarray: function(sQuery){
+                       var type='queryarray';
+                       var result= {sqldata:[]};
+                       //console.log(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery));
+                       //alert(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) + "\n");
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:this.url + '&db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) ,
+                               crossDomain: true,
+                               success: function (data){
+                                               result=data.result;
+                                       },
+                               error: function(data){
+                                       alert("Error:" + JSON.stringify(data));
+                                       console.log("Error:" + JSON.stringify(data));
+                               },
+                               async:false
+                       });
+                       return result;
+               },
+               dbexec: function(sQuery){
+                       var type='exec';
+                       var result= {sqldata:[]};
+                       //dump(this.url + 'db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) + "\n");
+                       console.log(this.url + '&db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) );
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:this.url + '&db=' + this.dbfile + '&type=' + type + '&sql=' +encodeURIComponent(sQuery) ,
+                               crossDomain: true,
+                               success: function (data){
+                                               result=data.result;
+                                       },
+                                       error: function(data){
+                                               alert("Error:" + JSON.stringify(data));
+                                               console.log("Error:" + JSON.stringify(data));
+                                       },
+                               async:false
+                       });
+                       return result;
+               },
+//             b64EncodeUnicode: function (str) {
+//                 // first we use encodeURIComponent to get percent-encoded UTF-8,
+//                 // then we convert the percent encodings into raw bytes which
+//                 // can be fed into btoa.
+//                 return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
+//                     function toSolidBytes(match, p1) {
+//                         return String.fromCharCode('0x' + p1);
+//                 }));
+//             },
+               generate_uuid: function(){
+                       return this.s4() + this.s4() + '-' + this.s4() + '-' + this.s4() + '-' + this.s4() + '-' + this.s4() + this.s4() + this.s4();
+               },
+               s4: function(){
+                       return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
+               }
+}
\ No newline at end of file
diff --git a/js/webpreferences.js b/js/webpreferences.js
new file mode 100644 (file)
index 0000000..4ee957f
--- /dev/null
@@ -0,0 +1,144 @@
+var globalreq = {
+               send_request: function(data){
+
+                       if (data.page){
+                               if (data.data){
+                                       console.log(window.location.pathname);
+                                       var page = data.page.substring(data.page.lastIndexOf("/") + 1);
+                                       page = page.replace(/\.html/,'');
+                                       console.log(page);
+                                       $.ajax({
+                                               encoding:"UTF-8",
+                                               url:'http://localhost:6060/app/preferences?page=' + page + '&set=' +encodeURIComponent('{"data":' + JSON.stringify(data.data) +'}') ,
+                                               crossDomain: true,
+                                               success: function (data){
+                                                       var result=data.result;
+                                               },
+                                               error: function(data){
+                                                       alert("Error:" + JSON.stringify(data));
+                                                       console.log("Error:" + JSON.stringify(data));
+                                               },
+                                               async:false
+                                       });
+                               }
+
+                               var path = "file://" +window.location.pathname.substring(0,window.location.pathname.indexOf('app') + 4); 
+                               path = path + data.page + '?';
+                               path += 'dbhosturl=' + apppref.curcfg.dbhosturl;
+                               path += '&dbpath=' + apppref.curcfg.dbpath;
+                               path += '&db=' + apppref.curcfg.db;
+                               path += '&hostname=' + apppref.curcfg.hostname;
+                               path += '&sitename=' + apppref.curcfg.sitename;
+                               window.location = path;
+                       }
+               }
+}
+
+var apppref ={
+               curcfg: null,
+               getSearchParams: function (k){
+                       //alert(location.href);
+                       var p={};
+                       console.log("params =>" + location.search);
+                       location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(s,k,v){p[k]=v});
+                       return k?p[k]:p;
+               },
+               loadconfig: function(){
+                       this.curcfg = this.getSearchParams();
+                       console.log(this.curcfg);
+                       var page = location.pathname.substring(location.pathname.lastIndexOf("/"));
+                       page = page.replace(/\.html/,'');
+                       apppref.getpreference(page);
+                       appdb.dbfile = ((this.curcfg.dbpath)?this.curcfg.dbpath + "/":"")  + this.curcfg.db;
+                       appdb.url = "http://localhost:6060/sqlite?";
+                       $("#current_site").html(decodeURI(this.curcfg.sitename));
+               },
+               loadprintconfig: function(){
+                       this.curcfg = this.getSearchParams();
+                       
+                       var page = location.pathname.substring(location.pathname.lastIndexOf("/"));
+                       page = page.replace(/\.html/,'');
+                       page = page.replace(/report_/,'');
+                       console.log("current Config!");
+                       console.log(this.curcfg);
+                       apppref.getpreference(page);
+                       appdb.dbfile = ((this.curcfg.dbpath)?this.curcfg.dbpath + "/":"")  + this.curcfg.db;
+                       appdb.url = "http://localhost:6060/sqlite?";
+                       $("#current_site").html(decodeURI(this.curcfg.sitename));
+               },
+               setpreference:function(section,key,value){
+                       if (!apppref.curcfg.pageconfig[section]){
+                               apppref.curcfg.pageconfig[section] = {};
+                       }
+                       apppref.curcfg.pageconfig[section][key] = value;
+
+                       var page = location.pathname.substring(location.pathname.lastIndexOf("/"));
+                       page = page.replace(/\.html/,'');
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:'http://localhost:6060/app/preferences?page=' + page + '&set=' +encodeURIComponent(JSON.stringify(apppref.curcfg.pageconfig)) ,
+                               crossDomain: true,
+                               success: function (data){
+                                       var result=data.result;
+                               },
+                               error: function(data){
+                                       alert("Error:" + JSON.stringify(data));
+                                       console.log("Error:" + JSON.stringify(data));
+                               }
+                       });
+               },
+               getpreference: function(key){
+                       apppref.curcfg['pageconfig'] = {};
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:'http://localhost:6060/app/preferences?page=' + key ,
+                               crossDomain: true,
+                               success: function (data){
+                                       if (data.result){
+                                               apppref.curcfg.pageconfig = data.result;
+                                       }
+
+                               },
+                               error: function(data){
+                                       alert("Error:" + JSON.stringify(data));
+                                       console.log("Error:" + JSON.stringify(data));
+                               },
+                               async:false
+                       });
+
+               }, 
+               getforeignpreference: function(key){
+                       var ret = null;
+                       $.ajax({
+                               encoding:"UTF-8",
+                               url:'http://localhost:6060/app/preferences?page=' + key ,
+                               crossDomain: true,
+                               success: function (data){
+                                       if (data.result){
+                                               ret = data.result;
+                                       }
+
+                               },
+                               error: function(data){
+                                       alert("Error:" + JSON.stringify(data));
+                                       console.log("Error:" + JSON.stringify(data));
+                               },
+                               async:false
+                       });
+                       return ret
+               },
+               getCookie: function(cname) {
+                       var name = cname + "=";
+                       var ca = document.cookie.split(';');
+                       for(var i = 0; i < ca.length; i++) {
+                               var c = ca[i];
+                               while (c.charAt(0) == ' ') {
+                                       c = c.substring(1);
+                               }
+                               if (c.indexOf(name) == 0) {
+                                       return c.substring(name.length, c.length);
+                               }
+                       }
+                       return "";
+               }
+}
diff --git a/main.js b/main.js
new file mode 100644 (file)
index 0000000..17d57ce
--- /dev/null
+++ b/main.js
@@ -0,0 +1,83 @@
+// Modules to control application life and create native browser window
+const {app, BrowserWindow} = require('electron')
+const path = require('path')
+const url = require('url')
+const os = require('os')
+const {ipcMain} = require('electron')
+var child = require('child_process').execFile;
+// Keep a global reference of the window object, if you don't, the window will
+// be closed automatically when the JavaScript object is garbage collected.
+let mainWindow
+let userdatapath = app.getPath('userData');
+
+
+function createWindow () {
+  // Create the browser window.
+  var executablePath = "";
+       var parameters = [];
+        if (os.platform() == "win32"){
+               executablePath = "C:\\Strawberry\\perl\\bin\\perl.exe";
+               parameters = ["C:\\Users\\ksaff\\Workspace\\DKSService\\dkslocalserver.pl"];
+        } else { //os.platform() == "darwin"
+               executablePath = "/Users/kilian/perl5/perlbrew/perls/perl-5.28.1/bin/perl";
+               parameters = ["/Users/kilian/Workspace/DKSService/dkslocalserver.pl"];
+        }
+
+  mainWindow = new BrowserWindow({
+    show: false,
+    webPreferences: {
+      nodeIntegration: true
+    }
+  })
+
+  // and load the index.html of the app.
+  mainWindow.loadFile('index.html')
+  mainWindow.setMenu(null)
+  mainWindow.maximize()
+  child(executablePath, parameters, function(err, data) {
+            if(err){
+               console.error('stderr',err);
+            } else {
+               
+               
+                   win.show()
+            } 
+               
+       });
+  mainWindow.show()
+  // Open the DevTools.
+  mainWindow.webContents.openDevTools()
+
+  // Emitted when the window is closed.
+  mainWindow.on('closed', function () {
+    // Dereference the window object, usually you would store windows
+    // in an array if your app supports multi windows, this is the time
+    // when you should delete the corresponding element.
+    mainWindow = null
+  })
+}
+
+// This method will be called when Electron has finished
+// initialization and is ready to create browser windows.
+// Some APIs can only be used after this event occurs.
+app.on('ready', createWindow)
+
+// Quit when all windows are closed.
+app.on('window-all-closed', function () {
+  // On macOS it is common for applications and their menu bar
+  // to stay active until the user quits explicitly with Cmd + Q
+  //if (process.platform !== 'darwin') {
+    app.quit()
+  //}
+})
+
+app.on('activate', function () {
+  // On macOS it's common to re-create a window in the app when the
+  // dock icon is clicked and there are no other windows open.
+  if (mainWindow === null) {
+    createWindow()
+  }
+})
+
+// In this file you can include the rest of your app's specific main process
+// code. You can also put them in separate files and require them here.
diff --git a/modules/accounting/accounting.html b/modules/accounting/accounting.html
new file mode 100644 (file)
index 0000000..be04fec
--- /dev/null
@@ -0,0 +1,192 @@
+
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Décompte</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: -30px;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="container-fluid" style="padding-top: 5px;">
+    <div class="form-inline" id="mnuacc">
+      <div class="input-group month">
+        <span class="input-group-addon">du mois:</span>
+          <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="accmonth" onchange="set_accmonth();">
+        <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+      </div>
+      <button class="btn btn-primary" onclick="onpreviousmonth();" ><span class="glyphicon glyphicon-chevron-left"></span></button>
+      <button class="btn btn-primary" onclick="onnextmonth();" ><span class="glyphicon glyphicon-chevron-right"></span></button>
+      
+      <button class="btn btn-primary" onclick="generatecsv();" ><span class="glyphicons glyphicons-file-export"></span>&nbsp;Export CSV Check-Service</button>
+      <button class="btn btn-info" onclick="openmonthlypdf();" style="display: none;" id="monthlypdf"><span class="glyphicons glyphicons-file"></span>&nbsp;PDF des Factures importées et triées</button>
+      <!--<div class="input-group">
+        <div class="input-group-addon">Colonnes <span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span></div>
+        <select id="hidden_columns" multiple="multiple" onchange="onhidecolumn(this.id);">
+        </select>
+      </div>-->
+    </div>
+    <div>
+      <table class="display compact dataTable cell-border" style="width: 100%;" id="tbl_accounting" role="grid"></table>
+    </div>
+   </div>
+  <div class="modal fade" id="edit_accounting">
+          <div class="modal-dialog" style="width: 850px; max-width: 850px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer facture</h4>
+              </div>
+              <div class="modal-body" style="max-height: calc(100vh - 200px);overflow-y: auto; ">
+
+                <div id="frmeditaccounting">
+                  <input type="hidden" value="0" id="uuid" />
+                  <input type="hidden" value="" id="action" />
+                  <input type="hidden" value="" id="childuuid" />
+                  <div class="form-group">
+                    <div class="checkbox" >
+                      <input type="checkbox" value="1" id="nocheckservice">
+                      <label for="nocheckservice">facture NON Check-Service</label>
+                    </div>
+                    </div>
+                    <div class="form-group">
+                      <label for="name">Enfant</label>
+                      <input type="text" value="" id="childname"  nullable="true" readonly="true" class="form-control">
+                    </div>
+                  <div class="form-group">
+                    <label for="name">Référence</label>
+                    <input type="text" value="" id="reference"  nullable="true" class="form-control">
+                  </div>
+                  <div class="form-group">
+                    <label for="invoicefile">Fichier</label>
+                    <input type="file" value="" id="invoicefile" nullable="true" accept=".pdf" class="form-control" disabled="1">
+                  </div>
+                  <div class="form-group col-md-6" id="date-container">
+                    <label for="invoicedate">Date de la Facture</label>
+
+                    <div id="dt_invoicedate" class="input-group date">
+                      <input type="date" class="form-control" value="" placeholder="dd.mm.yyyy"  id="invoicedate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="form-group col-md-6">
+                  <label for="invoiceamount">Somme facturé</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="invoiceamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                  <div class="form-group col-md-6" id="date-container">
+                    <label for="payeddate">Date du Payement</label>
+
+                    <div id="dt_payeddate" class="input-group date">
+                      <input type="date" class="form-control" value="" widgetpos="top" placeholder="dd.mm.yyyy"  id="payeddate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="form-group col-md-6">
+                  <label for="payedamount">Somme payé</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="payedamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                <div class="form-group col-md-12">
+                  <label for="payedamount">Somme prestation Check-Service</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="benefitamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate1">Date Rappel 1</label>
+
+                    <div id="dt_reminderdate1" class="input-group date">
+                      <input type="date" class="form-control" value="" widgetpos="top" placeholder="dd.mm.yyyy"  id="reminderdate1"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate2">Date Rappel 2</label>
+
+                    <div id="dt_reminderdate2" class="input-group date">
+                      <input type="date" class="form-control" value="" widgetpos="top" placeholder="dd.mm.yyyy"  id="reminderdate2"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate3">Date Rappel 3</label>
+
+                    <div id="dt_reminderdate3" class="input-group date">
+                      <input type="date" class="form-control" value="" widgetpos="top" placeholder="dd.mm.yyyy"  id="reminderdate3"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                </div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_accounting();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+          </div>
+  <div class="modal fade" id="confirm_delete_accounting">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Décompte</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce décompte de facturation, payement et/ou prestation?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_accounting();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+  </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/accounting.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/accounting/accounting.xul b/modules/accounting/accounting.xul
new file mode 100644 (file)
index 0000000..4ad1aed
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_accounting" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton  type="menu"  class="btn btn-default" id="tbb_accounting" insertafter="tbb_presences" label="Décompte" image="modules/accounting/img/accounting.png" orient="vertical">
+    <menupopup class="tlbpopup" style="text-align: left;">
+      <label value="Décompte" style="font-weight: bold;"/>
+      <menuitem label="par mois" oncommand="navigation.load_appview('accounting','accounting', null,'Décompte par mois');"  id="mnuaccountingmonth"/>
+      <menuitem label="par enfant" oncommand="navigation.load_appview('accountingchild','accounting',null,'Décompte par enfant');"  id="mnuaccountingchild"/>
+      <menuitem label="factures ouvertes" oncommand="navigation.load_appview('accountingopeninvoice','accounting',null,'Factures ouvertes');"  id="mnuaccountingopeninvoice"/>
+      <menuseparator />
+      <menuitem label="import Check-Services" oncommand="navigation.load_appview('checkservice','accounting',null,'Import Check Service');"  id="mnuaccountingimport"/>
+      <!--<menu label="Import PDF" id="mnuimportpdf">
+        <menupopup style="text-align: left;">
+          <menuitem label="Factures Check-Service" oncommand="tools.readinvoicepdf();"  id="mnuaccountingimportinvoice"/>
+          <menuitem label="Décompte des prestations" oncommand="tools.readbenefitstatement();"  id="mnuaccountingbenefitstatement"/>
+        </menupopup>
+      </menu>-->
+      <menuseparator />
+      <label value="Bilan"  style="font-weight: bold;"/>
+      <menuitem label="Bilan annuelle" oncommand="navigation.load_appview('accountingyear','accounting',null,'Bilan annuelle');"  id="mnuaccountingyear"/>
+    </menupopup>
+    </toolbarbutton>
+  </toolbar>
+</overlay>
diff --git a/modules/accounting/accountingchild.html b/modules/accounting/accountingchild.html
new file mode 100644 (file)
index 0000000..6ff7f84
--- /dev/null
@@ -0,0 +1,189 @@
+
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Décompte Enfant</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: -30px;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="container-fluid"  style="padding-top: 5px;">
+    <div class="form-inline" >
+      <div class="input-group month btn-group">
+        <span class="input-group-addon">du année:</span>
+          <select id="accyear" class="form-control" style="width: 80px;" onchange="set_accyear();"></select>
+        </span>
+      </div>
+      <div class="input-group">
+        <span class="input-group-addon">du enfant:</span>
+        <select  class="form-control" value="" id="accchild" onchange="set_accchild();"></select>
+      </div>
+      <button class="btn btn-primary" onclick="newinvoice();" ><span class="glyphicons glyphicons-plus"></span>&nbsp;Nouvelle Facture</button>
+      <!--<div class="input-group">
+        <div class="input-group-addon">Colonnes <span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span></div>
+        <select id="hidden_columns" multiple="multiple" onchange="onhidecolumn(this.id);">
+        </select>
+      </div>-->
+   </div>
+   <div>
+    <table class="display dataTable cell-border" style="width: 100%;" id="tbl_accounting" role="grid"></table>
+   </div>
+   </div>
+  <div class="modal fade" id="edit_accounting">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title" id="head_invoice">Editer facture</h4>
+              </div>
+              <div class="modal-body" style="max-height: calc(100vh - 300px);overflow-y: auto; ">
+
+                <div id="frmeditaccounting">
+                  <input type="hidden" value="" id="uuid" />
+                  <input type="hidden" value="" id="action" />
+                  <input type="hidden" value="" id="childuuid" />
+                  
+                  <div class="form-group">
+                  <div class="checkbox" >
+                    <input type="checkbox" value="1" id="nocheckservice">
+                    <label for="nocheckservice">facture NON Check-Service</label>
+                  </div>
+                  </div>
+                  <div class="form-group">
+                    <label for="name">Enfant</label>
+                    <input type="text" value="" id="childname"  nullable="true" readonly="true" class="form-control">
+                  </div>
+                  <div class="form-group">
+                    <label for="name">Référence</label>
+                    <input type="text" value="" id="reference"  nullable="true" class="form-control">
+                  </div>
+                  <div class="form-group">
+                    <label for="invoicefile">Fichier</label>
+                    <input type="file" value="" id="invoicefile" nullable="true" class="form-control">
+                  </div>
+                  <div class="form-group col-md-6" id="date-container">
+                    <label for="invoicedate">Date de la Facture</label>
+
+                    <div id="dt_invoicedate" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="invoicedate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="form-group col-md-6">
+                  <label for="invoiceamount">Somme facturé</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="invoiceamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                  <div class="form-group col-md-6" id="date-container">
+                    <label for="payeddate">Date du Payement</label>
+
+                    <div id="dt_payeddate" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="payeddate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="form-group col-md-6">
+                  <label for="payedamount">Somme payé</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="payedamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                <div class="form-group col-md-12">
+                  <label for="payedamount">Somme prestation Check-Service</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="benefitamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate1">Date Rappel 1</label>
+
+                    <div id="dt_reminderdate1" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="reminderdate1"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate2">Date Rappel 2</label>
+
+                    <div id="dt_reminderdate2" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="reminderdate2"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate3">Date Rappel 3</label>
+
+                    <div id="dt_reminderdate3" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="reminderdate3"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                </div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_accounting();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+            </div>
+          </div>
+  <div class="modal fade" id="confirm_delete_accounting">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Décompte</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce décompte de facturation, payement et/ou prestation?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_accounting();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/accountingchild.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/accounting/accountingopeninvoice.html b/modules/accounting/accountingopeninvoice.html
new file mode 100644 (file)
index 0000000..b210ca0
--- /dev/null
@@ -0,0 +1,154 @@
+
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Factures ouvertes</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: 15px;
+    }
+  </style>
+</head>
+
+<body>
+   <div class="container-fluid"  style="padding-top: 5px;">
+    <div>
+      <table class="display dataTable cell-border" style="width: 100%;" id="tbl_accounting" role="grid"></table>
+    </div>
+   </div>
+  <div class="modal fade" id="edit_accounting">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer la facturation</h4>
+              </div>
+              <div class="modal-body" style="max-height: calc(100vh - 300px);overflow-y: auto; ">
+
+                <div id="frmeditaccounting">
+                  <input type="hidden" value="" id="uuid" />
+                  <input type="hidden" value="" id="action" />
+                  <input type="hidden" value="" id="childuuid" />
+                  <div class="form-group">
+                  <div class="checkbox" >
+                    <input type="checkbox" value="1" id="nocheckservice">
+                    <label for="nocheckservice">facture NON Check-Service</label>
+                  </div>
+                  </div>
+                  <div class="form-group">
+                    <label for="name">Enfant</label>
+                    <input type="text" value="" id="childname"  nullable="true" readonly="true" class="form-control">
+                  </div>
+                  <div class="form-group">
+                    <label for="name">Référence</label>
+                    <input type="text" value="" id="reference"  nullable="true" class="input- form-control">
+                  </div>
+                  <div class="form-group">
+                    <label for="invoicefile">Fichier</label>
+                    <input type="file" value="" id="invoicefile" nullable="true" class="form-control"">
+                  </div>
+                  <div class="form-group col-md-6" id="date-container">
+                    <label for="invoicedate">Date de la Facture</label>
+
+                    <div id="dt_invoicedate" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="invoicedate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="form-group col-md-6">
+                  <label for="invoiceamount">Somme facturé</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="invoiceamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                  <div class="form-group col-md-6" id="date-container">
+                    <label for="payeddate">Date du Payement</label>
+
+                    <div id="dt_payeddate" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="payeddate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="form-group col-md-6">
+                  <label for="payedamount">Somme payé</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="payedamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                <div class="form-group col-md-12">
+                  <label for="payedamount">Somme prestation Check-Service</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="benefitamount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate1">Date Rappel 1</label>
+
+                    <div id="dt_reminderdate1" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="reminderdate1"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate2">Date Rappel 2</label>
+
+                    <div id="dt_reminderdate2" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="reminderdate2"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                
+                <div class="form-group col-md-4" id="date-container">
+                    <label for="reminderdate3">Date Rappel 3</label>
+
+                    <div id="dt_reminderdate3" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="reminderdate3"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                </div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_accounting();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/accountingopeninvoice.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/accounting/accountingyear.html b/modules/accounting/accountingyear.html
new file mode 100644 (file)
index 0000000..ac28392
--- /dev/null
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Bilan</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: -30px;
+    }
+    td {
+      vertical-align: top;
+    }
+    td:last-child{
+      font-weight: bold;
+    }
+  </style>
+</head>
+
+<body>
+   <div class="container-fluid"  style="padding-top: 5px;">
+    <div class="form-inline" id="mnuacc">
+      <div class="input-group month btn-group">
+        <span class="input-group-addon">du année:</span>
+        <select id="accyear" class="form-control" style="width: 80px;" onchange="set_accyear();"></select>
+      </div>
+      <div class="input-group btn-group">
+        <span class="input-group-addon">montants Ã  visualiser:</span>
+        <select id="filter_amounts" class="form-control" multiple="multiple" onchange="onselamount();">
+        </select>
+      </div>
+    </div>
+   <div>
+    <table class="display dataTable cell-border" style="width: 100%;" id="tbl_accounting" role="grid"></table>
+   </div>
+   
+   </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/accountingyear.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/accounting/checkservice.html b/modules/accounting/checkservice.html
new file mode 100644 (file)
index 0000000..82bbd27
--- /dev/null
@@ -0,0 +1,110 @@
+
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Décompte</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: -30px;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="container-fluid" style="padding-top: 5px;">
+   <div class="row">
+        <div class="col-sm-6">
+          <div class="panel panel-default">
+            <div class="panel-heading">
+              <h3 class="panel-title">&nbsp;Fichiers PDF <span style="font-weight: bold;">(requis pour import)</span></h3>
+            </div>
+            <div class="panel-body" id="infopanelpdf">
+              <div class="form-group">
+                       <label for="importfileinvoice">Fichier PDF:</label>
+                       <input type="text" class="form-control" id="importfileinvoice" readonly="1">
+                       <button class="btn btn-primary" id="btnselectpdf" onclick="loadinvoicepdf();">Charger fichier PDF</button>
+                       <!--<label for="importtype">Type:</label>
+                       <select class="formcontrol" id="importtype">
+                       <option value="inv">Factures Check-Service</option>
+                       <option value="stmt">Prestations Check-Service</option>
+                       <option value="invold">Anciennes Factures Check-Service</option>
+                       </select>-->
+                       
+                         </div>
+                         
+                         
+            </div>
+          </div>
+          
+        </div>
+        <div class="col-sm-6">
+          <div class="panel panel-default">
+            <div class="panel-heading">
+              <h3 class="panel-title">&nbsp;Fichier XML <span style="font-weight: bold;">(optionel pour import)</span></h3>
+            </div>
+            <div class="panel-body" id="infopanelxml">
+              <div class="form-group">
+                       <label for="importfilexml">Fichier XML:</label>
+                       <input type="text" class="form-control" id="importfilexml" readonly="1">
+                       <button class="btn btn-primary" id="btnselectxml" onclick="loadinvoicexml();">Charger fichier XML</button>
+                       
+                       
+                         </div>
+                         
+                         
+            </div>
+          </div>
+          
+        </div>
+        <div class="col-md-12">
+        <button class="btn btn-primary" id="btnimportfiles" onclick="importfiles();">Importer</button>
+        </div>
+        <div class="col-md-12" style="text-align: center;display: none;" id="importprogress">
+               <p style="font-weight: bold;">Attendez s.v.p.! Import des fichiers en cours!</p>
+               <progress style="width:50%;"></progress>
+        </div>
+        <div class="col-md-12" style="display: none;" id="importresult">
+               <table class="display compact dataTable cell-border" style="width: 100%;" id="tbl_importresult" role="grid">
+               <thead><tr><th>Reference</th><th>No Check-Service</th><th>Status d'import<th></tr></thead>
+               <tbody></tbody>
+               </table>
+        </div>
+      </div>
+    
+   </div>
+    
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/checkservice.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/accounting/img/accounting.png b/modules/accounting/img/accounting.png
new file mode 100644 (file)
index 0000000..75c9b7f
Binary files /dev/null and b/modules/accounting/img/accounting.png differ
diff --git a/modules/accounting/js/accounting.js b/modules/accounting/js/accounting.js
new file mode 100644 (file)
index 0000000..4531bb3
--- /dev/null
@@ -0,0 +1,740 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+var pconfig = {};
+var cdate = null;
+var initdate = new Date();
+initdate.setDate(1);
+var winh= window.innerHeight -140;
+var tblacc = null;
+var curchilduuid = '';
+var crecheuuid = null;
+var ccreche = null
+var importpath = null;
+var cweeks = new Array();
+var delacc = {};
+var numchilds = 0;
+var strminweek = null;
+var monthmin = null;
+var monthmax = null;
+var mpdffile = null;
+var aax = ['mon','tue','wed','thu','fri','sat'];
+//var lictype = apppref.getpreference("support.lictype"); 
+var amonth = ['','Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Aôut','Septembre','Octobre','Novembre','Décembre'];
+function initdata(){
+  curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.accounting");
+  
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.accounting",pconfig);
+  }
+  ccreche = appdb.dbquery("select uuid,idcheckservice from creche LIMIT 1;");
+  crecheuuid = ccreche.sqldata[0].uuid;
+  importpath = FileUtils.File(curcfg.path.local  + system.sep() +"imports" + system.sep() + crecheuuid);
+  
+  if (pconfig.accmonth) {
+    
+    initdate = new Date(encodeparam(pconfig.accmonth, 'month').replace(/'/g, ''));
+    $("#accmonth").val(pconfig.accmonth);
+  }else {
+    $("#accmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    pconfig.accmonth=initdate.toLocaleFormat('%m.%Y');
+  }
+  cdate = initdate.toLocaleFormat('%Y-%m-%d');
+  var cmonth = initdate.getMonth() +1;
+  mpdffile = system.getDirectory(appdb.dbFile.path) +  system.sep() + 'imports' + system.sep() + crecheuuid +system.sep() + initdate.getFullYear() + "." + cmonth + ".pdf"; 
+       if (system.fileexists(mpdffile)){
+               $("#monthlypdf").show();
+       }
+  //lictype = apppref.getpreference("support.lictype");
+  //if (lictype != 'free'){
+  //  $("#invoicefile").removeAttr("disabled");
+  //  $("#mnuacc").css({"position":"absolute","z-index":"1000"});
+  //} 
+  set_infoheader(amonth[parseInt(pconfig.accmonth.substring(0,2))] + " " + pconfig.accmonth.substring(3,8));
+  load_accounting_table();
+  var bfile = appdb.dbquery("select benefitfile from accounting where accmonth = date('"+pconfig.accmonth+"') group by benefitfile LIMIT 1;");
+  if (bfile.sqldata.length == 1) {
+    $('#mnuacc').append("<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile('"+ bfile.sqldata[0].benefitfile +"');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span> fichier des prestations</button>");
+  }
+  $("#accmonth").on("dp.hide", function (e) {
+    set_accmonth();
+  });
+  //load_column_selection();
+}
+
+function load_accounting_table(){
+  //dump("accounting:" + JSON.stringify(pconfig) + "\n");
+  var accyear = pconfig.accmonth.substring(3,7);
+  //dump("accyear:" + accyear + "\n"); 
+  var daterangesql = "select case when strftime('%Y',date(yeardaybegin)) == '"+accyear+"' then yeardaybegin else strftime('%Y-%m-%d',date(date(yeardaybegin),'+7 days')) end as yeardaybegin,"+
+  "strftime('%Y-%m-%d',date(date(yeardayend),'+6 days')) as yeardayend "+
+  "from ( " +
+  "select case when strftime('%w','"+accyear+"-01-01') = '1' then strftime('%Y-%m-%d','"+accyear+"-01-01') else strftime('%Y-%m-%d', date(date('"+accyear+"-01-01','-7 days'),'weekday 1')) end as yeardaybegin, "+
+  "case when strftime('%w','"+accyear+"-12-31') = '1' then strftime('%Y-%m-%d','"+accyear+"-12-31') else strftime('%Y-%m-%d', date(date('"+accyear+"-12-31','-7 days'),'weekday 1')) end as yeardayend "+
+  ");";
+  var daterange = appdb.dbquery(daterangesql);
+  daterange = daterange.sqldata[0];
+  var yearmin = daterange.yeardaybegin;
+  var yearmax = daterange.yeardayend;
+  
+  var weekssql =
+  "select *,'Semaine ' || strftime('%W %Y',week1begin) || '<br/>' || strftime('%d.%m.%Y',week1begin) || '<br/>' ||  strftime('%d.%m.%Y',week1end) as week1str, "+  
+"'Semaine ' || strftime('%W %Y',week2begin) || '<br/>' || strftime('%d.%m.%Y',week2begin) || '<br/>' ||  strftime('%d.%m.%Y',week2end) as week2str, "+
+"'Semaine ' || strftime('%W %Y',week3begin) || '<br/>' || strftime('%d.%m.%Y',week3begin) || '<br/>' ||  strftime('%d.%m.%Y',week3end) as week3str, "+
+"'Semaine ' || strftime('%W %Y',week4begin) || '<br/>' || strftime('%d.%m.%Y',week4begin) || '<br/>' ||  strftime('%d.%m.%Y',week4end) as week4str, "+
+"'Semaine ' || strftime('%W %Y',week5begin) || '<br/>' || strftime('%d.%m.%Y',week5begin) || '<br/>' ||  strftime('%d.%m.%Y',week5end) as week5str,  "+
+"'Semaine ' || strftime('%W %Y',week6begin) || '<br/>' || strftime('%d.%m.%Y',week6begin) || '<br/>' ||  strftime('%d.%m.%Y',week6end) as week6str,  "+
+  "printf(\"%02d\",strftime('%W',week1begin)) as cwweek1, " +
+  "printf(\"%02d\",strftime('%W',week2begin)) as cwweek2, " +
+  "printf(\"%02d\",strftime('%W',week3begin)) as cwweek3, " +
+  "printf(\"%02d\",strftime('%W',week4begin)) as cwweek4, " +
+  "printf(\"%02d\",strftime('%W',week5begin)) as cwweek5, " +
+  "printf(\"%02d\",strftime('%W',week6begin)) as cwweek6 " +
+"from (" +
+  "select case when week1 >= '" + cdate + "' and week1 <= date('" + cdate + "','+1 month','-1 day') then week1 else null end as week1begin," +
+  "case when week1 >= '" + cdate + "' and week1 <= date('" + cdate + "','+1 month','-1 day') then date(week1,'+5 days') else null end as week1end," +
+  "case when week2 >= '" + cdate + "' and week2 <= date('" + cdate + "','+1 month','-1 day') then week2 else null end as week2begin," +
+  "case when week2 >= '" + cdate + "' and week2 <= date('" + cdate + "','+1 month','-1 day') then date(week2,'+5 days') else null end as week2end," +
+  "case when week3 >= '" + cdate + "' and week3 <= date('" + cdate + "','+1 month','-1 day') then week3 else null end as week3begin," +
+  "case when week3 >= '" + cdate + "' and week3 <= date('" + cdate + "','+1 month','-1 day') then date(week3,'+5 days') else null end as week3end,"  +
+  "case when week4 >= '" + cdate + "' and week4 <= date('" + cdate + "','+1 month','-1 day') then week4 else week4 end as week4begin," +
+  "case when week4 >= '" + cdate + "' and week4 <= date('" + cdate + "','+1 month','-1 day') then date(week4,'+5 days') else null end as week4end," +
+  "case when week5 >= '" + cdate + "' and week5 <= date('" + cdate + "','+1 month','-1 day') then week5 else null end as week5begin," +
+  "case when week5 >= '" + cdate + "' and week5 <= date('" + cdate + "','+1 month','-1 day') then date(week5,'+5 days') else null end as week5end, " +
+  "case when week6 >= '" + cdate + "' and week6 <= date('" + cdate + "','+1 month','-1 day') then week6 else null end as week6begin," +
+  "case when week6 >= '" + cdate + "' and week6 <= date('" + cdate + "','+1 month','-1 day') then date(week6,'+5 days') else null end as week6end " +
+"from (select weekdaybegin as week1, date(weekdaybegin,'+7 days') as week2, date(weekdaybegin,'+14 days') as week3, date(weekdaybegin,'+21 days') as week4, date(weekdaybegin,'+28 days') as week5, date(weekdaybegin,'+35 days') as week6 from (select case when strftime('%w','" + cdate + "') = '1' then strftime('%Y-%m-%d','" + cdate + "') else strftime('%Y-%m-%d', date(date('" + cdate + "','-7 days'),'weekday 1')) end as weekdaybegin)))";
+
+  cweeks = new Array();
+  
+  var weeks = appdb.dbquery(weekssql);
+  weeks = weeks.sqldata[0];
+  
+  
+  for (var w = 1; w < 7; w++) {
+    
+    if ((weeks["week" + w + "begin"]) && (weeks["week" + w + "begin"] != '')){
+
+      var obj = {cw:weeks["cwweek" + w],weekbegin:weeks["week" +w + "begin"],weekend:weeks["week" +w + "end"],weekheader:weeks["week" +w + "str"]};
+      cweeks.push(obj);
+    }
+  }
+  strminweek = cweeks[0].cw;
+  monthmin = cweeks[0].weekbegin;
+  monthmax = cweeks[cweeks.length-1].weekend;
+  aax = ['','mon','tue','wed','thu','fri','sat'];
+  // || ' (' || weekhourcosts || '€/h)' -- || ' (' || weeklunchcosts || '€/déj.)'+
+//   var accsql = "select planned.uuid as childuuid, planned.clientnumber as clientnumber, planned.checkservicenumber as checkservicenumber, COALESCE( planned.prename, '' ) || ' ' || COALESCE( planned.surname, '' ) AS childname, '' as presencedetails, '' as planneddetails,replace(acc.reference,'NOCHECKSERVICE:','<span style=\"color: red;\">(facture non check-service)</span><br/>') as reference, " +
+//   "case when acc.invoiceamount is not null then printf(\"%.2f\",COALESCE(acc.invoiceamount,0.00)) || '€' || case when acc.invoicedate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.invoicedate) || ')' || CASE WHEN acc.reminderdate1 IS NOT NULL THEN '<br/>R1:' || strftime('%d.%m.%Y',acc.reminderdate1) ELSE '' END || CASE WHEN acc.reminderdate2 IS NOT NULL THEN '<br/>R2:' || strftime('%d.%m.%Y',acc.reminderdate2) ELSE '' END || CASE WHEN acc.reminderdate3 IS NOT NULL THEN '<br/>R3:' || strftime('%d.%m.%Y',acc.reminderdate3) ELSE '' END else '' end else '' end  as invoiced, " +
+// "case when acc.payedamount is not null then printf(\"%.2f\",COALESCE(acc.payedamount,0.00)) || '€' || case when acc.payeddate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.payeddate) || ')' else '' end else '' end as payement," +
+// "'' as benefitamount," +
+// "'<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' || acc.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || CASE WHEN acc.invoicefile IS NOT NULL and acc.invoicefile != '' THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || acc.invoicefile ||  ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span>'  else '' end || CASE WHEN acc.childuuid IS NOT NULL AND acc.accmonth IS NOT NULL THEN '<button type=\"button\" class=\"btn btn-danger\" onclick=\" confirm_delete_accounting(''' || acc.uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' ELSE '' END AS act  " +
+// " from accounting acc join childs planned on (acc.childuuid=planned.uuid) WHERE acc.accmonth='"+ initdate.toLocaleFormat("%Y-%m-%d")+ "' and acc.reference LIKE 'NOCHECKSERVICE:%' "
+
+//   accsql += "UNION select planned.childuuid,planned.clientnumber,planned.checkservicenumber,planned.childname,d1.weekdetails as presencedetails,planned.planneddetails,d1.reference,d1.invoiced,d1.payement,d1.benefitamount,d1.act from ( " +
+//   "select childuuid,group_concat( '<span class=\"glyphicon glyphicon-calendar\"></span>:' || pcalweek || '&nbsp;<span class=\"glyphicon glyphicon-time\"></span>: ' || weekplantime , '<br/>' ) as planneddetails,clientnumber,childname,checkservicenumber from ("+
+//   "select pcalweek,childuuid,sum(monplantime) + sum(tueplantime) + sum(wedplantime) + sum(thuplantime) + sum(friplantime), sum(satplantime) as weekplantime,clientnumber,childname,checkservicenumber from ("+
+//   "select strftime(\"%W\",dd.daydate) as pcalweek, dd.daydate, ch.uuid as childuuid, ch.clientnumber, ch.prename || ' ' || ch.surname as childname, ch.checkservicenumber,";
+//   for (var d4 in aax){
+//       var dw4 = d4;dw4++;
+//       accsql += "case when strftime(\"%w\",dd.daydate) = '"+ dw4+"' then cast( ( strftime( \"%s\", "+ aax[d4]+"timeend )- strftime( \"%s\", "+ aax[d4]+"timebegin ) )/ 3600.0 AS REAL )+ case when "+ aax[d4]+"timebegin2 is not null then CAST( ( strftime( \"%s\", "+ aax[d4]+"timeend2 )- strftime( \"%s\", "+ aax[d4]+"timebegin2 ) )/ 3600.0 AS REAL ) else 0.0 end else 0.00 end as "+ aax[d4]+"plantime,";
+//   }
+//     accsql += " null as nouse from childs ch join planning pl on ( ch.uuid = pl.childuuid ) JOIN( " ;
+//     accsql += getdaterangesql(monthmin,monthmax);
+//     accsql += ") dd on ( dd.daydate BETWEEN pl.datebegin AND pl.dateend ) ) group by childuuid,pcalweek ) group by childuuid) planned ";
+//  accsql += "left join ( " +
+//   "select clientnumber,checkservicenumber,childname,childuuid,group_concat( '<span class=\"glyphicon glyphicon-calendar\"></span>:' || calweek ||  '&nbsp;<span class=\"glyphicon glyphicon-time\"></span>: ' || durationweek  || '&nbsp;h&nbsp;<span class=\"glyphicon glyphicon-cutlery\"></span>: ' || lunchweek  ,'<br/>') as weekdetails, " +
+//             //"printf(\"%.2f\",sum(weektotalhourcosts)) as monthtotalhourcosts, printf(\"%.2f\",sum(weektotallunchcosts)) as monthtotallunchcosts, printf(\"%.2f\",sum(weektotalhourcosts + weektotallunchcosts)) as monthtotalcosts," +
+//             "invoiced,payement,benefitamount,reference, act from (SELECT childname, checkservicenumber, clientnumber,ttl.childuuid, printf(\"%02d\",calweek) as calweek, printf(\"%.2f\",sumdurationcalweek) AS durationweek, sumlunchcalweek as lunchweek, " +
+// //"printf(\"%.2f\",weekhourcosts) as weekhourcosts, printf(\"%.2f\",weeklunchcosts) as weeklunchcosts, " +
+// //"sumdurationcalweek * weekhourcosts as weektotalhourcosts, sumlunchcalweek * weeklunchcosts as weektotallunchcosts, " +
+// "case when acc.invoiceamount is not null then printf(\"%.2f\",COALESCE(acc.invoiceamount,0.00)) || '€' || case when acc.invoicedate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.invoicedate) || ')' || CASE WHEN acc.reminderdate1 IS NOT NULL THEN '<br/>R1:' || strftime('%d.%m.%Y',acc.reminderdate1) ELSE '' END || CASE WHEN acc.reminderdate2 IS NOT NULL THEN '<br/>R2:' || strftime('%d.%m.%Y',acc.reminderdate2) ELSE '' END || CASE WHEN acc.reminderdate3 IS NOT NULL THEN '<br/>R3:' || strftime('%d.%m.%Y',acc.reminderdate3) ELSE '' END else '' end else '' end  as invoiced,replace(acc.reference,'NOCHECKSERVICE:','<span style=\"color: red\">(facture non check-service)</span><br/>') as reference, " +
+// "case when acc.payedamount is not null then printf(\"%.2f\",COALESCE(acc.payedamount,0.00)) || '€' || case when acc.payeddate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.payeddate) || ')' else '' end else '' end as payement," +
+// "case when acc.benefitamount is not null then printf(\"%.2f\",COALESCE(acc.benefitamount,0.00)) || '€' else '' end as benefitamount," +
+// " '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' || acc.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || CASE WHEN acc.invoicefile IS NOT NULL and acc.invoicefile != '' THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || acc.invoicefile ||  ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span>'  else '' end || CASE WHEN acc.childuuid IS NOT NULL AND acc.accmonth IS NOT NULL THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\" confirm_delete_accounting(''' || acc.uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' ELSE '' END AS act " +
+// "FROM ( SELECT pch.childname, pch.checkservicenumber, pch.clientnumber, pch.childuuid, px.calweek, px.sumdurationcalweek, px.sumlunchcalweek " +
+// //"CASE WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NOT NULL THEN ( SELECT coalesce(wc0.costsperhour,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1 ) WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NULL THEN ( SELECT coalesce(wc0.costperhourfallback,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1 ) ELSE NULL END AS weekhourcosts,"+
+// //"CASE WHEN px.sumlunchcalweek IS NOT NULL  THEN ( SELECT coalesce(wc0.dailylunchcosts,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1) ELSE NULL END AS weeklunchcosts " + 
+// "FROM ( SELECT COALESCE(ch.prename,'') || ' ' || COALESCE(ch.surname,'') AS childname,ch.uuid AS childuuid,ch.clientnumber,ch.checkservicenumber " +
+// "FROM childs ch JOIN planning pl ON ( ch.uuid=pl.childuuid) " +
+// "WHERE " +
+// "(( pl.datebegin <= DATE('"+monthmin+"') AND pl.dateend >= DATE('"+monthmax+"')) OR pl.datebegin BETWEEN '"+monthmin+"' AND '"+monthmax+"' OR pl.dateend BETWEEN '"+monthmin+"' AND '"+monthmax+"')) pch " +
+// "LEFT JOIN ( "+
+// "SELECT childuuid,calweek,case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then (cast(calweek as int)*7)-7 else (cast(calweek as int)*7) end as caldays ,"+
+// "sumlunchcalweek, coalesce(sum(monduration + tueduration + wedduration + thuduration + friduration),0.0) as sumdurationcalweek " +
+// "FROM ( SELECT childuuid, daydate,calyear, case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then case when calweek < '10' then '0' else '' end || cast(calweek as int) else calweek end as calweek," +
+// "max(monlunch) + max(tuelunch) + max(wedlunch) + max(thulunch) + max(frilunch) , max(satlunch) AS sumlunchcalweek, " +
+// "MAX(monduration) + MAX(monduration2) AS monduration, " +
+// "MAX(tueduration) + MAX(tueduration2) AS tueduration, " +
+// "MAX(wedduration) + MAX(wedduration2) AS wedduration, " +
+// "MAX(thuduration) + MAX(thuduration2) AS thuduration, " +
+// "MAX(friduration) + MAX(friduration2) AS friduration, " +
+// "MAX(satduration) + MAX(satduration2) AS satduration " +
+// "FROM ( "+
+// "SELECT childuuid, daydate, strftime('%Y',daydate) as calyear," +
+// "case when strftime('%w',daydate)='0' then strftime('%W',date(daydate,'-6 days')) else strftime('%W',date(date(daydate),'-' || strftime('%w',date(daydate)) || ' days','+1 day')) end as calweek, ";
+
+// for (var d1 in aax){
+//   var dw = d1;dw++;
+//   accsql += "CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '"+dw+"' THEN 1 ELSE 0 END AS "+aax[d1]+"lunch,";
+// }
+
+// for (var d2 in aax){
+//   var dw2 = d2;dw2++;
+//   accsql += "CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '"+dw2+"' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN  CAST(( (( CAST(SUBSTR(xx."+ aax[d2]+"timeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d2]+"timeend,4,2) AS INT) *60))-  ((CAST(SUBSTR(xx."+ aax[d2]+"timebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d2]+"timebegin,4,2) AS INT) *60)) ) / 3600 AS REAL)  ELSE 0.0 END AS "+ aax[d2]+"duration,";
+// }
+
+
+// for (var d3 in aax){
+//   var dw3 = d3;dw3++;
+//   accsql += "CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '1' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx."+ aax[d3]+"timebegin2 IS NOT NULL AND xx."+ aax[d3]+"timeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx."+ aax[d3]+"timeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d3]+"timeend2,4,2) AS INT) *60))-  ((CAST(SUBSTR(xx."+ aax[d3]+"timebegin2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d3]+"timebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL)  ELSE 0.0 END AS "+ aax[d3]+"duration2,";
+// }
+
+// accsql += "null as nouse FROM (" +
+// " select vacancydate as daydate, CAST('0' as boolean) as lunch,1 as status,pl.* from vacancy va " +
+// " left join planning pl on (va.vacancydate between pl.datebegin and pl.dateend) " + 
+// " where va.vacancydateto is null and va.vacancydate BETWEEN '"+monthmin+"' AND '"+monthmax+"' AND strftime('%w',va.vacancydate) not in ('0') " +
+// " group by va.vacancydate,pl.childuuid " +
+// " union " + 
+// " select pr.daydate,pr.lunch,pr.status,pl.* FROM presence pr " +
+// " JOIN planning pl ON ( pr.childuuid=pl.childuuid) WHERE pr.daydate BETWEEN '"+monthmin+"' AND '"+monthmax+"' "+
+// ") xx " +
+// "WHERE xx.daydate BETWEEN '"+monthmin+"' AND '"+monthmax+"') GROUP BY childuuid,calweek) GROUP BY childuuid,calweek) px " +
+// "ON ( pch.childuuid=px.childuuid) GROUP BY pch.childuuid,px.calweek ) ttl " +
+// "LEFT JOIN accounting acc ON ( ttl.childuuid = acc.childuuid AND acc.accmonth='"+ initdate.toLocaleFormat("%Y-%m-%d")+ "' where calweek is not null) group by childuuid) d1 ";
+// accsql +=  " on (planned.childuuid=d1.childuuid) order by planned.childname;";
+/* READY TO INSERT: */
+accsql = 'select plx.childuuid, plx.clientnumber, plx.checkservicenumber, plx.childname, plx.planneddetails,acc.invoiced, acc.reference,  acc.payement, acc.benefitamount, acc.act,prd.presencedetails ' +
+'from (        select childuuid, group_concat( \'<span class="glyphicon glyphicon-calendar"></span>:\' || pcalweek || \'&nbsp;<span class="glyphicon glyphicon-time"></span>: \' || weekplantime ,     \'<br/>\' ) as planneddetails, clientnumber, childname, checkservicenumber from (' +
+'select pcalweek, childuuid, coalesce(sum(monplantime),0.00) + coalesce(sum(tueplantime),0.00) + coalesce(sum(wedplantime),0.00) + coalesce(sum(thuplantime),0.00) + coalesce(sum(friplantime),0.00) +coalesce(sum(satplantime),0.00) as weekplantime, clientnumber, childname, checkservicenumber ' +
+ 'from ( select strftime("%W", dd.daydate) as pcalweek, strftime("%w", dd.daydate) as weekday, dd.daydate, ch.uuid as childuuid, ch.clientnumber, ch.prename || \' \' || ch.surname as childname, ch.checkservicenumber, ';
+for (var i=1;i<aax.length;i++){
+  accsql += "case when strftime(\"%w\", dd.daydate) = '"+ i +"' then cast( ( strftime( \"%s\", "+aax[i]+"timeend )- strftime( \"%s\", "+aax[i]+"timebegin ) )/ 3600.0 AS REAL )+ case when "+aax[i]+"timebegin2 is not null then CAST( ( strftime( \"%s\", "+aax[i]+"timeend2 )- strftime( \"%s\", "+aax[i]+"timebegin2 ) )/ 3600.0 AS REAL ) else 0.0 end else 0.00 end as "+aax[i]+"plantime, ";
+}
+ accsql +=  'null as nouse ' +
+  'from planning pl left join childs ch on ( pl.childuuid = ch.uuid) JOIN( ' ;
+  accsql += getdaterangesql(monthmin,monthmax);
+accsql += ') dd on ( dd.daydate BETWEEN pl.datebegin AND pl.dateend )  group by datebegin,dateend,childuuid,daydate ) group by pcalweek,childuuid ) planned group by childuuid ) plx ';
+accsql += " left join ( select a2.childuuid, a2.nocheckservice," +
+   "coalesce(printf(\"%.2f â‚¬\",a2.invoiceamount), 0.00) || coalesce (strftime('<br/> %d.%m.%Y', a2.invoicedate),'') || coalesce(', R1: ' || strftime('%d.%m.%Y', a2.reminderdate1),'') || coalesce(', R2: ' || strftime('%d.%m.%Y', a2.reminderdate2),'') || coalesce(', R3: ' || strftime('%d.%m.%Y', a2.reminderdate3),'')         as invoiced, a2.reference, "+
+       "coalesce(printf(\"%.2f â‚¬\",a2.payedamount), 0.00) || coalesce (strftime('<br/> %d.%m.%Y', a2.payeddate),'') as payement,"+
+       "coalesce(printf(\"%.2f â‚¬\",a2.benefitamount), 0.00) as benefitamount," +
+       "'<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' || a2.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || CASE WHEN a2.invoicefile IS NOT NULL and a2.invoicefile != '' THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || a2.invoicefile || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span>' else '' end || "+
+       "CASE WHEN a2.childuuid IS NOT NULL AND a2.accmonth IS NOT NULL THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\" confirm_delete_accounting(''' || a2.uuid || ''');title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' " +
+       " ELSE '' END AS act from accounting a2 " +
+ " where a2.accmonth = '"+ initdate.toISOString().substring(0,10)+"' ) acc on (plx.childuuid=acc.childuuid) left join (" +
+"select childuuid, group_concat( '<span class=\"glyphicon glyphicon-calendar\"></span>:' || calweek || '&nbsp;<span class=\"glyphicon glyphicon-time\"></span>: ' || weekduration || '&nbsp;<span class=\"glyphicon glyphicon-cuterly\"></span>: ' || weeklunch,'<br/>') as presencedetails from ( "+
+"select childuuid, calweek, monlunch + tuelunch + wedlunch + thulunch + frilunch + satlunch  as weeklunch, "+
+"monduration + tueduration + wedduration + thuduration + friduration + satduration + monduration2 + tueduration2 + wedduration2 + thuduration2 + friduration2 + satduration2 as weekduration " +
+" from (       " +      "select childuuid,daydate,strftime('%Y', daydate) as calyear, " +
+ "case when strftime('%w', daydate)= '0' then strftime('%W', date(daydate, '-6 days')) else strftime('%W', date(date(daydate), '-' || strftime('%w', date(daydate)) || ' days', '+1 day')) end as calweek, ";
+ for (var i=1;i<aax.length;i++){
+  accsql += "CASE WHEN lunch = 1 AND status IN (1, 5) AND strftime('%w', daydate) = '"+ i +"' THEN 1 ELSE 0 END AS "+ aax[i]+"lunch, ";
+ }
+ for (var i=1;i<aax.length;i++){
+  accsql += "CASE WHEN status IS NOT NULL AND strftime('%w', daydate) = '"+ i +"'  THEN CAST(( (( coalesce(CAST(SUBSTR(endtime1, 1, 2) AS INT),0) * 3600)+( coalesce(CAST(SUBSTR(endtime1, 4, 2) AS INT),0) * 60))- ((coalesce(CAST(SUBSTR(begintime1, 1, 2) AS INT),0) * 3600)+( coalesce(CAST(SUBSTR(begintime1, 4, 2) AS INT),0) * 60)) ) / 3600 AS REAL) ELSE 0.0 END AS "+ aax[i]+"duration, ";
+  accsql += "CASE WHEN status IS NOT NULL AND strftime('%w', daydate) = '"+ i +"'  THEN CAST(( (( coalesce(CAST(SUBSTR(endtime2, 1, 2) AS INT),0) * 3600)+( coalesce(CAST(SUBSTR(endtime2, 4, 2) AS INT),0) * 60))- ((coalesce(CAST(SUBSTR(begintime2, 1, 2) AS INT),0) * 3600)+( coalesce(CAST(SUBSTR(begintime2, 4, 2) AS INT),0) * 60)) ) / 3600 AS REAL) ELSE 0.0 END AS "+ aax[i]+"duration2, ";
+ }
+ accsql +=  " null as nouse from presence where daydate between '"+monthmin+"' and '"+monthmax+"' ) prx group by calweek,childuuid ) prx2 group by childuuid ) prd on (prd.childuuid=acc.childuuid);";
+
+  jsdump("ACCMONTH" + accsql);
+  var accdata = appdb.dbquery(accsql);
+  jsdump(accdata);
+  //numchilds = accdata.sqldata.length;
+  var headerdata = [];
+  headerdata = getlabelswithkey("clientnumber,checkservicenumber,childname,presencedetails,planneddetails,reference,invoiced,payement,benefitamount,act");
+  //monthtotalhourcosts,monthtotallunchcosts,monthtotalcosts,
+  $("#tbl_accounting").html("");
+  //var hrow = [];
+  //hrow = headerdata;
+  //var tdclass= new Array();
+  var tblheader = '<tr>';
+  //dump("Headerdata:" + JSON.stringify(headerdata) + "\n")
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+    //if ((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf(headerdata[h].keyname) != -1)) {
+    //  if (headerdata[h].class.indexOf('colhidden') == -1) {
+    //    headerdata[h].class += " colhidden"; 
+    //  }
+    //}else {
+      headerdata[h].class.replace("colhidden","");
+    //}
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+  //tblh0 += '</tr>';
+  tblacc = null;
+  //dump("\n\nTBL header: " + tblheader + "\n\n\n");
+  $("#tbl_accounting").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_accounting").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_accounting").append("<tbody>");
+  var curchld = "";
+
+  
+  for (var i in accdata.sqldata){
+    var row = accdata.sqldata[i];
+    
+        var tr = '<tr>';
+        tr += '<td>' + row.clientnumber + '</td>';
+        tr += '<td>' + row.checkservicenumber + '</td>';
+        tr += '<td>' + row.childname + '</td>';
+        tr += '<td class="noprint infoweek">' + row.presencedetails + '</td>';
+        tr += '<td class="noprint infoweek">' + row.planneddetails + '</td>';
+        tr += '<td>' + row.reference + '</td>';
+        //tr += '<td class="alignright totalwidth'+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('monthtotalhourcosts') != -1))?" noprint colhidden":"") +'">' + row.monthtotalhourcosts + '€</td>';
+        //tr += '<td class="alignright totalwidth'+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('monthtotallunchcosts') != -1))?" noprint colhidden":"") +'">' + row.monthtotallunchcosts + '€</td>';
+        //tr += '<td class="alignright totalwidth'+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('monthtotalcosts') != -1))?" noprint colhidden":"") +'">' + row.monthtotalcosts + '€</td>';
+        tr += '<td class="alignright ">' + row.invoiced + '</td>';
+        tr += '<td class="alignright ">' + row.payement + '</td>';
+        tr += '<td class="alignright totalwidth ">' + row.benefitamount + '</td>';
+        tr += '<td class="noprint">' + row.act + '</td></tr>';
+        $("#tbl_accounting").append(tr);
+
+    }
+    
+  $("#tbl_accounting").append("</tbody>");
+  
+
+  tblacc = $("#tbl_accounting").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": true,
+        "destroy": true,
+        "footerCallback": function ( row, data, start, end, display ) {
+         var api = this.api(), data;
+
+            var intVal = function ( i ) {
+                return typeof i === 'string' ?
+                    i.substring(0,i.indexOf("\€"))*1 :
+                    typeof i === 'number' ?
+                        i : 0;
+            };
+            
+            //hTotal = api
+            //    .column( 2, { page: 'current'} )
+            //    .data()
+            //    .reduce( function (a, b) {
+            //        return intVal(a) + intVal(b);
+            //    }, 0 );
+            
+            //lTotal = api
+            //    .column( 3, { page: 'current'} )
+            //    .data()
+            //    .reduce( function (a, b) {
+            //        return intVal(a) + intVal(b);
+            //    }, 0 );
+            fTotal =  api
+                .column( 6, { page: 'current'} )
+                .data()
+                .reduce( function (a, b) {
+                    return intVal(a) + intVal(b);
+                }, 0 );
+            pTotal =  api
+                .column( 7, { page: 'current'} )
+                .data()
+                .reduce( function (a, b) {
+                    return intVal(a) + intVal(b);
+                }, 0 );
+            bTotal =  api
+                .column( 8, { page: 'current'} )
+                .data()
+                .reduce( function (a, b) {
+                    return intVal(a) + intVal(b);
+                }, 0 );
+            //pageTotal = api
+            //    .column( 4, { page: 'current'} )
+            //    .data()
+            //    .reduce( function (a, b) {
+            //        return intVal(a) + intVal(b);
+            //    }, 0 );
+            // Update footer
+            $( api.column( 6 ).footer() ).html(
+                ''+fTotal.toFixed(2) +' â‚¬' 
+            );
+            $( api.column( 7 ).footer() ).html(
+                ''+pTotal.toFixed(2) +' â‚¬' 
+            );
+            $( api.column( 8 ).footer() ).html(
+                ''+bTotal.toFixed(2) +' â‚¬' 
+            );
+            //$( api.column( 4 ).footer() ).html(
+            //    ''+pageTotal.toFixed(2) +' â‚¬' 
+            //);
+            // $( api.column( 3 ).footer() ).html(
+            //    ''+lTotal.toFixed(2) +' â‚¬' 
+            //);
+            //$( api.column( 2 ).footer() ).html(
+            //    ''+hTotal.toFixed(2) +' â‚¬' 
+            //);
+        }
+      });
+
+//  $('#tbl_accounting').on( 'search.dt', function () {
+//    
+//    pconfig.filter = tblacc.api().search();
+//
+//    apppref.setpreference("pageconfig.accounting",pconfig);
+//  } );
+
+  $('#tbl_accounting').on( 'order.dt', function () {
+    pconfig.order= tblacc.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.accounting",pconfig);
+    
+  } );
+  
+//  if (pconfig.filter) {
+//    tblacc.fnFilter(pconfig.filter);
+//  }
+  if (pconfig.order) {
+    //tblacc.fnDraw();
+    tblacc.fnSort(pconfig.order);
+  }
+  //tblacc.fnAdjustColumnSizing();
+  
+  
+
+$('#tbl_accounting tbody').on( 'click', 'tr', function () {
+        if ( $(this).hasClass('selected') ) {
+            //$(this).removeClass('selected');
+        }
+        else {
+            tblacc.$('tr.selected').removeClass('selected');
+            $(this).addClass('selected');
+        }
+    } );
+}
+
+function getdaterangesql(xmonthmin,xmonthmax){
+         var adays = [];
+         
+         var bdate = new Date(xmonthmin);
+         var bend = new Date(xmonthmax);
+         for (var cdt = bdate; cdt <= bend; cdt.setDate(cdt.getDate() + 1)) {
+           if ((cdt.getDay() !== 0) ){
+             adays.push("select date('" + cdt.toLocaleFormat('%Y-%m-%d') + "') as daydate");
+           }
+           
+         }
+         return adays.join(" UNION ");
+       }
+
+
+function set_accmonth(){
+  pconfig.accmonth = $('#accmonth').val();
+
+  apppref.setpreference("pageconfig.accounting",pconfig);
+      globelreq.send_request({
+            page: 'accounting',
+            module: 'accounting',
+            data: null,
+            header: 'Décompte par mois'
+      });
+}
+
+function confirm_delete_accounting(duuid) {
+  delacc.uuid = duuid;
+  $('#confirm_delete_accounting').modal('show');
+}
+
+function delete_accounting() {
+  var xsql = "DELETE FROM accounting where uuid='"+ delacc.uuid+"';";
+
+  appdb.dbexec(xsql);
+  load_accounting_table();
+  delacc ={};
+  
+  $('#confirm_delete_accounting').modal('hide');
+}
+
+function dlg_accounting(myuuid){
+  
+  //alert("TEST");
+  var acc1sql = "SELECT acc.uuid,acc.accmonth,ch.uuid as childuuid,COALESCE( ch.prename, '' ) || ' ' || COALESCE( ch.surname, '' ) || '(' || ch.checkservicenumber || ')' AS childname,case when acc.invoicedate is not null then strftime('%d.%m.%Y',acc.invoicedate) else null end as invoicedate, case when acc.payeddate is not null then strftime('%d.%m.%Y',acc.payeddate) else null end as payeddate, payedamount, invoiceamount,benefitamount, replace(acc.reference,'NOCHECKSERVICE:','') as reference, instr(acc.reference,'NOCHECKSERVICE:') as ischeckservice, case when acc.reminderdate1 is not null then strftime('%d.%m.%Y',acc.reminderdate1) else null end as reminderdate1, case when acc.reminderdate2 is not null then strftime('%d.%m.%Y',acc.reminderdate2) else null end as reminderdate2, case when acc.reminderdate3 is not null then strftime('%d.%m.%Y',acc.reminderdate3) else null end as reminderdate3, case when acc.invoicefile is not null and acc.invoicefile != '' then '"+ importpath.path + system.sep() +"' || acc.invoicefile else null end as invoicefile,'upd' as action FROM accounting acc join childs ch on (ch.uuid=acc.childuuid) where acc.uuid = '"+ myuuid+"';";
+  //jsdump(acc1sql);
+  var acc1data = appdb.dbquery(acc1sql);
+  
+  if (!acc1data.sqldata) {
+    return false;
+    //acc1sql = "SELECT '0' as uuid,'"+ childuuid+"' as childuuid, 1 as ischeckservice, null as invoicedate, null as payeddate, null as payedamount, null as invoiceamount, null as reference,null as benefitamount, null as reminderdate1, null as reminderdate2, null as reminderdate3, null as invoicefile, 'ins' as action;";
+    //acc1data = appdb.dbquery(acc1sql);
+  }
+  acc1data = acc1data.sqldata[0];
+  $("#frmeditaccounting #uuid").val(acc1data.uuid);
+  if (acc1data.ischeckservice > 0){
+    $("#frmeditaccounting #nocheckservice").prop("checked",true);
+  } else {
+    $("#frmeditaccounting #nocheckservice").prop("checked",false);
+  }
+  for (var a in acc1data){
+
+    if ($("#frmeditaccounting #" +a)) {
+      $("#frmeditaccounting #"+a).val(acc1data[a]);
+    }
+  }
+  $("#edit_accounting").modal('show');
+  
+}
+
+function save_accounting(){
+
+  var sql2 = new Array();
+  //var type = 'upd';
+  // if (type == 'ins'){
+  //   sql1.push('"accmonth"');
+  //   sql2.push("'" + initdate.toLocaleFormat('%Y-%m-%d') +"'");
+  // }
+  $("#frmeditaccounting :input").each(function(){
+    var input = $(this);
+    if (input.attr("id") ){
+      // if ((type == 'ins') && (input.attr("id") != 'action')) {
+      //   sql1.push('"' + input.attr("id") + '"');
+      //   if (input.attr("type") == "file") {
+      //     if (!system.fileexists(importpath.path)){
+      //       importpath.create(1,0755);
+      //     }
+      //     var newlocation= importpath.path + system.sep() + system.getFileName(input.val());
+      //     OS.File.copy(input.val(), newlocation);
+      //   }
+      //   var ival = encodeparam(input.val(),input.attr('type'));
+      //   sql2.push(ival);
+      // }
+     //else {
+        if ((input.attr("type") != 'hidden')  && (input.attr("id") != 'childname') && (input.attr("id") != 'ischeckservice'))  {
+          if (input.attr("type") == "file") {
+            if (system.getDirectory(input.val()) != importpath.path) {
+              var newlocation= importpath.path + system.sep() + system.getFileName(input.val());
+              OS.File.copy(input.val(), newlocation);
+            }
+          }
+          var ival = input.val();
+          if ((input.attr("id") == 'reference') && $("#frmeditaccounting #ischeckservice").is(":checked")){
+            ival = "NOCHECKSERVICE:" + ival;
+          }
+          
+          var ival = encodeparam(ival,input.attr('type'));
+          if (input.attr("id") == 'invoicedate'){
+            var newaccmonth = ival.replace(/'/g,"");
+            sql2.push('"accmonth"=\'' + newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7) +"-01'");
+          }
+          sql2.push('"' + input.attr("id") +'"='+ ival);
+
+        }
+      }
+    });
+  var xsql = "UPDATE accounting SET "+sql2.join(',')+" where \"uuid\"='" + $("#frmeditaccounting #uuid").val() + "';";
+  //}
+  // else {
+  //   xsql = "INSERT INTO accounting ("+sql1.join(',')+") VALUES ("+sql2.join(',')+");"; 
+  // }
+
+  appdb.dbexec(xsql);
+  load_accounting_table();
+  $("#frmeditaccounting #uuid").val("0");
+  $("#edit_accounting").modal('hide');
+}
+
+function openfile(fi){
+  var ddir = system.getDirectory(appdb.dbFile.path);
+  var ff = system.openFile(ddir +  system.sep() + 'imports' + system.sep() + crecheuuid +system.sep() + fi);
+}
+
+function onnextmonth() {
+  pconfig.accmonth = $('#accmonth').val();
+
+  
+  var tmpmonth = new Date(encodeparam(pconfig.accmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.accmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.accounting",pconfig);
+      globelreq.send_request({
+            page: 'accounting',
+            module: 'accounting',
+            data: null,
+            header: 'Décompte par mois'
+      });
+}
+
+function onpreviousmonth() {
+  pconfig.accmonth = $('#accmonth').val();
+  var tmpmonth = new Date(encodeparam(pconfig.accmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.accmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.accounting",pconfig);
+      globelreq.send_request({
+            page: 'accounting',
+            module: 'accounting',
+            data: null,
+            header: 'Décompte par mois'
+      });
+}
+
+function generatecsv(){
+       var lastdir = '';
+       if (pconfig.lastdir){
+               lastdir = pconfig.lastdir;
+       }
+       var expfolder = system.selectdirectory(lastdir,"Sélection dossier!");
+       //dump("EXPFOLDER:" + expfolder);
+       if (!expfolder){
+               return;
+       }else {
+               pconfig.lastdir = expfolder.path;
+               apppref.setpreference("pageconfig.accounting",pconfig);
+       }
+       var val = $("#accmonth").val();
+       var cdate = new Date();
+       var accsql = "select planned.childuuid,planned.checkservicenumber,planned.pcalweek,replace(printf(\"%.2f\",COALESCE(planned.weekplantime,0.00)),'.',',') as weekplantime,d1.calweek,replace(printf(\"%.2f\",COALESCE(d1.durationweek,0.00)),'.',',') as durationweek,COALESCE(d1.lunchweek,0) as lunchweek from ( " +
+         "select checkservicenumber || '-' || pcalweek as idjoin,childuuid,pcalweek, weekplantime,checkservicenumber from ("+
+         "select pcalweek,childuuid,sum(monplantime) + sum(tueplantime) + sum(wedplantime) + sum(thuplantime) + sum(friplantime) as weekplantime,checkservicenumber from ("+
+         "select strftime(\"%W\",dd.daydate) as pcalweek, dd.daydate, ch.uuid as childuuid, ch.checkservicenumber,";
+         for (var d4 in aax){
+                 var dw4 = d4;dw4++;
+                 accsql += "case when strftime(\"%w\",dd.daydate) = '"+ dw4+"' then cast( ( strftime( \"%s\", "+ aax[d4]+"timeend )- strftime( \"%s\", "+ aax[d4]+"timebegin ) )/ 3600.0 AS REAL )+ case when "+ aax[d4]+"timebegin2 is not null then CAST( ( strftime( \"%s\", "+ aax[d4]+"timeend2 )- strftime( \"%s\", "+ aax[d4]+"timebegin2 ) )/ 3600.0 AS REAL ) else 0.0 end else 0.00 end as "+ aax[d4]+"plantime,";
+         }
+               accsql += " null as nouse from childs ch join planning pl on ( ch.uuid = pl.childuuid ) JOIN( " ;
+               accsql += getdaterangesql(monthmin,monthmax);
+               accsql += ") dd on ( dd.daydate BETWEEN pl.datebegin AND pl.dateend ) ) group by childuuid,pcalweek ) group by childuuid,pcalweek) planned ";
+        accsql += "left join ( " +
+         "select checkservicenumber || '-' || calweek as idjoin,checkservicenumber,childuuid, calweek , durationweek  , lunchweek " +
+                       " from (SELECT checkservicenumber,ttl.childuuid,calweek, sumdurationcalweek AS durationweek, sumlunchcalweek as lunchweek " +
+
+       
+       "FROM ( SELECT  pch.checkservicenumber, pch.childuuid, px.calweek, px.sumdurationcalweek, px.sumlunchcalweek " +
+       //"CASE WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NOT NULL THEN ( SELECT coalesce(wc0.costsperhour,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || 
+       "FROM ( SELECT ch.uuid AS childuuid,ch.checkservicenumber " +
+       "FROM childs ch JOIN planning pl ON ( ch.uuid=pl.childuuid) " +
+       "WHERE " +
+       "(( pl.datebegin <= DATE('"+monthmin+"') AND pl.dateend >= DATE('"+monthmax+"')) OR pl.datebegin BETWEEN '"+monthmin+"' AND '"+monthmax+"' OR pl.dateend BETWEEN '"+monthmin+"' AND '"+monthmax+"')) pch " +
+       "LEFT JOIN ( "+
+       "SELECT childuuid,calweek,case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then (cast(calweek as int)*7)-7 else (cast(calweek as int)*7) end as caldays ,"+
+       "sumlunchcalweek, coalesce(sum(monduration + tueduration + wedduration + thuduration + friduration),0.0) as sumdurationcalweek " +
+       "FROM ( SELECT childuuid, daydate,calyear, case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then case when calweek < '10' then '0' else '' end || cast(calweek as int) else calweek end as calweek," +
+       "max(monlunch) + max(tuelunch) + max(wedlunch) + max(thulunch) + max(frilunch) AS sumlunchcalweek, " +
+       "MAX(monduration) + MAX(monduration2) AS monduration, " +
+       "MAX(tueduration) + MAX(tueduration2) AS tueduration, " +
+       "MAX(wedduration) + MAX(wedduration2) AS wedduration, " +
+       "MAX(thuduration) + MAX(thuduration2) AS thuduration, " +
+       "MAX(friduration) + MAX(friduration2) AS friduration " +
+       "FROM ( "+
+       "SELECT childuuid, daydate, strftime('%Y',daydate) as calyear," +
+       "case when strftime('%w',daydate)='0' then strftime('%W',date(daydate,'-6 days')) else strftime('%W',date(date(daydate),'-' || strftime('%w',date(daydate)) || ' days','+1 day')) end as calweek, ";
+
+       for (var d1 in aax){
+         var dw = d1;dw++;
+         accsql += "CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '"+dw+"' THEN 1 ELSE 0 END AS "+aax[d1]+"lunch,";
+       }
+
+       for (var d2 in aax){
+         var dw2 = d2;dw2++;
+         accsql += "CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '"+dw2+"' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN  CAST(( (( CAST(SUBSTR(xx."+ aax[d2]+"timeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d2]+"timeend,4,2) AS INT) *60))-  ((CAST(SUBSTR(xx."+ aax[d2]+"timebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d2]+"timebegin,4,2) AS INT) *60)) ) / 3600 AS REAL)  ELSE 0.0 END AS "+ aax[d2]+"duration,";
+       }
+
+
+       for (var d3 in aax){
+         var dw3 = d3;dw3++;
+         accsql += "CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '1' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx."+ aax[d3]+"timebegin2 IS NOT NULL AND xx."+ aax[d3]+"timeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx."+ aax[d3]+"timeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d3]+"timeend2,4,2) AS INT) *60))-  ((CAST(SUBSTR(xx."+ aax[d3]+"timebegin2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d3]+"timebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL)  ELSE 0.0 END AS "+ aax[d3]+"duration2,";
+       }
+
+       accsql += "null as nouse FROM (" +
+       " select vacancydate as daydate, CAST('0' as boolean) as lunch,1 as status,pl.* from vacancy va " +
+       " left join planning pl on (va.vacancydate between pl.datebegin and pl.dateend) " + 
+       " where va.vacancydateto is null and va.vacancydate BETWEEN '"+monthmin+"' AND '"+monthmax+"' AND strftime('%w',va.vacancydate) not in ('0','6') " +
+       " group by va.vacancydate,pl.childuuid " +
+       " union " + 
+       " select pr.daydate,pr.lunch,pr.status,pl.* FROM presence pr " +
+       " JOIN planning pl ON ( pr.childuuid=pl.childuuid) WHERE pr.daydate BETWEEN '"+monthmin+"' AND '"+monthmax+"' "+
+       ") xx " +
+       "WHERE xx.daydate BETWEEN '"+monthmin+"' AND '"+monthmax+"') GROUP BY childuuid,calweek) GROUP BY childuuid,calweek) px " +
+       "ON ( pch.childuuid=px.childuuid) GROUP BY pch.childuuid,px.calweek ) ttl " +
+       "LEFT JOIN accounting acc ON ( ttl.childuuid = acc.childuuid AND acc.accmonth='"+ initdate.toLocaleFormat("%Y-%m-%d")+ "') where calweek is not null) group by childuuid,calweek) d1 ";
+       accsql +=  " on (d1.idjoin=planned.idjoin) order by planned.childuuid,planned.pcalweek;";
+
+        dump("EXPSQL:" + accsql + "\n");
+       
+       var expdbdata = appdb.dbquery(accsql);
+       //dump(JSON.stringify(expdbdata));
+       numchilds = $("#tbl_accounting tbody tr").length -1;
+       var idchkserv = ccreche.sqldata[0].idcheckservice;
+       dump(JSON.stringify(cweeks) + "\n");
+       var wlen = cweeks.length;
+       var expdata = "E;"+ val.substring(3,7) + ";" + parseInt(val.substring(0,2)) + ";" + wlen + ";" + numchilds + ";" + cdate.toLocaleFormat('%d%m%Y') + ";;;;;;;;;;;;\r\n";
+       //expdata += "P;"+ ccreche.sqldata[0].idcheckservice +";"+";;;;;;;;;;;;;;;";
+       var minweek = cweeks[0].cw;
+       var expchild = "";
+       var cntweek = 0;
+       var objrow = {};
+       var allobjects = []
+       for (var r in expdbdata.sqldata){
+               var row = expdbdata.sqldata[r];
+               if (expchild != row.childuuid){
+                       if (expchild != ""){
+                               allobjects.push(objrow);
+
+                       }
+                       objrow = new Object();
+                       objrow["cs"] = row.checkservicenumber;
+                       objrow["weeks"] = {};
+                       for (var w in cweeks){
+                               objrow["weeks"][cweeks[w].cw] = {"time":"0,00","lunch":"0"};
+                       }
+                       expchild = row.childuuid;
+//                     if (r != numchilds-1){
+//                             expdata += "P;" + idchkserv + ";" + row.checkservicenumber + ";";
+//                     }
+               }
+               
+               objrow["weeks"][row.pcalweek]["time"] = ((row.durationweek == '' || row.weekplantime > row.durationweek)?row.weekplantime:row.durationweek);
+               objrow["weeks"][row.pcalweek]["lunch"] = ((row.lunchweek == '')?0:row.lunchweek); 
+//             
+               
+       
+               
+               //expdata += "P;"+ ccreche.sqldata[0].idcheckservice +";"+";;;;;;;;;;;;;;;";
+       }
+       for (var o in allobjects){
+               var obj = allobjects[o];
+               expdata += "P;" + idchkserv + ";"+ obj.cs + ";";
+               for (var w in obj.weeks){
+                       expdata += obj.weeks[w].time + ";" + obj.weeks[w].lunch + ";"; 
+               } 
+               if (wlen == 3){
+                       expdata += "0,00;0;0,00;0;";
+               }
+               if (wlen == 4){
+                       expdata += "0,00;0;";
+               }
+               expdata += "0,00;;0,00;0,00;0,00\r\n";
+               //dump(key(allobjects[0]) + "\n");
+       }
+       //dump(JSON.stringify(allobjects) + "\n");
+       system.WriteTextFile(expdata,expfolder.path + system.sep() + val + "_export_checkservice.csv");
+       //dump(expdata);
+}
+
+function openmonthlypdf(){
+         dump("PDF to Open: " + mpdffile + "\n");
+         var ff = system.openFile(mpdffile);
+}
+
diff --git a/modules/accounting/js/accountingchild.js b/modules/accounting/js/accountingchild.js
new file mode 100644 (file)
index 0000000..f77193a
--- /dev/null
@@ -0,0 +1,633 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+var pconfig = {};
+var winh= window.innerHeight -170;
+var tblacc = null;
+var curchilduuid = '';
+var crecheuuid = null;
+var importpath = null;
+var delacc = {};
+//var lictype = apppref.getpreference("support.lictype");
+
+function initdata(){
+  curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.accountingchild");
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.accountingchild",pconfig);
+  }
+  var ccreche = appdb.dbquery("select uuid from creche LIMIT 1;");
+  crecheuuid = ccreche.sqldata[0].uuid;
+  importpath = FileUtils.File(curcfg.path.local  + system.sep() +"imports" + system.sep() + crecheuuid);
+  //check_accountingtable();
+  load_childlist();
+  if (pconfig.accchild) {
+  //  
+
+    $("#accchild").val(pconfig.accchild);
+  }else {
+    $("#accchild").val($("#accchild option:first").val());
+    pconfig.accchild=$("#accchild option:first").val();
+  }
+  if (!pconfig.accyear){
+    pconfig.accyear=new Date().toLocaleFormat("%Y");
+    apppref.setpreference("pageconfig.accountingchild",pconfig);
+  }
+  //if (lictype != "free"){
+  //  $("#mnuacc").css({"position":"absolute","z-index":"1000"});
+  //}
+  set_selectyears();
+  ////cdate = initdate.toLocaleFormat('%Y-%m-%d');
+  set_infoheader($("#accchild option:selected").text() + " Année:" + pconfig.accyear);
+  //load_column_selection();
+  load_accounting_table();
+  
+}
+
+
+
+function load_accounting_table(){
+  //dump("accountingchild: " + JSON.stringify(pconfig) + "\n");
+  // var daterangesql = "select case when strftime('%Y',date(yeardaybegin)) == '"+pconfig.accyear+"' then yeardaybegin else strftime('%Y-%m-%d',date(date(yeardaybegin),'+7 days')) end as yeardaybegin,"+
+  // "strftime('%Y-%m-%d',date(date(yeardayend),'+6 days')) as yeardayend "+
+  // "from ( " +
+  // "select case when strftime('%w','"+pconfig.accyear+"-01-01') = '1' then strftime('%Y-%m-%d','"+pconfig.accyear+"-01-01') else strftime('%Y-%m-%d', date(date('"+pconfig.accyear+"-01-01','-7 days'),'weekday 1')) end as yeardaybegin, "+
+  // "case when strftime('%w','"+pconfig.accyear+"-12-31') = '1' then strftime('%Y-%m-%d','"+pconfig.accyear+"-12-31') else strftime('%Y-%m-%d', date(date('"+pconfig.accyear+"-12-31','-7 days'),'weekday 1')) end as yeardayend "+
+  // ");";
+  // var daterange = appdb.dbquery(daterangesql);
+  // daterange = daterange.sqldata[0];
+  // var yearmin = daterange.yeardaybegin;
+  // var yearmax = daterange.yeardayend;
+  
+  
+  // var chbornes = appdb.dbquery("select min(daydate) as mindate,max(daydate) as maxdate from presence where strftime('%Y',daydate)='" + pconfig.accyear + "' and childuuid='" + pconfig.accchild + "';");
+  
+  // var monthmin= chbornes.sqldata[0].mindate;
+  // var monthmax= chbornes.sqldata[0].maxdate;
+  var accsql = "select strftime('%m.%Y', acc.accmonth) as calmonth," +
+  "case when nocheckservice = '1' then '<span style=\"color: red;\">(facture non check-service)</span><br/>' else '' end || acc.reference as reference, "+
+   " case when acc.invoiceamount is not null then printf(\"%.2f\",  COALESCE(acc.invoiceamount,  0.00)) || '€' || " +
+    " case  when acc.invoicedate is not null then '<br/>(' || strftime('%d.%m.%Y', acc.invoicedate) || ')' || " +
+   " CASE  WHEN acc.reminderdate1 IS NOT NULL THEN '<br/>R1:' || strftime('%d.%m.%Y', acc.reminderdate1)  ELSE '' END || "+
+   " CASE WHEN acc.reminderdate2 IS NOT NULL THEN '<br/>R2:' || strftime('%d.%m.%Y', acc.reminderdate2)  ELSE ''  END || "+
+   "  CASE  WHEN acc.reminderdate3 IS NOT NULL THEN '<br/>R3:' || strftime('%d.%m.%Y', acc.reminderdate3) ELSE '' END else '' end  else '' end as invoiced,"+
+   " case  when acc.payedamount is not null then printf(\"%.2f\", COALESCE(acc.payedamount,  0.00)) || '€' || "+
+   " case  when acc.payeddate is not null then '<br/>(' || strftime('%d.%m.%Y', acc.payeddate) || ')' else '' end else '' end as payement, "+
+   " case when acc.benefitamount is not null then printf(\"%.2f\",COALESCE(acc.benefitamount,0.00)) || '€' else '' end as benefitamount," +
+   " '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' || acc.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || " +
+   " CASE WHEN acc.invoicefile IS NOT NULL and acc.invoicefile != '' THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || acc.invoicefile || ''');\"  title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span>' else '' end || CASE WHEN acc.childuuid IS NOT NULL AND acc.accmonth IS NOT NULL THEN '<button type=\"button\" class=\"btn btn-danger\" onclick=\" confirm_delete_accounting(''' || acc.uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' ELSE '' END AS act " +
+  " from accounting acc where childuuid='"+ pconfig.accchild+"' and strftime('%Y',acc.accmonth) = '" + pconfig.accyear +"' order by accmonth;";
+  
+//   var accsql = "select strftime( '%m.%Y',acc.accmonth) as calmonth,'' as weekdetails, '' as monthtotalhourcosts,'' as monthtotallunchcosts, '' as monthtotalcosts,replace(acc.reference,'NOCHECKSERVICE:','<span style=\"color: red;\">(facture non check-service)</span><br/>') as reference, " +
+//   "case when acc.invoiceamount is not null then printf(\"%.2f\",COALESCE(acc.invoiceamount,0.00)) || '€' || case when acc.invoicedate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.invoicedate) || ')' || CASE WHEN acc.reminderdate1 IS NOT NULL THEN '<br/>R1:' || strftime('%d.%m.%Y',acc.reminderdate1) ELSE '' END || CASE WHEN acc.reminderdate2 IS NOT NULL THEN '<br/>R2:' || strftime('%d.%m.%Y',acc.reminderdate2) ELSE '' END || CASE WHEN acc.reminderdate3 IS NOT NULL THEN '<br/>R3:' || strftime('%d.%m.%Y',acc.reminderdate3) ELSE '' END else '' end else '' end  as invoiced, " +
+// "case when acc.payedamount is not null then printf(\"%.2f\",COALESCE(acc.payedamount,0.00)) || '€' || case when acc.payeddate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.payeddate) || ')' else '' end else '' end as payement," +
+// "'' as benefitamount," +
+// "'<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' || acc.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || CASE WHEN acc.invoicefile IS NOT NULL and acc.invoicefile != '' THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || acc.invoicefile ||  ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span>'  else '' end || CASE WHEN acc.childuuid IS NOT NULL AND acc.accmonth IS NOT NULL THEN '<button type=\"button\" class=\"btn btn-danger\" onclick=\" confirm_delete_accounting(''' || acc.uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' ELSE '' END AS act  " +
+// " from accounting acc where acc.childuuid='"+ pconfig.accchild +"' and strftime( '%Y',acc.accmonth)='"+pconfig.accyear+"' and acc.reference LIKE 'NOCHECKSERVICE:%' "
+//   //|| ' (' || weekhourcosts || '€/h)' -- || ' (' || weeklunchcosts || '€/déj.)
+//   accsql += "UNION SELECT calmonth, " +
+//   "group_concat( '<span class=\"glyphicon glyphicon-calendar\"></span>:' || calweek || '&nbsp;<span class=\"glyphicon glyphicon-time\"></span>: ' || durationweek  || '&nbsp;h&nbsp;<span class=\"glyphicon glyphicon-cutlery\"></span>: ' || lunchweek ,'<br/>')   AS weekdetails, " +
+//   "printf(\"%.2f\",SUM(weektotalhourcosts)) AS monthtotalhourcosts, " +
+//   "printf(\"%.2f\",SUM(weektotallunchcosts)) AS monthtotallunchcosts, " +
+//   "printf(\"%.2f\",SUM(weektotalhourcosts + weektotallunchcosts)) AS monthtotalcosts, " +
+//   "reference, " +
+//   "invoiced,payement,benefitamount,act FROM ( " +
+//   "SELECT childname,ttl.childuuid,printf(\"%02d\",calweek) AS calweek,calmonth, " +
+//   "printf(\"%.2f\",sumdurationcalweek) AS durationweek, " +
+//   "sumlunchcalweek AS lunchweek, " +
+//   "printf(\"%.2f\",weekhourcosts) AS weekhourcosts, " +
+//   "printf(\"%.2f\",weeklunchcosts) AS weeklunchcosts, " +
+//   "sumdurationcalweek * weekhourcosts AS weektotalhourcosts, " +
+//   "sumlunchcalweek * weeklunchcosts   AS weektotallunchcosts, " +
+//   "REPLACE(acc.reference,'NOCHECKSERVICE:','') as reference," +
+//   "case when acc.invoiceamount is not null then printf(\"%.2f\",COALESCE(acc.invoiceamount,0.00)) || '€' || case when acc.invoicedate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.invoicedate) || ')' || CASE WHEN acc.reminderdate1 IS NOT NULL THEN '<br/>R1:' || strftime('%d.%m.%Y',acc.reminderdate1) ELSE '' END || CASE WHEN acc.reminderdate2 IS NOT NULL THEN '<br/>R2:' || strftime('%d.%m.%Y',acc.reminderdate2) ELSE '' END || CASE WHEN acc.reminderdate3 IS NOT NULL THEN '<br/>R3:' || strftime('%d.%m.%Y',acc.reminderdate3) ELSE '' END else '' end else '' end  as invoiced, " +
+//   "case when acc.payedamount is not null then printf(\"%.2f\",COALESCE(acc.payedamount,0.00)) || '€' || case when acc.payeddate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.payeddate) || ')' else '' end else '' end as payement," +
+//   "case when acc.benefitamount is not null then printf(\"%.2f\",COALESCE(acc.benefitamount,0.00)) || '€' else '' end as benefitamount," +
+//   "'<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' || acc.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || CASE WHEN acc.invoicefile IS NOT NULL and acc.invoicefile != '' THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || acc.invoicefile ||  ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span>'  else '' end || CASE WHEN acc.childuuid IS NOT NULL AND acc.accmonth IS NOT NULL THEN '<button type=\"button\" class=\"btn btn-danger\" onclick=\" confirm_delete_accounting(''' || acc.uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' ELSE '' END AS act  " +
+//   "FROM ( SELECT pch.childname, pch.childuuid, px.calweek, px.calmonth, px.sumdurationcalweek, px.sumlunchcalweek, " +
+//   "CASE WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NOT NULL THEN ( SELECT coalesce(wc0.costsperhour,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1 ) WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NULL THEN ( SELECT coalesce(wc0.costperhourfallback,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1 ) ELSE NULL END AS weekhourcosts,"+
+  
+//   "CASE WHEN px.sumlunchcalweek IS NOT NULL  THEN ( SELECT coalesce(wc0.dailylunchcosts,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1) ELSE NULL END AS weeklunchcosts " +
+//   "FROM ( SELECT COALESCE(ch.prename,'') || ' ' || COALESCE(ch.surname,'') || '<br>(' || " +
+//   "COALESCE(ch.checkservicenumber,'') || ')' AS childname,ch.uuid AS childuuid,ch.checkservicenumber " +
+//   "FROM childs ch JOIN planning pl ON ( ch.uuid=pl.childuuid) WHERE childuuid='"+pconfig.accchild+"' ) pch " +
+//   "LEFT JOIN ( SELECT childuuid, calweek, case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then (cast(calweek as int)*7)-7 else (cast(calweek as int)*7) end as caldays ,calmonth, sumlunchcalweek, COALESCE(SUM(monduration + tueduration + wedduration + thuduration + friduration),0.0) AS sumdurationcalweek FROM " +
+//   "( SELECT childuuid, daydate, calyear,"
+//   +"case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then case when calweek < '10' then '0' else '' end || cast(calweek as int)+1 else calweek end as calweek,"
+//   +"calmonth, MAX(monlunch) + MAX(tuelunch) + MAX(wedlunch) + MAX(thulunch) + MAX(frilunch) AS sumlunchcalweek, MAX(monduration) + MAX(monduration2) AS monduration, MAX(tueduration) + MAX(tueduration2) AS tueduration, MAX(wedduration) + MAX(wedduration2) AS wedduration, MAX(thuduration) + MAX(thuduration2) AS thuduration, MAX(friduration) + MAX(friduration2) AS friduration FROM " +
+//   "( SELECT xx.childuuid, xx.daydate,strftime('%Y',xx.daydate) as calyear, " +
+//   "case when strftime('%w',xx.daydate)='0' then strftime('%W',date(xx.daydate,'-6 days')) else strftime('%W',date(date(xx.daydate),'-' || strftime('%w',date(xx.daydate)) || ' days','+1 day')) end as calweek, " +
+//   "case when strftime('%w',xx.daydate)='0' then strftime('%m.%Y',date(xx.daydate,'-6 days')) else strftime('%m.%Y',date(date(xx.daydate),'-' || strftime('%w',date(xx.daydate)) || ' days','+1 day')) end as calmonth, ";
+//   var aax = ['mon','tue','wed','thu','fri','sat'];
+//   for (var d1 in aax){
+//     var dw = d1;dw++;
+//     accsql += "CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '"+dw+"' THEN 1 ELSE 0 END AS "+aax[d1]+"lunch,";
+//   }
+  
+//   for (var d2 in aax){
+//     var dw2 = d2;dw2++;
+//     accsql += "CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '"+dw2+"' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN  CAST(( (( CAST(SUBSTR(xx."+ aax[d2]+"timeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d2]+"timeend,4,2) AS INT) *60))-  ((CAST(SUBSTR(xx."+ aax[d2]+"timebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d2]+"timebegin,4,2) AS INT) *60)) ) / 3600 AS REAL)  ELSE 0.0 END AS "+ aax[d2]+"duration,";
+//   }
+  
+  
+//   for (var d3 in aax){
+//     var dw3 = d3;dw3++;
+//     accsql += "CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '"+dw3+"' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx."+ aax[d3]+"timebegin2 IS NOT NULL AND xx."+ aax[d3]+"timeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx."+ aax[d3]+"timeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d3]+"timeend2,4,2) AS INT) *60))-  ((CAST(SUBSTR(xx."+ aax[d3]+"timebegin2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d3]+"timebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL)  ELSE 0.0 END AS "+ aax[d3]+"duration2,";
+//   }
+  
+//   accsql += "null as nouse FROM (" +
+//   " select vacancydate as daydate, CAST('0' as boolean) as lunch,1 as status,pl.* from vacancy va " +
+//   " left join planning pl on (va.vacancydate between pl.datebegin and pl.dateend and pl.childuuid='"+pconfig.accchild+"') " + 
+//   " where va.vacancydateto is null and va.vacancydate BETWEEN '"+monthmin+"' AND '"+monthmax+"' AND strftime('%w',va.vacancydate) not in ('0') " +
+//   " group by va.vacancydate,pl.childuuid " +
+//   " union " + 
+//   " select pr.daydate,pr.lunch,pr.status,pl.* FROM presence pr " +
+//   " JOIN planning pl ON ( pr.childuuid=pl.childuuid and pr.childuuid='"+pconfig.accchild+"') WHERE pr.daydate BETWEEN '"+monthmin+"' AND '"+monthmax+"' "+
+//   ") xx " +
+//   "WHERE xx.daydate BETWEEN '"+monthmin+"' AND '"+monthmax+"') GROUP BY calweek) GROUP BY calweek) px " +
+//   "ON ( pch.childuuid=px.childuuid) GROUP BY px.calweek ) ttl LEFT JOIN accounting acc ON (ttl.childuuid = acc.childuuid AND  ttl.calmonth=strftime('%m.%Y',acc.accmonth) AND acc.reference NOT LIKE 'NOCHECKSERVICE:%') WHERE calweek IS NOT NULL) group by calmonth ORDER BY calmonth; ";var accsql = "select strftime( '%m.%Y',acc.accmonth) as calmonth,'' as weekdetails, '' as monthtotalhourcosts,'' as monthtotallunchcosts, '' as monthtotalcosts,replace(acc.reference,'NOCHECKSERVICE:','<span style=\"color: red;\">(facture non check-service)</span><br/>') as reference, " +
+//   "case when acc.invoiceamount is not null then printf(\"%.2f\",COALESCE(acc.invoiceamount,0.00)) || '€' || case when acc.invoicedate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.invoicedate) || ')' || CASE WHEN acc.reminderdate1 IS NOT NULL THEN '<br/>R1:' || strftime('%d.%m.%Y',acc.reminderdate1) ELSE '' END || CASE WHEN acc.reminderdate2 IS NOT NULL THEN '<br/>R2:' || strftime('%d.%m.%Y',acc.reminderdate2) ELSE '' END || CASE WHEN acc.reminderdate3 IS NOT NULL THEN '<br/>R3:' || strftime('%d.%m.%Y',acc.reminderdate3) ELSE '' END else '' end else '' end  as invoiced, " +
+// "case when acc.payedamount is not null then printf(\"%.2f\",COALESCE(acc.payedamount,0.00)) || '€' || case when acc.payeddate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.payeddate) || ')' else '' end else '' end as payement," +
+// "'' as benefitamount," +
+// "'<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' || acc.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || CASE WHEN acc.invoicefile IS NOT NULL and acc.invoicefile != '' THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || acc.invoicefile ||  ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span>'  else '' end || CASE WHEN acc.childuuid IS NOT NULL AND acc.accmonth IS NOT NULL THEN '<button type=\"button\" class=\"btn btn-danger\" onclick=\" confirm_delete_accounting(''' || acc.uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' ELSE '' END AS act  " +
+// " from accounting acc where acc.childuuid='"+ pconfig.accchild +"' and strftime( '%Y',acc.accmonth)='"+pconfig.accyear+"' and acc.reference LIKE 'NOCHECKSERVICE:%' "
+//   //|| ' (' || weekhourcosts || '€/h)' -- || ' (' || weeklunchcosts || '€/déj.)
+//   accsql += "UNION SELECT calmonth, " +
+//   "group_concat( '<span class=\"glyphicon glyphicon-calendar\"></span>:' || calweek || '&nbsp;<span class=\"glyphicon glyphicon-time\"></span>: ' || durationweek  || '&nbsp;h&nbsp;<span class=\"glyphicon glyphicon-cutlery\"></span>: ' || lunchweek ,'<br/>')   AS weekdetails, " +
+//   "printf(\"%.2f\",SUM(weektotalhourcosts)) AS monthtotalhourcosts, " +
+//   "printf(\"%.2f\",SUM(weektotallunchcosts)) AS monthtotallunchcosts, " +
+//   "printf(\"%.2f\",SUM(weektotalhourcosts + weektotallunchcosts)) AS monthtotalcosts, " +
+//   "reference, " +
+//   "invoiced,payement,benefitamount,act FROM ( " +
+//   "SELECT childname,ttl.childuuid,printf(\"%02d\",calweek) AS calweek,calmonth, " +
+//   "printf(\"%.2f\",sumdurationcalweek) AS durationweek, " +
+//   "sumlunchcalweek AS lunchweek, " +
+//   "printf(\"%.2f\",weekhourcosts) AS weekhourcosts, " +
+//   "printf(\"%.2f\",weeklunchcosts) AS weeklunchcosts, " +
+//   "sumdurationcalweek * weekhourcosts AS weektotalhourcosts, " +
+//   "sumlunchcalweek * weeklunchcosts   AS weektotallunchcosts, " +
+//   "REPLACE(acc.reference,'NOCHECKSERVICE:','') as reference," +
+//   "case when acc.invoiceamount is not null then printf(\"%.2f\",COALESCE(acc.invoiceamount,0.00)) || '€' || case when acc.invoicedate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.invoicedate) || ')' || CASE WHEN acc.reminderdate1 IS NOT NULL THEN '<br/>R1:' || strftime('%d.%m.%Y',acc.reminderdate1) ELSE '' END || CASE WHEN acc.reminderdate2 IS NOT NULL THEN '<br/>R2:' || strftime('%d.%m.%Y',acc.reminderdate2) ELSE '' END || CASE WHEN acc.reminderdate3 IS NOT NULL THEN '<br/>R3:' || strftime('%d.%m.%Y',acc.reminderdate3) ELSE '' END else '' end else '' end  as invoiced, " +
+//   "case when acc.payedamount is not null then printf(\"%.2f\",COALESCE(acc.payedamount,0.00)) || '€' || case when acc.payeddate is not null then '<br/>(' || strftime('%d.%m.%Y',acc.payeddate) || ')' else '' end else '' end as payement," +
+//   "case when acc.benefitamount is not null then printf(\"%.2f\",COALESCE(acc.benefitamount,0.00)) || '€' else '' end as benefitamount," +
+//   "'<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' || acc.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || CASE WHEN acc.invoicefile IS NOT NULL and acc.invoicefile != '' THEN '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || acc.invoicefile ||  ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span>'  else '' end || CASE WHEN acc.childuuid IS NOT NULL AND acc.accmonth IS NOT NULL THEN '<button type=\"button\" class=\"btn btn-danger\" onclick=\" confirm_delete_accounting(''' || acc.uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' ELSE '' END AS act  " +
+//   "FROM ( SELECT pch.childname, pch.childuuid, px.calweek, px.calmonth, px.sumdurationcalweek, px.sumlunchcalweek, " +
+//   "CASE WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NOT NULL THEN ( SELECT coalesce(wc0.costsperhour,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1 ) WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NULL THEN ( SELECT coalesce(wc0.costperhourfallback,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1 ) ELSE NULL END AS weekhourcosts,"+
+  
+//   "CASE WHEN px.sumlunchcalweek IS NOT NULL  THEN ( SELECT coalesce(wc0.dailylunchcosts,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+yearmin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1) ELSE NULL END AS weeklunchcosts " +
+//   "FROM ( SELECT COALESCE(ch.prename,'') || ' ' || COALESCE(ch.surname,'') || '<br>(' || " +
+//   "COALESCE(ch.checkservicenumber,'') || ')' AS childname,ch.uuid AS childuuid,ch.checkservicenumber " +
+//   "FROM childs ch JOIN planning pl ON ( ch.uuid=pl.childuuid) WHERE childuuid='"+pconfig.accchild+"' ) pch " +
+//   "LEFT JOIN ( SELECT childuuid, calweek, case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then (cast(calweek as int)*7)-7 else (cast(calweek as int)*7) end as caldays ,calmonth, sumlunchcalweek, COALESCE(SUM(monduration + tueduration + wedduration + thuduration + friduration),0.0) AS sumdurationcalweek FROM " +
+//   "( SELECT childuuid, daydate, calyear,"
+//   +"case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then case when calweek < '10' then '0' else '' end || cast(calweek as int)+1 else calweek end as calweek,"
+//   +"calmonth, MAX(monlunch) + MAX(tuelunch) + MAX(wedlunch) + MAX(thulunch) + MAX(frilunch) AS sumlunchcalweek, MAX(monduration) + MAX(monduration2) AS monduration, MAX(tueduration) + MAX(tueduration2) AS tueduration, MAX(wedduration) + MAX(wedduration2) AS wedduration, MAX(thuduration) + MAX(thuduration2) AS thuduration, MAX(friduration) + MAX(friduration2) AS friduration FROM " +
+//   "( SELECT xx.childuuid, xx.daydate,strftime('%Y',xx.daydate) as calyear, " +
+//   "case when strftime('%w',xx.daydate)='0' then strftime('%W',date(xx.daydate,'-6 days')) else strftime('%W',date(date(xx.daydate),'-' || strftime('%w',date(xx.daydate)) || ' days','+1 day')) end as calweek, " +
+//   "case when strftime('%w',xx.daydate)='0' then strftime('%m.%Y',date(xx.daydate,'-6 days')) else strftime('%m.%Y',date(date(xx.daydate),'-' || strftime('%w',date(xx.daydate)) || ' days','+1 day')) end as calmonth, ";
+//   var aax = ['mon','tue','wed','thu','fri','sat'];
+//   for (var d1 in aax){
+//     var dw = d1;dw++;
+//     accsql += "CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '"+dw+"' THEN 1 ELSE 0 END AS "+aax[d1]+"lunch,";
+//   }
+  
+//   for (var d2 in aax){
+//     var dw2 = d2;dw2++;
+//     accsql += "CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '"+dw2+"' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN  CAST(( (( CAST(SUBSTR(xx."+ aax[d2]+"timeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d2]+"timeend,4,2) AS INT) *60))-  ((CAST(SUBSTR(xx."+ aax[d2]+"timebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d2]+"timebegin,4,2) AS INT) *60)) ) / 3600 AS REAL)  ELSE 0.0 END AS "+ aax[d2]+"duration,";
+//   }
+  
+  
+//   for (var d3 in aax){
+//     var dw3 = d3;dw3++;
+//     accsql += "CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '"+dw3+"' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx."+ aax[d3]+"timebegin2 IS NOT NULL AND xx."+ aax[d3]+"timeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx."+ aax[d3]+"timeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d3]+"timeend2,4,2) AS INT) *60))-  ((CAST(SUBSTR(xx."+ aax[d3]+"timebegin2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx."+ aax[d3]+"timebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL)  ELSE 0.0 END AS "+ aax[d3]+"duration2,";
+//   }
+  
+//   accsql += "null as nouse FROM (" +
+//   " select vacancydate as daydate, CAST('0' as boolean) as lunch,1 as status,pl.* from vacancy va " +
+//   " left join planning pl on (va.vacancydate between pl.datebegin and pl.dateend and pl.childuuid='"+pconfig.accchild+"') " + 
+//   " where va.vacancydateto is null and va.vacancydate BETWEEN '"+monthmin+"' AND '"+monthmax+"' AND strftime('%w',va.vacancydate) not in ('0') " +
+//   " group by va.vacancydate,pl.childuuid " +
+//   " union " + 
+//   " select pr.daydate,pr.lunch,pr.status,pl.* FROM presence pr " +
+//   " JOIN planning pl ON ( pr.childuuid=pl.childuuid and pr.childuuid='"+pconfig.accchild+"') WHERE pr.daydate BETWEEN '"+monthmin+"' AND '"+monthmax+"' "+
+//   ") xx " +
+//   "WHERE xx.daydate BETWEEN '"+monthmin+"' AND '"+monthmax+"') GROUP BY calweek) GROUP BY calweek) px " +
+//   "ON ( pch.childuuid=px.childuuid) GROUP BY px.calweek ) ttl LEFT JOIN accounting acc ON (ttl.childuuid = acc.childuuid AND  ttl.calmonth=strftime('%m.%Y',acc.accmonth) AND acc.reference NOT LIKE 'NOCHECKSERVICE:%') WHERE calweek IS NOT NULL) group by calmonth ORDER BY calmonth; ";
+   //jsdump("accsql");
+ //jsdump(accsql);
+  
+  var accdata = appdb.dbquery(accsql);
+  jsdump("accchildsql");
+  jsdump(accsql);
+  var headerdata = getlabels("calmonth,reference,invoiced,payement,benefitamount,act");
+ //,monthtotalhourcosts,monthtotallunchcosts,monthtotalcosts
+  
+
+  $("#tbl_accounting").html("");
+  
+  //var hrow = headerdata;
+  //var tdclass= new Array();
+  var tblheader = '<tr>';
+
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+    //if ((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf(headerdata[h].keyname) != -1)) {
+    //  if (headerdata[h].class.indexOf('colhidden') == -1) {
+    //    headerdata[h].class += " colhidden"; 
+    //  }
+    //}else {
+      headerdata[h].class.replace("colhidden","");
+    //}
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+
+  
+  $("#tbl_accounting").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_accounting").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_accounting").append("<tbody>");
+  var curchld = "";
+
+  for (var i in accdata.sqldata){
+    var row = accdata.sqldata[i];
+        var tr = '<tr><td>' + row.calmonth + '</td>';
+        //tr += '<td class="infoweek noprint '+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('weekdetails') != -1))?" colhidden":"") +'">' + row.weekdetails + '</td>';
+        //tr += '<td class="alignright totalwidth '+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('monthtotalhourcosts') != -1))?" colhidden":"") +'">' + row.monthtotalhourcosts + '€</td>';
+        //tr += '<td class="alignright totalwidth '+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('monthtotallunchcosts') != -1))?" colhidden":"") +'">' + row.monthtotallunchcosts + '€</td>';
+        //tr += '<td class="alignright totalwidth '+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('monthtotalcosts') != -1))?" colhidden":"") +'">' + row.monthtotalcosts + '€</td>';
+        tr += '<td>'+row.reference+'</td>';
+        tr += '<td class="alignright '+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('invoiced') != -1))?" colhidden":"") +'">' + row.invoiced + '</td>';
+        tr += '<td class="alignright '+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('payement') != -1))?" colhidden":"") +'">' + row.payement + '</td>';
+        tr += '<td class="alignright totalwidth '+ (((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf('benefitamount') != -1))?" colhidden":"") +'">' + row.benefitamount + '</td>';
+        tr += '<td class="noprint">' + row.act + '</td></tr>';
+        $("#tbl_accounting").append(tr);
+    }
+    
+  $("#tbl_accounting").append("</tbody>");
+
+
+  tblacc = $("#tbl_accounting").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": true,
+        "destroy": true,
+        "footerCallback": function ( row, data, start, end, display ) {
+            var api = this.api(), data;
+
+            var intVal = function ( i ) {
+                return typeof i === 'string' ?
+                    i.substring(0,i.indexOf("\€"))*1 :
+                    typeof i === 'number' ?
+                        i : 0;
+            };
+            
+            //hTotal = api
+            //    .column( 2, { page: 'current'} )
+            //    .data()
+            //    .reduce( function (a, b) {
+            //        return intVal(a) + intVal(b);
+            //    }, 0 );
+            
+            //lTotal = api
+            //    .column( 3, { page: 'current'} )
+            //    .data()
+            //    .reduce( function (a, b) {
+            //        return intVal(a) + intVal(b);
+            //    }, 0 );
+            fTotal =  api
+                .column( 2, { page: 'current'} )
+                .data()
+                .reduce( function (a, b) {
+                    return intVal(a) + intVal(b);
+                }, 0 );
+            pTotal =  api
+                .column( 3, { page: 'current'} )
+                .data()
+                .reduce( function (a, b) {
+                    return intVal(a) + intVal(b);
+                }, 0 );
+            bTotal =  api
+                .column( 4, { page: 'current'} )
+                .data()
+                .reduce( function (a, b) {
+                    return intVal(a) + intVal(b);
+                }, 0 );
+            //pageTotal = api
+            //    .column( 4, { page: 'current'} )
+            //    .data()
+            //    .reduce( function (a, b) {
+            //        return intVal(a) + intVal(b);
+            //    }, 0 );
+            // Update footer
+            $( api.column( 2 ).footer() ).html(
+                ''+fTotal.toFixed(2)  +' â‚¬' 
+            );
+            $( api.column( 3 ).footer() ).html(
+                ''+pTotal.toFixed(2)  +' â‚¬' 
+            );
+            $( api.column( 4 ).footer() ).html(
+                ''+bTotal.toFixed(2) +' â‚¬' 
+            );
+            //$( api.column( 4 ).footer() ).html(
+            //    ''+pageTotal.toFixed(2)  +' â‚¬' 
+            //);
+            // $( api.column( 3 ).footer() ).html(
+            //    ''+lTotal.toFixed(2)  +' â‚¬' 
+            //);
+            //$( api.column( 2 ).footer() ).html(
+            //    ''+hTotal.toFixed(2)  +' â‚¬' 
+            //);
+        }
+      });
+  
+//  $('#tbl_accounting').on( 'search.dt', function () {
+//    pconfig.filter = tblacc.api().search();
+//    apppref.setpreference("pageconfig.accountingchild",pconfig);
+//  } );
+
+  $('#tbl_accounting').on( 'order.dt', function () {
+    pconfig.order= tblacc.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.accountingchild",pconfig);
+  } );
+//  if (pconfig.filter) {
+//    tblacc.fnFilter(pconfig.filter);
+//  }
+  if (pconfig.order) {
+  
+    tblacc.fnSort(pconfig.order);
+  }
+  
+  
+
+$('#tbl_accounting tbody').on( 'click', 'tr', function () {
+        if ( $(this).hasClass('selected') ) {
+           // $(this).removeClass('selected');
+        }
+        else {
+            tblacc.$('tr.selected').removeClass('selected');
+            $(this).addClass('selected');
+        }
+    } );
+}
+
+function set_accchild(){
+  pconfig.accchild = $('#accchild').val();
+  apppref.setpreference("pageconfig.accountingchild",pconfig);
+      globelreq.send_request({
+            page: 'accountingchild',
+            module: 'accounting',
+            data: null,
+            header: 'Décompte par enfant'
+      });
+}
+
+function load_childlist() {
+
+  var chlst = appdb.dbquery("select pr.childuuid,COALESCE(ch.prename,'') || ' ' || COALESCE(ch.surname,'') || ' (' || COALESCE(ch.checkservicenumber,'') || ')' AS childname from childs ch left join presence pr on (ch.uuid=pr.childuuid) where pr.childuuid is not null group by ch.uuid order by childname");
+  chlst = chlst.sqldata;
+  for (c in chlst){
+    $("#accchild").append('<option value="'+ chlst[c].childuuid+'">'+ chlst[c].childname +'</option>');
+  }
+}
+
+
+function dlg_accounting(myuuid){
+  $("#frmeditaccounting #action").val("upd");
+  $("#head_invoice").html("Editer facture");
+  $("#frmeditaccounting #childname").val($("#accchild  option:selected").text());
+  
+  var acc1sql = "SELECT uuid,accmonth,childuuid,case when invoicedate is not null then strftime('%d.%m.%Y',invoicedate) else null end as invoicedate, case when payeddate is not null then strftime('%d.%m.%Y',payeddate) else null end as payeddate, payedamount, benefitamount,invoiceamount, reference, nocheckservice, case when reminderdate1 is not null then strftime('%d.%m.%Y',reminderdate1) else null end as reminderdate1, case when reminderdate2 is not null then strftime('%d.%m.%Y',reminderdate2) else null end as reminderdate2, case when reminderdate3 is not null then strftime('%d.%m.%Y',reminderdate3) else null end as reminderdate3,case when invoicefile is not null  and invoicefile != '' then '"+ importpath.path + system.sep() +"' || invoicefile else null end as invoicefile,'upd' as action FROM accounting where uuid='" + myuuid +"';";
+  
+  var acc1data = appdb.dbquery(acc1sql);
+  
+  if (acc1data.sqldata.length == 0) {
+    acc1sql = "SELECT '0' as uuid,"+ accmonth.substring(3) + "-" + accmonth.substring(0,2) +"-01' as accmonth,'"+ pconfig.accchild+"' as childuuid, null as invoicedate, null as payeddate, null as payedamount, null as invoiceamount,1 as ischeckservice, null as reference, null as reminderdate1, null as reminderdate2, null as reminderdate3,null as benefitamount ,null as invoicefile, 'ins' as action;";
+    acc1data = appdb.dbquery(acc1sql);
+  }
+  acc1data = acc1data.sqldata[0];
+  if (acc1data.nocheckservice == 1){
+    $("#frmeditaccounting #nocheckservice").prop("checked",true);
+  } else {
+    $("#frmeditaccounting #nocheckservice").prop("checked",false);
+  }
+  for (var a in acc1data){
+  
+    if ($("#frmeditaccounting #" +a)) {
+  
+      $("#frmeditaccounting #"+a).val(acc1data[a]);
+    }
+  }
+  $("#edit_accounting").modal('show');
+  
+}
+
+function newinvoice(){
+  if ($("#accchild").val() == ""){
+    alert("Vous devez d'abort selectionner un enfant!");
+    return;
+  }
+  $("#frmeditaccounting :input").each(function(){
+    var input = $(this);
+    input.val("");
+  });
+  $("#frmeditaccounting #nocheckservice").prop("checked",true);
+  $("#frmeditaccounting #action").val("ins");
+  $("#frmeditaccounting #uuid").val("0");
+  $("#frmeditaccounting #childuuid").val($("#accchild").val());
+  $("#head_invoice").html("Ajouter une facture");
+
+  
+  $("#frmeditaccounting #childname").val($("#accchild  option:selected").text());
+  $("#edit_accounting").modal('show');
+}
+
+function save_accounting(){
+        var sql1 = new Array();
+        var sql2 = new Array();
+        // var cntnum = "01"; 
+        var type = $("#frmeditaccounting #action").val();
+        if (type == 'ins'){
+          sql1.push('childuuid');
+          sql2.push("'"+ pconfig.accchild +"'");
+          
+        }
+        
+        $("#frmeditaccounting :input").each(function(){
+          var input = $(this);
+          if (input.attr("id") ){
+            if ((type == 'ins') && (input.attr("type") != 'hidden') && (input.attr("id") != 'accmonth') && (input.attr("id") != 'childname')  && (input.attr("id") != 'ischeckservice')) {
+              
+              sql1.push('"' + input.attr("id") + '"');
+              if (input.attr("type") == "file") {
+                var newlocation= importpath.path + system.sep() + system.getFileName(input.val());
+                if (!system.fileexists(importpath.path)){
+                  importpath.create(1,0755);
+                }
+                OS.File.copy(input.val(), newlocation);
+              }
+              var ival = input.val();
+              if ((input.attr("id") == 'reference') && $("#frmeditaccounting #ischeckservice").is(":checked")){
+                sql1.push("nocheckservice");
+                sql2.push("'1'");
+              }
+              var ival = encodeparam(input.val(),input.attr('type'));
+              sql2.push(ival);
+              if (input.attr("id") == 'invoicedate'){
+                sql1.push('"accmonth"');
+                
+                var newaccmonth = ival.replace(/'/g,"");
+                // var cntx = appdb.dbquery("select count(accmonth)+1 as cnt from accounting where childuuid = '"+ pconfig.accchild +"' and accmonth between date('"+newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7)+"-01') and date('"+newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7)+"-01','+1 month','-1 day'); ");
+                // cntnum = cntx.sqldata[0].cntx;
+                // if (cntnum < 10){ cntnum = "0" + cntnum;}
+                sql2.push('\'' + newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7) +"-01'");
+              }
+            }else {
+              if ((input.attr("type") != 'hidden') &&  (input.attr("id") != 'childname')  && (input.attr("id") != 'ischeckservice')) {
+                if (input.attr("type") == "file") {
+                  if (system.getDirectory(input.val()) != importpath.path) {
+                    var newlocation= importpath.path + system.sep() + system.getFileName(input.val());
+                    OS.File.copy(input.val(), newlocation);
+                  }
+                }
+                var ival = input.val();
+                if ((input.attr("id") == 'reference') && $("#frmeditaccounting #ischeckservice").is(":checked")){
+                  sql2.push("nocheckservice='1'");
+                }
+                var ival = encodeparam(ival,input.attr('type'));
+                sql2.push('"' + input.attr("id") +'"='+ ival);
+                if (input.attr("id") == 'invoicedate'){
+                  var newaccmonth = ival.replace(/'/g,"");
+                //   var cntx = appdb.dbquery("select count(accmonth)+1 as cnt from accounting where childuuid = '"+ pconfig.accchild +"' and accmonth between date('"+newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7)+"-01') and date('"+newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7)+"-01','+1 month','-1 day'); ");
+                // cntnum = cntx.sqldata[0].cntx;
+                // if (cntnum < 10){ cntnum = "0" + cntnum;}
+                  sql2.push('"accmonth"=\'' + newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7) +"-01'");
+                }
+                
+              }
+            }
+          }
+
+        });
+        var xsql = "";
+        if (type == 'upd') {
+          xsql = "UPDATE accounting SET "+sql2.join(',')+" where \"uuid\"='" + $("#frmeditaccounting #uuid").val() +"';";
+        }else {
+          sql1.push("uuid");
+          sql2.push("'" + appdb.generate_uuid() + "'");
+          xsql = "INSERT INTO accounting ("+sql1.join(',')+") VALUES ("+sql2.join(',')+");"; 
+        }
+        //jsdump(xsql);
+        appdb.dbexec(xsql);
+        load_accounting_table();
+        $("#frmeditaccounting #uuid").val("0");
+        $("#edit_accounting").modal('hide');
+      }
+
+function print_list(){
+  globelreq.send_request({page:'preview2',data:{page: 'accountingchild'}});
+}
+
+function openfile(fi){
+  var ddir = system.getDirectory(appdb.dbFile.path);
+  var ff = system.openFile(ddir + system.sep() + 'imports' + system.sep() + crecheuuid +system.sep() + fi);
+}
+
+function set_accyear(){
+  pconfig.accyear = $('#accyear').val();
+  apppref.setpreference("pageconfig.accountingchild",pconfig);
+      globelreq.send_request({
+            page: 'accountingchild',
+            module: 'accounting',
+            data: null,
+            header: 'Décompte par enfant'
+      });
+}
+
+function set_selectyears() {
+  var years = appdb.dbquery("select strftime('%Y',min(entrydate)) as minyear,strftime('%Y',max(leavedate)) as maxyear from childs;");
+  var minyear = parseInt(years.sqldata[0].minyear);
+  var maxyear = parseInt(years.sqldata[0].maxyear);
+  for (var y=minyear;y<=maxyear;y++){
+    var sel = "";
+    if (y == pconfig.accyear) {
+      sel=' selected="1" ';
+    }
+    $("#accyear").append("<option value=\""+y+"\""+sel+">"+y+"</option>");
+  }
+  
+}
+
+function confirm_delete_accounting(myuuid) {
+  delacc.uuid = uuid;
+  $('#confirm_delete_accounting').modal('show');
+}
+
+function delete_accounting() {
+  var xsql = "DELETE FROM accounting where uuid='"+ delacc.uuid+"';";
+
+  appdb.dbexec(xsql);
+  load_accounting_table();
+  delacc ={};
+  
+  $('#confirm_delete_accounting').modal('hide');
+}
+
+function load_column_selection() {
+  var columns = 'weekdetails,monthtotalhourcosts,monthtotallunchcosts,monthtotalcosts,invoiced,payement,benefitamount';
+  var head = getlabelswithkey(columns);
+  var hidden_columns = [];
+  //if (pconfig.hidden_columns) {
+  //  hidden_columns = JSON.parse(columns);
+  //}
+  for (var h=0;h<head.length;h++){
+    $('#hidden_columns').append('<option value="'+ head[h].keyname +'" >&lt;span &gt;' +head[h].description+ '&lt;/span&gt;</option>');
+  }
+  $('#hidden_columns').multiselect({enableHTML: true,numberDisplayed:1,nonSelectedText:"Aucune",allSelectedText: 'Tous',nSelectedText: ' selections'});  
+  if (pconfig.hidden_columns) {
+    //$('#hidden_columns' + objid).multiselect({enableHTML: true,numberDisplayed:3,nonSelectedText:"Tous",allSelectedText: 'Tous',nSelectedText: ' selections'});
+    $('#hidden_columns').multiselect('select',pconfig.hidden_columns);
+  } 
+}
+
+function onhidecolumn(coltohide) {
+  pconfig.hidden_columns = $('#hidden_columns').val();//(()?$('#' + objid).val().split(','):null);
+  apppref.setpreference("pageconfig.accountingchild",pconfig);
+  //dump(JSON.stringify(pconfig) + "\n");
+   globelreq.send_request({
+            page: 'accountingchild',
+            module: 'accounting',
+            data: null,
+            header: 'Décompte par enfant'
+      });
+  //dump("Hide column " + coltohide + "\n");
+}
+
+// function check_accountingtable(){
+//   var cols = appdb.dbquery("SELECT type, name,tbl_name,sql FROM sqlite_master where tbl_name='accounting';");
+//   //jsdump(JSON.stringify(cols));
+//   if (cols.sqldata[0].sql.indexOf("nocheckservice") == -1){
+//     //jsdump("Install missing column! ALTER TABLE accounting add column nocheckservice integer");
+//     appdb.dbexec("ALTER TABLE accounting add column nocheckservice integer;");
+//   }
+//   // else {
+//   //   jsdump("missing column found!");
+//   // }
+// }
diff --git a/modules/accounting/js/accountingopeninvoice.js b/modules/accounting/js/accountingopeninvoice.js
new file mode 100644 (file)
index 0000000..30cdcbd
--- /dev/null
@@ -0,0 +1,284 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+var pconfig = {};
+var winh= window.innerHeight -140;
+var tblacc = null;
+var gpaccchild = null;
+var crecheuuid = null;
+var importpath = null;
+//var lictype = apppref.getpreference("support.lictype"); 
+
+function initdata(){
+  curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.accountingopeninvoice");
+
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.accountingopeninvoice",pconfig);
+  }
+  var ccreche = appdb.dbquery("select uuid from creche LIMIT 1;");
+  crecheuuid = ccreche.sqldata[0].uuid;
+  importpath = FileUtils.File(curcfg.path.local  + system.sep() +"imports" + system.sep() + crecheuuid);
+
+  set_infoheader("");
+  load_accounting_table();  
+}
+
+function load_accounting_table(){
+  var xsql = "DELETE from accounting where accmonth='' or accmonth is null;";
+  appdb.dbexec(xsql);
+  var accsql = "select strftime('%m.%Y',acc.accmonth) as calmonth,ch.clientnumber, "  +
+"COALESCE(ch.prename,'') || ' ' || COALESCE(ch.surname,'')  AS childname,ch.checkservicenumber, acc.reference as reference, "  +
+"CASE WHEN acc.invoiceamount IS NOT NULL THEN printf(\"%.2f\",COALESCE(acc.invoiceamount,0.00)) || '€' || CASE WHEN acc.invoicedate IS NOT NULL THEN '<br/>(' || strftime('%d.%m.%Y',acc.invoicedate) || ')' || CASE WHEN acc.reminderdate1 IS NOT NULL THEN '<br/>R1:' || strftime('%d.%m.%Y',acc.reminderdate1) ELSE '' END || CASE WHEN acc.reminderdate2 IS NOT NULL THEN '<br/>R2:' || strftime('%d.%m.%Y',acc.reminderdate2) ELSE '' END || CASE WHEN acc.reminderdate3 IS NOT NULL THEN '<br/>R3:' || strftime('%d.%m.%Y',acc.reminderdate3) ELSE '' END ELSE '' END ELSE '' END AS invoiced, "  +
+"CASE WHEN acc.payedamount IS NOT NULL THEN printf(\"%.2f\",COALESCE(acc.payedamount,0.00)) || '€' || CASE WHEN acc.payeddate IS NOT NULL THEN '<br/>(' || strftime('%d.%m.%Y',acc.payeddate) || ')' ELSE '' END ELSE '' END AS payement, "  +
+"'<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_accounting(''' ||  acc.uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' || case when acc.invoicefile is not null and acc.invoicefile != '' then '<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile(''' || acc.invoicefile || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span></button>' else '' end AS act "  +
+"from accounting acc join childs ch on (acc.childuuid=ch.uuid) "  +
+"where (acc.invoiceamount is not null and acc.payedamount is null) or (acc.payedamount < acc.invoiceamount) order by acc.accmonth desc;";
+
+  
+  var accdata = appdb.dbquery(accsql);
+  var headerdata = getlabels("calmonth,clientnumber,childname,checkservicenumber,reference,invoiced,payement,act");
+  
+
+  $("#tbl_accounting").html("");
+  
+  var hrow = headerdata;
+  var tdclass= new Array();
+  var tblheader = '<tr>';
+
+  for (var h=0;h<hrow.length;h++){
+    if (hrow[h] == 'act') {
+      headerdata[h].class =headerdata[h].class + " action1btn";
+    }
+
+    tdclass.push(headerdata[h].class);
+
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+  
+  $("#tbl_accounting").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_accounting").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_accounting").append("<tbody>");
+  var curchld = "";
+  for (var i in accdata.sqldata){
+    var row = accdata.sqldata[i];
+        var tr = '<tr><td>' + row.calmonth + '</td>';
+        tr += '<td>' + row.clientnumber + '</td>';
+        tr += '<td>' + row.childname + '</td>';
+        tr += '<td>' + row.checkservicenumber + '</td>';
+        tr += '<td>' + row.reference + '</td>';
+        tr += '<td class="alignright">' + row.invoiced + '</td>';
+        tr += '<td class="alignright">' + row.payement + '</td>';
+        tr += '<td class="noprint">' + row.act + '</td></tr>';
+        $("#tbl_accounting").append(tr);
+    }
+    
+  $("#tbl_accounting").append("</tbody>");
+  tblacc = $("#tbl_accounting").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": true,
+        "destroy": true,
+        "footerCallback": function ( row, data, start, end, display ) {
+            var api = this.api(), data;
+
+            var intVal = function ( i ) {
+                return typeof i === 'string' ?
+                    i.substring(0,i.indexOf("\€"))*1 :
+                    typeof i === 'number' ?
+                        i : 0;
+            };
+            
+            fTotal =  api
+                .column( 5, { page: 'current'} )
+                .data()
+                .reduce( function (a, b) {
+                    return intVal(a) + intVal(b);
+                }, 0 );
+            pTotal =  api
+                .column( 6, { page: 'current'} )
+                .data()
+                .reduce( function (a, b) {
+                    return intVal(a) + intVal(b);
+                }, 0 );
+  
+            // Update footer
+            $( api.column( 5 ).footer() ).html(
+                ''+fTotal.toFixed(2)  +' â‚¬' 
+            );
+            $( api.column( 6 ).footer() ).html(
+                ''+pTotal.toFixed(2)  +' â‚¬' 
+            );
+            
+        }
+      });
+  
+//  $('#tbl_accounting').on( 'search.dt', function () {
+//    pconfig.filter = tblacc.api().search();
+//    apppref.setpreference("pageconfig.accountingopeninvoice",pconfig);
+//  } );
+
+  $('#tbl_accounting').on( 'order.dt', function () {
+    pconfig.order= tblacc.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.accountingopeninvoice",pconfig);
+  } );
+//  if (pconfig.filter) {
+//    tblacc.fnFilter(pconfig.filter);
+//  }
+  if (pconfig.order) {
+   
+    tblacc.fnSort(pconfig.order);
+  }
+  
+  
+
+$('#tbl_accounting tbody').on( 'click', 'tr', function () {
+        if ( $(this).hasClass('selected') ) {
+
+        }
+        else {
+            tblacc.$('tr.selected').removeClass('selected');
+            $(this).addClass('selected');
+        }
+    } );
+}
+
+
+function dlg_accounting(myuuid){
+
+  
+  var acc1sql = "SELECT acc.uuid as uuid,acc.accmonth,ch.prename || ' ' || ch.surname as childname,acc.nocheckservice,acc.childuuid,case when acc.invoicedate is not null then strftime('%d.%m.%Y',acc.invoicedate) else null end as invoicedate, case when acc.payeddate is not null then strftime('%d.%m.%Y',acc.payeddate) else null end as payeddate, acc.payedamount,acc.benefitamount, acc.invoiceamount, acc.reference, case when acc.reminderdate1 is not null then strftime('%d.%m.%Y',acc.reminderdate1) else null end as reminderdate1, case when acc.reminderdate2 is not null then strftime('%d.%m.%Y',acc.reminderdate2) else null end as reminderdate2, case when acc.reminderdate3 is not null then strftime('%d.%m.%Y',acc.reminderdate3) else null end as reminderdate3,case when acc.invoicefile is not null and acc.invoicefile != '' then '"+ importpath.path + system.sep() +"' || acc.invoicefile else null end as invoicefile,'upd' as action FROM accounting acc join childs ch on (acc.childuuid=ch.uuid) where acc.uuid='"+myuuid+"';";
+  
+  //jsdump("acc1sql");
+  //jsdump(acc1sql);
+  var acc1data = appdb.dbquery(acc1sql);
+  if (!acc1data.sqldata) {
+    return false;
+  }
+  acc1data = acc1data.sqldata[0];
+  
+  for (var a in acc1data){
+    if (a == "nocheckservice"){
+      if (acc1data[a] == 1){
+        $("#frmeditaccounting #nocheckservice").prop("checked",true);
+      } else {
+        $("#frmeditaccounting #nocheckservice").prop("checked",false);
+      }
+    }
+    if ($("#frmeditaccounting #" +a)) {
+
+      $("#frmeditaccounting #"+a).val(acc1data[a]);
+    }
+  }
+  $("#edit_accounting").modal('show');
+  
+}
+
+function save_accounting(){
+  var sql1 = new Array();
+  var sql2 = new Array();
+  // var cntnum = "01"; 
+  var type = $("#frmeditaccounting #action").val();
+  if (type == 'ins'){
+    sql1.push('childuuid');
+    sql2.push("'"+ pconfig.accchild +"'");
+    
+  }
+  
+  $("#frmeditaccounting :input").each(function(){
+    var input = $(this);
+    if (input.attr("id") ){
+      if ((type == 'ins') && (input.attr("type") != 'hidden') && (input.attr("id") != 'accmonth') && (input.attr("id") != 'childname')  && (input.attr("id") != 'ischeckservice')) {
+        
+        sql1.push('"' + input.attr("id") + '"');
+        if (input.attr("type") == "file") {
+          var newlocation= importpath.path + system.sep() + system.getFileName(input.val());
+          if (!system.fileexists(importpath.path)){
+            importpath.create(1,0755);
+          }
+          OS.File.copy(input.val(), newlocation);
+        }
+        var ival = input.val();
+        if ((input.attr("id") == 'reference') && $("#frmeditaccounting #ischeckservice").is(":checked")){
+          sql1.push("nocheckservice");
+          sql2.push("'1'");
+        }
+        var ival = encodeparam(input.val(),input.attr('type'));
+        sql2.push(ival);
+        if (input.attr("id") == 'invoicedate'){
+          sql1.push('"accmonth"');
+          
+          var newaccmonth = ival.replace(/'/g,"");
+          // var cntx = appdb.dbquery("select count(accmonth)+1 as cnt from accounting where childuuid = '"+ pconfig.accchild +"' and accmonth between date('"+newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7)+"-01') and date('"+newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7)+"-01','+1 month','-1 day'); ");
+          // cntnum = cntx.sqldata[0].cntx;
+          // if (cntnum < 10){ cntnum = "0" + cntnum;}
+          sql2.push('\'' + newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7) +"-01'");
+        }
+      }else {
+        if ((input.attr("type") != 'hidden') &&  (input.attr("id") != 'childname')  && (input.attr("id") != 'ischeckservice')) {
+          if (input.attr("type") == "file") {
+            if (system.getDirectory(input.val()) != importpath.path) {
+              var newlocation= importpath.path + system.sep() + system.getFileName(input.val());
+              OS.File.copy(input.val(), newlocation);
+            }
+          }
+          var ival = input.val();
+          if ((input.attr("id") == 'reference') && $("#frmeditaccounting #ischeckservice").is(":checked")){
+            sql2.push("nocheckservice='1'");
+          }
+          var ival = encodeparam(ival,input.attr('type'));
+          sql2.push('"' + input.attr("id") +'"='+ ival);
+          if (input.attr("id") == 'invoicedate'){
+            var newaccmonth = ival.replace(/'/g,"");
+          //   var cntx = appdb.dbquery("select count(accmonth)+1 as cnt from accounting where childuuid = '"+ pconfig.accchild +"' and accmonth between date('"+newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7)+"-01') and date('"+newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7)+"-01','+1 month','-1 day'); ");
+          // cntnum = cntx.sqldata[0].cntx;
+          // if (cntnum < 10){ cntnum = "0" + cntnum;}
+            sql2.push('"accmonth"=\'' + newaccmonth.substring(0,4) + "-" + newaccmonth.substring(5,7) +"-01'");
+          }
+          
+        }
+      }
+    }
+
+  });
+  var xsql = "";
+  if (type == 'upd') {
+    xsql = "UPDATE accounting SET "+sql2.join(',')+" where \"uuid\"='" + $("#frmeditaccounting #uuid").val() +"';";
+  }else {
+    sql1.push("uuid");
+    sql2.push("'" + appdb.generate_uuid() + "'");
+    xsql = "INSERT INTO accounting ("+sql1.join(',')+") VALUES ("+sql2.join(',')+");"; 
+  }
+  //jsdump(xsql);
+  appdb.dbexec(xsql);
+  load_accounting_table();
+  $("#frmeditaccounting #uuid").val("0");
+  $("#edit_accounting").modal('hide');
+}
+
+function print_list(){
+  globelreq.send_request({page:'preview2',data:{page: 'accountingopeninvoice'}});
+}
+
+function openfile(fi){
+  var ddir = system.getDirectory(appdb.dbFile.path);
+  var ff = system.openFile(ddir + system.sep() + 'imports' + system.sep() + crecheuuid +system.sep() + fi);
+}
+
diff --git a/modules/accounting/js/accountingyear.js b/modules/accounting/js/accountingyear.js
new file mode 100644 (file)
index 0000000..5abcad1
--- /dev/null
@@ -0,0 +1,501 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg ) 
+
+var pconfig = {};
+var cdate = null;
+var initdate = new Date();
+initdate.setDate(1);
+var winh= window.innerHeight -120;
+var tblacc = null;
+var curchilduuid = '';
+var crecheuuid = null;
+var importpath = null;
+//var lictype = apppref.getpreference("support.lictype"); 
+//var amonth = ['','Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Aôut','Septembre','Novembre','Décembre'];
+//var amonth = ['','Janv','Févr','Mars','Avril','Mai','Juin','Juil','Aôut','Sept','Nov','Déc'];
+var defamountcolors ={ "invoiced":"#003300","payed":"#660066","benefit":"#663300","openinvoices":"#cc0000","income":"#000000"};
+//"preview":"#ff6600","calculated":"#003366",
+var defamounttitles ={
+  //"calculated":"calculées",
+      "invoiced":"facturées",
+      "payed":"payées",
+      "benefit":"prestations",
+      "openinvoices":"factures ouverts",
+      "income":"revenu (facturées + prestations)"
+      //"preview":"prévision"
+      };
+      
+function initdata(){
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.accountingyear");
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.accountingyear",pconfig);
+  }
+  if (!pconfig.amountcolors) {
+    pconfig.amountcolors = defamountcolors;
+  }
+  if (!pconfig.filteramount) {
+    pconfig.filteramount = ["calculated","openinvoices","income"];
+  }
+  if ((!pconfig) || (!pconfig.accyear)){
+    pconfig.accyear=new Date().toLocaleFormat("%Y");
+    apppref.setpreference("pageconfig.accountingyear",pconfig);
+  }
+  //if (lictype != "free"){
+  //  $("#mnuacc").css({"position":"absolute","z-index":"1000"});
+  //}
+  set_selectyears();
+  load_amount_selection("filter_amounts");
+
+  
+  set_infoheader( "Année " + pconfig.accyear);
+  load_accounting_table();
+  
+}
+
+function print_list(){
+  globelreq.send_request({page:'preview2',data:{page: 'accounting'}});
+}
+
+function load_accounting_table(){
+  
+  var daterangesql = "select case when strftime('%Y',date(yeardaybegin)) == '"+pconfig.accyear+"' then yeardaybegin else strftime('%Y-%m-%d',date(date(yeardaybegin),'+7 days')) end as yeardaybegin,"+
+  "strftime('%Y-%m-%d',date(date(yeardayend),'+6 days')) as yeardayend "+
+  "from ( " +
+  "select case when strftime('%w','"+pconfig.accyear+"-01-01') = '1' then strftime('%Y-%m-%d','"+pconfig.accyear+"-01-01') else strftime('%Y-%m-%d', date(date('"+pconfig.accyear+"-01-01','-7 days'),'weekday 1')) end as yeardaybegin, "+
+  "case when strftime('%w','"+pconfig.accyear+"-12-31') = '1' then strftime('%Y-%m-%d','"+pconfig.accyear+"-12-31') else strftime('%Y-%m-%d', date(date('"+pconfig.accyear+"-12-31','-7 days'),'weekday 1')) end as yeardayend "+
+  ");";
+  var daterange = appdb.dbquery(daterangesql);
+  daterange = daterange.sqldata[0];
+  var ydaybegin = daterange.yeardaybegin;
+  var ydayend = daterange.yeardayend;
+  
+  var accsql = "SELECT childname, CAST(substr(calmonth,1,2) as int) as calmonth, substr(calmonth,4) as calyear, ";
+  //if ((pconfig.filteramount.indexOf("calculated") != -1)  ){
+  //  accsql += "case when substr(calmonth,4) || substr(calmonth,1,2) <= strftime('%Y%m',date('now')) then printf(\"%.2f\",SUM(weektotalhourcosts + weektotallunchcosts)) else null end AS calculatedamount, ";
+  //}
+  //if ((pconfig.filteramount.indexOf("preview") != -1)  ){
+  //  accsql += "case when substr(calmonth,4) || substr(calmonth,1,2) > strftime('%Y%m',date('now')) then printf(\"%.2f\",SUM(weektotalhourcosts + weektotallunchcosts))  else null end AS previewamount, ";
+  //}
+  if (pconfig.filteramount.indexOf("invoiced") != -1) {
+    accsql += "case when invoiceamount is not null then printf(\"%.2f\",invoiceamount) else null end as invoicedamount, ";
+  }
+  if (pconfig.filteramount.indexOf("payed") != -1) {
+    accsql += "case when payedamount is not null then printf(\"%.2f\",payedamount) else null end as payedamount, ";
+  }
+  if (pconfig.filteramount.indexOf("benefit") != -1) {
+    accsql += "case when benefitamount is not null then printf(\"%.2f\",benefitamount) else null end as benefitamount, ";
+  }
+  if (pconfig.filteramount.indexOf("openinvoices") != -1) {
+    accsql += "case when invoiceamount is not null and (payedamount is null or payedamount < invoiceamount) is not null then printf(\"%.2f\",invoiceamount - coalesce(payedamount,0.00)) else null end as openinvoicesamount, ";
+  }
+  if (pconfig.filteramount.indexOf("income") != -1) {
+    accsql += "case when benefitamount is not null or invoiceamount is not null then printf(\"%.2f\",coalesce(benefitamount,0.00) + coalesce(invoiceamount,0.00)) else null end as incomeamount, ";
+  }
+
+accsql += "null as nouse FROM ( SELECT childname, ttl.childuuid, calmonth, sumdurationcalweek * weekhourcosts AS weektotalhourcosts, sumlunchcalweek * weeklunchcosts AS weektotallunchcosts, acc.invoiceamount, acc.payedamount, benefitamount " +
+"FROM ( SELECT pch.childname, pch.childuuid, px.calweek, px.calmonth, px.sumdurationcalweek, px.sumlunchcalweek, " +
+
+"CASE WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NOT NULL THEN ( SELECT coalesce(wc0.costsperhour,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+ydaybegin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1 ) WHEN px.sumdurationcalweek IS NOT NULL AND pch.checkservicenumber IS NULL THEN ( SELECT coalesce(wc0.costperhourfallback,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+ydaybegin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1 ) ELSE NULL END AS weekhourcosts,"+
+
+"CASE WHEN px.sumlunchcalweek IS NOT NULL  THEN ( SELECT coalesce(wc0.dailylunchcosts,0.00) FROM costs wc0 WHERE wc0.startdate < date('"+ydaybegin+"','+' || caldays || ' days') and wc0.weeklyhourslimit <= px.sumdurationcalweek ORDER BY wc0.startdate DESC,wc0.weeklyhourslimit DESC LIMIT 1) ELSE NULL END AS weeklunchcosts " +
+
+"FROM ( SELECT COALESCE(ch.prename,'') || ' ' || COALESCE(ch.surname,'') || '<br>(' || COALESCE(ch.checkservicenumber,'') || ')' AS childname, ch.uuid AS childuuid,ch.checkservicenumber FROM childs ch JOIN planning pl ON ( ch.uuid=pl.childuuid) ) pch " +
+"LEFT JOIN ( SELECT childuuid, calweek,case when strftime('%w',date(calyear ||'-01-01')) in ('1','2','3','4') then (cast(calweek as int)*7)-7 else (cast(calweek as int)*7) end as caldays, calmonth, sumlunchcalweek, " +
+"COALESCE(SUM(monduration + tueduration + wedduration + thuduration + friduration),0.0) AS sumdurationcalweek " +
+"FROM ( SELECT childuuid, daydate,calmonth,calyear, " +
+"CASE WHEN strftime('%w',DATE(calyear ||'-01-01')) IN ('1', '2', '3', '4') THEN CASE WHEN calweek < '10' THEN '0' ELSE '' END || CAST(calweek AS INT)+1 ELSE calweek END AS calweek, " +
+"MAX(monlunch) + MAX(tuelunch) + MAX(wedlunch) + MAX(thulunch) + MAX(frilunch) AS sumlunchcalweek, " +
+"MAX(monduration) + MAX(monduration2) AS monduration, " +
+"MAX(tueduration) + MAX(tueduration2) AS tueduration, " +
+"MAX(wedduration) + MAX(wedduration2) AS wedduration, " +
+"MAX(thuduration) + MAX(thuduration2) AS thuduration, " +
+"MAX(friduration) + MAX(friduration2) AS friduration " +
+"FROM ( SELECT xx.childuuid, xx.daydate, strftime('%Y',xx.daydate) AS calyear, " +
+"CASE WHEN strftime('%w',xx.daydate)='0' THEN strftime('%W',DATE(xx.daydate,'-6 days')) ELSE strftime('%W',DATE(DATE(xx.daydate),'-' || strftime('%w',DATE(xx.daydate)) || ' days', '+1 day')) END AS calweek, " +
+"CASE WHEN strftime('%w',xx.daydate)='0' THEN strftime('%m.%Y',DATE(xx.daydate,'-6 days')) ELSE strftime('%m.%Y',DATE(DATE(xx.daydate),'-' || strftime('%w',DATE(xx.daydate)) || ' days', '+1 day')) END AS calmonth, " +
+"CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '1' THEN 1 ELSE 0 END AS monlunch, " +
+"CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '2' THEN 1 ELSE 0 END AS tuelunch, " +
+"CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '3' THEN 1 ELSE 0 END AS wedlunch, " +
+"CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '4' THEN 1 ELSE 0 END AS thulunch, " +
+"CASE WHEN lunch=1 AND status IN (1,5) AND strftime('%w',daydate) = '5' THEN 1 ELSE 0 END AS frilunch, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '1' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN CAST(( (( CAST(SUBSTR(xx.montimeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.montimeend,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.montimebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.montimebegin,4, 2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS monduration, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '2' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN CAST(( (( CAST(SUBSTR(xx.tuetimeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.tuetimeend,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.tuetimebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.tuetimebegin,4, 2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS tueduration, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '3' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN CAST(( (( CAST(SUBSTR(xx.wedtimeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.wedtimeend,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.wedtimebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.wedtimebegin,4, 2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS wedduration, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '4' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN CAST(( (( CAST(SUBSTR(xx.thutimeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.thutimeend,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.thutimebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.thutimebegin,4, 2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS thuduration, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '5' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend THEN CAST(( (( CAST(SUBSTR(xx.fritimeend,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.fritimeend,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.fritimebegin,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.fritimebegin,4, 2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS friduration, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '1' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx.montimebegin2 IS NOT NULL AND xx.montimeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx.montimeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.montimeend2,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.montimebegin2,1 ,2) AS INT) *3600)+( CAST(SUBSTR (xx.montimebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS monduration2, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '1' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx.tuetimebegin2 IS NOT NULL AND xx.tuetimeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx.tuetimeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.tuetimeend2,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.tuetimebegin2,1 ,2) AS INT) *3600)+( CAST(SUBSTR (xx.tuetimebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS tueduration2, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '1' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx.wedtimebegin2 IS NOT NULL AND xx.wedtimeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx.wedtimeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.wedtimeend2,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.wedtimebegin2,1 ,2) AS INT) *3600)+( CAST(SUBSTR (xx.wedtimebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS wedduration2, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '1' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx.thutimebegin2 IS NOT NULL AND xx.thutimeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx.thutimeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.thutimeend2,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.thutimebegin2,1 ,2) AS INT) *3600)+( CAST(SUBSTR (xx.thutimebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS thuduration2, " +
+"CASE WHEN xx.status IS NOT NULL AND strftime('%w',xx.daydate) = '1' AND xx.daydate BETWEEN xx.datebegin AND xx.dateend AND xx.fritimebegin2 IS NOT NULL AND xx.fritimeend2 IS NOT NULL THEN CAST(( (( CAST(SUBSTR(xx.fritimeend2,1,2) AS INT) *3600)+( CAST(SUBSTR(xx.fritimeend2,4,2) AS INT) *60))- ((CAST(SUBSTR(xx.fritimebegin2,1 ,2) AS INT) *3600)+( CAST(SUBSTR (xx.fritimebegin2,4,2) AS INT) *60)) ) / 3600 AS REAL) ELSE 0.0 END AS friduration2, " +
+"NULL AS nouse FROM ( " +
+"SELECT vacancydate AS daydate, CAST('0' AS BOOLEAN) AS lunch, 1 AS status, pl.* FROM vacancy va LEFT JOIN planning pl ON ( va.vacancydate BETWEEN pl.datebegin AND pl.dateend) WHERE va.vacancydateto is null and va.vacancydate BETWEEN '"+ydaybegin+"' AND '"+ydayend+"' AND strftime('%w',va.vacancydate) NOT IN ('0', '6') GROUP BY va.vacancydate, pl.childuuid " +
+"UNION " +
+"SELECT pr.daydate, pr.lunch, pr.status, pl.* FROM presence" +
+" pr JOIN planning pl ON ( pr.childuuid=pl.childuuid) WHERE pr.daydate BETWEEN '"+ydaybegin+"' AND ";
+
+if (pconfig.filteramount.indexOf("preview") != -1) {
+  accsql += "(select max(zz.daydate)  from presence zz where strftime('%Y-%m',zz.daydate) = strftime('%Y-%m',date('now')))"
+  accsql += " UNION " +
+"SELECT tmp.daydate, CASE WHEN pa.monlunch='1' AND strftime('%w',tmp.daydate) = '1' THEN 1 " +
+"WHEN pa.tuelunch='1' AND strftime('%w',tmp.daydate) = '2' THEN 1 " +
+"WHEN pa.wedlunch='1' AND strftime('%w',tmp.daydate) = '3' THEN 1 " +
+"WHEN pa.thulunch='1' AND strftime('%w',tmp.daydate) = '4' THEN 1 " +
+"WHEN pa.frilunch='1' AND strftime('%w',tmp.daydate) = '5' THEN 1 else 0 end as lunch, 1 as status , pa.*  " +
+"FROM (select daydate from ( ";
+ accsql += getsqldaterange(ydaybegin,ydayend);
+ accsql += ") dd where dd.daydate not in (select vacancydate from vacancy where vacancydateto is null) and dd.daydate > (select max(yy.daydate)  from presence yy where strftime('%Y-%m',yy.daydate) = strftime('%Y-%m',date('now'))   ) and strftime('%w',dd.daydate) not in ('0','6') ) tmp  " +
+"LEFT JOIN planning pa ON ( tmp.daydate BETWEEN pa.datebegin AND pa.dateend) ";
+  
+}else {
+  accsql += "'"+ydayend+"'";
+}
+accsql += ") xx " +
+"WHERE xx.daydate BETWEEN '"+ydaybegin+"' AND '"+ydayend+"' ";
+if (pconfig.filteramount.indexOf("preview") == -1) {
+  accsql += " and strftime('%Y-%m',xx.daydate) <= strftime('%Y-%m',date('now')) ";
+}
+accsql += ") GROUP BY childuuid,calweek) GROUP BY childuuid,calweek) px    " +
+"ON ( pch.childuuid=px.childuuid) GROUP BY px.childuuid,px.calweek ) ttl " +
+"LEFT JOIN accounting acc ON ( ttl.childuuid = acc.childuuid AND ttl.calmonth=strftime('%m.%Y',acc.accmonth)) WHERE calweek IS NOT NULL) " +
+"GROUP BY childname,calmonth ORDER BY childname,calmonth;";
+
+  var accdata = appdb.dbquery(accsql);
+  //dump(accsql + "\n");
+  var headerdata = getlabels("childname,jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec,total");
+  $("#tbl_accounting").html("");
+  
+  var hrow = headerdata;
+  var tdclass= new Array();
+  var tblheader = '<tr>';
+
+  for (var h=0;h<hrow.length;h++){
+    tdclass.push(headerdata[h].class);
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+  }
+  tblheader += '</tr>';
+  
+  $("#tbl_accounting").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_accounting").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_accounting").append("<tbody>");
+  var curchild = "";
+  
+  var tbody = "";
+  var trcells = [];
+  var colmonthsum = new Array(12);
+  for (var i in accdata.sqldata){
+    var row = accdata.sqldata[i];
+    if (curchild != row.childname) {
+      if (i != 0) {
+        var cells = [];
+  
+        for (var t in trcells){
+          if (trcells.length > 0) {
+            if (t == 12) {
+              for (var s in trcells[t]){
+                if (trcells[t][s] == 0) {
+                  trcells[t][s] = '';
+                } else {
+                  trcells[t][s] = '<span style="color:' + defamountcolors[pconfig.filteramount[s]] + ';">' + trcells[t][s].toFixed(2) + "</span>";  
+                }
+              }
+            }
+            cells[t] = trcells[t].join("<br/>");
+          }else {
+            cells[t] = "";
+          }
+        }
+
+        tbody += "<td class=\"alignright\">" + cells.join("</td><td class=\"alignright\">") +'</td></tr>';
+      }
+      tbody += '<tr><td>' + row.childname + '</td>';
+      trcells = [[],[],[],[],[],[],[],[],[],[],[],[],[]];
+      
+    }
+    var cmon = parseInt(row.calmonth)-1;
+    for (var x in pconfig.filteramount){
+  
+      trcells[cmon][x] = ((row[pconfig.filteramount[x] + "amount"] != '')?'<span style="color:' + defamountcolors[pconfig.filteramount[x]] + ';">' +row[pconfig.filteramount[x] + "amount"] + "</span>":"");
+      if (!trcells[12][x]) {
+        trcells[12][x] = 0;
+      }
+      trcells[12][x] = trcells[12][x] + ((row[pconfig.filteramount[x] + "amount"] != '')?parseFloat(row[pconfig.filteramount[x] + "amount"]):0.00);  
+    }
+    
+    curchild = row.childname;
+  }
+  var cells = [];
+      
+        for (var t in trcells){
+          if (trcells.length > 0) {
+            if (t == 12) {
+              for (var s in trcells[t]){
+                if (trcells[t][s] == 0) {
+                  trcells[t][s] = '';
+                } else {
+                  trcells[t][s] = '<span style="color:' + defamountcolors[pconfig.filteramount[s]] + ';">' + trcells[t][s].toFixed(2) + "</span>";  
+                }
+              }
+            }
+            cells[t] = trcells[t].join("<br/>");
+          }else {
+            cells[t] = "";
+          }
+        }
+      
+        tbody += "<td class=\"alignright\">" + cells.join("</td><td class=\"alignright\">") +'</td></tr>';
+  $("#tbl_accounting").append(tbody); 
+  $("#tbl_accounting").append("</tbody>");
+  winh = window.innerHeight -130 - ((pconfig.filteramount.length == 0)? 80:pconfig.filteramount.length*16);
+  tblacc = $("#tbl_accounting").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": true,
+        "destroy": true,
+        "footerCallback": function ( row, data, start, end, display ) {
+         var api = this.api(), data;
+            
+            var formatfootercell = function(r){
+              var afil = 0;
+              var dspa = new Array();
+              //dump(r + "\n");
+              for (var x=0;x<r.length;x++){
+                
+                if (r[x] != 0) {
+                  
+                  dspa.push('<span style="color:' + defamountcolors[pconfig.filteramount[x]] + ';">' + r[x].toFixed(2)+ "</span>");
+                  afil++;
+                }
+              }
+              return dspa.join('<br/>');
+            }
+            //var emptarray
+            var nospan = /\d+\.\d+/g;
+            var intVal = function ( i ) {
+                var spl = [];
+                
+                if ((!i) || (i == '') ) {
+                  for (var x = 0;x<pconfig.filteramount.length;x++){
+                    spl.push(0);
+                  }
+                }
+                if (typeof i === 'string') {
+                 
+                  i= i.replace(/<span style="color:#\w+;">/g,'').replace(/<span>/g,'');
+                  spl = i.split("<br>");
+                 
+                  if (!spl) {
+                    spl =new Array();
+                  }
+                  for (var x = spl.length;x<pconfig.filteramount.length;x++){
+                    spl.push(0);
+                  }
+                  for (var x in spl){
+                    if(spl[x] == ''){
+                      spl[x] = 0;
+                    }
+                  }
+                }
+                if (typeof i === 'object') {
+                  spl = i;
+                }
+              
+                return spl;
+            };
+            retvals = function(c,d){
+              var nr = [];
+              
+              for (var s=0;s<pconfig.filteramount.length;s++){
+                if (!c[s]) { c[s] = 0;}
+                if (!d[s]) { d[s] = 0;}
+                nr.push(parseFloat(c[s]) + parseFloat(d[s]));
+              }
+              
+              return nr;
+            }
+            jantotal = api.column( 1, { page: 'current'} ).data().reduce( function (a, b) {
+                    
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            febtotal = api.column( 2, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            martotal = api.column( 3, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            aprtotal = api.column( 4, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            maytotal = api.column( 5, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            juntotal = api.column( 6, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            jultotal = api.column( 7, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            augtotal = api.column( 8, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            septotal = api.column( 9, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            octtotal = api.column( 10, { page: 'current'} ).data().reduce( function (a, b) {
+                    
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            novtotal = api.column( 11, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            dectotal = api.column( 12, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            alltotal = api.column( 13, { page: 'current'} ).data().reduce( function (a, b) {
+                    return retvals(intVal(a),intVal(b));
+                }, 0 );
+            $( api.column( 0).footer() ).html("Totaux");
+            $( api.column( 1 ).footer() ).html(formatfootercell(jantotal));
+            $( api.column( 1 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 2 ).footer() ).html(formatfootercell(febtotal));
+            $( api.column( 2 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 3 ).footer() ).html(formatfootercell(martotal));
+            $( api.column( 3 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 4 ).footer() ).html(formatfootercell(aprtotal));
+            $( api.column( 4 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 5 ).footer() ).html(formatfootercell(maytotal));
+            $( api.column( 5 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 6 ).footer() ).html(formatfootercell(juntotal));
+            $( api.column( 6 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 7 ).footer() ).html(formatfootercell(jultotal));
+            $( api.column( 7 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 8 ).footer() ).html(formatfootercell(augtotal));
+            $( api.column( 8 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 9 ).footer() ).html(formatfootercell(septotal));
+            $( api.column( 9 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 10 ).footer() ).html(formatfootercell(octtotal));
+            $( api.column( 10 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 11 ).footer() ).html(formatfootercell(novtotal));
+            $( api.column( 11 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 12 ).footer() ).html(formatfootercell(dectotal));
+            $( api.column( 12 ).footer() ).addClass("alignright aligntop");
+            $( api.column( 13 ).footer() ).html(formatfootercell(alltotal));
+            $( api.column( 13 ).footer() ).addClass("alignright aligntop");
+        }
+      });
+//  $('#tbl_accounting').on( 'search.dt', function () {
+//    
+//    pconfig.filter = tblacc.api().search();
+//    
+//    apppref.setpreference("pageconfig.accountingyear",pconfig);
+//  } );
+
+  $('#tbl_accounting').on( 'order.dt', function () {
+    pconfig.order= tblacc.fnSettings().aaSorting;
+    
+    apppref.setpreference("pageconfig.accountingyear",pconfig);
+    
+  } );
+  
+//  if (pconfig.filter) {
+//    tblacc.fnFilter(pconfig.filter);
+//  }
+  if (pconfig.order) {
+   
+    tblacc.fnSort(pconfig.order);
+  }
+  
+  
+
+$('#tbl_accounting tbody').on( 'click', 'tr', function () {
+        if ( $(this).hasClass('selected') ) {
+          
+        }
+        else {
+            tblacc.$('tr.selected').removeClass('selected');
+            $(this).addClass('selected');
+        }
+    } );
+}
+
+function getsqldaterange(ydb,yde) {
+  var dtydb = new Date(ydb);
+  
+  var dtyde = new Date(yde);
+  var sday = new Array();
+  for (var cdate=dtydb;cdate<=dtyde;cdate.setDate(cdate.getDate() +1)){
+            if ((cdate.getDay() != 0) && (cdate.getDay() != 6)){
+                sday.push("select date('" + cdate.toLocaleFormat('%Y-%m-%d') +"') as daydate");
+            }
+  }
+  
+  return sday.join(" UNION ");
+}
+
+function set_selectyears() {
+  var years = appdb.dbquery("select strftime('%Y',min(entrydate)) as minyear,strftime('%Y',max(leavedate)) as maxyear from childs;");
+  var minyear = parseInt(years.sqldata[0].minyear);
+  var maxyear = parseInt(years.sqldata[0].maxyear);
+  for (var y=minyear;y<=maxyear;y++){
+    var sel = "";
+    if (y == pconfig.accyear) {
+      sel=' selected="1" ';
+    }
+    $("#accyear").append("<option value=\""+y+"\""+sel+">"+y+"</option>");
+  }
+  
+}
+
+function load_amount_selection(objid) {
+  for (var s in defamounttitles){
+    $('#' + objid).append('<option value="'+ s +'">&lt;span style="color: '+defamountcolors[s]+';" &gt;' +defamounttitles[s]+ '&lt;/span&gt;</option>');
+  }
+  
+  if (pconfig.filteramount) {
+    $('#' + objid).multiselect({enableHTML: true,numberDisplayed:8,nonSelectedText:"Tous",allSelectedText: 'Tous'});
+    $('#' + objid).multiselect('select',pconfig.filteramount);
+  } else {
+    $('#' + objid).multiselect({enableHTML: true,numberDisplayed:8,nonSelectedText:"Tous",allSelectedText: 'Tous'});  
+  }
+}
+
+function onselamount() {
+  if ($('#filter_amounts').val()) {
+    pconfig.filteramount = $('#filter_amounts').val();
+  }else {
+    pconfig.filteramount = ["invoiced","payed","openinvoices","income","benefit"];
+  }
+  apppref.setpreference("pageconfig.accountingyear",pconfig);
+  load_accounting_table();
+}
+
+function set_accyear(){
+  pconfig.accyear = $('#accyear').val();
+  apppref.setpreference("pageconfig.accountingyear",pconfig);
+      globelreq.send_request({
+            page: 'accountingyear',
+            module: 'accounting',
+            data: null,
+            header: 'Bilan annuelle'
+      });
+}
+
+
+
+
diff --git a/modules/accounting/js/checkservice.js b/modules/accounting/js/checkservice.js
new file mode 100644 (file)
index 0000000..4d372a2
--- /dev/null
@@ -0,0 +1,137 @@
+function initdata(){
+       curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+       load_helpers();
+//  //var importpath = {path : apppref.curcfg.dbpath + '/' +apppref.curcfg.db.substring(0,-6) +'/import/' };
+//
+////    pconfig.printlayout = 'list';
+//  var ccreche = appdb.dbquery("select uuid from creche LIMIT 1;");
+//  crecheuuid = ccreche.sqldata[0].uuid;
+//
+//  
+//  if ((apppref.curcfg.pageconfig.data) && (apppref.curcfg.pageconfig.data.accmonth)) {
+//    
+//    initdate = new Date(apppref.curcfg.pageconfig.data.accmonth);
+//    
+//  }
+//  $("#accmonth").val(formatMonthYearDate(initdate));
+//  apppref.setpreference("data","accmonth",formatisodate(initdate));
+//  cdate = initdate.toISOString().substring(0,10);
+//
+//  load_accounting_table();
+//  var bfile = appdb.dbquery("select benefitfile from accounting where accmonth = date('"+apppref.curcfg.pageconfig.data.accmonth+"') group by benefitfile LIMIT 1;");
+//  
+//  if ((bfile.sqldata) && (bfile.sqldata.length == 1)) {
+//    $('#mnuacc').append("<button type=\"button\" class=\"btn btn-primary\" onclick=\"openfile('"+ bfile.sqldata[0].benefitfile +"');\" title=\"editer\"><span class=\"glyphicon glyphicon-open\"></span> fichier des prestations</button>");
+//  }
+//  $("#accmonth").on("change", function (e) {
+//    set_accmonth();
+//  });
+}
+
+function loadinvoicepdf(){
+       var lastdir = apppref.getpreference("support.lastfiledir");
+    var nsIFilePicker = Components.interfaces.nsIFilePicker;
+    var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+    fp.init(window, "selectionner fichier PDF", nsIFilePicker.modeOpen);
+    fp.appendFilter("PDF", "*.pdf");
+    if (lastdir != '') {
+      var nsILocalFile= Components.interfaces.nsILocalFile;
+      var f = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+      f.initWithPath(lastdir);
+      fp.displayDirectory = f;
+    }
+    var res = fp.show();
+    if (res != nsIFilePicker.returnCancel) {
+      var pdffile = fp.file.path;
+      dump("PDF File Selected: " + pdffile + "\n");
+      apppref.setpreference("support.lastfiledir",system.getDirectory(pdffile));
+      $("#importfileinvoice").val(pdffile);
+    }
+}
+
+function loadinvoicexml(){
+       var lastdir = apppref.getpreference("support.lastfiledir");
+    var nsIFilePicker = Components.interfaces.nsIFilePicker;
+    var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+    fp.init(window, "selectionner fichier XML", nsIFilePicker.modeOpen);
+    fp.appendFilter("XML", "*.xml");
+    if (lastdir != '') {
+      var nsILocalFile= Components.interfaces.nsILocalFile;
+      var f = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+      f.initWithPath(lastdir);
+      fp.displayDirectory = f;
+    }
+    var res = fp.show();
+    if (res != nsIFilePicker.returnCancel) {
+      var xmlfile = fp.file.path;
+      dump("XML File Selected: " + xmlfile + "\n");
+      apppref.setpreference("support.lastfiledir",system.getDirectory(xmlfile));
+      $('#importfilexml').val(xmlfile);
+    }
+}
+
+function importfiles(){
+       $("#btnimportfiles").hide();
+       $("#importresult").hide();
+       $("#importprogress").show();
+       
+       OS.File.remove(system.profiledir+ system.sep() + 'lastimport.json',{ignoreAbsent:true});
+       var cname = appdb.dbquery("select uuid from creche LIMIT 1;");
+    cruuid = cname.sqldata[0].uuid;
+    dump(curcfg.path.local  + system.sep() +"imports" + system.sep() + cruuid + "\n");
+    var importpath = FileUtils.File(curcfg.path.local  + system.sep() +"imports" + system.sep() + cruuid);
+    var args = ["-db",'"' + appdb.dbFile.path + '"',"-p",'"' +$("#importfileinvoice").val() + '"',"-o",'"' + importpath.path + '"',"-t",'"' + system.toolsdir() + '"',"-l", '"' + system.profiledir()+ system.sep() + 'lastimport.json'];
+    if ($('#importfilexml').val() != ""){
+       args.push("-x");
+       args.push('"' + $('#importfilexml').val() + '"');
+    }
+    
+    var binpdf = system.toolsdir() + system.sep() + "pdfextract.exe";
+    if (system.os != "WINNT") {
+      binpdf = system.toolsdir() + system.sep() + "pdfextract";
+    }
+    //dump(binpdf + " " +JSON.stringify(args) + "\n");
+    //system.popup("Import Factures!","Import du PDF '"+ pdffile.path +"' en cours!\n");
+    system.runcmdline(binpdf,args,setresult);
+
+}
+
+function setresult(data){
+    var strx = apppref.getpreference("pageconfig.lastpage");
+    var strjresult = system.readLocalTextFile(system.profiledir()+ system.sep() + 'lastimport.json');
+    var strx = apppref.getpreference("pageconfig.lastpage");
+    var x = JSON.parse(strx);
+    
+    if (x.module == 'accounting') {
+       $("#tbl_importresult > tbody").html("");
+       var tblx = sortByKey(JSON.parse(strjresult));
+       for (var i in tblx){
+               dump(i + "\n" + JSON.stringify(tblx[i][1]) + "\n-\n");
+               var xd = '<tr>';
+               xd += '<td>'+tblx[i][1].reference+'</td>';
+               xd += '<td>'+tblx[i][1].checkservice+'</td>';
+               xd += '<td>'+tblx[i][1].sqlresult+'</td>';
+               xd += '</tr>';
+               $("#tbl_importresult > tbody").append(xd);      
+       }
+       $("#importresult").html();
+       $("#importprogress").hide();
+       $("#btnimportfiles").show();
+       $("#importresult").show();
+    }
+    
+  }
+
+function sortByKey(jsObj){
+    var sortedArray = [];
+
+    // Push each JSON Object entry in array by [key, value]
+    for(var i in jsObj)
+    {
+        sortedArray.push([i, jsObj[i]]);
+    }
+
+    // Run native sort function and returns sorted array.
+    return sortedArray.sort();
+}
diff --git a/modules/calendar/calactivity.html b/modules/calendar/calactivity.html
new file mode 100644 (file)
index 0000000..333c09f
--- /dev/null
@@ -0,0 +1,483 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <title>Organisation Personnel</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/jquery.minicolors.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/calendar.css" rel="stylesheet" type="text/css">
+  <style>
+    #tbl_timetable {
+      height: calc(100vh - 90px);
+    }
+table#tbl_timetable {
+    display: flex;
+    flex-flow: column;
+    /*height: 100%;*/
+    
+    width: 100%;
+}
+table#tbl_timetable thead,table#tbl_timetable tfoot {
+    /* head takes the height it requires, 
+    and it's not scaled when table is resized */
+    /*flex: 0 0 auto;*/
+    width: calc(100% - 1.2em);
+}
+table#tbl_timetable tbody {
+    /* body takes all the remaining available space */
+    /*flex: 1 1 auto;*/
+    display: block;
+    overflow-y: scroll;
+}
+table#tbl_timetable tbody tr {
+    width: 100%;
+}
+table#tbl_timetable thead,
+table#tbl_timetable tfoot,
+table#tbl_timetable tbody tr {
+    display: table;
+    table-layout: fixed;
+}
+
+table#tbl_timetable tbody td {
+    padding-bottom: 1px;
+    padding-top: 1px;
+}
+
+td.vacday {
+  background-color: #666666;
+}
+  </style>
+</head> 
+
+<body>
+  <div class="container-fluid" style="padding-top: 5px;">
+    
+    <div class="form-inline"  style="margin-bottom: 5px;">
+  <div class="input-group month btn-group">
+    <span class="input-group-addon">du mois:</span>
+    <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="calmonth" onchange="set_calmonth();">
+    <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+  </div>
+  <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+  <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+  <!--<button class="btn btn-primary" onclick="dlg_event({'uuid':''},'ins');"><span class="glyphicon glyphicon-plus"></span>&nbsp;Planning</button>-->
+  <!--<div class="btn-group" data-toggle="buttons">
+        <label class="btn btn-primary">
+          <input name="view" id="view_bytable" value="table" type="radio"><span class="glyphicons glyphicons-table"></span>
+        </label>
+        <label class="btn btn-primary">
+          <input name="view" id="view_bylist" value="list" type="radio"><span class="glyphicons glyphicons-list"></span>
+        </label>
+        
+      </div>-->
+    
+    
+    <!-- <div class="input-group" id="divfilteractivity">
+      <div class="input-group-addon"><span class="glyphicon glyphicon-filter" aria-hidden="true"></span>&nbsp;Activité</div>
+  <select id="filter_activity" multiple="multiple" onchange="onselactivity(this.id);">
+    
+  </select>
+  </div> -->
+    <div class="input-group" id="divfilterstaff">
+      <div class="input-group-addon"><span class="glyphicon glyphicon-filter" aria-hidden="true"></span>&nbsp;Personnel</div>
+  <select id="filter_staff" multiple="multiple" onchange="onselstaff(this.id);">
+    
+  </select>
+  
+  </div>
+
+  
+  </div>
+    
+    
+    <div class="row" id="view_table">
+      <table id="tbl_timetable" class="table table-striped table-bordered" style="width: 95%;">
+        
+      </table>
+    </div>
+  </div>
+    <!---->
+        <div class="modal fade" id="edit_event">
+          <div class="modal-dialog" style="width: 800px; max-width: 800px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer/Ajouter Planning</h4>
+              </div>
+              <div class="modal-body" style=" height: 550px; max-height: 550px ">
+<div id="frmeditevent">
+                  <input type="hidden" value="0" id="uuid" />
+                  <div class="form-inline row">
+                    <label for="cmb_description" class="col-md-2">Activité</label>
+                    <select id="cmb_clone_activity" onchange="oncloneactivity(this.id);">
+                      <option value="">nouvelle activité...</option>
+                    </select>
+                    
+                  </div>
+                  <div class="form-inline row">
+                    <label for="description" class="col-md-2">Description</label>
+                    <div class="input-group form-inline col-md-8">
+                    <input type="text" value="" id="description"  class="form-control">
+                    <span class="input-group-addon" style="height: 20px; padding-top: 1px; padding-bottom: 1px;"><input type="hidden" id="color" class="form-control " value="" style="margin-top: 0px;"></span>
+                    </div>
+                    <!--<input type="color" value="" id="color"  class="form-control col-md-8" style="width: 10%;">-->
+                  </div>
+                  <div class="form-inline row">
+                    <label for="location" class="col-md-2">Lieu</label>
+                    <input type="text" value="" id="location" class="form-control col-md-6" style="width: 80%;">
+                  </div>
+                  <div class="form-inline row">
+                    <label for="activityuuid" class="col-md-2">Personnel</label>
+                    <select value="" id="staffuuid" class="form-control col-md-8" style="width: 80%;" multiple="multiple" ></select>
+                  </div>
+                  <div class="row">
+                    <div class="form-inline">
+                  <div id="date-container">
+                    <label class="col-md-3">Dates début / fin</label>
+                    <div id="dt_datefrom" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="datefrom"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                    <div id="dt_dateto" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="dateto"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  </div>
+                  </div>
+                  <div class="row">
+                  <div class="form-inline ">
+                    <label   class="col-md-3">heures début / fin</label>
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timefrom">
+                    </div>
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timeto">
+                    </div>
+                  </div>
+                  </div>
+                  <div class="row">
+                    
+                  </div>
+                  <div class="row">
+                    <div class="panel panel-default">
+                      <div class="panel-heading">
+                        <h3 class="panel-title">Récurrence
+                        <select id="freq" onchange="setfreq();">
+                          <option value="">pas de récurrence</option>
+                          <option value="daily">quotidienne</option>
+                          <option value="weekly">hebdomaire</option>
+                          <option value="monthly">mensuelle</option>
+                        </select>
+                        </h3>
+                      </div>
+                    <div class="panel-body">
+                        <div class="row" style="padding-left: 20px; padding-bottom: 3px;">
+                        <div class="form-inline" id="freqinterval">
+                          <label>interval: tous les</label>
+                          <input class="form-control" type="number" id="interval" style="width: 50px;" value="1"/>
+                          <label id="lblfreq"></label>
+                        </div>
+                        </div>
+                        <div class="row" id="freqweekly" style="padding-left: 20px; padding-bottom: 3px;">
+                           <div class="form-inline">
+                            <label>jours de semaine:</label>
+                            <!--<input class="col-md-2 form-control" style="width: 50px;" type="number" id="xtimes_num" value="1"/>-->
+                            <!--<label class="col-md-2">semaines,le </label>-->
+                            <div class="btn-group form-inline" id="weekly_byday" data-toggle="buttons">
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_mo" value="MO" /> Lundi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_tu" value="TU" /> Mardi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_we" value="WE" /> Mercredi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_th" value="TH" /> Jeudi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_fr" value="FR" /> Vendredi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_sa" value="SA" /> Samedi
+                            </label>
+                            <!--<label class="btn btn-primary">-->
+                            <!--  <input type="checkbox" id="weekly_byday_su" value="SU" /> Di-->
+                            <!--</label>-->
+                           </div>
+                           </div>
+                        </div>
+                        <div class="row" id="freqmonthly" style="padding-left: 20px; padding-bottom: 3px;">
+                          <div class="form-inline">
+                            <div class="btn-group" data-toggle="buttons" id="monthly_by">
+                            <label class="btn btn-primary active">
+                              <input type="radio" id="pnl_monthly_byday" value="monthly_byday" checked="1"/> par jour de semaine
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="radio" id="pnl_monthly_bymonthday" value="monthly_bymonthday"/> par jour du mois
+                            </label>
+                            </div>
+                          </div>
+                          <div class="form-inline" id="freq_monthly_byday">
+                            <!--<label class="col-md-2">tous les</label>-->
+                            <!--<input class="col-md-2 form-control" type="number" id="xtimes_num"  style="width: 50px;" value="1"/>-->
+                            <!--<label class="col-formmd-2">mois, le </label><br/>-->
+                            <div class="btn-group" data-toggle="buttons" id="monthly_bydaypos">
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_1" value="1" /> 1ier
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_2" value="2" /> 2ième
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_3" value="3" /> 3ième
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_4" value="4" /> 4ième
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_5" value="5" /> 5ième
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydayppos_last-1" value="-1" /> dernier
+                            </label>
+                          </div>
+                            <br/>
+                            <div class="btn-group" data-toggle="buttons" id="monthly_bydaywday">
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_mo" value="MO" /> Lundi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_tu" value="TU" /> Mardi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_we" value="WE" /> Mercredi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_th" value="TH" /> Jeudi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_fr" value="FR" /> Venedredi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_sa" value="SA" /> Samedi
+                            </label>
+                            <!--<label class="btn btn-primary">-->
+                            <!--  <input type="checkbox" id="monthly_bydaywday_su" value="SU" /> Di-->
+                            <!--</label>-->
+                           </div>
+                            </div>
+                           <div class="form-inline" id="freq_monthly_bymonthday">
+                            <div class="btn-group" data-toggle="buttons" id="monthly_bymonthday">
+                            <label class="btn btn-primary" style="width: 40px; border-radius: 0px;">
+                              <input type="checkbox" id="monthly_bymonthday_1" value="1" />1
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_2" value="2" />2
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_3" value="3" />3
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_4" value="4" />4
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_5" value="5" />5
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_6" value="6" />6
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_7" value="7" />7
+                            </label>                      
+                            <br/>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_8" value="8" />8
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_9" value="9" />9
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_10" value="10" /> 10
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_11" value="11" /> 11
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_12" value="12" /> 12
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_13" value="13" /> 13
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_14" value="14" /> 14
+                            </label>
+                           
+                            <br/>
+                            
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_15" value="15" /> 15
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_16" value="16" /> 16
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_17" value="17" /> 17
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_18" value="18" /> 18
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_19" value="19" /> 19
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_20" value="20" /> 20
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_21" value="21" /> 21
+                            </label>
+                           
+                            <br/>
+                            
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_22" value="22" /> 22
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_23" value="23" /> 23
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_24" value="24" /> 24
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_25" value="25" /> 25
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_26" value="26" /> 26
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_27" value="27" /> 27
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_28" value="28" /> 28
+                            </label>
+                           
+                            <br/>
+                            
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_29" value="29" /> 29
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_31" value="31" /> 30
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_31" value="31" /> 31
+                            </label>
+                            <label class="btn btn-primary" style="width: 157px;" >
+                              <input type="checkbox" id="monthly_bymonthday_-1" value="-1" /> dernier
+                            </label>
+                            
+                            <br/>
+                            <label class="btn btn-primary" style="width: 138px;">
+                              <input type="checkbox" id="monthly_bymonthday_-2" value="-2" /> av.-dernier
+                            </label>
+                            <label class="btn btn-primary" style="width: 138px; border-radius: 0px;">
+                              <input type="checkbox" id="monthly_bymonthday_-3" value="-3" /> av.-av.-dernier
+                            </label>
+                           </div>
+                            
+                          </div>
+                          
+                          
+                          
+                          <br/>
+                          
+                        </div>
+                    </div>
+                    
+                  </div>
+                  </div>
+</div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" id="btndeleteevent" onclick="confirm_delete_event();" class="btn">Supprimer</button>
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_event();" id="btn_save_event" class="btn btn-primary">Accepter</button>
+              </div>
+              </div>
+            </div>
+          </div>
+        <div class="modal fade" id="confirm_delete_event">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Activité</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette Activité?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_event();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="modal fade" id="dlg_vacancy_detail">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Congés</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                <div id="vacdetail">
+                  
+                </div>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn btn-primary">Fermer</button>
+              </div>
+            </div>
+          </div>
+        </div>
+    
+  </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="../../web/js/jquery.minicolors.min.js" type="text/javascript"></script>
+  <script src="js/rrule.js" type="text/javascript"></script>
+  <script src="js/nlp.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/calactivity.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/calendar/calchilds.html b/modules/calendar/calchilds.html
new file mode 100644 (file)
index 0000000..775ee18
--- /dev/null
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+
+  <title>Organisation Enfants</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/style.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/calendar.css" rel="stylesheet" type="text/css">
+<style>
+
+</style>
+</head>
+
+<body>
+    <div class="container-fluid">
+     
+        <div id="frmchart_child" class="form-inline" style="margin-bottom: 7px;">
+          <div class="input-group month btn-group">
+            <span class="input-group-addon">du mois:</span>
+            <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="calmonth">
+            <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+          </div>
+            <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+            <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+                    
+        <!--<div class="btn-group" data-toggle="buttons">
+        <label class="btn btn-primary">
+          <input name="view" id="view_bymonth" value="month" type="radio"><span class="glyphicons glyphicons-calendar"></span>
+        </label>
+
+        <label class="btn btn-primary">
+          <input name="view" id="view_bylist" value="list" type="radio"><span class="glyphicons glyphicons-list"></span>
+        </label>
+        <label class="btn btn-primary">
+          <input name="view" id="view_bytable" value="table" type="radio"><span class="glyphicons glyphicons-table"></span>
+        </label>
+      </div>-->
+        <!--<div class="input-group" id="divfiltergroupe">
+      <div class="input-group-addon"><span class="glyphicon glyphicon-filter" aria-hidden="true"></span>&nbsp; Groupe</div>
+      <select id="filter_group"  onchange="onselgroupe(this.id);">
+      
+  </select>
+  
+  </div>-->
+        <div class="input-group" id="divfiltercalendar">
+      <div class="input-group-addon"><span class="glyphicon glyphicon-filter" aria-hidden="true"></span>&nbsp; Calendrier</div>
+      <select id="filter_calendar">
+      <option value="childsbyplan">enfants heures planifié</option>
+      <!--<option value="childsbyhour">enfants par heure de présence planifié</option>-->
+      <!--<option value="childsbydayrange">enfants par matin/midi/après-midi</option>-->
+      <option value="childsbyweekhours">enfants par heures contractuelles</option>
+      <!--<option value="lunch">Déjeuner</option>-->
+  </select>
+  
+  </div>
+        </div>
+    <div class="row" id="view_table">
+      <table id="tbl_timetable" class="table table-bordered">
+        
+      </table>
+    </div>
+
+      </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="js/rrule.js" type="text/javascript"></script>
+  <script src="js/nlp.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/calchilds.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/calendar/calendar.xul b/modules/calendar/calendar.xul
new file mode 100644 (file)
index 0000000..db23bd1
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_calendar" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton   type="menu" class="btn btn-default" id="tbb_calendar" insertafter="tbb_staff" label="Calendriers" image="modules/calendar/img/calendar.png" orient="vertical">
+    <menupopup class="tlbpopup" style="text-align: left;">
+      <menuitem label="Organisation Enfants" oncommand="navigation.load_appview('calchilds','calendar',null,'Organisation Enfants)');"  id="mnuchilds"/>
+      <menuitem label="Organisation Personnel" oncommand="navigation.load_appview('calactivity','calendar',null,'Organisation Personnel');"  id="mnucalactivity"/>
+      <menuitem label="Congés" oncommand="navigation.load_appview('calvacancy','calendar',null,'Congés');"  id="mnucalvacancy"/>
+      <menuitem label="Jours feriés / Vacances" oncommand="navigation.load_appview('calglobal','calendar',null,'Jours feriés / Vacances');"  id="mnucalglobal"/>
+    </menupopup>
+    </toolbarbutton>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/calendar/calglobal.html b/modules/calendar/calglobal.html
new file mode 100644 (file)
index 0000000..7fa05d2
--- /dev/null
@@ -0,0 +1,200 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+
+<html>
+<head>
+  <title>Jours feriés</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css"><!--<link href="css/glyphicons.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/calendar.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+  <div class="container-fluid" style="padding-top: 5px;">
+    
+    <div class="form-inline">
+      <!--<div class="input-group">
+      <div class="input-group-addon"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>&nbsp; View</div>-->
+  <!--<select id="view_type" >
+    <option value="monthly">par mois</option>
+    <option value="weekly">par semaine</option>
+    <option value="list">liste</option>
+  </select>-->
+  <div class="input-group month btn-group">
+    <span class="input-group-addon">du mois:</span>
+    <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="calmonth">
+    <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+  </div>
+  <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+  <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+  <button class="btn btn-primary" onclick="dlg_vacancyrange({'vacancydate':'0000-00-00','vacancydateto':''},'ins');"><span class="glyphicon glyphicon-plus"></span>&nbsp;Jour Ferié</button>
+  <button class="btn btn-primary" onclick="dlg_vacancyrange({'vacancydate':'0000-00-00','vacancydateto':'0000-00-00'},'ins');"><span class="glyphicon glyphicon-plus"></span>&nbsp;Vacance Scolaire</button>
+<div class="dropdown btn-group">
+  <button class="btn btn-primary dropdown-toggle" type="button" id="ddnofficial" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
+    (ré)import des dates officielles
+    <span class="caret"></span>
+  </button>
+  <ul class="dropdown-menu" aria-labelledby="ddnofficial">
+    <li><a href="javascript:importdata('2016');">2016</a></li>
+    <li><a href="javascript:importdata('2017');">2017</a></li>
+    <li><a href="javascript:importdata('2018');">2018</a></li>
+  </ul>
+</div>  <!--<button class="btn btn-primary" onclick=""><span class="glyphicon glyphicon-print"></span></button>-->
+    </div>
+
+    <div class="row" id="view_monthly">
+      <table class="table table-bordered" id="cal_month">
+        <thead><tr><th>Lundi</th><th>Mardi</th><th>Mercredi</th><th>Jeudi</th><th>Vendredi</th><!--<th>Samedi</th><th>Dimanche</th>--></tr></thead>
+        <tbody>
+          <tr>
+            <td id="day01"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day02"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day03"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day04"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day05"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day06" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day00" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+          </tr>
+
+          <tr>
+            <td id="day11"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day12"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day13"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day14"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day15"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day16" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day10" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+          </tr>
+
+          <tr>
+            <td id="day21"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day22"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day23"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day24"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day25"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day26" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day20" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+          </tr>
+
+          <tr>
+            <td id="day31"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day32"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day33"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day34"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day35"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day36" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day30" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+          </tr>
+
+          <tr>
+            <td id="day41"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day42"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day43"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day44"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day45"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day46" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day40" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+          </tr>
+
+          <tr>
+            <td id="day51"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day52"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day53"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day54"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day55"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day56" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day50" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    <!---->
+        <div class="modal fade" id="edit_vacancyrange">
+          <div class="modal-dialog" style="width: 800px; max-width: 800px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title" id="dlgvacancytitle">Editer vacances scolaire</h4>
+              </div>
+              <div class="modal-body" style="max-height: calc(100vh - 200px);overflow-y: auto; ">
+<div id="frmeditvacancyrange">
+                  <input type="hidden" value="" id="id_vacancydate" />
+                  <input type="hidden" value="" id="id_vacancydateto" />
+                  <div class="form-inline row">
+                    <label for="description" class="col-md-2">Description</label>
+                    <input type="text" value="" id="vacancydescription"  nullable="true" class="form-control col-md-8" style="width: 70%;">
+                    <!--<input type="color" value="" id="color"  nullable="true" class="form-control col-md-8" style="width: 10%;">-->
+                  </div>
+                  <div class="row">
+                    <div class="form-inline">
+                  <div id="date-container">
+                    <label class="col-md-3" id="lbldatevacancy">Dates début / fin</label>
+                    <div id="dt_vacancydate" class="input-group date">
+                      <input type="date" class="form-control" value="" placeholder="dd.mm.yyyy" id="vacancydate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                    <div id="dt_vacancydateto" class="input-group date">
+                      <input type="date" class="form-control" value="" placeholder="dd.mm.yyyy" id="vacancydateto"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  </div>
+                  </div>
+                  <div class="row" style="height: 240px;"></div>
+</div>
+                </div>
+              <div class="modal-footer">
+                <button onclick="confirm_delete_vacancyrange();" id="btndeletevacancy" aria-hidden="true" data-dismiss="modal" class="btn">Supprimer</button>
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button>
+                <button onclick="save_vacancyrange();" id="btn_save_vacancyrange" class="btn btn-primary">Accepter</button>
+              </div>
+              </div>
+            </div>
+          </div>
+          <div class="modal fade" id="confirm_delete_vacancyrange">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Vacance / jour ferié</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce entrée calendrier?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_vacancyrange();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+    
+  </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="js/rrule.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="js/calglobal.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/calendar/callunch.html b/modules/calendar/callunch.html
new file mode 100644 (file)
index 0000000..cedb4f9
--- /dev/null
@@ -0,0 +1,125 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+
+<html>
+<head>
+  <title>Creorga - Calendrier - Organisation interne</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css"><!--<link href="css/glyphicons.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/calendar.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+  <div class="container-fluid" style="padding-top: 5px;">
+    
+    <div class="form-inline">
+      <!--<div class="input-group">
+      <div class="input-group-addon"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>&nbsp; View</div>-->
+  <!--<select id="view_type" >
+    <option value="monthly">par mois</option>
+    <option value="weekly">par semaine</option>
+    <option value="list">liste</option>
+  </select>-->
+  <div class="input-group month btn-group">
+    <span class="input-group-addon">du mois:</span>
+    <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="calmonth" onchange="set_calmonth();">
+    <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+  </div>
+  <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+  <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+  </div>
+    <div class="row" id="view_monthly">
+      <table class="table table-bordered" id="cal_month">
+        <thead><tr><th>Lundi</th><th>Mardi</th><th>Mercredi</th><th>Jeudi</th><th>Vendredi</th><!--<th>Samedi</th><th>Dimanche</th>--></tr></thead>
+        <tbody>
+          <tr>
+            <td id="day01"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day02"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day03"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day04"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day05"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <!--<td id="day06" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+            <!--<td id="day00" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+          </tr>
+
+          <tr>
+            <td id="day11"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day12"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day13"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day14"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day15"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <!--<td id="day16" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+            <!--<td id="day10" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+          </tr>
+
+          <tr>
+            <td id="day21"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day22"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day23"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day24"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day25"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <!--<td id="day26" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+            <!--<td id="day20" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+          </tr>
+
+          <tr>
+            <td id="day31"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day32"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day33"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day34"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day35"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <!--<td id="day36" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+            <!--<td id="day30" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+          </tr>
+
+          <tr>
+            <td id="day41"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day42"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day43"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day44"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day45"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <!--<td id="day46" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+            <!--<td id="day40" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+          </tr>
+
+          <tr>
+            <td id="day51"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day52"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody" ></div></div></td>
+            <td id="day53"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day54"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <td id="day55"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>
+            <!--<td id="day56" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+            <!--<td id="day50" class="panel-dayweekend"><div class="panel-day"><div class="panel-dayhead">00</div><div class="panel-daybody"></div></div></td>-->
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    
+  </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="js/rrule.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="js/callunch.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/calendar/calvacancy.html b/modules/calendar/calvacancy.html
new file mode 100644 (file)
index 0000000..7de44c4
--- /dev/null
@@ -0,0 +1,205 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+
+<html>
+<head>
+  <title>Congé</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/calendar.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+  <div class="container-fluid" style="padding-top: 5px;">
+    
+    <div class="form-inline">
+      <!--<div class="input-group">
+      <div class="input-group-addon"><span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>&nbsp; View</div>-->
+  <!--<select id="view_type" >
+    <option value="monthly">par mois</option>
+    <option value="weekly">par semaine</option>
+    <option value="list">liste</option>
+  </select>-->
+  <div class="input-group month btn-group">
+    <span class="input-group-addon">du mois:</span>
+    <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="calmonth" onchange="set_calmonth();">
+    <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+  </div>
+  <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+  <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+  <div class="input-group" id="divfiltercreche">
+      <div class="input-group-addon"><span class="glyphicon glyphicon-filter" aria-hidden="true"></span>&nbsp;Crèche</div>
+  <select id="filter_creche" multiple="multiple" onchange="onselcreche(this.id);">
+    
+  </select>
+  
+  </div>    
+      
+      
+    </div>
+
+    <div class="row" id="view_table">
+      <table id="tbl_timetable" class="table table-striped table-bordered">
+        
+      </table>
+    </div>
+    <!-- Sel creche -->
+    <!-- <div class="modal fade" id="select_creche">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Selectionner une crèche</h4>
+              </div>
+              <div class="modal-body">
+                               <div id="frmselcreche">
+                  <div class="input-group" id="divfiltercreche">
+                                       <div class="input-group-addon"><span class="glyphicon glyphicon-filter" aria-hidden="true"></span>&nbsp;Crèche</div>
+  <select id="sel_creche">
+    
+  </select>
+  
+  </div>
+                  
+                  
+                  
+                </div>
+              </div>
+              <div class="modal-footer">
+                
+                <button onclick="set_creche();" id="btn_set_creche" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+            </div>
+          </div> -->
+    <!--edit vacancy-->
+        <!-- <div class="modal fade" id="edit_vacancy">
+          <div class="modal-dialog" style="width: 800px; max-width: 800px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer Congé</h4>
+              </div>
+              <div class="modal-body" style="height: 410px; max-height: 410px; ">
+<div id="frmeditvacancy">
+                  <input type="hidden" value="0" id="uuid" />
+                  <div class="form-inline row">
+                    <label for="staffuuid" class="col-md-3">Employé(e)</label>
+                    <select value="" id="staffuuid"  nullable="true" class="form-control"></select>
+                  </div>
+                  <div class="form-inline row">
+                    <label for="dailyduration" class="col-md-3">Journée</label>
+                    <select value="" id="dailyduration"  class="form-control" onchange="setdailydurationfields();">
+                      <option value="1.0">Journée(s) complet(s)</option>
+                      <option value="0.4">demi(s) Journée(s)</option>
+                      <option value="0.">quelques heures</option>
+                    </select>
+                  </div>
+                  
+                    <div class="row form-inline">
+                    <label class="col-md-3">Date début</label>
+                    <div id="dt_datefrom" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="datefrom"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="row form-inline">
+                    <label class="col-md-3">Date fin</label>
+                    <div id="dt_dateto" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="dateto"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  
+                  <div id="ftimefrom" class="row form-inline">
+                  
+                    <label   class="col-md-3">heure début</label>
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timefrom">
+                    </div>
+                  </div>
+                  <div id="fhours" class="row form-line">
+                    <label   class="col-md-3">nbr. d'heures</label>
+                    <select value="" id="hours" class="form-control" style="width: 10%;">
+                      <option value="1">1h</option>
+                      <option value="2">2h</option>
+                      <option value="3">3h</option>
+                      <option value="4">4h</option>
+                      <option value="5">5h</option>
+                      <option value="6">6h</option>
+                      <option value="7">7h</option>
+                      <option value="8">8h</option>
+                    </select>
+                  </div>
+                  <div class="form-inline row">
+                    <label for="type" class="col-md-3">Type de congé</label>
+                    <select id="type" value="">
+                      <option value="0">Congé normal</option>
+                      <option value="1">Congé expetionelle</option> 
+                      <option value="-1">Congé de maladie</option>
+                    </select>          
+                  </div>
+                  <div class="form-inline row">
+                    <label for="description" class="col-md-3">Description</label>
+                    <input type="text" value="" id="description"  nullable="true" class="form-control col-md-6" style="width: 70%;">
+    
+                  </div>
+                  <div class="row" style="height: 120px;"></div>
+                </div>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" onclick="confirm_delete_vacancy();" data-dismiss="modal" id="btndeletevacancy" class="btn">Supprimer</button>
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button>
+                <button onclick="save_vacancy();" id="btn_save_vacancy" class="btn btn-primary">Accepter</button>
+              </div>
+              </div>
+            </div>
+          </div> -->
+         <!--  <div class="modal fade" id="confirm_delete_vacancy">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Congé</h4>
+              </div>
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce congé?<br>
+                
+              </div>
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_vacancy();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div> 
+        </div>-->
+  </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="js/rrule.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="js/calvacancy.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/calendar/img/calendar.png b/modules/calendar/img/calendar.png
new file mode 100644 (file)
index 0000000..cf44ff5
Binary files /dev/null and b/modules/calendar/img/calendar.png differ
diff --git a/modules/calendar/js/calactivity.js b/modules/calendar/js/calactivity.js
new file mode 100644 (file)
index 0000000..a1be271
--- /dev/null
@@ -0,0 +1,1133 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {};
+var initdate = new Date();
+initdate.setDate(1);
+var lastmonthday = null;
+var firstmonday = null;
+var lastsunday = null;
+var winh = window.innerHeight - 140;
+var tblacc = null;
+var lblfreq = {daily:'jour(s)',weekly:'semaine(s)',monthly:'mois'};
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre','Octobre', 'Novembre', 'Décembre'];
+var linkpos = {};
+var posday = {};
+var delac = null;
+var curfreq ={};
+var redate = /\d\d.\d\d.\d\d\d\d/;
+var tblcal = null;
+var vacpos = {};
+var vacdata = null;
+var drsql = "";
+var eventdates = {};
+var curevcolor = "";
+var alltr = {};
+var rtblall = {};
+var crsel = [];
+function initdata() {
+       //curcfg.loadconfig(apppref.getpreference("creorga.support.database.currentdb.num"));
+  load_helpers();
+  $('#view_list').hide();
+  var configdata = apppref.getpreference("pageconfig.calactivity");
+  if (!configdata) {
+    apppref.setpreference("pageconfig.calactivity", '');
+  }
+  if (configdata !== '') {
+    pconfig = JSON.parse(configdata);
+  }
+  pconfig.view = 'table';
+  //if (!pconfig.printlayout) {
+    pconfig.printlayout = 'table';
+    apppref.setpreference("pageconfig.calactivity",pconfig);
+  //}
+  if (pconfig.calmonth) {
+
+    initdate = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+    $("#calmonth").val(pconfig.calmonth);
+  } else {
+    $("#calmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    pconfig.calmonth = initdate.toLocaleFormat('%m.%Y');
+  }
+
+  load_staff_selection('filter_staff');
+  //load_activity_selection('filter_activity','multiple');
+  load_staff_selection('staffuuid');
+  //load_creche_selection();
+  set_infoheader(amonth[parseInt(pconfig.calmonth.substring(0,3))] + " " + pconfig.calmonth.substring(3,8));
+  load_calendar_month();
+  
+  $('#calmonth').on('dp.hide',function(e){
+    set_calmonth();
+  });
+//   $('#frmeditevent #color').minicolors({theme:'bootstrap',position: 'bottom right'});
+//   $("#weekly_byday :input").change(function() {
+
+//     if (this.checked) {
+//       this.setAttribute("checked",true);
+//     }else {
+//       this.removeAttribute("checked");
+//     }
+// });
+//   $("#monthly_bydaypos :input").change(function() {
+  
+//     if (this.checked) {
+//       this.setAttribute("checked",true);
+//     }else {
+//       this.removeAttribute("checked");
+//     }
+
+// });
+//   $("#monthly_bydaywday :input").change(function() {
+
+//     if (this.checked) {
+//       this.setAttribute("checked",true);
+//     }else {
+//       this.removeAttribute("checked");
+//     }
+
+// });
+//   $("#monthly_bymonthday :input").change(function() {
+
+//     if (this.checked) {
+//       this.setAttribute("checked",true);
+//     }else {
+//       this.removeAttribute("checked");
+//     }
+
+// });
+//   $("#monthly_by :input").change(function() {
+//     var xd = this.id.split("_");
+//     curfreq.freqtype=xd[2];
+
+//       this.setAttribute("checked",true);
+
+//     $('#freq_monthly_byday').hide();
+//     $('#freq_monthly_bymonthday').hide();
+//     $('#pnl_monthly_byday').removeAttr("checked");
+//     $('#pnl_monthly_bymonthday').removeAttr("checked");
+
+//     $('#freq_' + this.value).show();
+
+// });
+
+//   $('#frmeditevent #datefrom').on("blur",function (e) {
+//     var ok = true;
+//     if ($('#frmeditevent #datefrom').val().match(redate)) {
+//       $('#btn_save_event').removeAttr("disabled");
+//     }else {
+//       ok = false;
+//       $('#btn_save_event').attr("disabled","1");
+//     }
+//     if ((ok === true) && ($('#frmeditevent #dateto').val() !== '')) {
+//       var tmpdt1 = encodeparam($('#frmeditevent #datefrom').val(),'date');
+//       var tmpdt2 = encodeparam($('#frmeditevent #dateto').val(),'date');
+
+//       if (tmpdt1 >= tmpdt2) {
+//         $('#btn_save_event').attr("disabled","1");
+//       } else {
+//         $('#btn_save_event').removeAttr("disabled");
+//       }
+      
+//     }
+//   });
+//   $('#frmeditevent #dateto').on("blur",function (e) {
+//     var ok = true;
+//     if ($('#frmeditevent #dateto').val().match(redate)) {
+//       $('#btn_save_event').removeAttr("disabled");
+//     }else {
+//       ok = false;
+//       $('#btn_save_event').attr("disabled","1");
+//     }
+//     if ((ok === true) && ($('#frmeditevent #dateto').val() !== '')) {
+//       var tmpdt1 = encodeparam($('#frmeditevent #datefrom').val(),'date');
+//       var tmpdt2 = encodeparam($('#frmeditevent #dateto').val(),'date');
+
+//       if (tmpdt1 >= tmpdt2) {
+//         $('#btn_save_event').attr("disabled","1");
+//       } else {
+//         $('#btn_save_event').removeAttr("disabled");
+//       }
+      
+//     }
+//   });
+}
+
+function load_calendar_month() {
+
+  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), -1 * parseInt(initdate.toLocaleFormat('%w')) + 2);
+  if (firstmonday > initdate) {
+    firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  }
+  lastmonthday = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 1);
+  
+  lastsunday = new Date(lastmonthday.getFullYear(), lastmonthday.getMonth(), lastmonthday.getDate() + 7 - parseInt(lastmonthday.toLocaleFormat('%w')));
+  
+  var weeknum = 0;
+  var cmonth = initdate.getMonth();
+  var sday = [];
+  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), -1 * parseInt(initdate.toLocaleFormat('%w')) + 2);
+  if (firstmonday > initdate) {
+    firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  }
+  load_vacancy_data();
+  
+  load_calendar_data();
+    
+}
+
+function load_calendar_data() {
+  var where = [];
+  if ((pconfig.filterstaff) && (pconfig.filterstaff.length > 0)) {
+    where.push(" st.uuid in ('"+ pconfig.filterstaff.join("','") + "')");
+  }
+  if ((pconfig.filteractivity) && (pconfig.filteractivity.length > 0)) {
+    where.push(" cal.description in ('"+ pconfig.filteractivity.join("','") + "')");
+  }
+  var sql = "SELECT cal.uuid, cal.datefrom, cal.dateto, '<div style=\"display:none;\">' || strftime('%Y%m%d',cal.datefrom) ||'</div>' || strftime('%d.%m.%Y',cal.datefrom) AS tbldatefrom ,strftime('%Y%m%d',cal.datefrom) AS strdatefrom, strftime('%Y%m%d',cal.dateto)   AS strdateto,cal.timefrom, cal.timeto, cal.description, cal.location, cal.color, cal.freq, '[\"' || GROUP_CONCAT(sp.staffuuid,'\",\"') || '\"]' as staffuuid, GROUP_CONCAT(coalesce(st.surname,'') || ' ' || coalesce(st.prename,''), '<br/>' ) as staffnames ,'[\"' || GROUP_CONCAT(st.color,'\",\"') || '\"]' as staffcolors from eventcalendar cal " + ((pconfig.filterstaff)?"":" left ") +" join staffplanning sp on (cal.uuid=sp.eventcalendaruuid " + ((pconfig.filterstaff)?" AND sp.staffuuid in ('"+ pconfig.filterstaff.join("','") + "')":"") +") left join staff st on (sp.staffuuid=st.uuid) "+
+
+  " where (cal.datefrom between '" + initdate.toLocaleFormat('%Y-%m-%d') + "' and '" + lastmonthday.toLocaleFormat('%Y-%m-%d') + "' and (cal.dateto >= '" + initdate.toLocaleFormat('%Y-%m-%d') + "' or cal.dateto is null)) or (cal.dateto between '" + initdate.toLocaleFormat('%Y-%m-%d') + "' and '" + lastmonthday.toLocaleFormat('%Y-%m-%d') + "' and cal.datefrom < '" + initdate.toLocaleFormat('%Y-%m-%d') + "') or ((cal.datefrom <= '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "') and ((cal.dateto >= '" + lastmonthday.toLocaleFormat('%Y-%m-%d') + "') or cal.dateto is null)) "+ ((where.length > 0)?" AND (" + where.join(" or ") + ")":"")+"  group by cal.uuid order by cal.datefrom,cal.dateto;";
+
+  var caldata = appdb.dbquery(sql);
+
+  caldata = caldata.sqldata;
+  get_vacancy_data();
+
+  for (var c in caldata) {
+    if (!eventdates[caldata[c].uuid]) {
+      eventdates[caldata[c].uuid] = {};
+    }
+    var freq = caldata[c].freq;
+    if (freq !== '') {
+      freq += ';DTSTART='+caldata[c].strdatefrom + 'T000000Z';
+      if ((caldata[c].dateto !== '') && (caldata[c].dateto <= lastmonthday.toLocaleFormat('%Y-%m-%d'))){
+        freq += ';UNTIL='+caldata[c].strdateto + 'T000000Z';
+      }else {
+        freq += ';UNTIL='+lastmonthday.toLocaleFormat('%Y%m%d') + 'T000000Z';
+      }
+    }
+    
+    if (freq !== ""){
+      try {
+    var rule = RRule.fromString(freq);
+    rall = rule.all();
+    } catch (ex){
+      //dump("ERROR! loading data!" + ex  + " FREQ:" + freq + "\n");
+    }
+    } else {
+      continue;
+    }
+    for (var r in rall){
+      //dump(rall[r].toLocaleFormat('%Y-%m-%d') + " " +  initdate.toLocaleFormat('%Y-%m-%d')+ " " + lastmonthday.toLocaleFormat('%Y-%m-%d') + "\n" );
+      if ((rall[r].toLocaleFormat('%Y-%m-%d') >= initdate.toLocaleFormat('%Y-%m-%d')) && (rall[r].toLocaleFormat('%Y-%m-%d') <= lastmonthday.toLocaleFormat('%Y-%m-%d'))) {
+        //dump("OK " + rall[r].toLocaleFormat('%Y-%m-%d') + " " +  initdate.toLocaleFormat('%Y-%m-%d')+ " " + lastmonthday.toLocaleFormat('%Y-%m-%d') + "\n" );
+        if (!eventdates[caldata[c].uuid][rall[r].toLocaleFormat('%d')]) {
+          eventdates[caldata[c].uuid][rall[r].toLocaleFormat('%d')] = 1;
+        }
+      }
+
+    }
+  }
+  load_timetable();
+}
+
+function load_timetable() {
+  $('#tbl_timetable').html("");
+  drsql = getdaterangesql();
+  //var ophdata = getoph();
+
+  var thead = [];
+  var totalstaff = [];
+  var weekrange = {};
+  var ltd = "";
+  var bdate = new Date(initdate.toLocaleFormat('%Y-%m-%d'));
+  var enddate = new Date(initdate.getFullYear(),initdate.getMonth() + 1, 0);
+  while (bdate <= enddate){
+    if (!weekrange[parseInt(bdate.toLocaleFormat('%W'))]) {
+      weekrange[parseInt(bdate.toLocaleFormat('%W'))] = 0;
+    }
+    //else if (ltd != ophdata[t].daydate) {
+      weekrange[parseInt(bdate.toLocaleFormat('%W'))] += 1;
+    //}
+    var head = ((bdate.getDate() < 10)?"0"+bdate.getDate():bdate.getDate());//ophdata[t].daydate.substring(8,10);
+    if (thead.indexOf(head) == -1) {
+      thead.push(head);
+    }
+    totalstaff.push(0);
+
+    
+    //ltd = ophdata[t].daydate;
+    bdate = new Date (bdate.getFullYear(),bdate.getMonth(),bdate.getDate() + 1)
+  }
+  var actdata = getstaffactivity();
+
+  var lev = "";
+  var lst = "";
+  
+  var ev = {};
+
+  var alltrx = {};
+  for (var ac in actdata){
+    var evid = actdata[ac].eventuuid;
+
+    if ((evid) && (lev !== evid) && (!alltrx[evid]))  {
+      ev = {"eventuuid":evid,"description": actdata[ac].description ,"timefrom":actdata[ac].timefrom,"timeto":actdata[ac].timeto,"eventcolor":actdata[ac].eventcolor};
+      for (var h in thead){
+        ev[thead[h]] = {};
+      }
+      alltrx[evid] = ev;
+     
+    }
+    var cday = actdata[ac].daydate.substring(8,10);
+    
+    if ((evid) && (eventdates[evid]) && (eventdates[evid][cday])) {
+      
+      alltrx[evid][cday]={"staffuuid":JSON.parse(actdata[ac].staffuuid),"staffcolor":JSON.parse(actdata[ac].staffcolor),"staffnames":JSON.parse(actdata[ac].staffnames)};
+      
+    }
+    lev = null;
+    lev = evid;
+    
+  }
+  
+  var vacdata = getstaffvacancy();
+  var staffuuids = [];
+  for (var vc in vacdata){
+    var dx = new Date(vacdata[vc].daydate).toLocaleFormat('%d');
+    if (staffuuids.indexOf(vacdata[vc].staffuuid)) {
+      staffuuids.push(vacdata[vc].staffuuid);
+    }
+    for (var e in alltrx){
+      
+      if (alltrx[e][dx]['staffuuid']) {
+        var idx = alltrx[e][dx]['staffuuid'].indexOf(vacdata[vc].staffuuid);
+  
+        if (idx != -1) {
+  
+          if (vacdata[vc].timefrom==vacdata[vc].timeto) {
+            alltrx[e][dx]['staffcolor'][idx] = "transparent";
+          }else  {
+  
+            var tfto =((parseInt(vacdata[vc].timeto.substring(1,2)) - parseInt(vacdata[vc].timefrom.substring(1,2)))/8)*100;
+            var clr = alltrx[e][dx]['staffcolor'][idx];
+  
+            alltrx[e][dx]['staffcolor'][idx] = "linear-gradient(to right, "+convertHex(clr,1)+" 0%,"+convertHex(clr,1)+" "+tfto+"%,rgba(0,0,0,0) 100%)";
+          }
+          
+        }
+      }
+    }
+  
+  }
+  var cspan = 0;
+  var hdays = get_vacancydays();
+  //(JSON.stringify(hdays));
+  var strhead = '<thead><tr><th style="width: 120px;min-width: 120px;">Semaine</th>';
+  for (var w in weekrange){
+    strhead += '<th colspan="'+ weekrange[w] +'">' + w + '</th>';
+    cspan += weekrange[w];
+  }
+  //<th  class="noprint2">&nbsp;</th>
+  strhead += '</tr><tr><th style="width: 120px;min-width: 120px;"><span class="glyphicon glyphicon-time"></span></th>';
+  for (var th in thead){
+    var sty="";
+    if (hdays[thead[th]]) {
+      sty =' style="background-color: '+((hdays[thead[th]]=='vacancy')?'#FF7145':'#FF9C2A')+' !important;" ';
+    }
+    strhead += '<th'+sty+'>'+ thead[th]+'</th>';
+  }
+
+  strhead += '</tr></thead>';
+  $('#tbl_timetable').append(strhead);
+  $('#tbl_timetable').append('<tbody>');
+  cspan +=1;
+
+  var actchange = "";
+  //jsdump(JSON.stringify(alltrx));
+  for (var a in alltrx){
+      
+      var trn = "<tr class=\"tblstaffrow\">";
+      trn += '<td style="font-weight: bold;width: 120px;min-width: 120px;">'+alltrx[a].timefrom+' - '+alltrx[a].timeto+'</td>';
+      for (var h in thead){
+        if ((hdays[thead[h]]) && (hdays[thead[h]] == 'vacancy')) {
+          trn += '<td style="background-color: #666666  !important;"></td>';
+          continue;
+        }
+        if (alltrx[a][thead[h]]) {
+          //jsdump(thead[h]);
+          trn += '<td style="padding: 0px;">';
+          if (alltrx[a][thead[h]]["staffcolor"]) {
+            var xx = alltrx[a][thead[h]]["staffcolor"];
+            for (var r in xx){
+              var col = "";
+              if (xx[r] == 'transparent') {
+                col = 'color: transparent; display: none;';
+              }else {
+                if (xx[r].indexOf("linear-gradient") == -1){
+                  totalstaff[parseInt(thead[h])-1] += 1;
+                }
+                
+              }
+              trn += '<div style="display: block;margin: 0px; width: 100%; border: 1px solid '+xx[r]+'; background-color: '+xx[r]+' !important;'+col+'">'+alltrx[a][thead[h]]["staffnames"][r] +'</div>';
+            }
+            
+          }
+          
+          trn += '</td>';
+        }else {
+          trn += '<td></td>';
+        }
+      }
+      trn += '</tr>';
+      
+      $('#tbl_timetable').append(trn);
+
+  }
+  
+  $('#tbl_timetable').append('');
+  var tfoot = "<tfoot><tr><th style=\"width: 120px;min-width: 120px;\">Total:</th>";
+  for (var i in totalstaff){
+    tfoot += '<th>'+ (totalstaff[i] == 0?"":totalstaff[i]) +'</th>';
+  }
+  tfoot += '</tr></tfoot>';
+  $('#tbl_timetable').append(tfoot);
+  
+    $('#tbl_timetable').append('</tbody>');
+    //jsdump($('#tbl_timetable').html());
+//  }
+  if ((!(pconfig.filterstaff)) || ((pconfig.filterstaff) && (pconfig.filterstaff.length != 1))){  
+    sortHTML('#tbl_timetable','.tblstaffrow', 'td:nth-child(1)');
+  }
+}
+
+function getHTMLElements (id) {
+  if (typeof id == "object") {
+    return [id];
+  } else {
+    return document.querySelectorAll(id);
+  }
+}
+
+function sortHTML(id, sel, sortvalue) {
+  var a, b, i, ii, y, bytt, v1, v2, cc, j;
+  a = getHTMLElements(id);
+  for (i = 0; i < a.length; i++) {
+    for (j = 0; j < 2; j++) {
+      cc = 0;
+      y = 1;
+      while (y == 1) {
+        y = 0;
+        b = a[i].querySelectorAll(sel);
+        for (ii = 0; ii < (b.length - 1); ii++) {
+          bytt = 0;
+          if (sortvalue) {
+            v1 = b[ii].querySelector(sortvalue).innerHTML.toLowerCase();
+            v2 = b[ii + 1].querySelector(sortvalue).innerHTML.toLowerCase();
+          } else {
+            v1 = b[ii].innerHTML.toLowerCase();
+            v2 = b[ii + 1].innerHTML.toLowerCase();
+          }
+          if ((j == 0 && (v1 > v2)) || (j == 1 && (v1 < v2))) {
+            bytt = 1;
+            break;
+          }
+        }
+        if (bytt == 1) {
+          b[ii].parentNode.insertBefore(b[ii + 1], b[ii]);
+          y = 1;
+          cc++;
+        }
+      }
+      if (cc > 0) {break;}
+    }
+  }
+};
+
+
+function load_vacancy_data() {
+  var sql = "select vacancydate,strftime('%Y%m%d',vacancydate) as strvacancydate,vacancydateto,case when vacancydateto is not null then strftime('%Y%m%d',vacancydateto) else null end as strvacancydateto,vacancydescription from vacancy " +
+  "where (vacancydate between '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' and '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "' and (vacancydateto >= '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' or vacancydateto is null)) or (vacancydateto between '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' and '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "' and vacancydate < '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "') or ((vacancydate <= '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "') and (vacancydateto >= '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "')) " +
+  "order by vacancydate,vacancydateto;";
+  var caldata = appdb.dbquery(sql);
+  caldata = caldata.sqldata;
+  for (var c in caldata) {
+    var freq = "FREQ=DAILY";
+    freq += ';DTSTART='+caldata[c].strvacancydate + 'T000000Z';
+
+    if (caldata[c].vacancydateto !== ''){
+        freq += ';UNTIL='+caldata[c].strvacancydateto + 'T000000Z';
+    }else {
+        freq += ';UNTIL='+caldata[c].strvacancydate + 'T000000Z';
+    }
+    try {
+    var rule = RRule.fromString(freq);
+    var rall = rule.all();
+    
+    for (var r in rall){
+      if ((rall[r].toLocaleFormat('%Y-%m-%d') >= initdate.toLocaleFormat('%Y-%m-%d')) && (rall[r].toLocaleFormat('%Y-%m-%d') <= lastmonthday.toLocaleFormat('%Y-%m-%dT00:00.000Z'))) {
+
+        $("#" + linkpos["" + rall[r].toLocaleFormat('%Y-%m-%d')] + " > div.panel-day > div.panel-dayhead").addClass(((caldata[c].vacancydateto == '')?'calvacancy':'calvacrange'));
+        $("#" + linkpos["" + rall[r].toLocaleFormat('%Y-%m-%d')] + " > div.panel-day > div.panel-dayhead > div#vacname").remove();
+        $("#" + linkpos["" + rall[r].toLocaleFormat('%Y-%m-%d')] + " > div.panel-day > div.panel-dayhead").prepend('<div id="vacname" class="calvacheader">'+ caldata[c].vacancydescription + "</div>&nbsp;");
+      }
+    }
+    } catch (ex){
+    }
+  }
+}
+
+function load_staff_selection(objid,option){
+  var stdata = appdb.dbquery("select uuid, coalesce(surname,'') || ' ' || coalesce(prename,'') as name,case when color is null then '#000' else color end as color from staff order by surname,prename");
+  stdata = stdata.sqldata;
+  for (var s in stdata){
+    $('#' + objid).append('<option value="'+ stdata[s].uuid+'">&lt;span style="color: '+stdata[s].color+';" &gt;' +stdata[s].name+ '&lt;/span&gt;</option>');
+  }
+  if (objid == 'filter_staff') {
+       $('#' + objid).multiselect({enableHTML: true,numberDisplayed:1,nonSelectedText:"Tous",allSelectedText: 'Tous',nSelectedText: ' selections'}); 
+    if (pconfig.filterstaff) {
+      $('#' + objid).multiselect('select',pconfig.filterstaff);
+    }
+  }else {
+    var copt = {};
+    if (option) {
+      copt = option;
+    }
+    copt['enableHTML'] = true;
+    copt['nonSelectedText']="Sélectionner un(e) employé(e)...";
+    copt['numberDisplayed']=5;
+    copt['allSelectedText']='Tous';
+    copt['nSelectedText']=' selections';
+    
+    $('#' + objid).multiselect(copt);
+  }
+  
+}
+
+//function load_creche_selection(){
+//     var accdb = appdb.getaccessibledatabases();
+//     for (var i in accdb){
+//             
+//             $('#filter_creche').append('<option value="'+ accdb[i].dbnum+'">' +accdb[i].name+ '</option>');
+//             //dump(JSON.stringify(accdb[i]) + "\n");
+//     }
+//     
+//     $('#filter_creche').multiselect({enableHTML: true,numberDisplayed:1,nonSelectedText:"Crèche Courrant",allSelectedText: 'Tous',nSelectedText: ' selections'}); 
+//     if (pconfig.filtercreche) {
+//             $('#filter_creche').multiselect('select',pconfig.filtercreche);
+//     }else {
+//             var xar = [];
+//             xar.push(curcfg.dbnum);
+//             $('#filter_creche').multiselect('select',curcfg.dbnum);
+//             pconfig.filtercreche = xar;
+//     }
+//}
+
+function load_activity_selection(objid,type) {
+  var stdata = appdb.dbquery("select uuid,description as activity,color from eventcalendar group by description,color;");
+  stdata = stdata.sqldata;
+  for (var s in stdata){
+    $('#' + objid).append('<option value="'+ stdata[s].activity +'" >&lt;span style="color: '+stdata[s].color+';" &gt;' +stdata[s].activity+ '&lt;/span&gt;</option>');
+  }
+  if (pconfig.filteractivity) {
+    $('#' + objid).multiselect({enableHTML: true,numberDisplayed:1,nonSelectedText:"Tous",allSelectedText: 'Tous',nSelectedText: ' selections'});
+    $('#' + objid).multiselect('select',pconfig.filteractivity);
+  } else if (type == 'multiple') {
+    $('#' + objid).multiselect({enableHTML: true,numberDisplayed:1,nonSelectedText:"Tous",allSelectedText: 'Tous',nSelectedText: ' selections'});  
+  } else {
+    var copt = {};
+    copt['enableHTML'] = true;
+    copt['nonSelectedText']="Sélectionner une activité..";
+    $('#' + objid).multiselect(copt);
+    $('#' + objid).multiselect('select',null);
+  }
+}
+
+function set_calmonth() {
+  pconfig.calmonth = $('#calmonth').val();
+  apppref.setpreference("pageconfig.calactivity", pconfig);
+  globelreq.send_request({
+    page: 'calactivity',
+    module: 'calendar',
+    header: 'Organisation Personnel'
+  }, null);
+}
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.calactivity", pconfig);
+  globelreq.send_request({
+    page: 'calactivity',
+    module: 'calendar',
+    header: 'Organisation Personnel'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.calactivity", pconfig);
+  globelreq.send_request({
+    page: 'calactivity',
+    module: 'calendar',
+    header: 'Organisation Personnel'
+  }, null);
+}
+
+function dlg_vacancy_detail(stuuids) {
+  //dump(JSON.stringify(stuuids) + "\n");
+  var obj = stuuids.split(',')
+  var vsql = "select coalesce(surname,'') || ' ' || coalesce(prename,'') as staffname,color from staff where uuid in ('" + obj.join("','") + "');";
+  //dump(vsql + "\n");
+  var vst = appdb.dbquery(vsql);
+  vst = vst.sqldata;
+  $('#vacdetail').html("");
+  for (var v in vst){
+    $('#vacdetail').append('<div style="color: '+ vst[v].color+'">'+ vst[v].staffname+'</div>');
+  }
+  $("#dlg_vacancy_detail").modal('show');
+  
+}
+
+function dlg_event(uuid, type) {
+  $('#staffuuid').multiselect('deselectAll', false);
+  
+  //$('#cmb_clone_activity').val('none');
+  $('#staffuuid').multiselect('updateButtonText');
+  //$('#cmb_clone_activity').html("");
+  if (type== "ins") {
+    $('#btndeleteevent').hide();
+    
+  }else {
+    $('#btndeleteevent').show();
+  }
+  $('#frmeditevent #freqinterval').hide();
+  $('#frmeditevent #freqmonthly').hide();
+  $('#frmeditevent #freqweekly').hide();
+  $('#frmeditevent #freq_monthly_byday').show();
+  $('#frmeditevent #freq_monthly_bymonthday').hide();
+  $('#frmeditevent #freq').val("");
+  $('#frmeditevent .active').removeClass('active');
+  load_activity_selection('cmb_clone_activity','single');
+  $('#cmb_clone_activity').multiselect('select', ['none']);
+  if ((type == 'upd') || (type == 'ins')) {
+    var evdata = {
+      uuid: '0',
+      description: '',
+      activityuuid:'',
+      location: '',
+      color: '',
+      datefrom:new Date().toLocaleFormat("%d.%m.%Y"),
+      dateto:'',
+      staffuuid:'',
+      timefrom: '00:00',
+      timeto: '00:00',
+      freq: ''
+    };
+    
+    if (type == 'upd') {
+     var evsql = "SELECT uuid, strftime(\"%d.%m.%Y\",datefrom) as datefrom, strftime(\"%d.%m.%Y\",dateto) as dateto, timefrom, timeto, description, location, color, freq,  GROUP_CONCAT(st.staffuuid,',') as staffuuid FROM eventcalendar ev left join staffplanning st on (ev.uuid=st.eventcalendaruuid) where ev.uuid='" + uuid.uuid + "' group by ev.uuid;";
+      evdata = appdb.dbquery(evsql);
+      evdata = evdata.sqldata[0];
+      if (evdata.freq !== '') {
+        var tmpfreq = evdata.freq.split(';');
+        for (var t in tmpfreq){
+          if (tmpfreq[t] !== '') {
+            var spl = tmpfreq[t].split("=");
+            evdata[spl[0].toLowerCase()] = spl[1].toLowerCase();
+          }
+        }
+      }
+    }
+    for (var w in evdata) {
+      if ($("#frmeditevent #" + w)) {
+        if (w == 'staffuuid') {
+          if (evdata[w] === '') {
+            $("#frmeditevent #" + w).multiselect('select',[]);
+          } else {
+            $("#frmeditevent #" + w).multiselect('select',evdata[w].split(','));
+          }
+          
+        }else if (w == 'color') {
+          //dump("load color: " + evdata[w]);
+          curevcolor = evdata[w];
+          $("#frmeditevent #color").val(evdata[w]);
+          $('#frmeditevent #color').minicolors('value',{color: evdata[w]});
+        }
+        else {
+          $("#frmeditevent #" + w).val(evdata[w]);
+          if ((w === "description") && (evdata[w] !== "")) {
+            $("#cmb_clone_activity").multiselect('select',evdata[w]);
+          }
+        }
+      }
+    }
+    if ((evdata.freq == 'weekly') && (evdata.byday)) {
+      var bd = evdata.byday.split(',');
+      for (var i in bd){
+        document.getElementById('weekly_byday_' + bd[i]).setAttribute("checked",true);
+        $('#frmeditevent #weekly_byday_' + bd[i]).parent().addClass("active");
+      }
+    }
+    if (evdata.freq == 'monthly') {
+       $('#freq_monthly_byday').hide();
+       $('#freq_monthly_bymonthday').hide();
+       $('#pnl_monthly_byday').removeAttr("checked");
+       $('#pnl_monthly_bymonthday').removeAttr("checked");
+      if (evdata.byday) {
+        document.getElementById('pnl_monthly_byday').setAttribute("checked",true);
+        $('#frmeditevent #pnl_monthly_byday').parent().addClass("active");
+        $('#freq_monthly_byday').show();
+        var bd = evdata.byday.split(',');
+        var adpos = [];
+        var awday = [];
+        for (var i in bd){
+          var wday = bd[i].substr(bd[i].length-2);
+          var pos = bd[i].substring(0,bd[i].length-2);
+          awday.push(wday.toLowerCase());
+          adpos.push(pos);
+        }
+        for (var i in adpos){
+          document.getElementById('monthly_bydaypos_' + adpos[i]).setAttribute("checked",true);
+          $('#frmeditevent #monthly_bydaypos_' + adpos[i]).parent().addClass("active");
+        }
+        for (var i in awday){
+          document.getElementById('monthly_bydaywday_' + awday[i]).setAttribute("checked",true);
+          $('#frmeditevent #monthly_bydaywday_' + awday[i]).parent().addClass("active");
+        }
+      }else if (evdata.bymonthday) {
+        document.getElementById('pnl_monthly_bymonthday').setAttribute("checked",true);
+        $('#frmeditevent #pnl_monthly_bymonthday').parent().addClass("active");
+        $('#freq_monthly_bymonthday').show();
+        var bd = evdata.bymonthday.split(',');
+        for (var i in bd){
+          document.getElementById('monthly_bymonthday_' + bd[i]).setAttribute("checked",true);
+          $('#frmeditevent #monthly_bymonthday_' + bd[i]).parent().addClass("active");
+        }
+      }
+    }
+    setfreq();
+    $("#edit_event").modal('show');
+  } 
+}
+
+function save_event() {
+  var sql1 = new Array();
+  var sql2 = new Array();
+  if ($('#timefrom').val() == $('#timeto').val() || $('#timefrom').val() == "00:00" || $('#timeto').val() == "00:00"){
+    errormsg("Erreur","les heures doivent Ãªtre différent et différent de la valeur 00:00!");
+    return false;
+  }
+  if ($('#timefrom').val() > $('#timeto').val()){
+    errormsg("Erreur","l'heure de début ne peux pas Ãªtre supérieur Ã  l'heure de fin!");
+    return false;
+  }
+  if (!$('#staffuuid').val()){
+    errormsg("Erreur","Vous devez selectionner au moin 1 membre du staff!");
+    return false;
+  }
+  if ($('#dateto').val() != '' && (encodeparam($('#datefrom').val()) > encodeparam($('#dateto').val()))  ) {
+    errormsg("Erreur","La Date début ne peut pas Ãªtre supérieur Ã  la date fin!");
+    return false;
+  }
+  // if ($('#timeto').val() != '' && (encodeparam($('#timefrom').val()) > encodeparam($('#timeto').val()))  ) {
+  //   errormsg("Erreur","L'heure de début ne peut pas Ãªtre supérieur Ã  la heure de fin!");
+  //   return false;
+  // }
+  var type = 'ins';
+  var cuuid = "";
+  if ($("#frmeditevent #uuid").val() != 0) {
+    type = 'upd';
+    cuuid = $("#frmeditevent #uuid").val();
+  } else {
+    cuuid = appdb.generate_uuid();
+  }
+  var cactv = $('#frmeditevent #cmb_clone_activity').val();
+  if (cactv == 'none') {
+    var dtest = appdb.dbquery("select count(*) as cnt from eventcalendar where description='"+ $("#frmeditevent #description").val() + "';");
+    if (dtest && dtest.sqldata[0].cnt != "0") {
+      $("#frmeditevent #description").val($("#frmeditevent #description").val() + " Copy");
+    }
+  }else if ((cactv != $("#frmeditevent #description").val()) || (curevcolor != $("#frmeditevent #color").val())) {
+    appdb.dbexec("update eventcalendar set description='"+$("#frmeditevent #description").val()+"',color='"+$("#frmeditevent #color").val()+"' where description='"+ cactv +"';");
+    //update description and color off all events with same name
+  } 
+  var freqdata = {};
+  var cfreq = $("#frmeditevent #freq").val();
+  $("#frmeditevent :input").each(function() {
+    var input = $(this);
+    
+    if (input.attr("id") && (input.attr("id") != "staffuuid") && (input.attr("id") != "cmb_clone_activity")) {
+      if ((input.attr("type") == "checkbox") && (input.attr("id").indexOf(cfreq) >= 0)){
+        var xd = input.attr("id").split("_");
+        if (input.attr("checked")) {
+          if (!freqdata[xd[1]]) {
+            freqdata[xd[1]] = new Array();
+          }
+          freqdata[xd[1]].push(input.val());
+        }
+      }
+      else if ((input.attr("type") == "radio") && (input.attr("id").indexOf(cfreq) >= 0)) {
+        var xd = input.attr("id").split("_");
+        if (input.attr("checked")) { 
+          freqdata['freqtype'] = xd[2];
+        }
+      }
+      else if ((input.attr("type") != "checkbox") && ((input.attr("type") != "radio"))){
+        if ((input.attr("id") == 'interval') || (input.attr("id") == 'freq')) {
+          freqdata[input.attr("id")] = input.val();
+        } else if ((type == 'ins') && (input.attr("id") != 'staffuuid')) {
+          
+          sql1.push('"' + input.attr("id") + '"');
+          if (input.attr("id") == 'uuid') {
+            if (input.val() == "" || input.val() == "0") {
+              sql2.push("'" + cuuid + "'");
+            } else {
+              sql2.push("'" + input.val() + "'");
+            }
+          } else {
+            var ival = encodeparam(input.val(), input.attr('type'));
+            sql2.push(ival);
+          }
+        } else {
+          if ((input.attr("id") != 'uuid') && (input.attr("id") != 'staffuuid')){
+            var ival = encodeparam(input.val(), input.attr('type'));
+            sql2.push('"' + input.attr("id") + '"=' + ival);
+          }
+        }
+      }
+    }
+
+  });
+  if (!freqdata.freqtype) {
+    freqdata['freqtype'] = curfreq.freqtype;
+  }
+
+  var strfreq ="";
+  if (cfreq != "") {
+    strfreq='FREQ=' + cfreq.toUpperCase()+';INTERVAL=' + freqdata.interval +';';
+    if ((cfreq == 'weekly') && (freqdata.byday)){
+      strfreq += 'BYDAY=' + freqdata.byday.join(","); 
+    }
+    if ((cfreq == 'monthly') && (freqdata.bydaypos) || ((freqdata.bydaywday)) || (freqdata.bymonthday)){
+      strfreq += freqdata.freqtype.toUpperCase() + '=';
+      if (freqdata.freqtype == 'bymonthday') {
+        strfreq += freqdata.bymonthday.join(',') + ";"
+      }else {
+        var abyday = new Array();
+        for (var p in freqdata.bydaypos){
+          for (var w in freqdata.bydaywday){
+            abyday.push(freqdata.bydaypos[p] + freqdata.bydaywday[w]);
+          }
+        }
+        strfreq += abyday.join(",");
+      }
+    }
+    if (strfreq.slice(-1) == ';') {
+      strfreq = strfreq.substring(0,strfreq.length-1);
+    }
+  }
+  var staffuuids = $('#staffuuid').val();
+  var xsql=[];
+  var delsql = "";
+  if (type != 'ins') {
+    xsql.push("DELETE FROM staffplanning where eventcalendaruuid = '"+cuuid+"';");
+  }
+  var staffinssql = "";
+  if (staffuuids && (staffuuids.length != 0)) {
+    staffinssql = "INSERT INTO staffplanning (eventcalendaruuid,staffuuid) VALUES ";
+    var tmps = [];
+    for (var s in staffuuids){
+      tmps.push("('"+cuuid+"','"+staffuuids[s]+"')");
+    }
+    staffinssql += tmps.join(',') + ";"; 
+    xsql.push(staffinssql);
+  }
+  
+  if (type == 'upd') {
+    sql2.push('freq=' + encodeparam(strfreq));
+    xsql.push("UPDATE eventcalendar SET " + sql2.join(',') + " where \"uuid\"='" + cuuid + "';");
+  } else {
+    sql1.push('freq');
+    sql2.push(encodeparam(strfreq));
+    xsql.push("INSERT INTO eventcalendar (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");");
+  }
+  for (var i in xsql){
+         appdb.dbexec(xsql[i]); 
+  }
+  
+  //load_calendar_data();
+
+  $("#frmeditevent #uuid").val("0");
+  $("#edit_event").modal('hide');
+  globelreq.send_request({
+    page: 'calactivity',
+    module: 'calendar',
+    header: 'Organisation Personnel'
+  }, null);
+}
+
+function confirm_delete_event() {
+  $("#confirm_delete_event").modal('show');
+  return false;
+}
+
+function delete_event() {
+
+  appdb.dbexec("DELETE FROM eventcalendar where uuid='" + $('#frmeditevent #uuid').val()+"';");
+  appdb.dbexec("DELETE FROM staffplanning where eventcalendaruuid='" + $('#frmeditevent #uuid').val()+"';");
+  
+  load_activity_selection('filter_activity','multiple');
+  load_calendar_data();
+  $("#confirm_delete_event").modal('hide');
+  
+  return false;
+}
+
+function setfreq() {
+
+  curfreq.freq = $('#freq option:selected').val();
+  $('#freqinterval').hide();
+  $('#freqmonthly').hide();
+  $('#freqweekly').hide();
+  if (curfreq.freq != "") {
+    $('#lblfreq').text(lblfreq[curfreq.freq]);
+    $('#freqinterval').show();
+    if (curfreq.freq !=  'daily') {
+      $('#freq' + curfreq.freq).show();
+    }
+  }
+  
+}
+
+function invertColor(hexTripletColor) {
+  var color = hexTripletColor;
+  color = color.substring(1); // remove #
+  color = parseInt(color, 16); // convert to integer
+  color = 0xFFFFFF ^ color; // invert three bytes
+  color = color.toString(16); // convert to hex
+  color = ("000000" + color).slice(-6); // pad with leading zeros
+  color = "#" + color; // prepend #
+  return color;
+}
+
+// function onselactivity(objid) {
+//   pconfig.filteractivity = $('#' + objid).val()//(()?$('#' + objid).val().split(','):null);
+//   apppref.setpreference("pageconfig.calactivity",pconfig);
+//   load_calendar_data();
+// }
+function onselstaff(objid) {
+
+  pconfig.filterstaff = $('#' + objid).val();
+  apppref.setpreference("pageconfig.calactivity",pconfig);
+  load_calendar_data();
+}
+
+function get_vacancy_data() {
+  vacpos = {};
+  var where = "";
+  if ((pconfig.filterstaff) && (pconfig.filterstaff.length > 0)) {
+    where = " st.uuid in ('"+ pconfig.filterstaff.join("','") + "')";
+  }
+  var sql = getvacancysql(new Date(initdate.toLocaleFormat("%Y-%m-%d")),new Date(lastmonthday.toLocaleFormat("%Y-%m-%d")),where);
+  vacdata = appdb.dbquery(sql);
+  vacdata = vacdata.sqldata;
+  
+  for (var v in vacdata) {
+    var freq = "FREQ=DAILY";
+    
+    freq += ';DTSTART='+vacdata[v].strdatefrom + 'T000000Z';
+    if (vacdata[v].vacancydateto != ''){
+      freq += ';UNTIL='+vacdata[v].strdateto + 'T000000Z';
+    }else {
+      freq += ';UNTIL='+vacdata[v].strstrdatefrom + 'T000000Z';
+    }
+    try {
+      var vacrule = RRule.fromString(freq);
+      var vacrall = vacrule.all();
+    } catch (ex){
+      //dump("ERROR! loading data!" + ex  + " FREQ:" + freq + "\n");
+    }
+    for (var r in vacrall){
+      if ((vacrall[r].toLocaleFormat('%Y-%m-%d') >= initdate.toLocaleFormat('%Y-%m-%d')) && (vacrall[r].toLocaleFormat('%Y-%m-%d') <= lastmonthday.toLocaleFormat('%Y-%m-%dT00:00.000Z'))) {
+        if (!vacpos[vacrall[r].toLocaleFormat('%Y-%m-%d')]) {
+          vacpos[vacrall[r].toLocaleFormat('%Y-%m-%d')] = {'staffuuid':[vacdata[v].staffuuid],color:[vacdata[v].color]};
+        }else {
+          vacpos[vacrall[r].toLocaleFormat('%Y-%m-%d')]['staffuuid'].push(vacdata[v].staffuuid);
+          vacpos[vacrall[r].toLocaleFormat('%Y-%m-%d')]['color'].push(vacdata[v].color);
+        }
+      }
+    }
+  }
+}
+
+function getvacancysql(datefrom2,dateto2,where) {
+      var sqlret = "SELECT vc.uuid, vc.datefrom,strftime('%Y%m%d',vc.datefrom) as strdatefrom,'<span style=\"display: none;\"> ' || strftime('%Y%m%d',vc.datefrom) || strftime('%Y%m%d',vc.dateto) || '</span>' || strftime('%d.%m.%Y',vc.datefrom)  || ' - '  || strftime('%d.%m.%Y',vc.dateto) as tbldaterange, vc.dateto,strftime('%Y%m%d',vc.dateto) as strdateto,vc.timefrom,vc.timeto "+
+", vc.staffuuid,coalesce(st.surname,'') || ' ' || coalesce(st.prename,'') as staffname,vc.type,st.color FROM vacancycalendar vc left join staff st on (vc.staffuuid=st.uuid) " +
+        "LEFT JOIN ( SELECT  * FROM ( ";
+      var sqldays = new Array();
+      
+      for (var cdate2=datefrom2;cdate2<=dateto2;cdate2.setDate(cdate2.getDate() +1)){
+            if ((cdate2.getDay() != 0)){
+                  sqldays.push ("SELECT date('" + cdate2.toLocaleFormat('%Y-%m-%d') +"') as daydate");
+            }
+      }
+
+      sqlret += sqldays.join(' UNION ALL ') + " )) oph " +
+      "ON (oph.daydate BETWEEN vc.datefrom AND vc.dateto) " +
+        "WHERE oph.daydate IS NOT NULL and strftime('%w',oph.daydate) not in ('0') " +
+        "AND oph.daydate NOT IN ( SELECT vacancydate FROM vacancy WHERE vacancydateto IS NULL AND vacancydate BETWEEN '"+initdate.toLocaleFormat("%Y-%m-%d") + "' AND '" + dateto2.toLocaleFormat("%Y-%m-%d")+"') " +
+        ((where != '')?" AND " + where + " ":"") +
+        " GROUP BY vc.uuid ORDER BY st.uuid,vc.datefrom, vc.dateto; ";
+      return sqlret;
+}
+
+// function getoph() {
+//   var ophsql = "select dd.daydate,max(wh.datestart) as baseopendate, "+
+// "case when strftime('%w',daydate) = '1' then montimeopen "+
+// "when strftime('%w',daydate) = '2' then tuetimeopen "+
+// "when strftime('%w',daydate) = '3' then wedtimeopen "+
+// "when strftime('%w',daydate) = '4' then thutimeopen "+
+// "when strftime('%w',daydate) = '6' then sattimeopen "+
+// "when strftime('%w',daydate) = '5' then fritimeopen when strftime('%w',daydate) = '6' then sattimeopen else null end as begintime, "+
+// "case when strftime('%w',daydate) = '1' then montimeclose "+
+// "when strftime('%w',daydate) = '2' then tuetimeclose "+
+// "when strftime('%w',daydate) = '3' then wedtimeclose "+
+// "when strftime('%w',daydate) = '4' then thutimeclose "+
+// "when strftime('%w',daydate) = '6' then sattimeclose "+
+// "when strftime('%w',daydate) = '5' then fritimeclose when strftime('%w',daydate) = '6' then sattimeclose else null end as endtime "+
+//  "from workinghours wh left join (";
+//   ophsql += drsql + 
+//   ") dd on (dd.daydate > wh.datestart) group by dd.daydate order by dd.daydate";
+//   jsdump("OPH Time");
+//   jsdump(ophsql);
+//   var ophdata = appdb.dbquery(ophsql);
+//   ophdata = ophdata.sqldata;
+//   return ophdata;
+// }
+
+function getdaterangesql(){
+  var adays = [];
+  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+  for (var cdt = bdate; cdt <= bend; cdt.setDate(cdt.getDate() + 1)) {
+    //if ((cdt.getDay() != 0)){
+      adays.push("select date('" + cdt.toLocaleFormat('%Y-%m-%d') + "') as daydate");
+    //}
+    
+  }
+  return adays.join(" UNION ");
+}
+
+function getstaffactivity() {
+  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+  var actsql = "select dd.daydate as daydate, '[\"' || GROUP_CONCAT(ev.staffuuid,'\",\"') || '\"]' AS staffuuid,'[\"' || GROUP_CONCAT(st.color,'\",\"') || '\"]' as staffcolor,'[\"' || GROUP_CONCAT(coalesce(substr(st.surname,1,2),'') || ' ' || coalesce(substr(st.prename,1,2),''), '\",\"' ) || '\"]' as staffnames, ev.timefrom as timefrom,ev.timeto as timeto, ev.description as description,ev.color as eventcolor,ev.uuid as eventuuid from ( "+
+"select sp.staffuuid,ec.description,ec.color,ec.uuid, "+
+"case when datefrom < '"+bdate.toLocaleFormat("%Y-%m-%d")+"' then '"+bdate.toLocaleFormat("%Y-%m-%d")+"' else  datefrom end as datefrom, "+
+"case when dateto > '"+bend.toLocaleFormat("%Y-%m-%d")+"' then '"+bend.toLocaleFormat("%Y-%m-%d")+"' else dateto end as dateto, "+
+"timefrom,timeto  "+
+"from eventcalendar ec join staffplanning sp on (ec.uuid=sp.eventcalendaruuid) where datefrom <= '"+bend.toLocaleFormat("%Y-%m-%d")+"' and (dateto is null or dateto >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"')) ev "+
+"join staff st on (ev.staffuuid=st.uuid) "+
+"join ("+ drsql+") dd  "+
+"on (dd.daydate between ev.datefrom and ev.dateto) ";
+var wh = [];
+if (pconfig.filterstaff) {
+  wh.push("st.uuid in ('"+ pconfig.filterstaff.join("','")+"')");
+}
+// if (pconfig.filteractivity) {
+//   //dump(pconfig.filteractivity + "\n");
+//   wh.push("ev.description in ('"+ pconfig.filteractivity.join("','")+"')");
+// }
+if (wh.length > 0) {
+  actsql += " WHERE " + wh.join( " OR "); 
+}
+actsql += " GROUP BY dd.daydate,ev.uuid ORDER BY ev.description,dd.daydate,ev.timefrom,ev.timeto; ";
+//jsdump("STAFF ACTIVITY");
+//jsdump(actsql);
+//dump("\n\n\nSTAFF ACTIVITY: " + actsql + "\n\n\n");
+  var actdata = appdb.dbquery(actsql);
+  actdata = actdata.sqldata;
+  return actdata;
+}
+
+function getstaffvacancy() {
+  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+  var vacsql = "select dd.daydate as daydate,staffuuid, timefrom,timeto,type from ( "+
+"select staffuuid, "+
+"case when datefrom < '"+bdate.toLocaleFormat("%Y-%m-%d")+"' then '"+bdate.toLocaleFormat("%Y-%m-%d")+"' else  datefrom end as datefrom, "+
+"case when dateto > '"+bend.toLocaleFormat("%Y-%m-%d")+"' then '"+bend.toLocaleFormat("%Y-%m-%d")+"' else dateto end as dateto, "+
+"timefrom,timeto, type "+
+"from vacancycalendar where (datefrom is null or datefrom <= '"+bend.toLocaleFormat("%Y-%m-%d")+"') and (dateto is null or dateto >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"')) vc "+
+"join ("+drsql+") dd  "+
+"on (dd.daydate between vc.datefrom and vc.dateto); ";
+var wh = [];
+if (pconfig.filterstaff) {
+  wh.push("staffuuid in ('"+ pconfig.filterstaff.join("','")+"')");
+}
+if (wh.length > 0) {
+  vacsql += " WHERE " + wh.join( " OR "); 
+}
+//jsdump(" " + ophsql );
+  var vacdata = appdb.dbquery(vacsql);
+  vacdata = vacdata.sqldata;
+  return vacdata;
+}
+
+function get_vacancydays(){
+  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+  var sql = "select dd.daydate,strftime('%d',dd.daydate) as strday,type from ( "+
+"select vacancydate,  "+
+"case when vacancydateto is null then vacancydate else vacancydateto end as vacancydateto, "+
+"case when vacancydateto is null then 'vacancy' else 'holiday' end as type, "+
+"vacancydescription from vacancy where (vacancydate between '"+bdate.toLocaleFormat("%Y-%m-%d")+"' and '"+bend.toLocaleFormat("%Y-%m-%d")+"' and (vacancydateto >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"' or vacancydateto is null)) or (vacancydateto between '"+bdate.toLocaleFormat("%Y-%m-%d")+"' and '"+bend.toLocaleFormat("%Y-%m-%d")+"' and vacancydate < '"+bdate.toLocaleFormat("%Y-%m-%d")+"') or ((vacancydate <= '"+bdate.toLocaleFormat("%Y-%m-%d")+"') and (vacancydateto >= '"+bend.toLocaleFormat("%Y-%m-%d")+"')) order by vacancydate,vacancydateto) vc "+
+"join ( "+ drsql +") dd  "+
+"on (dd.daydate between vc.vacancydate and vc.vacancydateto) group by dd.daydate order by daydate;";
+  var hdata = appdb.dbquery(sql);
+  //jsdump("vacancydays");
+  //jsdump(sql);
+  hdata = hdata.sqldata;
+  var hs = {};
+  for (var h in hdata){
+    hs[hdata[h].strday] = hdata[h].type; 
+  }
+  return hs;
+}
+
+function convertHex(hex,opacity){
+    hex = hex.replace('#','');
+    r = parseInt(hex.substring(0,2), 16);
+    g = parseInt(hex.substring(2,4), 16);
+    b = parseInt(hex.substring(4,6), 16);
+
+    result = 'rgba('+r+','+g+','+b+','+opacity+')';
+    return result;
+}
+
+function oncloneactivity(actv_id) {
+  var aid = $("#cmb_clone_activity :selected").val();
+  //dump('value: ' + $("#cmb_clone_activity :selected").val() + "\n");
+  if (aid != '') {
+    //dump(actv_id + "\n");
+    $("#frmeditevent #description").val(aid);
+    var seltxt = $("#cmb_clone_activity :selected").text();
+    //dump("seltxt:" + seltxt + "\n");
+    var colre = /<span style=\"color:\s(.+);\"\s>/;
+    var ccolor =seltxt.match(colre);
+    //dump("CREs: " + JSON.stringify(ccolor) + "\n");
+    $('#frmeditevent #color').minicolors('value',{color: ccolor[1]});
+  }
+}
+
+function onselcreche(){
+       
+}
+
+
+
+
diff --git a/modules/calendar/js/calchilds.js b/modules/calendar/js/calchilds.js
new file mode 100644 (file)
index 0000000..88b6a00
--- /dev/null
@@ -0,0 +1,904 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {};
+//var cdate = null;
+var initdate = new Date();
+initdate.setDate(1);
+
+
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre', 'Octobre','Novembre', 'Décembre'];
+var drsql = "";
+
+function initdata() {
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.calchilds");
+  if (!configdata) {
+    apppref.setpreference("pageconfig.calchilds", '');
+  }
+  if (configdata !== '') {
+    pconfig = JSON.parse(configdata);
+  }
+  //if (!pconfig.printlayout) {
+    pconfig.printlayout = 'table';
+    apppref.setpreference("pageconfig.calchilds",pconfig);
+  //}
+  if (pconfig.calmonth) {
+
+    initdate = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+    $("#calmonth").val(pconfig.calmonth);
+  } else {
+    $("#calmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    pconfig.calmonth = initdate.toLocaleFormat('%m.%Y');
+  }
+  var infogrp ="Nombre d'enfants";
+  if (!pconfig.calendar){
+    pconfig.calendar = "childsbyplan";
+  }
+   
+  set_infoheader(infogrp+" - " + amonth[parseInt(pconfig.calmonth.substring(0, 3))] + " " + pconfig.calmonth.substring(3, 8));
+  drsql = getdaterangesql();
+
+  $('#calmonth').on('dp.hide', function() {
+    set_calmonth();
+  });
+  $("#filter_calendar option[value='"+ pconfig.calendar+"']").attr("selected", true);
+  $('#filter_calendar').on('change', function(){
+    onselcalendar($(this).attr("id"));
+  });
+  
+  if (pconfig.calendar == "childsbyweekhours"){
+    load_calendar_weekhours();
+  }else if (pconfig.calendar == "childsbyplan"){
+    load_calendar_plan();
+  }
+  // else if (pconfig.calendar == "lunch"){
+  //   load_calendar_lunch();
+  // }
+  // else if (pconfig.calendar == "childsbydayrange"){
+  //   load_calendar_dayranges();
+  // }
+  // else if (pconfig.calendar == "childsbyhour"){
+  //   load_calendar_childs();
+  // }
+  
+}
+
+function load_calendar_weekhours(){ //enfants par heures contractuelles
+  var cgr = appdb.dbquery("select uuid,grpname,maxchilds,color from groups");
+  cgr = cgr.sqldata;
+  var hdays = get_vacancydays();
+  var strhead = '<thead><tr><th>Semaine</th>';
+  var totalspan = 2;
+  var coldata=getcolumndays();
+  var coldays=coldata[0];
+  var weekrange=coldata[1];
+  for (var w in weekrange){
+    strhead += '<th colspan="'+ weekrange[w] +'">' + w + '</th>';
+    totalspan += weekrange[w];
+  }
+  
+  strhead += '</tr><tr><th>h / Semaine</th>';
+  for (var th in coldays){
+    var sty="";
+    if (hdays[coldays[th]]) {
+      sty =' class="'+((hdays[coldays[th]]=='vacancy')?'calvacancy':'calvacrange')+'" ';
+    }
+    strhead += '<th'+sty+'>'+ coldays[th]+'</th>';
+  }
+  strhead += '</tr></thead>';
+  $('#tbl_timetable').append(strhead);
+  $('#tbl_timetable').append('<tbody>');
+  var tfooter = {};
+      for (var c in coldays){
+        tfooter[parseInt(coldays[c])] = 0;
+      }
+  for (var g in cgr) {
+    $('#tbl_timetable').append('<tr ><td colspan="'+ totalspan+'" style="background-color: '+ cgr[g].color+' !important;">Groupe:<span style="font-weight: bold;"> '+  cgr[g].grpname+'</span> (max. '+cgr[g].maxchilds+' enfants)</td></tr>');
+    var ttdata = getchildweekhoursbygroup(cgr[g].uuid);
+
+    if (!ttdata){
+      $('#tbl_timetable').append('<tr><td colspan="'+ totalspan+'"> Pas de données</td></tr>');
+      continue;
+    }
+
+    var alltr ={};
+
+      for (var tt in ttdata) {
+        var dtmp = ttdata[tt].weekhours;
+        if (!alltr[ttdata[tt].weekhours]){ 
+          alltr[ttdata[tt].weekhours]  = {};
+          for (var c in coldays){
+            alltr[ttdata[tt]["weekhours"]][coldays[c]] = 0;
+          }
+
+        }
+      }
+      for (var t in ttdata){
+        var rdata = ttdata[t];
+        var ctday = rdata.daydate.substring(8,10);
+        if (alltr[rdata.weekhours]){
+          if (alltr[rdata.weekhours][ctday]){
+            alltr[rdata.weekhours][ctday] = ttdata[t].childcnt;
+          }else {
+            alltr[rdata.weekhours][ctday] = ttdata[t].childcnt;
+          }
+        }
+        
+      }
+  for (var a in alltr){
+    var trn = '<tr><td><strong>'+a+' h</strong></td>';
+    for (var h in coldays){
+      if (hdays[coldays[h]] == 'vacancy') {
+        trn += '<td style="background-color: #6D6D6D !important"></td>';
+        continue;
+      }
+      trn += '<td class="alignright" ><span>' +((alltr[a][coldays[h]] != 0)?alltr[a][coldays[h]]:'')+ '</span>';
+      trn +='</td>';
+      if (alltr[a][coldays[h]] != 0){
+        tfooter[parseInt(coldays[h])] += alltr[a][coldays[h]];
+      }
+    }
+    trn += '</tr>';
+    $('#tbl_timetable').append(trn);
+  }
+  }
+  $('#tbl_timetable').append('</tbody>');
+  var tstrfoot = "<tfoot><tr><th>Total:</th>";
+    tfooter = tfooter;
+    for (var f in coldays){
+      tstrfoot += '<th class="alignright">'+ ((tfooter[parseInt(coldays[f])] != 0)?tfooter[parseInt(coldays[f])]:'') +'</th>';
+    }
+    tstrfoot += "</tr></tfoot>";
+    $('#tbl_timetable').append(tstrfoot);
+}
+
+
+
+function load_calendar_plan(){
+  //jsdump("load load_calendar_plan");
+    var cgr = appdb.dbquery("select uuid,grpname,maxchilds,color from groups");
+    cgr = cgr.sqldata;
+    var hdays = get_vacancydays();
+    var strhead = '<thead><tr><th>Semaine</th>';
+    var totalspan = 1;
+    var coldata=getcolumndays();
+    var coldays=coldata[0];
+    var weekrange=coldata[1];
+    for (var w in weekrange){
+      strhead += '<th colspan="'+ weekrange[w] +'">' + w + '</th>';
+      totalspan += weekrange[w];
+    }
+    
+    strhead += '</tr><tr><th><span class="glyphicon glyphicon-time"></span></th>';
+    for (var th in coldays){
+      var sty="";
+      if (hdays[coldays[th]]) {
+        sty =' class="'+((hdays[coldays[th]]=='vacancy')?'calvacancy':'calvacrange')+'" ';
+      }
+      strhead += '<th'+sty+'>'+ coldays[th]+'</th>';
+    }
+    strhead += '</tr></thead>';
+    $('#tbl_timetable').append(strhead);
+    $('#tbl_timetable').append('<tbody>');
+    var tfooter = {};
+      for (var c in coldays){
+        tfooter[parseInt(coldays[c])] = 0;
+      }
+      
+    for (var g in cgr) {
+      $('#tbl_timetable').append('<tr ><td colspan="'+ totalspan+'" style="background-color: '+ cgr[g].color+' !important;">Groupe:<span style="font-weight: bold;"> '+  cgr[g].grpname+'</span> (max. '+cgr[g].maxchilds+' enfants)</td></tr>');
+      var ttdata = getplannedtimesbygroup(cgr[g].uuid);
+      if (!ttdata){
+        $('#tbl_timetable').append('<tr><td colspan="'+ totalspan+'"> Pas de données</td></tr>');
+        continue;
+      }
+      var alltr ={};
+      for (var tt in ttdata) {
+        var dtmp = ttdata[tt].daytime;
+        if (!alltr[ttdata[tt].daytime]){
+          alltr[ttdata[tt].daytime]  = {};
+          for (var c in coldays){
+            alltr[ttdata[tt]["daytime"]][coldays[c]] = 0;
+          }
+        }
+      }
+
+      for (var t in ttdata){
+        var rdata = ttdata[t];
+        var ctday = rdata.daydate.substring(8,10);
+        if (alltr[rdata.daytime]){
+          if (alltr[rdata.daytime][ctday]){
+            alltr[rdata.daytime][ctday] = ttdata[t].childcnt;
+          }else {
+            alltr[rdata.daytime][ctday] = ttdata[t].childcnt;
+          }
+        }
+        
+      }
+
+    for (var a in alltr){
+      var dsptime = a.match(/.{1,5}/g);
+      var trn = '<tr><td><strong>'+a+'</strong></td>';
+      if (dsptime.length == 2){
+        trn = '<tr><td><strong>'+dsptime[0]+ ' - ' + dsptime[1]+'</strong></td>';
+      }
+      if (dsptime.length == 3){
+        trn = '<tr><td><strong>'+dsptime[0]+ ' - ' + dsptime[1]+ '<br/>'+ +dsptime[2]+ ' - ?</strong></td>';
+      }
+      if (dsptime.length == 4){
+        trn = '<tr><td><strong>'+dsptime[0]+ ' - ' + dsptime[1]+ '<br/>'+ +dsptime[2]+ ' - ' + dsptime[3] + '</strong></td>';
+      } 
+      
+      for (var h in coldays){
+        if (hdays[coldays[h]] == 'vacancy') {
+          trn += '<td style="background-color: #6D6D6D !important"></td>';
+          continue;
+        }
+        trn += '<td class="alignright" ><span>' +((alltr[a][coldays[h]] != 0)?alltr[a][coldays[h]]:'')+ '</span>';
+        trn +='</td>';
+        if (alltr[a][coldays[h]] != 0){
+          tfooter[parseInt(coldays[h])] += alltr[a][coldays[h]];
+        }
+      }
+      trn += '</tr>';
+      
+      $('#tbl_timetable').append(trn);
+    }
+    }
+    $('#tbl_timetable').append('</tbody>');
+    var tstrfoot = "<tfoot><tr><th>Total:</th>";
+    for (var f in coldays){
+      tstrfoot += '<th class="alignright">'+ ((tfooter[parseInt(coldays[f])] != 0)?tfooter[parseInt(coldays[f])]:'') +'</th>';
+    }
+    tstrfoot += "</tr></tfoot>";
+    $('#tbl_timetable').append(tstrfoot);
+  }
+
+// function load_calendar_lunch(){
+//   jsdump("load load_calendar_lunch");
+//   var hdays = get_vacancydays();
+//   var strhead = '<thead><tr><th colspan="1">Semaine</th>';
+//   var totalspan = 1;
+//   var coldata=getcolumndays();
+//   var coldays=coldata[0];
+//   var weekrange=coldata[1];
+//   var thead = [];
+//   for (var w in weekrange){
+//     strhead += '<th colspan="'+ weekrange[w] +'">' + w + '</th>';
+//     totalspan += weekrange[w];
+//   }
+  
+//   strhead += '</tr><tr><th>Groupe</th>';
+//   for (var th in coldays){
+//     var sty="";
+//     if (hdays[coldays[th]]) {
+//       sty =' class="'+((hdays[coldays[th]]=='vacancy')?'calvacancy':'calvacrange')+'" ';
+//     }
+//     strhead += '<th'+sty+'>'+ coldays[th]+'</th>';
+//     if (thead.indexOf(coldays[th]) == -1) {
+//       thead.push(coldays[th]);
+//     }
+//   }
+//   strhead += '</tr></thead>';
+//   $('#tbl_timetable').append(strhead);
+//   $('#tbl_timetable').append('<tbody>');
+//   var ldata = getlunchdata();
+  
+//   var cgr = appdb.dbquery("select uuid,grpname,color from groups");
+//   cgr = cgr.sqldata;
+//   var alltr ={};
+  
+//   for (var g in cgr){
+    
+//     alltr[cgr[g].uuid] = {name:cgr[g].grpname,color:cgr[g].color};
+//   }
+  
+//   //dump(JSON.stringify(alltr) + "\n");
+//   for (var l in ldata){
+//     //dump(JSON.stringify(ldata[l]) + "\n");
+      
+//       var guuid= ldata[l].groupuuid;
+//       var dd = ldata[l].daydate;
+      
+//       //if (!alltr[guuid][dd]) {
+//       alltr[guuid][dd] = {"lunch":ldata[l].lunch};
+//       //}
+      
+//   }
+//   //dump(JSON.stringify(alltr) + "\n");
+//   //dump(JSON.stringify(thead) + "\n");
+//   for (var i in alltr){
+//     var trn = '<tr style="background-color: '+alltr[i].color+' !important"><td><strong>'+alltr[i].name+'</strong></td>';
+//     //dump(alltr[i] + "\n");
+//     for (var h in thead){
+//       if ((hdays[thead[h]]) && (hdays[thead[h]] == 'vacancy')) {
+//         trn += '<td style="background-color: #6D6D6D !important"></td>';
+//         continue;
+//       }
+//       //dump(thead[h] + " "+  h+  "\n");
+//       trn += '<td class="alignright">' +alltr[i][thead[h]].lunch+ '';
+//       trn +='</td>';  
+      
+      
+//     }
+//     trn += '</tr>';
+//     $('#tbl_timetable').append(trn);
+//   }
+  
+//   $('#tbl_timetable').append('</tbody>');
+  
+  
+// }
+
+function set_calmonth(){
+      pconfig.calmonth =$("#calmonth").val();
+      apppref.setpreference("pageconfig.calchilds",pconfig);
+      globelreq.send_request({
+            page: 'calchilds',
+            module: 'calendar',
+            data: null,
+            header: 'Organisation Enfants'
+      });
+}
+
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.calchilds", pconfig);
+  globelreq.send_request({
+    page: 'calchilds',
+    module: 'calendar',
+    header: 'Organisation Enfants'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.calchilds", pconfig);
+  globelreq.send_request({
+    page: 'calchilds',
+    module: 'calendar',
+    header: 'Organisation Enfants'
+  }, null);
+}
+
+//get childs planning with exact hours (planning)
+// function gettimetable(groupfilter) {
+//   var ttsql = "select aa.daydate, " +
+// "case when aa.begintime is null or aa.begintime ='00:00' then wx.opentime else aa.begintime end as begintime, " +
+// "case when aa.endtime is null or aa.endtime ='00:00' then wx.closetime else aa.endtime end as endtime,"+
+// "childcnt,aa.groupuuid,CAST(CAST (gr.maxchilds/gr.minstaff as REAL) + 0.5 as INT) as childsperstaff from ( "+
+// "select daydate,groupuuid,"+
+// "case when strftime('%w',daydate) = '1' then montimebegin  "+
+// "when strftime('%w',daydate) = '2' then tuetimebegin "+
+// "when strftime('%w',daydate) = '3' then wedtimebegin "+
+// "when strftime('%w',daydate) = '4' then thutimebegin "+
+// "when strftime('%w',daydate) = '5' then fritimebegin when strftime('%w',daydate) = '6' then sattimebegin else null end as begintime, "+
+// "case when strftime('%w',daydate) = '1' then montimeend  "+
+// "when strftime('%w',daydate) = '2' then tuetimeend "+
+// "when strftime('%w',daydate) = '3' then wedtimeend "+
+// "when strftime('%w',daydate) = '4' then thutimeend "+
+// "when strftime('%w',daydate) = '5' then fritimeend when strftime('%w',daydate) = '6' then sattimeend else null end as endtime, "+
+// "count(distinct(childuuid)) as childcnt "+
+// "from planning pl join (";
+//   ttsql += drsql + ") dd on (dd.daydate between pl.datebegin and pl.dateend) group by daydate,groupuuid,begintime,endtime ) " +
+//  "aa " +
+// " left join (select dd.daydate,max(wh.datestart) as baseopendate, "+
+// "case when strftime('%w',daydate) = '1' then montimeopen  "+
+// "when strftime('%w',daydate) = '2' then tuetimeopen "+
+// "when strftime('%w',daydate) = '3' then wedtimeopen "+
+// "when strftime('%w',daydate) = '4' then thutimeopen "+
+// "when strftime('%w',daydate) = '5' then fritimeopen when strftime('%w',daydate) = '6' then sattimeopen else null end as opentime, "+
+// "case when strftime('%w',daydate) = '1' then montimeclose "+
+// "when strftime('%w',daydate) = '2' then tuetimeclose "+
+// "when strftime('%w',daydate) = '3' then wedtimeclose "+
+// "when strftime('%w',daydate) = '4' then thutimeclose "+
+// "when strftime('%w',daydate) = '5' then fritimeclose when strftime('%w',daydate) = '6' then sattimeclose else null end as closetime "+
+// " from workinghours wh left join ( " + drsql +
+// ") dd on (dd.daydate > wh.datestart) group by dd.daydate) wx on (aa.daydate=wx.daydate) " +
+// " left join groups gr on (gr.uuid=aa.groupuuid) ";
+//  if (groupfilter === ""){
+//    ttsql +=  " where gr.uuid='' or gr.uuid is null";
+//  } else {
+//    ttsql +=  " where gr.uuid='"+ groupfilter +"' ";
+//  }
+//  ttsql += " order by aa.daydate,begintime,endtime";
+//  jsdump( ttsql);
+//  var ttdata = appdb.dbquery(ttsql);
+//   ttdata = ttdata.sqldata;
+//   return ttdata;
+// }
+
+function getplannedtimesbygroup(groupfilter){
+  var endmdate = new Date(initdate.getFullYear(),initdate.getMonth()+1,0);
+  var d1 = ['','mon','tue','wed','thu','fri', 'sat'];
+  var sql = "select daydate,count(childuuid) as childcnt,groupuuid,case ";
+  var adt = [];
+  for (var i=1;i<d1.length;i++){
+    adt.push("when strftime(\"%w\", daydate)= '"+i+"' then "+ d1[i]+"time");
+  }
+  sql += adt.join(" ") + " else null end as daytime " +
+  'from (select daydate, childuuid ,groupuuid, '; 
+
+  var adt2 = [];
+  for (var i=1;i<d1.length;i++){
+    adt2.push('case when strftime("%w",daydate)= \''+i+'\' and '+ d1[i]+'time != \'\' then '+ d1[i]+'time else null end as '+ d1[i]+'time');
+  }
+  
+   sql += adt2.join(",") + ' from ( select dd.daydate,pl.childuuid,pl.groupuuid, ';
+   var adt3 = [];
+    for (var i=1;i<d1.length;i++){
+      adt3.push(" case when "+ d1[i]+"timebegin = "+ d1[i]+"timeend or ch.entrydate > dd.daydate or ch.leavedate < dd.daydate then '' else coalesce("+ d1[i]+"timebegin, '') || coalesce("+ d1[i]+"timeend, '') end || "+ 
+      " case when "+ d1[i]+"timebegin2 = "+ d1[i]+"timeend2 or ch.entrydate > dd.daydate or ch.leavedate < dd.daydate then '' else coalesce("+ d1[i]+"timebegin2, '') || coalesce("+ d1[i]+"timeend2, '') end as "+ d1[i]+"time");
+
+    }  
+   sql += adt3.join(",") + ' from childs ch join planning pl on (ch.uuid = pl.childuuid) JOIN ('
+      + drsql + ") dd on ( dd.daydate BETWEEN pl.datebegin AND pl.dateend) " +
+      "where ch.leavedate >= date('"+initdate.toLocaleFormat('%Y-%m-%d')+"') and ch.entrydate <= date('"+endmdate.toLocaleFormat('%Y-%m-%d')+"')  " +
+       " GROUP BY daydate, pl.childuuid) aa " +
+  "group by daydate,childuuid,montime,tuetime,wedtime,thutime,fritime,sattime) where daytime is not null and groupuuid='"+ groupfilter +"' group by daydate,daytime,groupuuid  "+
+  "order by daydate,daytime;";
+
+  var ttdata = appdb.dbquery(sql);
+   ttdata = ttdata.sqldata;
+   return ttdata;
+
+}
+
+function getchildweekhoursbygroup(groupfilter) {
+   var endmdate = new Date(initdate.getFullYear(),initdate.getMonth()+1,0);
+   var d1 = ['','mon','tue','wed','thu','fri', 'sat'];
+    var sql = "select daydate, count(childuuid) as childcnt, groupuuid, case ";
+    var adt = [];
+    for (var i=1;i<d1.length;i++){
+      adt.push("when strftime(\"%w\", daydate)= '"+i+"' and "+ d1[i]+"time is not null then weekhours2");
+    }
+    sql += adt.join(" ") + " else null end as weekhours " +
+      "from ( select daydate, childuuid, weekhours2, groupuuid, ";
+      var adt2 = [];
+      for (var i=1;i<d1.length;i++){
+        adt2.push('case when strftime("%w",daydate)= \''+i+'\' and '+ d1[i]+'time != \'\' then '+ d1[i]+'time else null end as '+ d1[i]+'time');
+      }
+      
+       sql += adt2.join(",") + " from ( select daydate, pl.childuuid, pl.groupuuid, ";
+       var adt3 = [];
+       for (var i=1;i<d1.length;i++){
+         adt3.push(" case when "+ d1[i]+"timebegin = "+ d1[i]+"timeend or ch.entrydate > dd.daydate or ch.leavedate < dd.daydate then '' else coalesce("+ d1[i]+"timebegin, '') || coalesce("+ d1[i]+"timeend, '') end || "+ 
+         " case when "+ d1[i]+"timebegin2 = "+ d1[i]+"timeend2 or ch.entrydate > dd.daydate or ch.leavedate < dd.daydate then '' else coalesce("+ d1[i]+"timebegin2, '') || coalesce("+ d1[i]+"timeend2, '') end as "+ d1[i]+"time");
+   
+       }  
+      sql += adt3.join(",") + ",";
+
+      var adt4 = [];
+      for (var i=1;i<d1.length;i++){
+        adt4.push("coalesce(cast((strftime(\"%s\","+ d1[i]+"timeend) - strftime(\"%s\","+ d1[i]+"timebegin))/3600.0 AS REAL),0.0) +  " +
+        "case when "+ d1[i]+"timebegin2 is not null then CAST((strftime(\"%s\","+ d1[i]+"timeend2) - strftime(\"%s\","+ d1[i]+"timebegin2))/3600.0 AS REAL) else 0.0 end ");
+      }
+           
+           sql += adt4.join(" + ") + "as weekhours2 " +
+           "from childs ch join planning pl on (ch.uuid = pl.childuuid) JOIN " +
+           " ("+ drsql + ") dd on (  " +
+                " dd.daydate BETWEEN pl.datebegin AND pl.dateend) where ch.leavedate >= date('"+initdate.toLocaleFormat('%Y-%m-%d')+"') and ch.entrydate <= date('"+endmdate.toLocaleFormat('%Y-%m-%d')+"')  GROUP BY daydate,pl.childuuid )" +
+               " group by daydate, childuuid, groupuuid ) " +
+"where weekhours is not null and groupuuid='"+ groupfilter +"'" +
+" group by daydate, weekhours, groupuuid  order by daydate,weekhours;";
+
+   var ttdata = appdb.dbquery(sql);
+    ttdata = ttdata.sqldata;
+    return ttdata;
+  }
+
+
+
+function getdaterangesql(){
+  var adays = [];
+  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+  for (var cdt = bdate; cdt <= bend; cdt.setDate(cdt.getDate() + 1)) {
+    if ((cdt.getDay() !== 0)){
+      adays.push("select date('" + cdt.toLocaleFormat('%Y-%m-%d') + "') as daydate");
+    }
+    
+  }
+  return adays.join(" UNION ");
+}
+
+function getcolumndays(){
+  var adays = [];
+  var wrs = [];
+  var firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), 1);
+  //if (firstmonday > initdate) {
+  //  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  //}
+  var lastmonthday = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 1);
+  //lastsunday = new Date(lastmonthday.getFullYear(), lastmonthday.getMonth(), lastmonthday.getDate() + 7 - parseInt(lastmonthday.toLocaleFormat('%w')));
+  var lwr = -1;
+  //dump (initdate + ": " + firstmonday + " -> " + lastmonthday + "\n");
+  for (var cdt = firstmonday; cdt < lastmonthday; cdt.setDate(cdt.getDate() + 1)) {
+    if ((cdt.getDay() !== 0)){
+      if ((lwr === -1) || (!wrs[parseInt(cdt.toLocaleFormat('%W'))])) {
+        wrs[parseInt(cdt.toLocaleFormat('%W'))] = 1;
+      }else {
+        wrs[parseInt(cdt.toLocaleFormat('%W'))] += 1;
+      }
+      lwr = parseInt(cdt.toLocaleFormat('%W'));
+      adays.push(cdt.toLocaleFormat('%d'));
+    }
+    
+  }
+  //dump(JSON.stringify(wrs) + "\n");
+  return [adays,wrs];
+}
+
+//function getstaffglobal() {
+//  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+//  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+//  var staffsql = "select dd.daydate as daydate,uuid as staffuuid from ( "+
+//"select uuid, "+
+//"case when entrydate is null or entrydate < '"+bdate.toLocaleFormat("%Y-%m-%d")+"' then '"+bdate.toLocaleFormat("%Y-%m-%d")+"' else  entrydate end as entrydate, "+
+//"case when exitdate is null or exitdate > '"+bend.toLocaleFormat("%Y-%m-%d")+"' then '"+bend.toLocaleFormat("%Y-%m-%d")+"' else exitdate end as exitdate "+
+//"from staff st  "+
+//"where (entrydate is null or entrydate <= '"+bend.toLocaleFormat("%Y-%m-%d")+"') and (exitdate is null or exitdate >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"')) sf "+
+//"join ("+drsql+") dd  "+
+//"on (dd.daydate between sf.entrydate and sf.exitdate) order by daydate";
+//  //dump("\n\n\nGLOBSQL: " + staffsql + "\n\n\n");
+//  var sgldata = appdb.dbquery(staffsql);
+//  sgldata = sgldata.sqldata;
+//  return sgldata;
+//}
+
+//function getstaffactivity() {
+//  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+//  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+//  var actsql = "select dd.daydate as daydate,ev.staffuuid as staffuuid,st.prename || ' ' || st.surname as staffname,st.color as color, ev.timefrom as timefrom,ev.timeto as timeto from ( "+
+//"select sp.staffuuid, "+
+//"case when datefrom < '"+bdate.toLocaleFormat("%Y-%m-%d")+"' then '"+bdate.toLocaleFormat("%Y-%m-%d")+"' else  datefrom end as datefrom, "+
+//"case when dateto > '"+bend.toLocaleFormat("%Y-%m-%d")+"' then '"+bend.toLocaleFormat("%Y-%m-%d")+"' else dateto end as dateto, "+
+//"timefrom,timeto  "+
+//"from eventcalendar ec join staffplanning sp on (ec.uuid=sp.eventcalendaruuid) where datefrom <= '"+bend.toLocaleFormat("%Y-%m-%d")+"' and (dateto is null or dateto >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"')) ev "+
+//"join staff st on (ev.staffuuid=st.uuid) "+
+//"join ("+ drsql+") dd  "+
+//"on (dd.daydate between ev.datefrom and ev.dateto) order by staffname,dd.daydate,ev.timefrom,ev.timeto; ";
+////dump("\n\n\nACTSQL: " + actsql + "\n\n\n");
+//  var actdata = appdb.dbquery(actsql);
+//  actdata = actdata.sqldata;
+//  return actdata;
+//}
+
+//function getstaffvacancy() {
+//  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+//  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+//  var vacsql = "select dd.daydate as daydate,staffuuid, timefrom,timeto from ( "+
+//"select staffuuid, "+
+//"case when datefrom < '"+bdate.toLocaleFormat("%Y-%m-%d")+"' then '"+bdate.toLocaleFormat("%Y-%m-%d")+"' else  datefrom end as datefrom, "+
+//"case when dateto > '"+bend.toLocaleFormat("%Y-%m-%d")+"' then '"+bend.toLocaleFormat("%Y-%m-%d")+"' else dateto end as dateto, "+
+//"timefrom,timeto "+
+//"from vacancycalendar where (datefrom is null or datefrom <= '"+bend.toLocaleFormat("%Y-%m-%d")+"') and (dateto is null or dateto >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"')) vc "+
+//"join ("+drsql+") dd  "+
+//"on (dd.daydate between vc.datefrom and vc.dateto); ";
+// //dump("\n\n\nVACSQL: " + vacsql + "\n\n\n");
+//  var vacdata = appdb.dbquery(vacsql);
+//  vacdata = vacdata.sqldata;
+//  return vacdata;
+//}
+
+function get_vacancydays(){
+  var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+  var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+  var sql = "select dd.daydate,strftime('%d',dd.daydate) as strday,type from ( "+
+"select vacancydate,  "+
+"case when vacancydateto is null then vacancydate else vacancydateto end as vacancydateto, "+
+"case when vacancydateto is null then 'vacancy' else 'holiday' end as type, "+
+"vacancydescription from vacancy where (vacancydate between '"+bdate.toLocaleFormat("%Y-%m-%d")+"' and '"+bend.toLocaleFormat("%Y-%m-%d")+"' and (vacancydateto >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"' or vacancydateto is null)) or (vacancydateto between '"+bdate.toLocaleFormat("%Y-%m-%d")+"' and '"+bend.toLocaleFormat("%Y-%m-%d")+"' and vacancydate < '"+bdate.toLocaleFormat("%Y-%m-%d")+"') or ((vacancydate <= '"+bdate.toLocaleFormat("%Y-%m-%d")+"') and (vacancydateto >= '"+bend.toLocaleFormat("%Y-%m-%d")+"')) order by vacancydate,vacancydateto) vc "+
+"join ( "+ drsql +") dd  "+
+"on (dd.daydate between vc.vacancydate and vc.vacancydateto) group by dd.daydate order by daydate;";
+ //dump("VACSQL: " + sql + "\n");
+  var hdata = appdb.dbquery(sql);
+  hdata = hdata.sqldata;
+  var hs = {};
+  for (var h in hdata){
+    hs[hdata[h].strday] = hdata[h].type; 
+  }
+  return hs;
+}
+
+function onselcalendar(objid){
+  //$('#' + objid).val() + "\n");
+  pconfig.calendar = $('#' + objid).val();
+  apppref.setpreference("pageconfig.calchilds",pconfig);
+  globelreq.send_request({
+    page: 'calchilds',
+    module: 'calendar',
+    header: 'Organisation Enfants'
+  }, null);
+}
+
+
+
+//function getgroups(){
+//  var grpsdata = appdb.dbquery("select uuid,grpname from groups order by minage,maxage;");
+//  grpsdata = grpsdata.sqldata;
+//  $("#filter_group").html('');
+//  $("#filter_group").append('<option value="0">tous</option>');
+//  for (var g in grpsdata) {
+//    var sel = "";
+//    if ((pconfig) && (pconfig.filtergroup) && (pconfig.filtergroup == grpsdata[g].uuid)){
+//      sel = ' selected="1"';
+//    }
+//    $("#filter_group").append('<option value="' + grpsdata[g].uuid + '"'+ sel +'>' + grpsdata[g].grpname + '</option>');
+//  }
+//}
+
+// function load_calendar_childs() {
+//   jsdump("load load_calendar_childs");
+  
+//   var cgr = appdb.dbquery("select uuid,grpname,maxchilds,color from groups");
+//   cgr = cgr.sqldata;
+//   var ophdata = getoph();
+//   var timeranges = [];
+//   //openhours
+//   for (var o in ophdata) {
+//     if (timeranges.indexOf(ophdata[o].begintime) == -1) {
+//       timeranges.push(ophdata[o].begintime);
+//     }
+//     if (timeranges.indexOf(ophdata[o].endtime) == -1) {
+//       timeranges.push(ophdata[o].endtime);
+//     }
+//   }
+  
+//   //set Table header
+//   var hdays = get_vacancydays();
+//   var strhead = '<thead><tr><th colspan="2">Semaine</th>';
+//   var totalspan = 2;
+//   var coldata=getcolumndays();
+//   var coldays=coldata[0];
+//   var weekrange=coldata[1];
+//   for (var w in weekrange){
+//     strhead += '<th colspan="'+ weekrange[w] +'">' + w + '</th>';
+//     totalspan += weekrange[w];
+//   }
+  
+//   strhead += '</tr><tr><th><span class="glyphicon glyphicon-time"></span> de </th><th><span class="glyphicon glyphicon-time"></span> Ã  </th>';
+//   for (var th in coldays){
+//     var sty="";
+//     if (hdays[coldays[th]]) {
+//       sty =' class="'+((hdays[coldays[th]]=='vacancy')?'calvacancy':'calvacrange')+'" ';
+//     }
+//     strhead += '<th'+sty+'>'+ coldays[th]+'</th>';
+//   }
+//   strhead += '</tr></thead>';
+//   $('#tbl_timetable').append(strhead);
+//   $('#tbl_timetable').append('<tbody>');
+//   for (var g in cgr) {
+//     $('#tbl_timetable').append('<tr ><td colspan="'+ totalspan+'" style="background-color: '+ cgr[g].color+' !important;">Groupe:<span style="font-weight: bold;"> '+  cgr[g].grpname+'</span></td></tr>');
+//     var ttdata = gettimetable(cgr[g].uuid);
+//     //dump(cgr[g].grpname + ":" + ttdata.length  + "=>" + cgr[g].color + "\n");
+//     if (!ttdata){
+//       $('#tbl_timetable').append('<tr><td colspan="'+ totalspan+'"> Pas de données</td></tr>');
+//       continue;
+//     }
+//     var alltr =[];
+//     var grtrange = timeranges;
+    
+//     for (var tt in ttdata) {
+//       if (timeranges.indexOf(ttdata[tt].begintime) == -1) {
+//         grtrange.push(ttdata[tt].begintime);
+//       }
+//       if (timeranges.indexOf(ttdata[tt].endtime) == -1) {
+//         grtrange.push(ttdata[tt].endtime);
+//       }
+//     }
+//     grtrange=grtrange.sort();
+//     for (var t=0;t<grtrange.length-1;t++){
+//       var tr = {begintime:grtrange[t],endtime:grtrange[t+1]};
+//       alltr.push(tr);
+//     }
+    
+
+//     var thead = [];
+//     //var weekrange = {};
+//     var ltd = "";
+//     for (var t in ttdata){
+//       var dx = new Date(ttdata[t].daydate);
+//       var head = ttdata[t].daydate.substring(8,10);
+//       if (thead.indexOf(head) == -1) {
+//         thead.push(head);
+//       } 
+    
+//       for (var y in alltr) {
+//         if (!alltr[y][head]) {
+//           alltr[y][head] = {childs:0};
+//         }
+//         if ((ttdata[t].begintime <= alltr[y].begintime) && (ttdata[t].endtime >= alltr[y].endtime)) {
+//           alltr[y][head]['childs'] += parseInt(ttdata[t].childcnt); 
+//         }
+//       }  
+//     }
+//   for (var a in alltr){
+//     var trn = '<tr><td><strong>'+alltr[a].begintime+'</strong></td><td><strong>'+alltr[a].endtime+'</strong></td>';
+//     for (var h in thead){
+//       if ((hdays[thead[h]]) && (hdays[thead[h]] == 'vacancy')) {
+//         trn += '<td style="background-color: #6D6D6D !important"></td>';
+//         continue;
+//       }
+//       trn += '<td class="alignright" style="background-color: '+((alltr[a][thead[h]].childs <= cgr[g].maxchilds)?((alltr[a][thead[h]].childs == cgr[g].maxchilds)?'orange':'green'):'red')+' !important;"><span>' +alltr[a][thead[h]].childs+ '</span>';
+//       trn +='</td>';
+//     }
+//     trn += '</tr>';
+//     $('#tbl_timetable').append(trn);
+//   }
+//   }
+//   $('#tbl_timetable').append('</tbody>');
+
+
+// }
+
+//get opening hours for list by splittet times
+// function getoph() {
+//   var ophsql = "select dd.daydate,max(wh.datestart) as baseopendate, "+
+// "case when strftime('%w',daydate) = '1' then montimeopen "+
+// "when strftime('%w',daydate) = '2' then tuetimeopen "+
+// "when strftime('%w',daydate) = '3' then wedtimeopen "+
+// "when strftime('%w',daydate) = '4' then thutimeopen "+
+// "when strftime('%w',daydate) = '5' then fritimeopen when strftime('%w',daydate) = '6' then sattimeopen else null end as begintime, "+
+// "case when strftime('%w',daydate) = '1' then montimeclose "+
+// "when strftime('%w',daydate) = '2' then tuetimeclose "+
+// "when strftime('%w',daydate) = '3' then wedtimeclose "+
+// "when strftime('%w',daydate) = '4' then thutimeclose "+
+// "when strftime('%w',daydate) = '5' then fritimeclose when strftime('%w',daydate) = '6' then sattimeclose else null end as endtime "+
+//  "from workinghours wh left join (";
+//   ophsql += drsql + 
+//   ") dd on (dd.daydate > wh.datestart) group by dd.daydate order by dd.daydate";
+//   //dump("\n\n\nOPHSQL: " + ophsql + "\n\n\n");
+//   var ophdata = appdb.dbquery(ophsql);
+//   ophdata = ophdata.sqldata;
+//   return ophdata;
+// }
+
+// function getlunchdata() {
+//   var dateto2 = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 1);
+//       var sqlret = "select strftime('%d',daydate) as daydate,groupuuid,sum(monlunch+tuelunch+wedlunch+thulunch+frilunch) as lunch from ( " +
+// "select oph.daydate,gr.grpname,gr.uuid as groupuuid, " +
+// "SUM( CASE WHEN strftime('%w',oph.daydate) == '1' AND pl.monlunch == '1' THEN 1 ELSE 0 END ) AS monlunch, " +
+// "SUM( CASE WHEN strftime('%w',oph.daydate) == '2' AND pl.tuelunch == '1' THEN 1 ELSE 0 END ) AS tuelunch, " +
+// "SUM( CASE WHEN strftime('%w',oph.daydate) == '3' AND pl.wedlunch == '1' THEN 1 ELSE 0 END ) AS wedlunch, " +
+// "SUM( CASE WHEN strftime('%w',oph.daydate) == '4' AND pl.thulunch == '1' THEN 1 ELSE 0 END ) AS thulunch, " +
+// "SUM( CASE WHEN strftime('%w',oph.daydate) == '5' AND pl.frilunch == '1' THEN 1 ELSE 0 END ) AS frilunch " +
+// "SUM( CASE WHEN strftime('%w',oph.daydate) == '6' AND pl.satlunch == '1' THEN 1 ELSE 0 END ) AS satlunch " +
+// "FROM planning pl LEFT JOIN groups gr ON (pl.groupuuid=gr.uuid) " +
+// "LEFT JOIN " +
+// "( SELECT * FROM ( ";
+     
+//       sqlret += drsql + " )) oph " +
+// "ON ( oph.daydate BETWEEN pl.datebegin AND pl.dateend) " +
+// "WHERE oph.daydate IS NOT NULL " +
+// "AND oph.daydate not in (select vacancydate from vacancy where vacancydateto is null and vacancydate between '"+initdate.toLocaleFormat("%Y-%m-%d") + "' AND '" + dateto2.toLocaleFormat("%Y-%m-%d")+"') " +
+// "GROUP BY daydate,gr.uuid " +
+// "ORDER BY oph.daydate, gr.minage, gr.maxage " +
+// ") group by daydate,grpname; ";
+//   //"LunchSQL:" + sqlret + "\n");
+//   var lunchdata = appdb.dbquery(sqlret);
+//   lunchdata = lunchdata.sqldata;
+//   return lunchdata;
+// }
+
+// function load_calendar_dayranges(){
+//   jsdump("load load_calendar_dayranges");
+//     var cgr = appdb.dbquery("select uuid,grpname,maxchilds,color from groups");
+//     cgr = cgr.sqldata;
+//     var hdays = get_vacancydays();
+//     var strhead = '<thead><tr><th colspan="1">Semaine</th>';
+//     var totalspan = 1;
+//     var coldata=getcolumndays();
+//     var coldays=coldata[0];
+//     var weekrange=coldata[1];
+//     for (var w in weekrange){
+//       strhead += '<th colspan="'+ weekrange[w] +'">' + w + '</th>';
+//       totalspan += weekrange[w];
+//     }
+    
+//     strhead += '</tr><tr><th>&nbsp;</th>';
+//     for (var th in coldays){
+//       var sty="";
+//       if (hdays[coldays[th]]) {
+//         sty =' class="'+((hdays[coldays[th]]=='vacancy')?'calvacancy':'calvacrange')+'" ';
+//       }
+//       strhead += '<th'+sty+'>'+ coldays[th]+'</th>';
+//     }
+//     strhead += '</tr></thead>';
+//     $('#tbl_timetable').append(strhead);
+//     $('#tbl_timetable').append('<tbody>');
+//     for (var g in cgr) {
+//       $('#tbl_timetable').append('<tr ><td colspan="'+ totalspan+'" style="background-color: '+ cgr[g].color+' !important;">Groupe:<span style="font-weight: bold;"> '+  cgr[g].grpname+'</span> (max. '+cgr[g].maxchilds+' enfants)</td></tr>');
+//       var ttdata = gettimetable(cgr[g].uuid);
+//       //dump(cgr[g].grpname + ":" + ttdata.length  + "=>" + cgr[g].color + "\n");
+//       if (!ttdata){
+//         $('#tbl_timetable').append('<tr><td colspan="'+ totalspan+'"> Pas de données</td></tr>');
+//         continue;
+//       }
+//       var alltr =[];
+//       var grtrange=['ouverture-12:00','12:00-14:00','14:00-fermeture'];
+      
+      
+//       var tfooter = [];
+//       var tr = {begintime:'00:01',endtime:'12:00',name:'matin'};
+//       alltr.push(tr);
+//       tr = {begintime:'12:00',endtime:'14:00',name:'midi'};
+//       alltr.push(tr);
+//       tr = {begintime:'14:00',endtime:'23:59',name:'après-midi'};
+//       alltr.push(tr);
+//       //dump(JSON.stringify(alltr) + "\n");
+//       var thead = [];
+//       var tfoot = [];
+//       //var weekrange = {};
+//       var ltd = "";
+//       for (var t in ttdata){
+//         var dx = new Date(ttdata[t].daydate);
+//         var head = ttdata[t].daydate.substring(8,10);
+//         if (thead.indexOf(head) == -1) {
+//           thead.push(head);
+          
+//         } 
+        
+//         for (var y in alltr) {
+//             //dump(JSON.stringify(alltr))
+//           if (!alltr[y][head]) {
+//             alltr[y][head] = {childs:0};
+//           }
+//           //dump(alltr[y].begintime + "=>" + ttdata[t].begintime + "\n");
+//           //dump(alltr[y].begintime + "<=>" + ttdata[t].endtime + "<=>"+ alltr[y].endtime + "\n----------------\n");
+//           if (y == "matin"){
+//               if (ttdata[t].begintime >= alltr[y].begintime)
+//               {
+//               alltr[y][head]['childs'] += parseInt(ttdata[t].childcnt);
+//               }
+//           }else if (y == "midi") {
+//               if (((ttdata[t].begintime <= alltr[y].begintime) && (ttdata[t].endtime >= alltr[y].endtime)) ||
+//                  ((ttdata[t].begintime >= alltr[y].begintime) && (ttdata[t].endtime >= alltr[y].endtime)) ||  
+//                  ((ttdata[t].begintime <= alltr[y].begintime) && (ttdata[t].endtime <= alltr[y].endtime)) || 
+//                  ((ttdata[t].begintime >= alltr[y].begintime) && (ttdata[t].endtime <= alltr[y].endtime)))
+//               {
+//               alltr[y][head]['childs'] += parseInt(ttdata[t].childcnt);
+//               }
+//           }else {
+//               if (ttdata[t].endtime >= alltr[y].begintime){
+//               alltr[y][head]['childs'] += parseInt(ttdata[t].childcnt);
+//               }
+//           }
+//         }
+//         //if (!tfoot[head]){
+//         //  tfoot[head] = {total:0};
+//         //}
+//         //dump(head + ":" +JSON.stringify(tfoot[head])+"\n");
+//         //tfoot[head].total =  tfoot[head].total + parseInt(ttdata[t].childcnt);
+//       }
+//     //dump("FOOTER: " + tfoot.length +" : " + JSON.stringify(tfoot) + "\n");
+//     var grpcount = [];
+//     for (var a in alltr){
+//       var trn = '<tr><td><strong>'+alltr[a].name+'</strong></td>';
+//       for (var h in thead){
+//         if ((hdays[thead[h]]) && (hdays[thead[h]] == 'vacancy')) {
+//           trn += '<td style="background-color: #6D6D6D !important"></td>';
+//           continue;
+//         }
+//         trn += '<td class="alignright" ><span>' +alltr[a][thead[h]].childs+ '</span>';
+//         trn +='</td>';
+
+//       }
+//       trn += '</tr>';
+      
+//       $('#tbl_timetable').append(trn);
+//     }
+    
+//     //trf += '</tr>';
+//     //$('#tbl_timetable').append(trf);
+//     //dump(JSON.stringify(tfoot) + "\n");
+     
+//     }
+//     $('#tbl_timetable').append('</tbody>');
+//   }
\ No newline at end of file
diff --git a/modules/calendar/js/calglobal.js b/modules/calendar/js/calglobal.js
new file mode 100644 (file)
index 0000000..1cb264f
--- /dev/null
@@ -0,0 +1,326 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {};
+//var cdate = null;
+var initdate = new Date();
+initdate.setDate(1);
+var lastmonthday = null;
+var firstmonday = null;
+var lastsunday = null;
+var winh = window.innerHeight - 140;
+var tblacc = null;
+//var lblfreq = {daily:'jour(s)',weekly:'semaine(s)',monthly:'mois'};
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre','Octobre', 'Novembre', 'Décembre'];
+var linkpos = {};
+var posday = {};
+var redate = /\d\d.\d\d.\d\d\d\d/;
+//var lictype = apppref.getpreference("support.lictype"); 
+
+function initdata() {
+  load_helpers();
+  
+  var configdata = apppref.getpreference("pageconfig.calglobal");
+  if (!configdata) {
+    apppref.setpreference("pageconfig.calglobal", '');
+  }
+  //if (lictype == "free"){
+  //  $("#ddnofficial").hide();
+  //}
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'calendar';
+    apppref.setpreference("pageconfig.calglobal",pconfig);
+  }
+  if (pconfig.calmonth) {
+
+    initdate = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+    $("#calmonth").val(pconfig.calmonth);
+  } else {
+    $("#calmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    pconfig.calmonth = initdate.toLocaleFormat('%m.%Y');
+  }
+  set_infoheader(amonth[parseInt(pconfig.calmonth.substring(0,3))] + " " + pconfig.calmonth.substring(3,8));
+  load_calendar_month();
+  
+  $('#calmonth').on('dp.hide',function(e){
+    set_calmonth();
+  });
+}
+
+function load_calendar_month() {
+
+  lastmonthday = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), -1 * parseInt(initdate.toLocaleFormat('%w')) + 2);
+
+  if (firstmonday > initdate) {
+    firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  }
+
+  lastsunday = new Date(lastmonthday.getFullYear(), lastmonthday.getMonth(), lastmonthday.getDate() + 7 - parseInt(lastmonthday.toLocaleFormat('%w')));
+
+  var weeknum = 0;
+  var cmonth = initdate.getMonth();
+  var sday = new Array();
+  for (var cdate = firstmonday; cdate <= lastsunday; cdate.setDate(cdate.getDate() + 1)) {
+    dayident = "day" + weeknum + cdate.toLocaleFormat('%w');
+
+    linkpos[cdate.toLocaleFormat('%Y-%m-%d')] = "day" + weeknum + cdate.toLocaleFormat('%w');
+    posday["day" + weeknum + cdate.toLocaleFormat('%w')] = cdate.toLocaleFormat('%Y-%m-%d');
+    $("#" + dayident + " > div.panel-day > div.panel-dayhead").html(cdate.toLocaleFormat('%d'));
+   if (cdate.getMonth() == cmonth) {
+      $("#" + dayident + " > div.panel-day > div.panel-dayhead").addClass("panel-dayheadcurrent");
+    } else {
+      $("#" + dayident).addClass("panel-dayother");
+
+    }
+    if (cdate.toLocaleFormat('%w') == "0") {
+      weeknum++;
+    }
+
+  }
+  if (weeknum == 5) {
+    var curnum = cdate.toLocaleFormat('%d');
+    $("#day51").addClass("panel-dayother");
+    curnum = parseInt(curnum++);if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day51 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day52").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day52 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day53").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day53 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day54").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day54 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day55").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day55 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day56").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day56 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day50").addClass("panel-dayother");
+    curnum = parseInt(curnum) +1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day50 > div.panel-day > div.panel-dayhead").html(curnum);
+  }
+  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), -1 * parseInt(initdate.toLocaleFormat('%w')) + 2);
+
+  if (firstmonday > initdate) {
+    firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  }
+  lastsunday = new Date(lastmonthday.getFullYear(), lastmonthday.getMonth(), lastmonthday.getDate() + 7 - parseInt(lastmonthday.toLocaleFormat('%w')));
+  load_calendar_data();
+
+  $('#frmeditvacancyrange #vacancydate').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditvacancyrange #vacancydate').val().match(redate)) {
+      $('#btn_save_vacancyrange').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_vacancyrange').attr("disabled","1");
+    }
+    if ((ok == true) && ($('#frmeditvacancyrange #vacancydateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditvacancyrange #vacancydate').val(),'date');
+      var tmpdt2 = encodeparam($('#frmeditvacancyrange #vacancydateto').val(),'date');
+      if (tmpdt1 >= tmpdt2) {
+        $('#btn_save_vacancyrange').attr("disabled","1");
+      } else {
+        $('#btn_save_vacancyrange').removeAttr("disabled");
+      }
+      
+    }
+  });
+  $('#frmeditvacancyrange #vacancydateto').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditvacancyrange #vacancydateto').val().match(redate)) {
+      $('#btn_save_vacancyrange').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_vacancyrange').attr("disabled","1");
+    }
+    if ((ok == true) && ($('#frmeditvacancyrange #vacancydateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditvacancyrange #vacancydate').val(),'date');
+      var tmpdt2 = encodeparam($('#frmeditvacancyrange #vacancydateto').val(),'date');
+      if (tmpdt1 >= tmpdt2) {
+        $('#btn_save_vacancyrange').attr("disabled","1");
+      } else {
+        $('#btn_save_vacancyrange').removeAttr("disabled");
+      }
+      
+    }
+  });
+}
+
+function load_calendar_data() {
+  $("div.panel-daybody").html("");
+  var sql = "select vacancydate,strftime('%Y%m%d',vacancydate) as strvacancydate,vacancydateto,case when vacancydateto is not null then strftime('%Y%m%d',vacancydateto) else null end as strvacancydateto,vacancydescription from vacancy " +
+  "where (vacancydate between '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' and '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "' and (vacancydateto >= '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' or vacancydateto is null)) or (vacancydateto between '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' and '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "' and vacancydate < '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "') or ((vacancydate <= '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "') and (vacancydateto >= '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "')) " +
+  "order by vacancydate,vacancydateto;";
+
+  var caldata = appdb.dbquery(sql);
+  caldata = caldata.sqldata;
+  for (var c in caldata) {
+    var freq = "FREQ=DAILY";
+    freq += ';DTSTART='+caldata[c].strvacancydate + 'T000000Z';
+
+    if (caldata[c].vacancydateto != ''){
+        freq += ';UNTIL='+caldata[c].strvacancydateto + 'T000000Z';
+    }else {
+        freq += ';UNTIL='+caldata[c].strvacancydate + 'T000000Z';
+    }
+    try {
+    var rule = RRule.fromString(freq);
+    var rall = rule.all();
+    } catch (ex){
+      //dump("ERROR! loading data!" + ex  + " FREQ:" + freq + "\n");
+    }
+    for (var r in rall){
+      var bgstyle='background-color: ' + ((caldata[c].vacancydateto == '')?'#0099cc':'#0000cc');
+      $("#" + linkpos["" + rall[r].toLocaleFormat('%Y-%m-%d')] + " > div.panel-day > div.panel-daybody").append('<div class="calevent" onclick="dlg_vacancyrange({vacancydate:\''+caldata[c].vacancydate+'\',vacancydateto:\''+caldata[c].vacancydateto+'\'},\'upd\');" style="' + bgstyle + '; color: #fff;">' + caldata[c].vacancydescription + '</div>');
+    }
+  }
+}
+
+
+function set_calmonth() {
+  pconfig.calmonth = $('#calmonth').val();
+  apppref.setpreference("pageconfig.calglobal", pconfig);
+  globelreq.send_request({
+    page: 'calglobal',
+    module: 'calendar',
+    header: 'Jours feriés / Vacances'
+  }, null);
+}
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.calglobal", pconfig);
+  globelreq.send_request({
+    page: 'calglobal',
+    module: 'calendar',
+    header: 'Jours feriés / Vacances'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.calglobal", pconfig);
+  globelreq.send_request({
+    page: 'calglobal',
+    module: 'calendar',
+    header: 'Jours feriés / Vacances'
+  }, null);
+}
+
+function dlg_vacancyrange(data, type) {
+  $("#frmeditvacancyrange #vacancydateto").val("");
+  $("#frmeditvacancyrange #vacancydate").val("");
+  $("#frmeditvacancyrange #id_vacancydateto").val("");
+  $("#frmeditvacancyrange #id_vacancydate").val("");
+  $("#frmeditvacancyrange #vacancydescription").val("");
+  var evdata = {
+      vacancydescription: '',
+      vacancydate:new Date(initdate.getFullYear(),initdate.getMonth(),initdate.getDate()).toLocaleFormat("%d.%m.%Y"),
+      vacancydateto: null
+    };
+  if (data.vacancydateto == '') {
+    $('#dt_vacancydateto').hide();
+    $('#dlgvacancytitle').html("Editer jour ferié");
+    $('#lbldatevacancy').html("Date");
+  }else {
+    $('#dt_vacancydateto').show();
+    $('#dlgvacancytitle').html("Editer vacance scolaire");
+    $('#lbldatevacancy').html("Date debut / fin");
+    evdata.vacancydateto = new Date(initdate.getFullYear(),initdate.getMonth(),initdate.getDate()).toLocaleFormat("%d.%m.%Y");
+  }
+  if (type == 'ins') {
+    $('#btndeletevacancy').hide();
+  }else {
+    $('#btndeletevacancy').show();
+  }
+  if ((type == 'upd') || (type == 'ins')) {
+    if (type == 'upd') {
+     var evsql = "SELECT strftime(\"%d.%m.%Y\",vacancydate) as vacancydate,vacancydate as id_vacancydate, strftime(\"%d.%m.%Y\",vacancydateto) as vacancydateto, vacancydateto as id_vacancydateto, vacancydescription FROM vacancy where vacancydate=date('"+data.vacancydate+"') and vacancydateto "+ ((data.vacancydateto == '')?'is null':"=date('"+data.vacancydateto+"')")+";";
+      evdata = appdb.dbquery(evsql);
+      evdata = evdata.sqldata[0];
+    }
+    for (var w in evdata) {
+      if ($("#frmeditvacancyrange #" + w)) {
+        $("#frmeditvacancyrange #" + w).val(evdata[w]);
+      }
+    }
+
+    $("#edit_vacancyrange").modal('show');
+  }
+}
+
+function confirm_delete_vacancyrange() {
+  $("#confirm_delete_vacancyrange").modal('show');
+  return false;
+}
+
+function delete_vacancyrange() {
+  var delsql = "DELETE FROM vacancy where vacancydate=date('" + $('#frmeditvacancyrange #id_vacancydate').val()+"') and vacancydateto " + (($('#frmeditvacancyrange #id_vacancydateto').val()== '')?'is null':"=date('" + $('#frmeditvacancyrange #id_vacancydateto').val() + "')")+";";
+  appdb.dbexec(delsql);
+
+  $("#confirm_delete_vacancyrange").modal('hide');
+  load_calendar_data();
+  return false;
+}
+
+function importdata(sqlfile) {
+  var abssqlfile = system.appdir() + system.sep() + 'defaults' + system.sep() + 'data'+  system.sep() + sqlfile + ".sql";
+  if (system.fileexists(abssqlfile)) {
+    var data = system.readLocalTextFile(abssqlfile);
+    var repldata = data.split(';');
+    for (var r in repldata){
+      appdb.dbquery(repldata[r] + ";");
+    }
+  }
+  load_calendar_data();
+}
+
+function save_vacancyrange() {
+  var sql1 = new Array();
+  var sql2 = new Array();
+  if ($('#vacancydateto').val() != '' && (encodeparam($('#vacancydate').val(),'date') > encodeparam($('#vacancydateto').val(),'date'))  ) {
+    errormsg("Erreur","La Date début ne peut pas Ãªtre supérieur Ã  la date fin!");
+    return false;
+  }
+  var type = 'ins';
+  if ($('#frmeditvacancyrange #id_vacancydate').val() != '') {
+    type = 'upd';
+  }
+  $("#frmeditvacancyrange :input").each(function() {
+    var input = $(this);
+    
+    if (input.attr("id") && (input.attr("id").substring(0,3) != 'id_')) {
+        if (type == 'ins') {
+          
+          sql1.push('"' + input.attr("id") + '"');
+            var ival = encodeparam(input.val(), input.attr('type'));
+            sql2.push(ival);
+        } else {
+            var ival = encodeparam(input.val(), input.attr('type'));
+            sql2.push('"' + input.attr("id") + '"=' + ival);
+        }
+    }
+  });
+
+  var xsql = "";
+  if (type == 'upd') {
+    xsql = "UPDATE vacancy SET " + sql2.join(',') + " where vacancydate=date('"+$('#frmeditvacancyrange #id_vacancydate').val()+"') and vacancydateto "+ (($('#frmeditvacancyrange #id_vacancydateto').val() == '')?'is null':"=date('"+$('#frmeditvacancyrange #id_vacancydateto').val()+"')")+";";
+  } else {
+    xsql = "INSERT INTO vacancy (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+  }
+
+  appdb.dbexec(xsql);
+  load_calendar_data();
+
+  $("#edit_vacancyrange").modal('hide');
+}
diff --git a/modules/calendar/js/callunch.js b/modules/calendar/js/callunch.js
new file mode 100644 (file)
index 0000000..cb24bbb
--- /dev/null
@@ -0,0 +1,216 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {};
+var initdate = new Date();
+initdate.setDate(1);
+var lastmonthday = null;
+var firstmonday = null;
+var lastsunday = null;
+var winh = window.innerHeight - 140;
+var tblacc = null;
+var lblfreq = {daily:'jour(s)',weekly:'semaine(s)',monthly:'mois'};
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre','Octobre', 'Novembre', 'Décembre'];
+var linkpos = {};
+var posday = {};
+var delac = null;
+var curfreq ={};
+//var lictype = apppref.getpreference("support.lictype"); 
+
+function initdata() {
+  load_helpers();
+  
+  var configdata = apppref.getpreference("pageconfig.callunch");
+  if (!configdata) {
+    apppref.setpreference("pageconfig.callunch", '');
+  }
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'calendar';
+    apppref.setpreference("pageconfig.callunch",pconfig);
+  }
+  if (pconfig.calmonth) {
+
+    initdate = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+    $("#calmonth").val(pconfig.calmonth);
+  } else {
+    $("#calmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    pconfig.calmonth = initdate.toLocaleFormat('%m.%Y');
+  }
+  set_infoheader(amonth[parseInt(pconfig.calmonth.substring(0,3))] + " " + pconfig.calmonth.substring(3,8));
+  load_calendar_month();
+  $('#calmonth').on('dp.hide',function(e){
+    set_calmonth();
+  });
+}
+
+function load_calendar_month() {
+
+  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), -1 * parseInt(initdate.toLocaleFormat('%w')) + 2);
+  if (firstmonday > initdate) {
+    firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  }
+  lastmonthday = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+  lastsunday = new Date(lastmonthday.getFullYear(), lastmonthday.getMonth(), lastmonthday.getDate() + 7 - parseInt(lastmonthday.toLocaleFormat('%w')));
+  var weeknum = 0;
+  var cmonth = initdate.getMonth();
+  var sday = new Array();
+  for (var cdate = firstmonday; cdate <= lastsunday; cdate.setDate(cdate.getDate() + 1)) {
+    dayident = "day" + weeknum + cdate.toLocaleFormat('%w');
+
+    linkpos[cdate.toLocaleFormat('%Y-%m-%d')] = "day" + weeknum + cdate.toLocaleFormat('%w');
+    posday["day" + weeknum + cdate.toLocaleFormat('%w')] = cdate.toLocaleFormat('%Y-%m-%d');
+    $("#" + dayident + " > div.panel-day > div.panel-dayhead").html(cdate.toLocaleFormat('%d'));
+    if (cdate.getMonth() == cmonth) {
+      $("#" + dayident + " > div.panel-day > div.panel-dayhead").addClass("panel-dayheadcurrent");
+     
+    } else {
+      $("#" + dayident).addClass("panel-dayother");
+    }
+    if (cdate.toLocaleFormat('%w') == "0") {
+      weeknum++;
+    }
+
+  }
+  if (weeknum == 5) {
+    var curnum = cdate.toLocaleFormat('%d');
+    $("#day51").addClass("panel-dayother");
+    curnum = parseInt(curnum++);if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day51 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day52").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day52 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day53").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day53 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day54").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day54 > div.panel-day > div.panel-dayhead").html(curnum);
+    $("#day55").addClass("panel-dayother");
+    curnum = parseInt(curnum)+1;if (curnum < 10) {curnum = "0" + curnum;}
+    $("#day55 > div.panel-day > div.panel-dayhead").html(curnum);
+
+  }
+  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), -1 * parseInt(initdate.toLocaleFormat('%w')) + 2);
+  if (firstmonday > initdate) {
+    firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  }
+  load_vacancy_data();
+  load_calendar_data();
+    
+}
+
+function load_vacancy_data() {
+  var sql = "select vacancydate,strftime('%Y%m%d',vacancydate) as strvacancydate,vacancydateto,case when vacancydateto is not null then strftime('%Y%m%d',vacancydateto) else null end as strvacancydateto,vacancydescription from vacancy " +
+  "where (vacancydate between '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' and '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "' and (vacancydateto >= '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' or vacancydateto is null)) or (vacancydateto between '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "' and '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "' and vacancydate < '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "') or ((vacancydate <= '" + firstmonday.toLocaleFormat('%Y-%m-%d') + "') and (vacancydateto >= '" + lastsunday.toLocaleFormat('%Y-%m-%d') + "')) " +
+  "order by vacancydate,vacancydateto;";
+  var caldata = appdb.dbquery(sql);
+  caldata = caldata.sqldata;
+  for (var c in caldata) {
+    var freq = "FREQ=DAILY";
+    freq += ';DTSTART='+caldata[c].strvacancydate + 'T000000Z';
+
+    if (caldata[c].vacancydateto != ''){
+        freq += ';UNTIL='+caldata[c].strvacancydateto + 'T000000Z';
+    }else {
+        freq += ';UNTIL='+caldata[c].strvacancydate + 'T000000Z';
+    }
+    try {
+    var rule = RRule.fromString(freq);
+    var rall = rule.all();
+    } catch (ex){
+      //dump("ERROR! loading data!" + ex  + " FREQ:" + freq + "\n");
+    }
+    for (var r in rall){
+      $("#" + linkpos["" + rall[r].toLocaleFormat('%Y-%m-%d')] + " > div.panel-day > div.panel-dayhead").addClass(((caldata[c].vacancydateto == '')?'calvacancy':'calvacrange'));
+      $("#" + linkpos["" + rall[r].toLocaleFormat('%Y-%m-%d')] + " > div.panel-day > div.panel-dayhead > div#vacname").remove();
+      $("#" + linkpos["" + rall[r].toLocaleFormat('%Y-%m-%d')] + " > div.panel-day > div.panel-dayhead").prepend('<div id="vacname" class="calvacheader" >'+ caldata[c].vacancydescription + "</div>&nbsp;");
+    }
+  }
+}
+
+
+function load_calendar_data() {
+
+  $("div.panel-daybody").html("");
+  var sql = getsql(new Date(initdate.toLocaleFormat("%Y-%m-%d")),new Date(lastmonthday.toLocaleFormat("%Y-%m-%d")));
+  var caldata = appdb.dbquery(sql);
+  caldata = caldata.sqldata;
+  var totals = {};
+  for (var c in caldata) {
+    $("#" + linkpos["" + caldata[c].daydate] + " > div.panel-day > div.panel-daybody").append('<span style="white-space: nowrap;">' + caldata[c].grpname + ": <span style=\"font-weight: bold;\">"+ caldata[c].lunch +'&nbsp;</span></span> ');
+    if (totals[caldata[c].daydate]) {
+      totals[caldata[c].daydate] += caldata[c].lunch;
+    }else {
+      totals[caldata[c].daydate] = caldata[c].lunch;
+    }
+  }
+  for (var t in totals){
+    $("#" + linkpos["" + t] + " > div.panel-day > div.panel-daybody").prepend('<span style="white-space: nowrap;">TOTAL:' + " <span style=\"font-weight: bold; font-size: 16px;\">"+ totals[t] +'&nbsp;</span></span><br/>');
+  }
+}
+
+function getsql(datefrom2,dateto2) {
+      var sqlret = "select daydate,grpname,sum(monlunch+tuelunch+wedlunch+thulunch+frilunch) as lunch from ( " +
+"select oph.daydate,gr.grpname, " +
+"SUM( CASE WHEN strftime('%w',oph.daydate) == '1' AND pl.monlunch == '1' THEN 1 ELSE 0 END ) AS monlunch, " +
+"SUM( CASE WHEN strftime('%w',oph.daydate) == '2' AND pl.tuelunch == '1' THEN 1 ELSE 0 END ) AS tuelunch, " +
+"SUM( CASE WHEN strftime('%w',oph.daydate) == '3' AND pl.wedlunch == '1' THEN 1 ELSE 0 END ) AS wedlunch, " +
+"SUM( CASE WHEN strftime('%w',oph.daydate) == '4' AND pl.thulunch == '1' THEN 1 ELSE 0 END ) AS thulunch, " +
+"SUM( CASE WHEN strftime('%w',oph.daydate) == '5' AND pl.frilunch == '1' THEN 1 ELSE 0 END ) AS frilunch " +
+"FROM planning pl LEFT JOIN groups gr ON (pl.groupuuid=gr.uuid) " +
+"LEFT JOIN " +
+"( SELECT * FROM ( ";
+      var sqldays = new Array();
+      
+      for (var cdate2=datefrom2;cdate2<=dateto2;cdate2.setDate(cdate2.getDate() +1)){
+            if ((cdate2.getDay() != 0) && (cdate2.getDay() != 6)){
+                  sqldays.push ("SELECT date('" + cdate2.toLocaleFormat('%Y-%m-%d') +"') as daydate");
+            }
+      }
+
+      sqlret += sqldays.join(' UNION ALL ') + " )) oph " +
+"ON ( oph.daydate BETWEEN pl.datebegin AND pl.dateend) " +
+"WHERE oph.daydate IS NOT NULL " +
+"AND oph.daydate not in (select vacancydate from vacancy where vacancydateto is null and vacancydate between '"+initdate.toLocaleFormat("%Y-%m-%d") + "' AND '" + dateto2.toLocaleFormat("%Y-%m-%d")+"') " +
+"GROUP BY daydate,gr.uuid " +
+"ORDER BY oph.daydate, gr.minage, gr.maxage " +
+") group by daydate,grpname; ";
+      return sqlret;
+}
+
+
+function set_calmonth() {
+  pconfig.calmonth = $('#calmonth').val();
+  apppref.setpreference("pageconfig.callunch", pconfig);
+  globelreq.send_request({
+    page: 'callunch',
+    module: 'calendar',
+    header: 'Déjeuner'
+  }, null);
+}
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.callunch", pconfig);
+  globelreq.send_request({
+    page: 'callunch',
+    module: 'calendar',
+    header: 'Déjeuner'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.callunch", pconfig);
+  globelreq.send_request({
+    page: 'callunch',
+    module: 'calendar',
+    header: 'Déjeuner'
+  }, null);
+}
diff --git a/modules/calendar/js/calvacancy.js b/modules/calendar/js/calvacancy.js
new file mode 100644 (file)
index 0000000..564bf7f
--- /dev/null
@@ -0,0 +1,685 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {};
+//var cdate = null;
+var initdate = new Date();
+initdate.setDate(1);
+var lastmonthday = null;
+var firstmonday = null;
+var lastsunday = null;
+var winh = window.innerHeight - 140;
+var tblcal = null;
+var lblfreq = {daily:'jour(s)',weekly:'semaine(s)',monthly:'mois'};
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre','Octobre', 'Novembre', 'Décembre'];
+var linkpos = {};
+var posday = {};
+var delac = null;
+var curfreq ={};
+var redate = /\d\d.\d\d.\d\d\d\d/;
+var curdatediff = null;
+var accdb = null;
+var drsql = "";
+var defaultcreche = null;
+var curcreche=null;
+
+function initdata() {
+  load_helpers();
+
+  var configdata = apppref.getpreference("pageconfig.calvacancy");
+  if (!configdata) {
+    apppref.setpreference("pageconfig.calvacancy", '');
+  }
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'calendar';
+    apppref.setpreference("pageconfig.calvacancy",pconfig);
+  }
+  if (pconfig.calmonth) {
+
+    initdate = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g, ''));
+    $("#calmonth").val(pconfig.calmonth);
+  } else {
+    $("#calmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    pconfig.calmonth = initdate.toLocaleFormat('%m.%Y');
+  }
+  load_creche_selection();
+  set_infoheader(amonth[parseInt(pconfig.calmonth.substring(0,3))] + " " + pconfig.calmonth.substring(3,8));
+  load_calendar_month();
+  $('#calmonth').on('dp.hide',function(e){
+    set_calmonth();
+  });
+  // $('#frmeditvacancy #datefrom').on("blur",function (e) {
+  //   var ok = true;
+  //   if ($('#frmeditvacancy #datefrom').val().match(redate)) {
+  //     $('#btn_save_vacancy').removeAttr("disabled");
+  //   }else {
+  //     ok = false;
+  //     $('#btn_save_vacancy').attr("disabled","1");
+  //   }
+  //   if ((ok == true) && ($('#frmeditvacancy #dateto').val() != '')) {
+  //     var tmpdt1 = encodeparam($('#frmeditvacancy #datefrom').val(),'date');
+  //     var nd = new Date(tmpdt1.replace(/'/g,''));
+  //     var xd = new Date(nd.getFullYear(),nd.getMonth(),nd.getDate() + curdatediff);
+  //     $('#frmeditvacancy #dateto').val(xd.toLocaleFormat("%d.%m.%Y"));
+  //     var tmpdt2 = encodeparam($('#frmeditvacancy #dateto').val(),'date');
+  //     if (tmpdt1 > tmpdt2) {
+  //       $('#btn_save_vacancy').attr("disabled","1");
+  //     } else {
+  //       $('#btn_save_vacancy').removeAttr("disabled");
+  //     }
+      
+  //   }
+  // });
+  // $('#frmeditvacancy #dateto').on("blur",function (e) {
+  //   var ok = true;
+  //   if ($('#frmeditvacancy #dateto').val().match(redate)) {
+  //     $('#btn_save_vacancy').removeAttr("disabled");
+  //   }else {
+  //     ok = false;
+  //     $('#btn_save_vacancy').attr("disabled","1");
+  //   }
+  //   curdatediff=daysBetween(new Date(encodeparam($('#frmeditvacancy #datefrom').val(),'date').replace(/'/g,'')),new Date(encodeparam($('#frmeditvacancy #dateto').val(),'date').replace(/'/g,''))); 
+  //   if ((ok == true) && ($('#frmeditvacancy #dateto').val() != '')) {
+  //     var tmpdt1 = encodeparam($('#frmeditvacancy #datefrom').val(),'date');
+  //     var tmpdt2 = encodeparam($('#frmeditvacancy #dateto').val(),'date');
+  //     if (tmpdt1 > tmpdt2) {
+  //       $('#btn_save_vacancy').attr("disabled","1");
+  //     } else {
+  //       $('#btn_save_vacancy').removeAttr("disabled");
+  //     }
+      
+  //   }
+  // });
+
+}
+
+
+
+function load_calendar_month() {
+
+  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), -1 * parseInt(initdate.toLocaleFormat('%w')) + 2);
+  if (firstmonday > initdate) {
+    firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  }
+
+  lastmonthday = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+
+  lastsunday = new Date(lastmonthday.getFullYear(), lastmonthday.getMonth(), lastmonthday.getDate() + 7 - parseInt(lastmonthday.toLocaleFormat('%w')));
+
+  var weeknum = 0;
+  var cmonth = initdate.getMonth();
+  var sday = new Array();
+  for (var cdate = firstmonday; cdate <= lastsunday; cdate.setDate(cdate.getDate() + 1)) {
+    dayident = "day" + weeknum + cdate.toLocaleFormat('%w');
+
+    linkpos[cdate.toLocaleFormat('%Y-%m-%d')] = "day" + weeknum + cdate.toLocaleFormat('%w');
+    posday["day" + weeknum + cdate.toLocaleFormat('%w')] = cdate.toLocaleFormat('%Y-%m-%d');
+    $("#" + dayident + " > div.panel-day > div.panel-dayhead").html(cdate.toLocaleFormat('%d'));
+
+    if (cdate.getMonth() == cmonth) {
+      $("#" + dayident + " > div.panel-day > div.panel-dayhead").addClass("panel-dayheadcurrent");
+    } else {
+      $("#" + dayident).addClass("panel-dayother");
+
+    }
+    if (cdate.toLocaleFormat('%w') == "0") {
+      weeknum++;
+    }
+
+  }
+
+  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), -1 * parseInt(initdate.toLocaleFormat('%w')) + 2);
+
+  if (firstmonday > initdate) {
+    firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+  }
+  //load_vacancy_data();
+  load_calendar_data();
+    
+}
+
+function load_calendar_data() {
+  var where = "";
+
+  var sql = getmonthlysql(new Date(initdate.toLocaleFormat("%Y-%m-%d")),new Date(lastmonthday.toLocaleFormat("%Y-%m-%d")),where);
+  //jsdump("monthlysql");
+  //jsdump(sql);
+  $("#tbl_timetable").html("");
+  
+
+  // set timetable header
+  drsql = getdaterangesql();
+  //var ophdata = getoph();
+
+  var thead = [];
+  var weekrange = {};
+  var ltd = "";
+  var coldata=getcolumndays();
+  var thead=coldata[0];
+  var weekrange=coldata[1];
+  // var mbdate = new Date(initdate.getFullYear(),initdate.getMonth(),1);
+  // var medate = new Date(initdate.getFullYear(),initdate.getMonth()+1,0);
+  // var cdate = mbdate;
+  // while (cdate <= medate ){
+  //   var dx = new Date(ophdata[t].daydate);
+  //   if (!weekrange[parseInt(dx.toLocaleFormat('%W'))]) {
+  //     weekrange[parseInt(dx.toLocaleFormat('%W'))] = 1;
+  //   }else if (ltd != ophdata[t].daydate) {
+  //     weekrange[parseInt(dx.toLocaleFormat('%W'))] += 1;
+  //   }
+  //   var head = ophdata[t].daydate.substring(8,10);
+  //   if (thead.indexOf(head) == -1) {
+  //     thead.push(head);
+      
+  //   }
+  //   cdate = cdate + 1;
+  //   ltd = ophdata[t].daydate;
+
+  // }
+  var cspan = 0;
+  var hdays = get_vacancydays();
+  var strhead = '<thead><tr><th style="width: 170px; min-width: 170px;">Semaine</th>';
+  for (var w in weekrange){
+    strhead += '<th colspan="'+ weekrange[w] +'">' + w + '</th>';
+    cspan += weekrange[w];
+  }
+  strhead += '</tr><tr><th style="width: 120px; min-width: 120px;">&nbsp;</th>';
+  for (var th in thead){
+    var sty="";
+    if (hdays[thead[th]]) {
+      sty =' style="background-color: '+((hdays[thead[th]]=='vacancy')?'#FF7145':'#FF9C2A')+' !important;" ';
+    }
+    strhead += '<th'+sty+'>'+ thead[th]+'</th>';
+  }
+
+  strhead += '</tr></thead>';
+  $('#tbl_timetable').append(strhead);
+  $('#tbl_timetable').append('<tbody>');
+  //dump(JSON.stringify(accdb) + "\n");
+  if (pconfig.filtercreche){
+         //dump(JSON.stringify(pconfig.filtercreche) + "\n");
+         for (var c in pconfig.filtercreche){
+                 //dump(c + "\n");
+                 var xnum = pconfig.filtercreche[c];
+                 var crspan = thead.length + 1; 
+                 curcreche = accdb[xnum];
+                 var crhead = '<tr><th colspan="'+crspan+'" style="background-color: #286090; color: #fff; font-weight: bold;">' + curcreche.name +'</th></tr>';
+                 $('#tbl_timetable').append(crhead);
+                 appdb.closeConnection();
+                 appdb.setdbFile(curcreche.path.local + system.sep() + curcreche.uuid + ".sqlite");
+                 appdb.openDatabase();
+                 setcrechevacancydata(thead,hdays);
+         }
+  }
+  $('#tbl_timetable').append('</tbody>');
+}
+
+function setcrechevacancydata(thead,hdays){
+       var vacdata = getstaffvacancy();
+               //dump(JSON.stringify(vacdata) + "\n" );
+      var staffsql = "SELECT uuid,prename || ' ' || substr(surname,1,2) as fullname,color from staff where entrydate <= date('"+initdate.toLocaleFormat('%Y-%m-%d')+"','+1 month','-1 day') and (exitdate is null or exitdate >= date('"+initdate.toLocaleFormat('%Y-%m-%d')+"'));";
+         //dump("SSQL:" + staffsql + "\n");
+      var staffnames = appdb.dbquery(staffsql);   
+         staffnames = staffnames.sqldata;
+         var stxcolor = {};
+         //dump(JSON.stringify(staffnames));
+         for (var stu in staffnames){
+                 //dump(JSON.stringify(staffnames[stu]) + "\n");
+                 stxcolor[staffnames[stu].uuid] = staffnames[stu].color;
+                 var row = '<tr><td><span style="font-weight: bold;">'+ staffnames[stu].fullname+'.</span></td>';
+    
+                 for (var d in thead){
+                         if ((hdays[thead[d]]) && (hdays[thead[d]] == 'vacancy')){
+                                 row += '<td style="background-color: #666666  !important;"></td>';
+                         }else {
+                                 row += '<td id="tblcon_'+staffnames[stu].uuid+'_'+thead[d]+'" style="padding: 0px;"></td>';
+                         }
+      
+                 }
+                 row += '</tr>';
+                 $('#tbl_timetable').append(row);
+         }
+       if (vacdata.length > 0){
+         for (var vc in vacdata){
+                 //dump(JSON.stringify(vacdata[vc]) + "\n");
+                 var da = vacdata[vc].daydate.substring(8,10);
+                 var hh = "";
+                 //if (vacdata[vc].timefrom==vacdata[vc].timeto) {
+                       //  hh="8h";
+                 //}else {
+               //        hh=parseInt(vacdata[vc].timeto.substring(1,2))-parseInt(vacdata[vc].timefrom.substring(1,2)) + "h";
+                 //}
+                 
+                 $('#tblcon_' + vacdata[vc].staffuuid + '_' + da + "").append('<button class="btn" style="padding: 2px;'+((vacdata[vc].type == "-1")?'border: 1px solid red;':"")+';background-color: '+stxcolor[vacdata[vc].staffuuid] +' !important;">'+ vacdata[vc].hours +'</button>');
+                 //$('#tblcon_' + vacdata[vc].staffuuid + '_' + da + "").append('<button class="btn" style="'+((vacdata[vc].type == "-1")?'border: 1px solid red;':"")+';background-color: '+stxcolor[vacdata[vc].staffuuid] +' !important;" onclick="dlg_vacancy(\''+curcreche.dbnum+'\',\''+ vacdata[vc].uuid +'\',\'upd\');">'+ hh +'</button>');
+         }
+
+  }
+
+}
+
+function setdailydurationfields() {
+  var dd = $('#dailyduration :selected').val();
+  if (dd=='1.0') {
+    $("#ftimefrom").hide();
+    $("#fhours").hide();
+  }else if (dd=='0.4') {
+    $("#ftimefrom").show();
+    $("#fhours").hide();
+  }else if (dd=='0.') {
+    $("#ftimefrom").show();
+    $("#fhours").show();
+  }
+}
+
+function getmonthlysql(datefrom2,dateto2,where) {
+      var sqlret = "SELECT vc.uuid, vc.datefrom,strftime('%Y%m%d',vc.datefrom) as strdatefrom,'<span style=\"display: none;\"> ' || strftime('%Y%m%d',vc.datefrom) || strftime('%Y%m%d',vc.dateto) || '</span>' || strftime('%d.%m.%Y',vc.datefrom)  || ' - '  || strftime('%d.%m.%Y',vc.dateto) as tbldaterange, vc.dateto,strftime('%Y%m%d',vc.dateto) as strdateto, "+
+"case when vc.timefrom=vc.timeto then '8h' else (cast(substr(vc.timeto,1,2) as int) - cast(substr(vc.timefrom,1,2) as int)) || 'h' end as hours , " +
+"vc.description, vc.staffuuid,coalesce(st.surname,'') || ' ' || coalesce(st.prename,'') as staffname,vc.type,st.color FROM vacancycalendar vc left join staff st on (vc.staffuuid=st.uuid) " +
+        "LEFT JOIN ( SELECT  * FROM ( ";
+      var sqldays = new Array();
+      
+      for (var cdate2=datefrom2;cdate2<=dateto2;cdate2.setDate(cdate2.getDate() +1)){
+            if ((cdate2.getDay() != 0) && (cdate2.getDay() != 6)){
+                  sqldays.push ("SELECT date('" + cdate2.toLocaleFormat('%Y-%m-%d') +"') as daydate");
+            }
+      }
+
+      sqlret += sqldays.join(' UNION ALL ') + " )) oph " +
+      "ON (oph.daydate BETWEEN vc.datefrom AND vc.dateto) " +
+        "WHERE oph.daydate IS NOT NULL and strftime('%w',oph.daydate) not in ('0') " +
+        "AND oph.daydate NOT IN ( SELECT vacancydate FROM vacancy WHERE vacancydateto IS NULL AND vacancydate BETWEEN '"+initdate.toLocaleFormat("%Y-%m-%d") + "' AND '" + dateto2.toLocaleFormat("%Y-%m-%d")+"') " +
+        ((where != '')?" AND " + where + " ":"") +
+        " GROUP BY vc.uuid ORDER BY st.uuid,vc.datefrom, vc.dateto; ";
+      return sqlret;
+}
+
+
+function set_calmonth() {
+  pconfig.calmonth = $('#calmonth').val();
+  apppref.setpreference("pageconfig.calvacancy", pconfig);
+  globelreq.send_request({
+    page: 'calvacancy',
+    module: 'calendar',
+    header: 'Congés'
+  }, null);
+}
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g,''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.calvacancy", pconfig);
+  globelreq.send_request({
+    page: 'calvacancy',
+    module: 'calendar',
+    header: 'Congés'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.calmonth, 'month').replace(/'/g,''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.calmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.calvacancy", pconfig);
+  globelreq.send_request({
+    page: 'calvacancy',
+    module: 'calendar',
+    header: 'Congés'
+  }, null);
+}
+
+// function dlg_sel_creche(){
+//     $('#select_creche').modal('show');
+// }
+
+function set_creche(){
+       $('#select_creche').modal('hide');
+       dlg_vacancy($('#sel_creche :selected').val(),null, 'ins')
+}
+
+// function dlg_vacancy(xnum,uuid, type) {
+//     if (!xnum){
+//             return false;
+//     }
+//     curcreche = accdb[xnum];
+       
+//     appdb.closeConnection();
+//     appdb.setdbFile(curcreche.path.local + system.sep() + curcreche.uuid + ".sqlite");
+//     appdb.openDatabase();
+       
+//     load_staff_selection('staffuuid',{maxHeight: 300});
+//     //dump("TYPE " + type +" CUUID:" + uuid +"\n");
+// if (type == 'ins') {
+    
+//     //load staffdata
+//     $('#frmeditvacancy #staffuuid').multiselect('select',[]);
+//     $('#btndeletevacancy').hide();
+//   }else {
+//     $('#btndeletevacancy').show();
+//   }
+
+//     var evdata = {
+//       uuid: '0',
+//       description: '',
+//       datefrom:new Date().toLocaleFormat("%d.%m.%Y"),
+//       dateto:new Date().toLocaleFormat("%d.%m.%Y"),
+//       staffuuid:'',
+//       timefrom: '00:00',
+//       hours: '1',
+//       type:'0',
+//       dailyduration:'1.0'
+//     };
+    
+//     if (type == 'upd') {
+//      var evsql = "SELECT uuid, strftime(\"%d.%m.%Y\",datefrom) as datefrom, strftime(\"%d.%m.%Y\",dateto) as dateto, timefrom, description, staffuuid,type, case when timefrom!=timeto then '0.' || (cast(substr(timeto,1,2) as int) - cast(substr(timefrom,1,2) as int)) else 1.0 end as dailyduration,null as hours FROM vacancycalendar where uuid='" + uuid + "';";
+//      //dump("UPDSQL:" +evsql + "\n"); 
+//      evdata = appdb.dbquery(evsql);
+//       evdata = evdata.sqldata[0];
+//       if (evdata.dailyduration == '1') {
+//         evdata.dailyduration = '1.0';
+//         evdata.hours = '8';
+//       }else {
+//         evdata.hours = evdata.dailyduration.substring(2,3);
+//         if (evdata.dailyduration != '0.4') {
+//           evdata.dailyduration = '0.';
+//         }
+//       }
+//       $('#frmeditvacancy #staffuuid').multiselect('select',[evdata.staffuuid]);
+//     }
+
+//     for (var w in evdata) {
+//       if ($("#frmeditvacancy #" + w)) {
+//         $("#frmeditvacancy #" + w).val(evdata[w]);
+//       }
+//     }
+//     curdatediff=daysBetween(new Date(encodeparam($('#frmeditvacancy #datefrom').val(),'date').replace(/'/g,'')),new Date(encodeparam($('#frmeditvacancy #dateto').val(),'date').replace(/'/g,''))); 
+//     setdailydurationfields();
+//     $("#edit_vacancy").modal('show');
+// }
+
+// function confirm_delete_vacancy() {
+//   $("#confirm_delete_vacancy").modal('show');
+//   return false;
+// }
+
+// function delete_vacancy() {
+//   var delsql = "DELETE FROM vacancycalendar where uuid='" + $('#frmeditvacancy #uuid').val()+"';";
+//   appdb.dbexec(delsql);
+//   load_calendar_data();
+//   $("#confirm_delete_vacancy").modal('hide');
+  
+//   return false;
+// }
+
+// function save_vacancy() {
+//   var sql1 = new Array();
+//   var sql2 = new Array();
+//   if (($('#datefrom').val() != '') &&
+//       (encodeparam($('#datefrom').val(),'date') > encodeparam($('#dateto').val(),'date'))) {
+//     errormsg("Erreur","La Date début ne peut pas Ãªtre supérieur Ã  la date fin!");
+//     return false;
+//   }
+
+//   var type = 'ins';
+//   var cuuid = "";
+//   if ($("#frmeditvacancy #uuid").val() != 0) {
+//     type = 'upd';
+//     cuuid = $("#frmeditvacancy #uuid").val();
+//   }
+  
+//   $("#frmeditvacancy :input").each(function() {
+//     var input = $(this);
+    
+//     if (input.attr("id")) {
+        
+//         if (type == 'ins') {
+          
+          
+//           if (input.attr("id") == 'uuid') {
+//             sql1.push('"' + input.attr("id") + '"');
+//             if (input.val() == "" || input.val() == "0") {
+//               sql2.push("'" + appdb.generate_uuid() + "'");
+//             } else {
+//               sql2.push("'" + input.val() + "'");
+//             }
+//           } else if (input.attr("id") == 'dailyduration') {
+//             sql1.push('"timeto"');
+//             if (input.val() == '1.0') {
+//               sql2.push("'" +$('#timefrom').val() + "'");
+//             }else if (input.val() == '0.4') {
+//               var xval = parseInt($('#timefrom').val().substring(1,2)) + 4;
+//               if (xval < 10) { xval = "0" + xval;}
+//               xval += ":00";
+//               sql2.push("'" + xval + "'");
+//             }else {
+//               var xval = parseInt($('#timefrom').val().substring(1,2)) + parseInt($('#hours').val());
+//               if (xval < 10) { xval = "0" + xval;}
+//               xval += ":00";
+//               sql2.push("'" + xval + "'");
+//             }
+//           } else if ((input.attr("id") != 'dailyduration') && (input.attr("id") != 'hours')) {
+//             sql1.push('"' + input.attr("id") + '"');
+//             var ival = encodeparam(input.val(), input.attr('type'));
+//             sql2.push(ival);
+//           }
+//         } else {
+//           if ((input.attr("id") != 'uuid') && (input.attr("id") != 'dailyduration') && (input.attr("id") != 'hours')) {
+//             var ival = encodeparam(input.val(), input.attr('type'));
+//             sql2.push('"' + input.attr("id") + '"=' + ival);
+//           } else if (input.attr("id") == 'dailyduration') {
+//             if (input.val() == '1.0') {
+//               sql2.push('"timeto"='+ "'" + $('#timefrom').val() + "'");
+//             }else if (input.val() == '0.4') {
+//               var xval = parseInt($('#timefrom').val().substring(1,2)) + 4;
+//               if (xval < 10) { xval = "0" + xval;}
+//               xval += ":00";
+//               sql2.push('"timeto"=' +"'" + xval + "'");
+//             }else {
+//               var xval = parseInt($('#timefrom').val().substring(1,2)) + parseInt($('#hours').val());
+//               if (xval < 10) { xval = "0" + xval;}
+//               xval += ":00";
+//               sql2.push('"timeto"=' +"'" + xval + "'");
+//             }
+//           }
+//         }
+//       //}
+//     }
+
+//   });
+  
+//   var xsql = "";
+//   if (type == 'upd') {
+//     xsql = "UPDATE vacancycalendar SET " + sql2.join(',') + " where \"uuid\"='" + cuuid + "';";
+//   } else {
+
+//     xsql = "INSERT INTO vacancycalendar (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+//   }
+
+//   appdb.dbexec(xsql);
+
+//   load_calendar_data();
+
+//   $("#frmeditvacancy #uuid").val("0");
+//   $("#edit_vacancy").modal('hide');
+// }
+
+function invertColor(hexTripletColor) {
+  var color = hexTripletColor;
+  color = color.substring(1); // remove #
+  color = parseInt(color, 16); // convert to integer
+  color = 0xFFFFFF ^ color; // invert three bytes
+  color = color.toString(16); // convert to hex
+  color = ("000000" + color).slice(-6); // pad with leading zeros
+  color = "#" + color; // prepend #
+  return color;
+}
+
+// function onselstaff(objid) {
+
+//   pconfig.filterstaff = $('#' + objid).val();
+//   apppref.setpreference("pageconfig.calvacancy",pconfig);
+//   load_calendar_data();
+// }
+
+function load_dlgprint(){
+  if ($('#view_month').css('display') == 'none') {
+    globelreq.send_request({page:'preview2',data:{page: 'table'}});
+  }else {
+    globelreq.send_request({page:'preview2',data:{page: 'calendar'}});
+  }
+}
+
+function load_creche_selection(){
+       accdb = appdb.getaccessibledatabases();
+       
+       for (var i in accdb){
+               //dump("DBcfg: " +JSON.stringify(i) + "\n");
+               if (appdb.dbFile == accdb[i].path.local){
+                       defaultcreche = accdb[i].dbnum;
+               }
+               $('#filter_creche').append('<option value="'+ accdb[i].dbnum+'">' +accdb[i].name+ '</option>');
+               $('#sel_creche').append('<option value="'+ accdb[i].dbnum+'">' +accdb[i].name+ '</option>');
+       }
+
+       $('#filter_creche').multiselect({enableHTML: true,numberDisplayed:1,nonSelectedText:"Crèche Courrant",allSelectedText: 'Tous',nSelectedText: ' selections'}); 
+       if (pconfig.filtercreche) {
+               $('#filter_creche').multiselect('select',pconfig.filtercreche);
+       }else {
+               var xar = [];
+               xar.push(defaultcreche);
+               $('#filter_creche').multiselect('select',xar);
+               pconfig.filtercreche = xar;
+       }
+       apppref.setpreference("pageconfig.calvacancy",pconfig);
+}
+
+function onselcreche(){
+       pconfig.filtercreche = $('#filter_creche').val();
+       apppref.setpreference("pageconfig.calvacancy",pconfig);
+       load_calendar_data();
+}
+
+// function getoph() {
+//       var ophsql = "select dd.daydate,max(wh.datestart) as baseopendate, "+
+//     "case when strftime('%w',daydate) = '1' then montimeopen "+
+//     "when strftime('%w',daydate) = '2' then tuetimeopen "+
+//     "when strftime('%w',daydate) = '3' then wedtimeopen "+
+//     "when strftime('%w',daydate) = '4' then thutimeopen "+
+//     "when strftime('%w',daydate) = '5' then fritimeopen when strftime('%w',daydate) = '6' then sattimeopen else null end as begintime, "+
+//     "case when strftime('%w',daydate) = '1' then montimeclose "+
+//     "when strftime('%w',daydate) = '2' then tuetimeclose "+
+//     "when strftime('%w',daydate) = '3' then wedtimeclose "+
+//     "when strftime('%w',daydate) = '4' then thutimeclose "+
+//     "when strftime('%w',daydate) = '5' then fritimeclose else null when strftime('%w',daydate) = '6' then sattimeclose else null  end as endtime "+
+//      "from workinghours wh left join (";
+//       ophsql += drsql + 
+//       ") dd on (dd.daydate > wh.datestart) group by dd.daydate order by dd.daydate";
+//       //dump("\n\n\nOPHSQL: " + ophsql + "\n\n\n");
+//       var ophdata = appdb.dbquery(ophsql);
+//       ophdata = ophdata.sqldata;
+//       return ophdata;
+//     }
+
+       function getdaterangesql(){
+         var adays = [];
+         var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+         var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+         for (var cdt = bdate; cdt <= bend; cdt.setDate(cdt.getDate() + 1)) {
+           if ((cdt.getDay() != 0)){
+             adays.push("select date('" + cdt.toLocaleFormat('%Y-%m-%d') + "') as daydate");
+           }
+           
+         }
+         return adays.join(" UNION ");
+       }
+       
+       function get_vacancydays(){
+                 var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+                 var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+                 var sql = "select dd.daydate,strftime('%d',dd.daydate) as strday,type from ( "+
+               "select vacancydate,  "+
+               "case when vacancydateto is null then vacancydate else vacancydateto end as vacancydateto, "+
+               "case when vacancydateto is null then 'vacancy' else 'holiday' end as type, "+
+               "vacancydescription from vacancy where (vacancydate between '"+bdate.toLocaleFormat("%Y-%m-%d")+"' and '"+bend.toLocaleFormat("%Y-%m-%d")+"' and (vacancydateto >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"' or vacancydateto is null)) or (vacancydateto between '"+bdate.toLocaleFormat("%Y-%m-%d")+"' and '"+bend.toLocaleFormat("%Y-%m-%d")+"' and vacancydate < '"+bdate.toLocaleFormat("%Y-%m-%d")+"') or ((vacancydate <= '"+bdate.toLocaleFormat("%Y-%m-%d")+"') and (vacancydateto >= '"+bend.toLocaleFormat("%Y-%m-%d")+"')) order by vacancydate,vacancydateto) vc "+
+               "join ( "+ drsql +") dd  "+
+               "on (dd.daydate between vc.vacancydate and vc.vacancydateto) group by dd.daydate order by daydate;";
+      var hdata = appdb.dbquery(sql);
+      //jsdump("Vacancy SQL");
+      //jsdump(sql);
+                 hdata = hdata.sqldata;
+                 var hs = {};
+                 for (var h in hdata){
+                   hs[hdata[h].strday] = hdata[h].type; 
+                 }
+                 return hs;
+               }
+
+       function getstaffvacancy() {
+                 var bdate = new Date(initdate.getFullYear(), initdate.getMonth(), initdate.getDate());
+                 var bend = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 0);
+                 var vacsql = "SELECT vc.uuid as uuid, dd.daydate AS daydate, vc.staffuuid as staffuuid, printf(\"%.2f\",CASE WHEN vc.timefrom=vc.timeto THEN CAST(st.weekhours/5.00 AS REAL) ELSE CAST((CAST(strftime(\"%s\",vc.timeto) AS REAL)- CAST(strftime(\"%s\",vc.timefrom) AS REAL))/3600.00 AS REAL) END) AS hours, vc.type as type" +
+                 " from ( "+
+               "select uuid,staffuuid, "+
+               "case when datefrom < '"+bdate.toLocaleFormat("%Y-%m-%d")+"' then '"+bdate.toLocaleFormat("%Y-%m-%d")+"' else  datefrom end as datefrom, "+
+               "case when dateto > '"+bend.toLocaleFormat("%Y-%m-%d")+"' then '"+bend.toLocaleFormat("%Y-%m-%d")+"' else dateto end as dateto, "+
+               "timefrom,timeto, type "+
+               "from vacancycalendar where (datefrom is null or datefrom <= '"+bend.toLocaleFormat("%Y-%m-%d")+"') and (dateto is null or dateto >= '"+bdate.toLocaleFormat("%Y-%m-%d")+"')) vc "+
+               "join ("+drsql+") dd  "+
+               "on (dd.daydate between vc.datefrom and vc.dateto) left join staff st on (st.uuid=vc.staffuuid); ";
+                 //dump("VACCALSQL:" +vacsql + "\n");
+                 var vacdata = appdb.dbquery(vacsql);
+                 vacdata = vacdata.sqldata;
+                 return vacdata;
+               }
+
+       // function load_staff_selection(objid,option){
+       //      $('#' + objid).html("");
+       //        var stdata = appdb.dbquery("select uuid, coalesce(surname,'') || ' ' || coalesce(prename,'') as name,case when color is null then '#000' else color end as color from staff order by surname,prename");
+       //        stdata = stdata.sqldata;
+       //        for (var s in stdata){
+       //          $('#' + objid).append('<option value="'+ stdata[s].uuid+'">&lt;span style="color: '+stdata[s].color+';" &gt;' +stdata[s].name+ '&lt;/span&gt;</option>');
+       //        }
+
+       //          var copt = {};
+       //          if (option) {
+       //            copt = option;
+       //          }
+       //          copt['enableHTML'] = true;
+       //          copt['nonSelectedText']="Sélectionner un(e) employé(e)...";
+       //          copt['numberDisplayed']=5;
+       //          copt['allSelectedText']='Tous';
+       //          copt['nSelectedText']=' selections';
+                   
+       //          $('#' + objid).multiselect(copt);
+                 
+  //   }
+    
+    function getcolumndays(){
+      var adays = [];
+      var wrs = [];
+      var firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(), 1);
+      //if (firstmonday > initdate) {
+      //  firstmonday = new Date(initdate.getFullYear(), initdate.getMonth(),firstmonday.getDate()-7);
+      //}
+      var lastmonthday = new Date(initdate.getFullYear(), initdate.getMonth() + 1, 1);
+      //lastsunday = new Date(lastmonthday.getFullYear(), lastmonthday.getMonth(), lastmonthday.getDate() + 7 - parseInt(lastmonthday.toLocaleFormat('%w')));
+      var lwr = -1;
+      //dump (initdate + ": " + firstmonday + " -> " + lastmonthday + "\n");
+      for (var cdt = firstmonday; cdt < lastmonthday; cdt.setDate(cdt.getDate() + 1)) {
+        if ((cdt.getDay() !== 0)){
+          if ((lwr === -1) || (!wrs[parseInt(cdt.toLocaleFormat('%W'))])) {
+            wrs[parseInt(cdt.toLocaleFormat('%W'))] = 1;
+          }else {
+            wrs[parseInt(cdt.toLocaleFormat('%W'))] += 1;
+          }
+          lwr = parseInt(cdt.toLocaleFormat('%W'));
+          adays.push(cdt.toLocaleFormat('%d'));
+        }
+        
+      }
+      //dump(JSON.stringify(wrs) + "\n");
+      return [adays,wrs];
+    }
\ No newline at end of file
diff --git a/modules/calendar/js/nlp.js b/modules/calendar/js/nlp.js
new file mode 100644 (file)
index 0000000..ec37367
--- /dev/null
@@ -0,0 +1,1042 @@
+/*!
+ * rrule.js - Library for working with recurrence rules for calendar dates.
+ * https://github.com/jkbrzt/rrule
+ *
+ * Copyright 2010, Jakub Roztocil and Lars Schoning
+ * Licenced under the BSD licence.
+ * https://github.com/jkbrzt/rrule/blob/master/LICENCE
+ *
+ */
+
+/**
+ *
+ * Implementation of RRule.fromText() and RRule::toText().
+ *
+ *
+ * On the client side, this file needs to be included
+ * when those functions are used.
+ *
+ */
+/* global module, define */
+
+;(function (root, factory) {
+  if (typeof module === 'object' && module.exports) {
+    module.exports = factory()
+  } else if (typeof define === 'function' && define.amd) {
+    define([], factory)
+  } else {
+    root._getRRuleNLP = factory()
+  }
+}(typeof window === 'object' ? window : this, function () {
+  // =============================================================================
+  // Helper functions
+  // =============================================================================
+
+  /**
+   * Return true if a value is in an array
+   */
+  var contains = function (arr, val) {
+    return arr.indexOf(val) !== -1
+  }
+
+  return function (RRule) {
+    // =============================================================================
+    // ToText
+    // =============================================================================
+
+    /**
+     *
+     * @param {RRule} rrule
+     * Optional:
+     * @param {Function} gettext function
+     * @param {Object} language definition
+     * @constructor
+     */
+    var ToText = function (rrule, gettext, language) {
+      this.text = ''
+      this.language = language || FRENCH
+      this.gettext = gettext || function (id) {
+        return id
+      }
+
+      this.rrule = rrule
+      this.freq = rrule.options.freq
+      this.options = rrule.options
+      this.origOptions = rrule.origOptions
+
+      if (this.origOptions.bymonthday) {
+        var bymonthday = [].concat(this.options.bymonthday)
+        var bynmonthday = [].concat(this.options.bynmonthday)
+
+        bymonthday.sort()
+        bynmonthday.sort()
+        bynmonthday.reverse()
+        // 1, 2, 3, .., -5, -4, -3, ..
+        this.bymonthday = bymonthday.concat(bynmonthday)
+        if (!this.bymonthday.length) this.bymonthday = null
+      }
+
+      if (this.origOptions.byweekday) {
+        var byweekday = !(this.origOptions.byweekday instanceof Array)
+          ? [this.origOptions.byweekday] : this.origOptions.byweekday
+        var days = String(byweekday)
+
+        this.byweekday = {
+          allWeeks: byweekday.filter(function (weekday) {
+            return !Boolean(weekday.n)
+          }),
+          someWeeks: byweekday.filter(function (weekday) {
+            return Boolean(weekday.n)
+          }),
+          isWeekdays: (
+            days.indexOf('MO') !== -1 &&
+            days.indexOf('TU') !== -1 &&
+            days.indexOf('WE') !== -1 &&
+            days.indexOf('TH') !== -1 &&
+            days.indexOf('FR') !== -1 &&
+            days.indexOf('SA') === -1 &&
+            days.indexOf('SU') === -1
+          )
+        }
+
+        var sortWeekDays = function (a, b) {
+          return a.weekday - b.weekday
+        }
+
+        this.byweekday.allWeeks.sort(sortWeekDays)
+        this.byweekday.someWeeks.sort(sortWeekDays)
+
+        if (!this.byweekday.allWeeks.length) this.byweekday.allWeeks = null
+        if (!this.byweekday.someWeeks.length) this.byweekday.someWeeks = null
+      } else {
+        this.byweekday = null
+      }
+    }
+
+    var common = [
+      'count', 'until', 'interval',
+      'byweekday', 'bymonthday', 'bymonth'
+    ]
+    ToText.IMPLEMENTED = []
+    ToText.IMPLEMENTED[RRule.HOURLY] = common
+    ToText.IMPLEMENTED[RRule.DAILY] = ['byhour'].concat(common)
+    ToText.IMPLEMENTED[RRule.WEEKLY] = common
+    ToText.IMPLEMENTED[RRule.MONTHLY] = common
+    ToText.IMPLEMENTED[RRule.YEARLY] = ['byweekno', 'byyearday'].concat(common)
+
+    /**
+     * Test whether the rrule can be fully converted to text.
+     * @param {RRule} rrule
+     * @return {Boolean}
+     */
+    ToText.isFullyConvertible = function (rrule) {
+      var canConvert = true
+
+      if (!(rrule.options.freq in ToText.IMPLEMENTED)) return false
+      if (rrule.origOptions.until && rrule.origOptions.count) return false
+
+      for (var key in rrule.origOptions) {
+        if (contains(['dtstart', 'wkst', 'freq'], key)) return true
+        if (!contains(ToText.IMPLEMENTED[rrule.options.freq], key)) return false
+      }
+
+      return canConvert
+    }
+
+    ToText.prototype = {
+      constructor: ToText,
+
+      isFullyConvertible: function () {
+        return ToText.isFullyConvertible(this.rrule)
+      },
+
+      /**
+       * Perform the conversion. Only some of the frequencies are supported.
+       * If some of the rrule's options aren't supported, they'll
+       * be omitted from the output an "(~ approximate)" will be appended.
+       * @return {*}
+       */
+      toString: function () {
+        var gettext = this.gettext
+
+        if (!(this.options.freq in ToText.IMPLEMENTED)) {
+          return gettext('RRule error: Unable to fully convert this rrule to text')
+        }
+
+        this.text = [gettext('tous les')]
+        this[RRule.FREQUENCIES[this.options.freq]]()
+
+        if (this.options.until) {
+          this.add(gettext('jusqu\'au'))
+          var until = this.options.until
+          this.add(until.getDate() + ' ').add(this.language.monthNames[until.getMonth()]).add(until.getFullYear())
+        } else if (this.options.count) {
+          this.add(gettext('pour'))
+            .add(this.options.count)
+            .add(this.plural(this.options.count)
+              ? gettext('fois') : gettext('fois'))
+        }
+
+        if (!this.isFullyConvertible()) this.add(gettext('(~ Ã -peu-près)'))
+
+        return this.text.join('')
+      },
+
+      HOURLY: function () {
+        var gettext = this.gettext
+
+        if (this.options.interval !== 1) this.add(this.options.interval)
+
+        this.add(this.plural(this.options.interval)
+          ? gettext('heures') : gettext('heure'))
+      },
+
+      DAILY: function () {
+        var gettext = this.gettext
+
+        if (this.options.interval !== 1) this.add(this.options.interval)
+
+        if (this.byweekday && this.byweekday.isWeekdays) {
+          this.add(this.plural(this.options.interval)
+            ? gettext('jours ouvrables') : gettext('jour ouvrable'))
+        } else {
+          this.add(this.plural(this.options.interval)
+            ? gettext('jours') : gettext('jour'))
+        }
+
+        if (this.origOptions.bymonth) {
+          this.add(gettext('dans'))
+          this._bymonth()
+        }
+
+        if (this.bymonthday) {
+          this._bymonthday()
+        } else if (this.byweekday) {
+          this._byweekday()
+        } else if (this.origOptions.byhour) {
+          this._byhour()
+        }
+      },
+
+      WEEKLY: function () {
+        var gettext = this.gettext
+
+        if (this.options.interval !== 1) {
+          this.add(this.options.interval)
+            .add(this.plural(this.options.interval)
+              ? gettext('semaines') : gettext('semaine'))
+        }
+
+        if (this.byweekday && this.byweekday.isWeekdays) {
+          if (this.options.interval === 1) {
+            this.add(this.plural(this.options.interval)
+              ? gettext('jours ouvrables') : gettext('jour ouvrable'))
+          } else {
+            this.add(gettext('au')).add(gettext('jours ouvrables'))
+          }
+        } else {
+          if (this.options.interval === 1) this.add(gettext('semaine'))
+
+          if (this.origOptions.bymonth) {
+            this.add(gettext('dans'))
+            this._bymonth()
+          }
+
+          if (this.bymonthday) {
+            this._bymonthday()
+          } else if (this.byweekday) {
+            this._byweekday()
+          }
+        }
+      },
+
+      MONTHLY: function () {
+        var gettext = this.gettext
+
+        if (this.origOptions.bymonth) {
+          if (this.options.interval !== 1) {
+            this.add(this.options.interval).add(gettext('mois'))
+            if (this.plural(this.options.interval)) this.add(gettext('dans'))
+          } else {
+            // this.add(gettext('MONTH'))
+          }
+          this._bymonth()
+        } else {
+          if (this.options.interval !== 1) this.add(this.options.interval)
+          this.add(this.plural(this.options.interval)
+            ? gettext('mois') : gettext('mois'))
+        }
+        if (this.bymonthday) {
+          this._bymonthday()
+        } else if (this.byweekday && this.byweekday.isWeekdays) {
+          this.add(gettext('au')).add(gettext('jours ouvrables'))
+        } else if (this.byweekday) {
+          this._byweekday()
+        }
+      },
+
+      YEARLY: function () {
+        var gettext = this.gettext
+
+        if (this.origOptions.bymonth) {
+          if (this.options.interval !== 1) {
+            this.add(this.options.interval)
+            this.add(gettext('ans'))
+          } else {
+            // this.add(gettext('YEAR'))
+          }
+          this._bymonth()
+        } else {
+          if (this.options.interval !== 1) this.add(this.options.interval)
+          this.add(this.plural(this.options.interval)
+            ? gettext('ans') : gettext('an'))
+        }
+
+        if (this.bymonthday) {
+          this._bymonthday()
+        } else if (this.byweekday) {
+          this._byweekday()
+        }
+
+        if (this.options.byyearday) {
+          this.add(gettext('au'))
+            .add(this.list(this.options.byyearday, this.nth, gettext('et')))
+            .add(gettext('jour'))
+        }
+
+        if (this.options.byweekno) {
+          this.add(gettext('dans'))
+            .add(this.plural(this.options.byweekno.length) ? gettext('semaines') : gettext('semaine'))
+            .add(this.list(this.options.byweekno, null, gettext('et')))
+        }
+      },
+
+      _bymonthday: function () {
+        var gettext = this.gettext
+        if (this.byweekday && this.byweekday.allWeeks) {
+          this.add(gettext('au'))
+            .add(this.list(this.byweekday.allWeeks, this.weekdaytext, gettext('ou')))
+            .add(gettext('le'))
+            .add(this.list(this.bymonthday, this.nth, gettext('ou')))
+        } else {
+          this.add(gettext('au'))
+            .add(this.list(this.bymonthday, this.nth, gettext('et')))
+        }
+      // this.add(gettext('DAY'))
+      },
+
+      _byweekday: function () {
+        var gettext = this.gettext
+        if (this.byweekday.allWeeks && !this.byweekday.isWeekdays) {
+          this.add(gettext('au'))
+            .add(this.list(this.byweekday.allWeeks, this.weekdaytext))
+        }
+
+        if (this.byweekday.someWeeks) {
+          if (this.byweekday.allWeeks) this.add(gettext('et'))
+
+          this.add(gettext('au'))
+            .add(this.list(this.byweekday.someWeeks, this.weekdaytext, gettext('et')))
+        }
+      },
+
+      _byhour: function () {
+        var gettext = this.gettext
+
+        this.add(gettext('à'))
+          .add(this.list(this.origOptions.byhour, null, gettext('et')))
+      },
+
+      _bymonth: function () {
+        this.add(this.list(this.options.bymonth, this.monthtext, this.gettext('et')))
+      },
+
+      nth: function (n) {
+        var nth, npos
+        var gettext = this.gettext
+
+        if (n === -1) return gettext('dernier')
+
+        npos = Math.abs(n)
+        switch (npos) {
+          case 1:
+          case 21:
+          case 31:
+            nth = npos + gettext('ier')
+            break
+          case 2:
+          case 22:
+            nth = npos + gettext('ième')
+            break
+          case 3:
+          case 23:
+            nth = npos + gettext('ième')
+            break
+          default:
+            nth = npos + gettext('ième')
+        }
+
+        return n < 0 ? nth + ' ' + gettext('dernier') : nth
+      },
+
+      monthtext: function (m) {
+        return this.language.monthNames[m - 1]
+      },
+
+      weekdaytext: function (wday) {
+        var weekday = typeof wday === 'number' ? wday : wday.getJsWeekday()
+        return (wday.n ? this.nth(wday.n) + ' ' : '') +
+          this.language.dayNames[weekday]
+      },
+
+      plural: function (n) {
+        return n % 100 !== 1
+      },
+
+      add: function (s) {
+        this.text.push(' ')
+        this.text.push(s)
+        return this
+      },
+
+      list: function (arr, callback, finalDelim, delim) {
+        var delimJoin = function (array, delimiter, finalDelimiter) {
+          var list = ''
+
+          for (var i = 0; i < array.length; i++) {
+            if (i !== 0) {
+              if (i === array.length - 1) {
+                list += ' ' + finalDelimiter + ' '
+              } else {
+                list += delimiter + ' '
+              }
+            }
+            list += array[i]
+          }
+          return list
+        }
+
+        delim = delim || ','
+        callback = callback || function (o) {
+          return o
+        }
+        var self = this
+        var realCallback = function (arg) {
+          return callback.call(self, arg)
+        }
+
+        if (finalDelim) {
+          return delimJoin(arr.map(realCallback), delim, finalDelim)
+        } else {
+          return arr.map(realCallback).join(delim + ' ')
+        }
+      }
+    }
+
+    // =============================================================================
+    // fromText
+    // =============================================================================
+    /**
+     * Will be able to convert some of the below described rules from
+     * text format to a rule object.
+     *
+     *
+     * RULES
+     *
+     * Every ([n])
+     *       day(s)
+     *     | [weekday], ..., (and) [weekday]
+     *     | weekday(s)
+     *     | week(s)
+     *     | month(s)
+     *     | [month], ..., (and) [month]
+     *     | year(s)
+     *
+     *
+     * Plus 0, 1, or multiple of these:
+     *
+     * on [weekday], ..., (or) [weekday] the [monthday], [monthday], ... (or) [monthday]
+     *
+     * on [weekday], ..., (and) [weekday]
+     *
+     * on the [monthday], [monthday], ... (and) [monthday] (day of the month)
+     *
+     * on the [nth-weekday], ..., (and) [nth-weekday] (of the month/year)
+     *
+     *
+     * Plus 0 or 1 of these:
+     *
+     * for [n] time(s)
+     *
+     * until [date]
+     *
+     * Plus (.)
+     *
+     *
+     * Definitely no supported for parsing:
+     *
+     * (for year):
+     *     in week(s) [n], ..., (and) [n]
+     *
+     *     on the [yearday], ..., (and) [n] day of the year
+     *     on day [yearday], ..., (and) [n]
+     *
+     *
+     * NON-TERMINALS
+     *
+     * [n]: 1, 2 ..., one, two, three ..
+     * [month]: January, February, March, April, May, ... December
+     * [weekday]: Monday, ... Sunday
+     * [nth-weekday]: first [weekday], 2nd [weekday], ... last [weekday], ...
+     * [monthday]: first, 1., 2., 1st, 2nd, second, ... 31st, last day, 2nd last day, ..
+     * [date]:
+     *     [month] (0-31(,) ([year])),
+     *     (the) 0-31.(1-12.([year])),
+     *     (the) 0-31/(1-12/([year])),
+     *     [weekday]
+     *
+     * [year]: 0000, 0001, ... 01, 02, ..
+     *
+     * Definitely not supported for parsing:
+     *
+     * [yearday]: first, 1., 2., 1st, 2nd, second, ... 366th, last day, 2nd last day, ..
+     *
+     * @param {String} text
+     * @return {Object, Boolean} the rule, or null.
+     */
+    var fromText = function (text, language) {
+      return new RRule(parseText(text, language))
+    }
+
+    var parseText = function (text, language) {
+      var options = {}
+      var ttr = new Parser((language || FRENCH).tokens)
+
+      if (!ttr.start(text)) return null
+
+      S()
+      return options
+
+      function S () {
+        // every [n]
+        var n
+
+        ttr.expect('every')
+        if ((n = ttr.accept('number'))) options.interval = parseInt(n[0], 10)
+        if (ttr.isDone()) throw new Error('Unexpected end')
+
+        switch (ttr.symbol) {
+          case 'day(s)':
+            options.freq = RRule.DAILY
+            if (ttr.nextSymbol()) {
+              AT()
+              F()
+            }
+            break
+
+          // FIXME Note: every 2 weekdays != every two weeks on weekdays.
+          // DAILY on weekdays is not a valid rule
+          case 'weekday(s)':
+            options.freq = RRule.WEEKLY
+            options.byweekday = [
+              RRule.MO,
+              RRule.TU,
+              RRule.WE,
+              RRule.TH,
+              RRule.FR
+            ]
+            ttr.nextSymbol()
+            F()
+            break
+
+          case 'week(s)':
+            options.freq = RRule.WEEKLY
+            if (ttr.nextSymbol()) {
+              ON()
+              F()
+            }
+            break
+
+          case 'hour(s)':
+            options.freq = RRule.HOURLY
+            if (ttr.nextSymbol()) {
+              ON()
+              F()
+            }
+            break
+
+          case 'month(s)':
+            options.freq = RRule.MONTHLY
+            if (ttr.nextSymbol()) {
+              ON()
+              F()
+            }
+            break
+
+          case 'year(s)':
+            options.freq = RRule.YEARLY
+            if (ttr.nextSymbol()) {
+              ON()
+              F()
+            }
+            break
+
+          case 'monday':
+          case 'tuesday':
+          case 'wednesday':
+          case 'thursday':
+          case 'friday':
+          case 'saturday':
+          case 'sunday':
+            options.freq = RRule.WEEKLY
+            options.byweekday = [RRule[ttr.symbol.substr(0, 2).toUpperCase()]]
+
+            if (!ttr.nextSymbol()) return
+
+            // TODO check for duplicates
+            while (ttr.accept('comma')) {
+              if (ttr.isDone()) throw new Error('Unexpected end')
+
+              var wkd
+              if (!(wkd = decodeWKD())) {
+                throw new Error('Unexpected symbol ' + ttr.symbol + ', expected weekday')
+              }
+
+              options.byweekday.push(RRule[wkd])
+              ttr.nextSymbol()
+            }
+            MDAYs()
+            F()
+            break
+
+          case 'january':
+          case 'february':
+          case 'march':
+          case 'april':
+          case 'may':
+          case 'june':
+          case 'july':
+          case 'august':
+          case 'september':
+          case 'october':
+          case 'november':
+          case 'december':
+            options.freq = RRule.YEARLY
+            options.bymonth = [decodeM()]
+
+            if (!ttr.nextSymbol()) return
+
+            // TODO check for duplicates
+            while (ttr.accept('comma')) {
+              if (ttr.isDone()) throw new Error('Unexpected end')
+
+              var m
+              if (!(m = decodeM())) {
+                throw new Error('Unexpected symbol ' + ttr.symbol + ', expected month')
+              }
+
+              options.bymonth.push(m)
+              ttr.nextSymbol()
+            }
+
+            ON()
+            F()
+            break
+
+          default:
+            throw new Error('Unknown symbol')
+
+        }
+      }
+
+      function ON () {
+        var on = ttr.accept('on')
+        var the = ttr.accept('the')
+        if (!(on || the)) return
+
+        do {
+          var nth, wkd, m
+
+          // nth <weekday> | <weekday>
+          if ((nth = decodeNTH())) {
+            // ttr.nextSymbol()
+
+            if ((wkd = decodeWKD())) {
+              ttr.nextSymbol()
+              if (!options.byweekday) options.byweekday = []
+              options.byweekday.push(RRule[wkd].nth(nth))
+            } else {
+              if (!options.bymonthday) options.bymonthday = []
+              options.bymonthday.push(nth)
+              ttr.accept('day(s)')
+            }
+            // <weekday>
+          } else if ((wkd = decodeWKD())) {
+            ttr.nextSymbol()
+            if (!options.byweekday) options.byweekday = []
+            options.byweekday.push(RRule[wkd])
+          } else if (ttr.symbol === 'weekday(s)') {
+            ttr.nextSymbol()
+            if (!options.byweekday) options.byweekday = []
+            options.byweekday.push(RRule.MO)
+            options.byweekday.push(RRule.TU)
+            options.byweekday.push(RRule.WE)
+            options.byweekday.push(RRule.TH)
+            options.byweekday.push(RRule.FR)
+          } else if (ttr.symbol === 'week(s)') {
+            ttr.nextSymbol()
+            var n
+            if (!(n = ttr.accept('number'))) {
+              throw new Error('Unexpected symbol ' + ttr.symbol + ', expected week number')
+            }
+            options.byweekno = [n[0]]
+            while (ttr.accept('comma')) {
+              if (!(n = ttr.accept('number'))) {
+                throw new Error('Unexpected symbol ' + ttr.symbol + '; expected monthday')
+              }
+              options.byweekno.push(n[0])
+            }
+          } else if ((m = decodeM())) {
+            ttr.nextSymbol()
+            if (!options.bymonth) options.bymonth = []
+            options.bymonth.push(m)
+          } else {
+            return
+          }
+        } while (ttr.accept('comma') || ttr.accept('the') || ttr.accept('on'))
+      }
+
+      function AT () {
+        var at = ttr.accept('at')
+        if (!at) return
+
+        do {
+          var n
+          if (!(n = ttr.accept('number'))) {
+            throw new Error('Unexpected symbol ' + ttr.symbol + ', expected hour')
+          }
+          options.byhour = [n[0]]
+          while (ttr.accept('comma')) {
+            if (!(n = ttr.accept('number'))) {
+              throw new Error('Unexpected symbol ' + ttr.symbol + '; expected hour')
+            }
+            options.byhour.push(n[0])
+          }
+        } while (ttr.accept('comma') || ttr.accept('at'))
+      }
+
+      function decodeM () {
+        switch (ttr.symbol) {
+          case 'january':
+            return 1
+          case 'february':
+            return 2
+          case 'march':
+            return 3
+          case 'april':
+            return 4
+          case 'may':
+            return 5
+          case 'june':
+            return 6
+          case 'july':
+            return 7
+          case 'august':
+            return 8
+          case 'september':
+            return 9
+          case 'october':
+            return 10
+          case 'november':
+            return 11
+          case 'december':
+            return 12
+          default:
+            return false
+        }
+      }
+
+      function decodeWKD () {
+        switch (ttr.symbol) {
+          case 'monday':
+          case 'tuesday':
+          case 'wednesday':
+          case 'thursday':
+          case 'friday':
+          case 'saturday':
+          case 'sunday':
+            return ttr.symbol.substr(0, 2).toUpperCase()
+          default:
+            return false
+        }
+      }
+
+      function decodeNTH () {
+        switch (ttr.symbol) {
+          case 'last':
+            ttr.nextSymbol()
+            return -1
+          case 'first':
+            ttr.nextSymbol()
+            return 1
+          case 'second':
+            ttr.nextSymbol()
+            return ttr.accept('last') ? -2 : 2
+          case 'third':
+            ttr.nextSymbol()
+            return ttr.accept('last') ? -3 : 3
+          case 'nth':
+            var v = parseInt(ttr.value[1], 10)
+            if (v < -366 || v > 366) throw new Error('Nth out of range: ' + v)
+
+            ttr.nextSymbol()
+            return ttr.accept('last') ? -v : v
+
+          default:
+            return false
+        }
+      }
+
+      function MDAYs () {
+        ttr.accept('on')
+        ttr.accept('the')
+
+        var nth
+        if (!(nth = decodeNTH())) return
+
+        options.bymonthday = [nth]
+        ttr.nextSymbol()
+
+        while (ttr.accept('comma')) {
+          if (!(nth = decodeNTH())) {
+            throw new Error('Unexpected symbol ' + ttr.symbol + '; expected monthday')
+          }
+
+          options.bymonthday.push(nth)
+          ttr.nextSymbol()
+        }
+      }
+
+      function F () {
+        if (ttr.symbol === 'until') {
+          var date = Date.parse(ttr.text)
+
+          if (!date) throw new Error('Cannot parse until date:' + ttr.text)
+          options.until = new Date(date)
+        } else if (ttr.accept('for')) {
+          options.count = ttr.value[0]
+          ttr.expect('number')
+          // ttr.expect('times')
+        }
+      }
+    }
+
+    // =============================================================================
+    // Parser
+    // =============================================================================
+
+    var Parser = function (rules) {
+      this.rules = rules
+    }
+
+    Parser.prototype.start = function (text) {
+      this.text = text
+      this.done = false
+      return this.nextSymbol()
+    }
+
+    Parser.prototype.isDone = function () {
+      return this.done && this.symbol == null
+    }
+
+    Parser.prototype.nextSymbol = function () {
+      var best, bestSymbol
+      var p = this
+
+      this.symbol = null
+      this.value = null
+      do {
+        if (this.done) return false
+
+        var match, rule
+        best = null
+        for (var name in this.rules) {
+          rule = this.rules[name]
+          if ((match = rule.exec(p.text))) {
+            if (best == null || match[0].length > best[0].length) {
+              best = match
+              bestSymbol = name
+            }
+          }
+        }
+
+        if (best != null) {
+          this.text = this.text.substr(best[0].length)
+
+          if (this.text === '') this.done = true
+        }
+
+        if (best == null) {
+          this.done = true
+          this.symbol = null
+          this.value = null
+          return
+        }
+      } while (bestSymbol === 'SKIP')
+
+      this.symbol = bestSymbol
+      this.value = best
+      return true
+    }
+
+    Parser.prototype.accept = function (name) {
+      if (this.symbol === name) {
+        if (this.value) {
+          var v = this.value
+          this.nextSymbol()
+          return v
+        }
+
+        this.nextSymbol()
+        return true
+      }
+
+      return false
+    }
+
+    Parser.prototype.expect = function (name) {
+      if (this.accept(name)) return true
+
+      throw new Error('expected ' + name + ' but found ' + this.symbol)
+    }
+
+    // =============================================================================
+    // i18n
+    // =============================================================================
+
+    var ENGLISH = {
+      dayNames: [
+        'Sunday', 'Monday', 'Tuesday', 'Wednesday',
+        'Thursday', 'Friday', 'Saturday'
+      ],
+      monthNames: [
+        'January', 'February', 'March', 'April', 'May',
+        'June', 'July', 'August', 'September', 'October',
+        'November', 'December'
+      ],
+      tokens: {
+        'SKIP': /^[ \r\n\t]+|^\.$/,
+        'number': /^[1-9][0-9]*/,
+        'numberAsText': /^(one|two|three)/i,
+        'every': /^every/i,
+        'day(s)': /^days?/i,
+        'weekday(s)': /^weekdays?/i,
+        'week(s)': /^weeks?/i,
+        'hour(s)': /^hours?/i,
+        'month(s)': /^months?/i,
+        'year(s)': /^years?/i,
+        'on': /^(on|in)/i,
+        'at': /^(at)/i,
+        'the': /^the/i,
+        'first': /^first/i,
+        'second': /^second/i,
+        'third': /^third/i,
+        'nth': /^([1-9][0-9]*)(\.|th|nd|rd|st)/i,
+        'last': /^last/i,
+        'for': /^for/i,
+        'time(s)': /^times?/i,
+        'until': /^(un)?til/i,
+        'monday': /^mo(n(day)?)?/i,
+        'tuesday': /^tu(e(s(day)?)?)?/i,
+        'wednesday': /^we(d(n(esday)?)?)?/i,
+        'thursday': /^th(u(r(sday)?)?)?/i,
+        'friday': /^fr(i(day)?)?/i,
+        'saturday': /^sa(t(urday)?)?/i,
+        'sunday': /^su(n(day)?)?/i,
+        'january': /^jan(uary)?/i,
+        'february': /^feb(ruary)?/i,
+        'march': /^mar(ch)?/i,
+        'april': /^apr(il)?/i,
+        'may': /^may/i,
+        'june': /^june?/i,
+        'july': /^july?/i,
+        'august': /^aug(ust)?/i,
+        'september': /^sep(t(ember)?)?/i,
+        'october': /^oct(ober)?/i,
+        'november': /^nov(ember)?/i,
+        'december': /^dec(ember)?/i,
+        'comma': /^(,\s*|(and|or)\s*)+/i
+      }
+    }
+    
+    var FRENCH = {
+      dayNames: [
+        'Dimanche', 'Lundi', 'Mardi', 'Mercredi',
+        'Jeudi', 'Vendredi', 'Samedi'
+      ],
+      monthNames: [
+        'Janvier', 'Février', 'Mars', 'Avril', 'Mai',
+        'Juin', 'Julliet', 'Août', 'Septembre', 'Octobre',
+        'Novembre', 'Décembre'
+      ],
+      tokens: {
+        'SKIP': /^[ \r\n\t]+|^\.$/,
+        'number': /^[1-9][0-9]*/,
+        'numberAsText': /^(one|two|three)/i,
+        'every': /^every/i,
+        'day(s)': /^days?/i,
+        'weekday(s)': /^weekdays?/i,
+        'week(s)': /^weeks?/i,
+        'hour(s)': /^hours?/i,
+        'month(s)': /^months?/i,
+        'year(s)': /^years?/i,
+        'on': /^(on|in)/i,
+        'at': /^(at)/i,
+        'the': /^the/i,
+        'first': /^first/i,
+        'second': /^second/i,
+        'third': /^third/i,
+        'nth': /^([1-9][0-9]*)(\.|th|nd|rd|st)/i,
+        'last': /^last/i,
+        'for': /^for/i,
+        'time(s)': /^times?/i,
+        'until': /^(un)?til/i,
+        'monday': /^mo(n(day)?)?/i,
+        'tuesday': /^tu(e(s(day)?)?)?/i,
+        'wednesday': /^we(d(n(esday)?)?)?/i,
+        'thursday': /^th(u(r(sday)?)?)?/i,
+        'friday': /^fr(i(day)?)?/i,
+        'saturday': /^sa(t(urday)?)?/i,
+        'sunday': /^su(n(day)?)?/i,
+        'january': /^jan(uary)?/i,
+        'february': /^feb(ruary)?/i,
+        'march': /^mar(ch)?/i,
+        'april': /^apr(il)?/i,
+        'may': /^may/i,
+        'june': /^june?/i,
+        'july': /^july?/i,
+        'august': /^aug(ust)?/i,
+        'september': /^sep(t(ember)?)?/i,
+        'october': /^oct(ober)?/i,
+        'november': /^nov(ember)?/i,
+        'december': /^dec(ember)?/i,
+        'comma': /^(,\s*|(and|or)\s*)+/i
+      }
+    }
+    
+    
+
+    // =============================================================================
+    // Export
+    // =============================================================================
+
+    return {
+      fromText: fromText,
+      parseText: parseText,
+      isFullyConvertible: ToText.isFullyConvertible,
+      toText: function (rrule, gettext, language) {
+        return new ToText(rrule, gettext, language).toString()
+      }
+    }
+  }
+}))
diff --git a/modules/calendar/js/rrule.js b/modules/calendar/js/rrule.js
new file mode 100644 (file)
index 0000000..b75e991
--- /dev/null
@@ -0,0 +1,2278 @@
+/*!
+ * rrule.js - Library for working with recurrence rules for calendar dates.
+ * https://github.com/jkbrzt/rrule
+ *
+ * Copyright 2010, Jakub Roztocil and Lars Schoning
+ * Licenced under the BSD licence.
+ * https://github.com/jkbrzt/rrule/blob/master/LICENCE
+ *
+ * Based on:
+ * python-dateutil - Extensions to the standard Python datetime module.
+ * Copyright (c) 2003-2011 - Gustavo Niemeyer <gustavo@niemeyer.net>
+ * Copyright (c) 2012 - Tomi Pieviläinen <tomi.pievilainen@iki.fi>
+ * https://github.com/jkbrzt/rrule/blob/master/LICENCE
+ *
+ */
+/* global module, define */
+
+;(function (root, factory) {
+  if (typeof module === 'object' && module.exports) {
+    module.exports = factory()
+  } else if (typeof define === 'function' && define.amd) {
+    define([], factory)
+  } else {
+    root.RRule = factory(root)
+    root.RRuleSet = root.RRule.RRuleSet
+    root.rrulestr = root.RRule.rrulestr
+  }
+}(typeof window === 'object' ? window : this, function (root) {
+  // =============================================================================
+  // Date utilities
+  // =============================================================================
+
+  /**
+   * General date-related utilities.
+   * Also handles several incompatibilities between JavaScript and Python
+   *
+   */
+  var dateutil = {
+    MONTH_DAYS: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
+
+    /**
+     * Number of milliseconds of one day
+     */
+    ONE_DAY: 1000 * 60 * 60 * 24,
+
+    /**
+     * @see: <http://docs.python.org/library/datetime.html#datetime.MAXYEAR>
+     */
+    MAXYEAR: 9999,
+
+    /**
+     * Python uses 1-Jan-1 as the base for calculating ordinals but we don't
+     * want to confuse the JS engine with milliseconds > Number.MAX_NUMBER,
+     * therefore we use 1-Jan-1970 instead
+     */
+    ORDINAL_BASE: new Date(1970, 0, 1),
+
+    /**
+     * Python: MO-SU: 0 - 6
+     * JS: SU-SAT 0 - 6
+     */
+    PY_WEEKDAYS: [6, 0, 1, 2, 3, 4, 5],
+
+    /**
+     * py_date.timetuple()[7]
+     */
+    getYearDay: function (date) {
+      var dateNoTime = new Date(
+        date.getFullYear(), date.getMonth(), date.getDate())
+      return Math.ceil(
+        (dateNoTime - new Date(date.getFullYear(), 0, 1)) / dateutil.ONE_DAY) + 1
+    },
+
+    isLeapYear: function (year) {
+      if (year instanceof Date) year = year.getFullYear()
+      return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)
+    },
+
+    /**
+     * @return {Number} the date's timezone offset in ms
+     */
+    tzOffset: function (date) {
+      return date.getTimezoneOffset() * 60 * 1000
+    },
+
+    /**
+     * @see: <http://www.mcfedries.com/JavaScript/DaysBetween.asp>
+     */
+    daysBetween: function (date1, date2) {
+      // The number of milliseconds in one day
+      // Convert both dates to milliseconds
+      var date1_ms = date1.getTime() - dateutil.tzOffset(date1)
+      var date2_ms = date2.getTime() - dateutil.tzOffset(date2)
+      // Calculate the difference in milliseconds
+      var difference_ms = Math.abs(date1_ms - date2_ms)
+      // Convert back to days and return
+      return Math.round(difference_ms / dateutil.ONE_DAY)
+    },
+
+    /**
+     * @see: <http://docs.python.org/library/datetime.html#datetime.date.toordinal>
+     */
+    toOrdinal: function (date) {
+      return dateutil.daysBetween(date, dateutil.ORDINAL_BASE)
+    },
+
+    /**
+     * @see - <http://docs.python.org/library/datetime.html#datetime.date.fromordinal>
+     */
+    fromOrdinal: function (ordinal) {
+      var millisecsFromBase = ordinal * dateutil.ONE_DAY
+      return new Date(dateutil.ORDINAL_BASE.getTime() -
+        dateutil.tzOffset(dateutil.ORDINAL_BASE) +
+        millisecsFromBase +
+        dateutil.tzOffset(new Date(millisecsFromBase)))
+    },
+
+    /**
+     * @see: <http://docs.python.org/library/calendar.html#calendar.monthrange>
+     */
+    monthRange: function (year, month) {
+      var date = new Date(year, month, 1)
+      return [dateutil.getWeekday(date), dateutil.getMonthDays(date)]
+    },
+
+    getMonthDays: function (date) {
+      var month = date.getMonth()
+      return month === 1 && dateutil.isLeapYear(date)
+        ? 29 : dateutil.MONTH_DAYS[month]
+    },
+
+    /**
+     * @return {Number} python-like weekday
+     */
+    getWeekday: function (date) {
+      return dateutil.PY_WEEKDAYS[date.getDay()]
+    },
+
+    /**
+     * @see: <http://docs.python.org/library/datetime.html#datetime.datetime.combine>
+     */
+    combine: function (date, time) {
+      time = time || date
+      return new Date(
+        date.getFullYear(), date.getMonth(), date.getDate(),
+        time.getHours(), time.getMinutes(), time.getSeconds(),
+        time.getMilliseconds())
+    },
+
+    clone: function (date) {
+      var dolly = new Date(date.getTime())
+      return dolly
+    },
+
+    cloneDates: function (dates) {
+      var clones = []
+      for (var i = 0; i < dates.length; i++) {
+        clones.push(dateutil.clone(dates[i]))
+      }
+      return clones
+    },
+
+    /**
+     * Sorts an array of Date or dateutil.Time objects
+     */
+    sort: function (dates) {
+      dates.sort(function (a, b) {
+        return a.getTime() - b.getTime()
+      })
+    },
+
+    timeToUntilString: function (time) {
+      var comp
+      var date = new Date(time)
+      var comps = [
+        date.getUTCFullYear(),
+        date.getUTCMonth() + 1,
+        date.getUTCDate(),
+        'T',
+        date.getUTCHours(),
+        date.getUTCMinutes(),
+        date.getUTCSeconds(),
+        'Z'
+      ]
+
+      for (var i = 0; i < comps.length; i++) {
+        comp = comps[i]
+        if (!/[TZ]/.test(comp) && comp < 10) comps[i] = '0' + String(comp)
+      }
+      return comps.join('')
+    },
+
+    untilStringToDate: function (until) {
+      var re = /^(\d{4})(\d{2})(\d{2})(T(\d{2})(\d{2})(\d{2})Z)?$/
+      var bits = re.exec(until)
+      if (!bits) throw new Error('Invalid UNTIL value: ' + until)
+      return new Date(Date.UTC(
+        bits[1],
+        bits[2] - 1,
+        bits[3],
+        bits[5] || 0,
+        bits[6] || 0,
+        bits[7] || 0))
+    }
+  }
+
+  dateutil.Time = function (hour, minute, second, millisecond) {
+    this.hour = hour
+    this.minute = minute
+    this.second = second
+    this.millisecond = millisecond || 0
+  }
+
+  dateutil.Time.prototype = {
+    constructor: dateutil.Time,
+    getHours: function () {
+      return this.hour
+    },
+    getMinutes: function () {
+      return this.minute
+    },
+    getSeconds: function () {
+      return this.second
+    },
+    getMilliseconds: function () {
+      return this.millisecond
+    },
+    getTime: function () {
+      return ((this.hour * 60 * 60) + (this.minute * 60) + this.second) * 1000 +
+        this.millisecond
+    }
+  }
+
+  // =============================================================================
+  // Helper functions
+  // =============================================================================
+
+  /**
+   * Simplified version of python's range()
+   */
+  var range = function (start, end) {
+    if (arguments.length === 1) {
+      end = start
+      start = 0
+    }
+    var rang = []
+    for (var i = start; i < end; i++) rang.push(i)
+    return rang
+  }
+
+  var repeat = function (value, times) {
+    var i = 0
+    var array = []
+
+    if (value instanceof Array) {
+      for (; i < times; i++) array[i] = [].concat(value)
+    } else {
+      for (; i < times; i++) array[i] = value
+    }
+    return array
+  }
+
+  /**
+   * Python like split
+   */
+  var split = function (str, sep, num) {
+    var splits = str.split(sep)
+    return num
+      ? splits.slice(0, num).concat([splits.slice(num).join(sep)]) : splits
+  }
+
+  /**
+   * closure/goog/math/math.js:modulo
+   * Copyright 2006 The Closure Library Authors.
+   * The % operator in JavaScript returns the remainder of a / b, but differs from
+   * some other languages in that the result will have the same sign as the
+   * dividend. For example, -1 % 8 == -1, whereas in some other languages
+   * (such as Python) the result would be 7. This function emulates the more
+   * correct modulo behavior, which is useful for certain applications such as
+   * calculating an offset index in a circular list.
+   *
+   * @param {number} a The dividend.
+   * @param {number} b The divisor.
+   * @return {number} a % b where the result is between 0 and b (either 0 <= x < b
+   *     or b < x <= 0, depending on the sign of b).
+   */
+  var pymod = function (a, b) {
+    var r = a % b
+    // If r and b differ in sign, add b to wrap the result to the correct sign.
+    return (r * b < 0) ? r + b : r
+  }
+
+  /**
+   * @see: <http://docs.python.org/library/functions.html#divmod>
+   */
+  var divmod = function (a, b) {
+    return {div: Math.floor(a / b), mod: pymod(a, b)}
+  }
+
+  /**
+   * Python-like boolean
+   * @return {Boolean} value of an object/primitive, taking into account
+   * the fact that in Python an empty list's/tuple's
+   * boolean value is False, whereas in JS it's true
+   */
+  var plb = function (obj) {
+    return (obj instanceof Array && obj.length === 0)
+      ? false : Boolean(obj)
+  }
+
+  /**
+   * Return true if a value is in an array
+   */
+  var contains = function (arr, val) {
+    return arr.indexOf(val) !== -1
+  }
+
+  // =============================================================================
+  // Date masks
+  // =============================================================================
+
+  // Every mask is 7 days longer to handle cross-year weekly periods.
+
+  var M365MASK = [].concat(
+    repeat(1, 31), repeat(2, 28), repeat(3, 31),
+    repeat(4, 30), repeat(5, 31), repeat(6, 30),
+    repeat(7, 31), repeat(8, 31), repeat(9, 30),
+    repeat(10, 31), repeat(11, 30), repeat(12, 31),
+    repeat(1, 7))
+
+  var M366MASK = [].concat(
+    repeat(1, 31), repeat(2, 29), repeat(3, 31),
+    repeat(4, 30), repeat(5, 31), repeat(6, 30),
+    repeat(7, 31), repeat(8, 31), repeat(9, 30),
+    repeat(10, 31), repeat(11, 30), repeat(12, 31),
+    repeat(1, 7))
+
+  var M28 = range(1, 29)
+  var M29 = range(1, 30)
+  var M30 = range(1, 31)
+  var M31 = range(1, 32)
+
+  var MDAY366MASK = [].concat(
+    M31, M29, M31,
+    M30, M31, M30,
+    M31, M31, M30,
+    M31, M30, M31,
+    M31.slice(0, 7))
+
+  var MDAY365MASK = [].concat(
+    M31, M28, M31,
+    M30, M31, M30,
+    M31, M31, M30,
+    M31, M30, M31,
+    M31.slice(0, 7))
+
+  M28 = range(-28, 0)
+  M29 = range(-29, 0)
+  M30 = range(-30, 0)
+  M31 = range(-31, 0)
+
+  var NMDAY366MASK = [].concat(
+    M31, M29, M31,
+    M30, M31, M30,
+    M31, M31, M30,
+    M31, M30, M31,
+    M31.slice(0, 7))
+
+  var NMDAY365MASK = [].concat(
+    M31, M28, M31,
+    M30, M31, M30,
+    M31, M31, M30,
+    M31, M30, M31,
+    M31.slice(0, 7))
+
+  var M366RANGE = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]
+  var M365RANGE = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]
+
+  var WDAYMASK = (function () {
+    for (var wdaymask = [], i = 0; i < 55; i++) wdaymask = wdaymask.concat(range(7))
+    return wdaymask
+  }())
+
+  // =============================================================================
+  // Weekday
+  // =============================================================================
+
+  var Weekday = function (weekday, n) {
+    if (n === 0) throw new Error("Can't create weekday with n == 0")
+    this.weekday = weekday
+    this.n = n
+  }
+
+  Weekday.prototype = {
+    constructor: Weekday,
+    // __call__ - Cannot call the object directly, do it through
+    // e.g. RRule.TH.nth(-1) instead,
+    nth: function (n) {
+      return this.n === n ? this : new Weekday(this.weekday, n)
+    },
+
+    // __eq__
+    equals: function (other) {
+      return this.weekday === other.weekday && this.n === other.n
+    },
+
+    // __repr__
+    toString: function () {
+      var s = ['MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU'][this.weekday]
+      if (this.n) s = (this.n > 0 ? '+' : '') + String(this.n) + s
+      return s
+    },
+
+    getJsWeekday: function () {
+      return this.weekday === 6 ? 0 : this.weekday + 1
+    }
+
+  }
+
+  // =============================================================================
+  // RRule
+  // =============================================================================
+
+  /**
+   *
+   * @param {Object?} options - see <http://labix.org/python-dateutil/#head-cf004ee9a75592797e076752b2a889c10f445418>
+   *        The only required option is `freq`, one of RRule.YEARLY, RRule.MONTHLY, ...
+   * @constructor
+   */
+  var RRule = function (options, noCache) {
+    options = options || {}
+    // RFC string
+    this._string = null
+    this._cache = noCache ? null : {
+      all: false,
+      before: [],
+      after: [],
+      between: []
+    }
+
+    // used by toString()
+    this.origOptions = {}
+
+    var invalid = []
+    var keys = Object.keys(options)
+    var defaultKeys = Object.keys(RRule.DEFAULT_OPTIONS)
+
+    // Shallow copy for origOptions and check for invalid
+    keys.forEach(function (key) {
+      this.origOptions[key] = options[key]
+      if (!contains(defaultKeys, key)) invalid.push(key)
+    }, this)
+
+    if (invalid.length) throw new Error('Invalid options: ' + invalid.join(', '))
+
+    if (!RRule.FREQUENCIES[options.freq] && options.byeaster === null) {
+      throw new Error('Invalid frequency: ' + String(options.freq))
+    }
+
+    // Merge in default options
+    defaultKeys.forEach(function (key) {
+      if (!contains(keys, key)) options[key] = RRule.DEFAULT_OPTIONS[key]
+    })
+
+    var opts = this.options = options
+
+    if (opts.byeaster !== null) opts.freq = RRule.YEARLY
+    if (!opts.dtstart) opts.dtstart = new Date()
+
+    var millisecondModulo = opts.dtstart.getTime() % 1000
+    if (opts.wkst === null) {
+      opts.wkst = RRule.MO.weekday
+    } else if (typeof opts.wkst === 'number') {
+      // cool, just keep it like that
+    } else {
+      opts.wkst = opts.wkst.weekday
+    }
+
+    if (opts.bysetpos !== null) {
+      if (typeof opts.bysetpos === 'number') opts.bysetpos = [opts.bysetpos]
+
+      for (var i = 0; i < opts.bysetpos.length; i++) {
+        var v = opts.bysetpos[i]
+        if (v === 0 || !(v >= -366 && v <= 366)) {
+          throw new Error('bysetpos must be between 1 and 366,' +
+            ' or between -366 and -1')
+        }
+      }
+    }
+
+    if (!(plb(opts.byweekno) || plb(opts.byyearday) || plb(opts.bymonthday) ||
+      opts.byweekday !== null || opts.byeaster !== null)) {
+      switch (opts.freq) {
+        case RRule.YEARLY:
+          if (!opts.bymonth) opts.bymonth = opts.dtstart.getMonth() + 1
+          opts.bymonthday = opts.dtstart.getDate()
+          break
+        case RRule.MONTHLY:
+          opts.bymonthday = opts.dtstart.getDate()
+          break
+        case RRule.WEEKLY:
+          opts.byweekday = dateutil.getWeekday(opts.dtstart)
+          break
+      }
+    }
+
+    // bymonth
+    if (opts.bymonth !== null && !(opts.bymonth instanceof Array)) {
+      opts.bymonth = [opts.bymonth]
+    }
+    // byyearday
+    if (opts.byyearday !== null && !(opts.byyearday instanceof Array)) {
+      opts.byyearday = [opts.byyearday]
+    }
+
+    // bymonthday
+    if (opts.bymonthday === null) {
+      opts.bymonthday = []
+      opts.bynmonthday = []
+    } else if (opts.bymonthday instanceof Array) {
+      var bymonthday = []
+      var bynmonthday = []
+
+      for (i = 0; i < opts.bymonthday.length; i++) {
+        v = opts.bymonthday[i]
+        if (v > 0) {
+          bymonthday.push(v)
+        } else if (v < 0) {
+          bynmonthday.push(v)
+        }
+      }
+      opts.bymonthday = bymonthday
+      opts.bynmonthday = bynmonthday
+    } else {
+      if (opts.bymonthday < 0) {
+        opts.bynmonthday = [opts.bymonthday]
+        opts.bymonthday = []
+      } else {
+        opts.bynmonthday = []
+        opts.bymonthday = [opts.bymonthday]
+      }
+    }
+
+    // byweekno
+    if (opts.byweekno !== null && !(opts.byweekno instanceof Array)) {
+      opts.byweekno = [opts.byweekno]
+    }
+
+    // byweekday / bynweekday
+    if (opts.byweekday === null) {
+      opts.bynweekday = null
+    } else if (typeof opts.byweekday === 'number') {
+      opts.byweekday = [opts.byweekday]
+      opts.bynweekday = null
+    } else if (opts.byweekday instanceof Weekday) {
+      if (!opts.byweekday.n || opts.freq > RRule.MONTHLY) {
+        opts.byweekday = [opts.byweekday.weekday]
+        opts.bynweekday = null
+      } else {
+        opts.bynweekday = [
+          [opts.byweekday.weekday, opts.byweekday.n]
+        ]
+        opts.byweekday = null
+      }
+    } else {
+      var byweekday = []
+      var bynweekday = []
+
+      for (i = 0; i < opts.byweekday.length; i++) {
+        var wday = opts.byweekday[i]
+
+        if (typeof wday === 'number') {
+          byweekday.push(wday)
+        } else if (!wday.n || opts.freq > RRule.MONTHLY) {
+          byweekday.push(wday.weekday)
+        } else {
+          bynweekday.push([wday.weekday, wday.n])
+        }
+      }
+      opts.byweekday = plb(byweekday) ? byweekday : null
+      opts.bynweekday = plb(bynweekday) ? bynweekday : null
+    }
+
+    // byhour
+    if (opts.byhour === null) {
+      opts.byhour = (opts.freq < RRule.HOURLY) ? [opts.dtstart.getHours()] : null
+    } else if (typeof opts.byhour === 'number') {
+      opts.byhour = [opts.byhour]
+    }
+
+    // byminute
+    if (opts.byminute === null) {
+      opts.byminute = (opts.freq < RRule.MINUTELY)
+        ? [opts.dtstart.getMinutes()] : null
+    } else if (typeof opts.byminute === 'number') {
+      opts.byminute = [opts.byminute]
+    }
+
+    // bysecond
+    if (opts.bysecond === null) {
+      opts.bysecond = (opts.freq < RRule.SECONDLY)
+        ? [opts.dtstart.getSeconds()] : null
+    } else if (typeof opts.bysecond === 'number') {
+      opts.bysecond = [opts.bysecond]
+    }
+
+    if (opts.freq >= RRule.HOURLY) {
+      this.timeset = null
+    } else {
+      this.timeset = []
+      for (i = 0; i < opts.byhour.length; i++) {
+        var hour = opts.byhour[i]
+        for (var j = 0; j < opts.byminute.length; j++) {
+          var minute = opts.byminute[j]
+          for (var k = 0; k < opts.bysecond.length; k++) {
+            var second = opts.bysecond[k]
+            // python:
+            // datetime.time(hour, minute, second,
+            // tzinfo=self._tzinfo))
+            this.timeset.push(new dateutil.Time(hour, minute, second, millisecondModulo))
+          }
+        }
+      }
+      dateutil.sort(this.timeset)
+    }
+  }
+
+  // RRule class 'constants'
+
+  RRule.FREQUENCIES = [
+    'YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY',
+    'HOURLY', 'MINUTELY', 'SECONDLY'
+  ]
+
+  RRule.YEARLY = 0
+  RRule.MONTHLY = 1
+  RRule.WEEKLY = 2
+  RRule.DAILY = 3
+  RRule.HOURLY = 4
+  RRule.MINUTELY = 5
+  RRule.SECONDLY = 6
+
+  RRule.MO = new Weekday(0)
+  RRule.TU = new Weekday(1)
+  RRule.WE = new Weekday(2)
+  RRule.TH = new Weekday(3)
+  RRule.FR = new Weekday(4)
+  RRule.SA = new Weekday(5)
+  RRule.SU = new Weekday(6)
+
+  RRule.DEFAULT_OPTIONS = {
+    freq: null,
+    dtstart: null,
+    interval: 1,
+    wkst: RRule.MO,
+    count: null,
+    until: null,
+    bysetpos: null,
+    bymonth: null,
+    bymonthday: null,
+    bynmonthday: null,
+    byyearday: null,
+    byweekno: null,
+    byweekday: null,
+    bynweekday: null,
+    byhour: null,
+    byminute: null,
+    bysecond: null,
+    byeaster: null
+  }
+
+  RRule.parseText = function (text, language) {
+    return getnlp().parseText(text, language)
+  }
+
+  RRule.fromText = function (text, language) {
+    return getnlp().fromText(text, language)
+  }
+
+  RRule.optionsToString = function (options) {
+    var key, value, strValues
+    var pairs = []
+    var keys = Object.keys(options)
+    var defaultKeys = Object.keys(RRule.DEFAULT_OPTIONS)
+
+    for (var i = 0; i < keys.length; i++) {
+      if (!contains(defaultKeys, keys[i])) continue
+
+      key = keys[i].toUpperCase()
+      value = options[keys[i]]
+      strValues = []
+
+      if (value === null || value instanceof Array && !value.length) continue
+
+      switch (key) {
+        case 'FREQ':
+          value = RRule.FREQUENCIES[options.freq]
+          break
+        case 'WKST':
+          value = value.toString()
+          break
+        case 'BYWEEKDAY':
+          /*
+          NOTE: BYWEEKDAY is a special case.
+          RRule() deconstructs the rule.options.byweekday array
+          into an array of Weekday arguments.
+          On the other hand, rule.origOptions is an array of Weekdays.
+          We need to handle both cases here.
+          It might be worth change RRule to keep the Weekdays.
+
+          Also, BYWEEKDAY (used by RRule) vs. BYDAY (RFC)
+
+          */
+          key = 'BYDAY'
+          if (!(value instanceof Array)) value = [value]
+
+          for (var wday, j = 0; j < value.length; j++) {
+            wday = value[j]
+            if (wday instanceof Weekday) {
+              // good
+            } else if (wday instanceof Array) {
+              wday = new Weekday(wday[0], wday[1])
+            } else {
+              wday = new Weekday(wday)
+            }
+            strValues[j] = wday.toString()
+          }
+          value = strValues
+          break
+        case 'DTSTART':
+        case 'UNTIL':
+          value = dateutil.timeToUntilString(value)
+          break
+        default:
+          if (value instanceof Array) {
+            for (j = 0; j < value.length; j++) strValues[j] = String(value[j])
+            value = strValues
+          } else {
+            value = String(value)
+          }
+
+      }
+      pairs.push([key, value])
+    }
+
+    var strings = []
+    for (i = 0; i < pairs.length; i++) {
+      var attr = pairs[i]
+      strings.push(attr[0] + '=' + attr[1].toString())
+    }
+    return strings.join(';')
+  }
+
+  RRule.prototype = {
+    constructor: RRule,
+
+    /**
+     * @param {Function} iterator - optional function that will be called
+     *                   on each date that is added. It can return false
+     *                   to stop the iteration.
+     * @return Array containing all recurrences.
+     */
+    all: function (iterator) {
+      if (iterator) {
+        return this._iter(new CallbackIterResult('all', {}, iterator))
+      } else {
+        var result = this._cacheGet('all')
+        if (result === false) {
+          result = this._iter(new IterResult('all', {}))
+          this._cacheAdd('all', result)
+        }
+        return result
+      }
+    },
+
+    /**
+     * Returns all the occurrences of the rrule between after and before.
+     * The inc keyword defines what happens if after and/or before are
+     * themselves occurrences. With inc == True, they will be included in the
+     * list, if they are found in the recurrence set.
+     * @return Array
+     */
+    between: function (after, before, inc, iterator) {
+      var args = {
+        before: before,
+        after: after,
+        inc: inc
+      }
+
+      if (iterator) {
+        return this._iter(new CallbackIterResult('between', args, iterator))
+      }
+      var result = this._cacheGet('between', args)
+      if (result === false) {
+        result = this._iter(new IterResult('between', args))
+        this._cacheAdd('between', result, args)
+      }
+      return result
+    },
+
+    /**
+     * Returns the last recurrence before the given datetime instance.
+     * The inc keyword defines what happens if dt is an occurrence.
+     * With inc == True, if dt itself is an occurrence, it will be returned.
+     * @return Date or null
+     */
+    before: function (dt, inc) {
+      var args = {dt: dt, inc: inc}
+      var result = this._cacheGet('before', args)
+      if (result === false) {
+        result = this._iter(new IterResult('before', args))
+        this._cacheAdd('before', result, args)
+      }
+      return result
+    },
+
+    /**
+     * Returns the first recurrence after the given datetime instance.
+     * The inc keyword defines what happens if dt is an occurrence.
+     * With inc == True, if dt itself is an occurrence, it will be returned.
+     * @return Date or null
+     */
+    after: function (dt, inc) {
+      var args = {dt: dt, inc: inc}
+      var result = this._cacheGet('after', args)
+      if (result === false) {
+        result = this._iter(new IterResult('after', args))
+        this._cacheAdd('after', result, args)
+      }
+      return result
+    },
+
+    /**
+     * Returns the number of recurrences in this set. It will have go trough
+     * the whole recurrence, if this hasn't been done before.
+     */
+    count: function () {
+      return this.all().length
+    },
+
+    /**
+     * Converts the rrule into its string representation
+     * @see <http://www.ietf.org/rfc/rfc2445.txt>
+     * @return String
+     */
+    toString: function () {
+      return RRule.optionsToString(this.origOptions)
+    },
+
+    /**
+    * Will convert all rules described in nlp:ToText
+    * to text.
+    */
+    toText: function (gettext, language) {
+      return getnlp().toText(this, gettext, language)
+    },
+
+    isFullyConvertibleToText: function () {
+      return getnlp().isFullyConvertible(this)
+    },
+
+    /**
+     * @param {String} what - all/before/after/between
+     * @param {Array,Date} value - an array of dates, one date, or null
+     * @param {Object?} args - _iter arguments
+     */
+    _cacheAdd: function (what, value, args) {
+      if (!this._cache) return
+
+      if (value) {
+        value = (value instanceof Date)
+          ? dateutil.clone(value) : dateutil.cloneDates(value)
+      }
+
+      if (what === 'all') {
+        this._cache.all = value
+      } else {
+        args._value = value
+        this._cache[what].push(args)
+      }
+    },
+
+    /**
+     * @return false - not in the cache
+     *         null  - cached, but zero occurrences (before/after)
+     *         Date  - cached (before/after)
+     *         []    - cached, but zero occurrences (all/between)
+     *         [Date1, DateN] - cached (all/between)
+     */
+    _cacheGet: function (what, args) {
+      if (!this._cache) return false
+
+      var cached = false
+      var argsKeys = args ? Object.keys(args) : []
+      var findCacheDiff = function (item) {
+        for (var key, i = 0; i < argsKeys.length; i++) {
+          key = argsKeys[i]
+          if (String(args[key]) !== String(item[key])) return true
+        }
+        return false
+      }
+
+      if (what === 'all') {
+        cached = this._cache.all
+      } else {
+        // Let's see whether we've already called the
+        // 'what' method with the same 'args'
+        for (var item, i = 0; i < this._cache[what].length; i++) {
+          item = this._cache[what][i]
+          if (argsKeys.length && findCacheDiff(item)) continue
+          cached = item._value
+          break
+        }
+      }
+
+      if (!cached && this._cache.all) {
+        // Not in the cache, but we already know all the occurrences,
+        // so we can find the correct dates from the cached ones.
+        var iterResult = new IterResult(what, args)
+        for (i = 0; i < this._cache.all.length; i++) {
+          if (!iterResult.accept(this._cache.all[i])) break
+        }
+        cached = iterResult.getValue()
+        this._cacheAdd(what, cached, args)
+      }
+
+      return cached instanceof Array
+        ? dateutil.cloneDates(cached)
+        : (cached instanceof Date ? dateutil.clone(cached) : cached)
+    },
+
+    /**
+     * @return a RRule instance with the same freq and options
+     *          as this one (cache is not cloned)
+     */
+    clone: function () {
+      return new RRule(this.origOptions)
+    },
+
+    _iter: function (iterResult) {
+      /* Since JavaScript doesn't have the python's yield operator (<1.7),
+         we use the IterResult object that tells us when to stop iterating.
+
+      */
+
+      var dtstart = this.options.dtstart
+      var dtstartMillisecondModulo = this.options.dtstart % 1000
+
+      var year = dtstart.getFullYear()
+      var month = dtstart.getMonth() + 1
+      var day = dtstart.getDate()
+      var hour = dtstart.getHours()
+      var minute = dtstart.getMinutes()
+      var second = dtstart.getSeconds()
+      var weekday = dateutil.getWeekday(dtstart)
+
+      // Some local variables to speed things up a bit
+      var freq = this.options.freq
+      var interval = this.options.interval
+      var wkst = this.options.wkst
+      var until = this.options.until
+      var bymonth = this.options.bymonth
+      var byweekno = this.options.byweekno
+      var byyearday = this.options.byyearday
+      var byweekday = this.options.byweekday
+      var byeaster = this.options.byeaster
+      var bymonthday = this.options.bymonthday
+      var bynmonthday = this.options.bynmonthday
+      var bysetpos = this.options.bysetpos
+      var byhour = this.options.byhour
+      var byminute = this.options.byminute
+      var bysecond = this.options.bysecond
+
+      var ii = new Iterinfo(this)
+      ii.rebuild(year, month)
+
+      var getdayset = {}
+      getdayset[RRule.YEARLY] = ii.ydayset
+      getdayset[RRule.MONTHLY] = ii.mdayset
+      getdayset[RRule.WEEKLY] = ii.wdayset
+      getdayset[RRule.DAILY] = ii.ddayset
+      getdayset[RRule.HOURLY] = ii.ddayset
+      getdayset[RRule.MINUTELY] = ii.ddayset
+      getdayset[RRule.SECONDLY] = ii.ddayset
+
+      getdayset = getdayset[freq]
+
+      var timeset
+      if (freq < RRule.HOURLY) {
+        timeset = this.timeset
+      } else {
+        var gettimeset = {}
+        gettimeset[RRule.HOURLY] = ii.htimeset
+        gettimeset[RRule.MINUTELY] = ii.mtimeset
+        gettimeset[RRule.SECONDLY] = ii.stimeset
+        gettimeset = gettimeset[freq]
+        if ((freq >= RRule.HOURLY && plb(byhour) && !contains(byhour, hour)) ||
+          (freq >= RRule.MINUTELY && plb(byminute) && !contains(byminute, minute)) ||
+          (freq >= RRule.SECONDLY && plb(bysecond) && !contains(bysecond, minute))) {
+          timeset = []
+        } else {
+          timeset = gettimeset.call(ii, hour, minute, second, dtstartMillisecondModulo)
+        }
+      }
+
+      var total = 0
+      var count = this.options.count
+      var i, j, k, dm, div, mod, tmp, pos, dayset, start, end, fixday, filtered
+
+      while (true) {
+        // Get dayset with the right frequency
+        tmp = getdayset.call(ii, year, month, day)
+        dayset = tmp[0]
+        start = tmp[1]
+        end = tmp[2]
+
+        // Do the "hard" work ;-)
+        filtered = false
+        for (j = start; j < end; j++) {
+          i = dayset[j]
+
+          filtered = (plb(bymonth) && !contains(bymonth, ii.mmask[i])) ||
+            (plb(byweekno) && !ii.wnomask[i]) ||
+            (plb(byweekday) && !contains(byweekday, ii.wdaymask[i])) ||
+            (plb(ii.nwdaymask) && !ii.nwdaymask[i]) ||
+            (byeaster !== null && !contains(ii.eastermask, i)) ||
+            ((plb(bymonthday) || plb(bynmonthday)) &&
+              !contains(bymonthday, ii.mdaymask[i]) &&
+              !contains(bynmonthday, ii.nmdaymask[i])) ||
+            (plb(byyearday) &&
+              ((i < ii.yearlen &&
+                !contains(byyearday, i + 1) &&
+                !contains(byyearday, -ii.yearlen + i)) ||
+              (i >= ii.yearlen &&
+                !contains(byyearday, i + 1 - ii.yearlen) &&
+                !contains(byyearday, -ii.nextyearlen + i - ii.yearlen))))
+
+          if (filtered) dayset[i] = null
+        }
+
+        // Output results
+        if (plb(bysetpos) && plb(timeset)) {
+          var daypos, timepos
+          var poslist = []
+
+          for (i, j = 0; j < bysetpos.length; j++) {
+            pos = bysetpos[j]
+
+            if (pos < 0) {
+              daypos = Math.floor(pos / timeset.length)
+              timepos = pymod(pos, timeset.length)
+            } else {
+              daypos = Math.floor((pos - 1) / timeset.length)
+              timepos = pymod((pos - 1), timeset.length)
+            }
+
+            try {
+              tmp = []
+              for (k = start; k < end; k++) {
+                var val = dayset[k]
+                if (val === null) continue
+                tmp.push(val)
+              }
+              if (daypos < 0) {
+                // we're trying to emulate python's aList[-n]
+                i = tmp.slice(daypos)[0]
+              } else {
+                i = tmp[daypos]
+              }
+
+              var time = timeset[timepos]
+              var date = dateutil.fromOrdinal(ii.yearordinal + i)
+              var res = dateutil.combine(date, time)
+              // XXX: can this ever be in the array?
+              // - compare the actual date instead?
+              if (!contains(poslist, res)) poslist.push(res)
+            } catch (e) {}
+          }
+
+          dateutil.sort(poslist)
+          for (j = 0; j < poslist.length; j++) {
+            res = poslist[j]
+            if (until && res > until) {
+              this._len = total
+              return iterResult.getValue()
+            } else if (res >= dtstart) {
+              ++total
+              if (!iterResult.accept(res)) return iterResult.getValue()
+              if (count) {
+                --count
+                if (!count) {
+                  this._len = total
+                  return iterResult.getValue()
+                }
+              }
+            }
+          }
+        } else {
+          for (j = start; j < end; j++) {
+            i = dayset[j]
+            if (i !== null) {
+              date = dateutil.fromOrdinal(ii.yearordinal + i)
+              for (k = 0; k < timeset.length; k++) {
+                time = timeset[k]
+                res = dateutil.combine(date, time)
+                if (until && res > until) {
+                  this._len = total
+                  return iterResult.getValue()
+                } else if (res >= dtstart) {
+                  ++total
+                  if (!iterResult.accept(res)) return iterResult.getValue()
+                  if (count) {
+                    --count
+                    if (!count) {
+                      this._len = total
+                      return iterResult.getValue()
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+
+        // Handle frequency and interval
+        fixday = false
+        if (freq === RRule.YEARLY) {
+          year += interval
+          if (year > dateutil.MAXYEAR) {
+            this._len = total
+            return iterResult.getValue()
+          }
+          ii.rebuild(year, month)
+        } else if (freq === RRule.MONTHLY) {
+          month += interval
+          if (month > 12) {
+            div = Math.floor(month / 12)
+            mod = pymod(month, 12)
+            month = mod
+            year += div
+            if (month === 0) {
+              month = 12
+              --year
+            }
+            if (year > dateutil.MAXYEAR) {
+              this._len = total
+              return iterResult.getValue()
+            }
+          }
+          ii.rebuild(year, month)
+        } else if (freq === RRule.WEEKLY) {
+          if (wkst > weekday) {
+            day += -(weekday + 1 + (6 - wkst)) + interval * 7
+          } else {
+            day += -(weekday - wkst) + interval * 7
+          }
+          weekday = wkst
+          fixday = true
+        } else if (freq === RRule.DAILY) {
+          day += interval
+          fixday = true
+        } else if (freq === RRule.HOURLY) {
+          if (filtered) {
+            // Jump to one iteration before next day
+            hour += Math.floor((23 - hour) / interval) * interval
+          }
+          while (true) {
+            hour += interval
+            dm = divmod(hour, 24)
+            div = dm.div
+            mod = dm.mod
+            if (div) {
+              hour = mod
+              day += div
+              fixday = true
+            }
+            if (!plb(byhour) || contains(byhour, hour)) break
+          }
+          timeset = gettimeset.call(ii, hour, minute, second)
+        } else if (freq === RRule.MINUTELY) {
+          if (filtered) {
+            // Jump to one iteration before next day
+            minute += Math.floor(
+              (1439 - (hour * 60 + minute)) / interval) * interval
+          }
+
+          while (true) {
+            minute += interval
+            dm = divmod(minute, 60)
+            div = dm.div
+            mod = dm.mod
+            if (div) {
+              minute = mod
+              hour += div
+              dm = divmod(hour, 24)
+              div = dm.div
+              mod = dm.mod
+              if (div) {
+                hour = mod
+                day += div
+                fixday = true
+                filtered = false
+              }
+            }
+            if ((!plb(byhour) || contains(byhour, hour)) &&
+              (!plb(byminute) || contains(byminute, minute))) {
+              break
+            }
+          }
+          timeset = gettimeset.call(ii, hour, minute, second)
+        } else if (freq === RRule.SECONDLY) {
+          if (filtered) {
+            // Jump to one iteration before next day
+            second += Math.floor(
+                (86399 - (hour * 3600 + minute * 60 + second)) / interval) * interval
+          }
+          while (true) {
+            second += interval
+            dm = divmod(second, 60)
+            div = dm.div
+            mod = dm.mod
+            if (div) {
+              second = mod
+              minute += div
+              dm = divmod(minute, 60)
+              div = dm.div
+              mod = dm.mod
+              if (div) {
+                minute = mod
+                hour += div
+                dm = divmod(hour, 24)
+                div = dm.div
+                mod = dm.mod
+                if (div) {
+                  hour = mod
+                  day += div
+                  fixday = true
+                }
+              }
+            }
+            if ((!plb(byhour) || contains(byhour, hour)) &&
+              (!plb(byminute) || contains(byminute, minute)) &&
+              (!plb(bysecond) || contains(bysecond, second))) {
+              break
+            }
+          }
+          timeset = gettimeset.call(ii, hour, minute, second)
+        }
+
+        if (fixday && day > 28) {
+          var daysinmonth = dateutil.monthRange(year, month - 1)[1]
+          if (day > daysinmonth) {
+            while (day > daysinmonth) {
+              day -= daysinmonth
+              ++month
+              if (month === 13) {
+                month = 1
+                ++year
+                if (year > dateutil.MAXYEAR) {
+                  this._len = total
+                  return iterResult.getValue()
+                }
+              }
+              daysinmonth = dateutil.monthRange(year, month - 1)[1]
+            }
+            ii.rebuild(year, month)
+          }
+        }
+      }
+    }
+
+  }
+
+  RRule.parseString = function (rfcString) {
+    rfcString = rfcString.replace(/^\s+|\s+$/, '')
+    if (!rfcString.length) return null
+
+    var i, j, key, value, attr
+    var attrs = rfcString.split(';')
+    var options = {}
+
+    for (i = 0; i < attrs.length; i++) {
+      attr = attrs[i].split('=')
+      key = attr[0]
+      value = attr[1]
+      switch (key) {
+        case 'FREQ':
+          options.freq = RRule[value]
+          break
+        case 'WKST':
+          options.wkst = RRule[value]
+          break
+        case 'COUNT':
+        case 'INTERVAL':
+        case 'BYSETPOS':
+        case 'BYMONTH':
+        case 'BYMONTHDAY':
+        case 'BYYEARDAY':
+        case 'BYWEEKNO':
+        case 'BYHOUR':
+        case 'BYMINUTE':
+        case 'BYSECOND':
+          if (value.indexOf(',') !== -1) {
+            value = value.split(',')
+            for (j = 0; j < value.length; j++) {
+              if (/^[+-]?\d+$/.test(value[j])) value[j] = Number(value[j])
+            }
+          } else if (/^[+-]?\d+$/.test(value)) {
+            value = Number(value)
+          }
+          key = key.toLowerCase()
+          options[key] = value
+          break
+        case 'BYDAY': // => byweekday
+          var n, wday, day
+          var days = value.split(',')
+
+          options.byweekday = []
+          for (j = 0; j < days.length; j++) {
+            day = days[j]
+            if (day.length === 2) { // MO, TU, ...
+              wday = RRule[day] // wday instanceof Weekday
+              options.byweekday.push(wday)
+            } else { // -1MO, +3FR, 1SO, ...
+              day = day.match(/^([+-]?\d)([A-Z]{2})$/)
+              n = Number(day[1])
+              wday = day[2]
+              wday = RRule[wday].weekday
+              options.byweekday.push(new Weekday(wday, n))
+            }
+          }
+          break
+        case 'DTSTART':
+          options.dtstart = dateutil.untilStringToDate(value)
+          break
+        case 'UNTIL':
+          options.until = dateutil.untilStringToDate(value)
+          break
+        case 'BYEASTER':
+          options.byeaster = Number(value)
+          break
+        default:
+          throw new Error("Unknown RRULE property '" + key + "'")
+      }
+    }
+    return options
+  }
+
+  RRule.fromString = function (string) {
+    return new RRule(RRule.parseString(string))
+  }
+
+  // =============================================================================
+  // Iterinfo
+  // =============================================================================
+
+  var Iterinfo = function (rrule) {
+    this.rrule = rrule
+    this.lastyear = null
+    this.lastmonth = null
+    this.yearlen = null
+    this.nextyearlen = null
+    this.yearordinal = null
+    this.yearweekday = null
+    this.mmask = null
+    this.mrange = null
+    this.mdaymask = null
+    this.nmdaymask = null
+    this.wdaymask = null
+    this.wnomask = null
+    this.nwdaymask = null
+    this.eastermask = null
+  }
+
+  Iterinfo.prototype.easter = function (y, offset) {
+    offset = offset || 0
+
+    var a = y % 19
+    var b = Math.floor(y / 100)
+    var c = y % 100
+    var d = Math.floor(b / 4)
+    var e = b % 4
+    var f = Math.floor((b + 8) / 25)
+    var g = Math.floor((b - f + 1) / 3)
+    var h = Math.floor(19 * a + b - d - g + 15) % 30
+    var i = Math.floor(c / 4)
+    var k = c % 4
+    var l = Math.floor(32 + 2 * e + 2 * i - h - k) % 7
+    var m = Math.floor((a + 11 * h + 22 * l) / 451)
+    var month = Math.floor((h + l - 7 * m + 114) / 31)
+    var day = (h + l - 7 * m + 114) % 31 + 1
+    var date = Date.UTC(y, month - 1, day + offset)
+    var yearStart = Date.UTC(y, 0, 1)
+
+    return [Math.ceil((date - yearStart) / (1000 * 60 * 60 * 24))]
+  }
+
+  Iterinfo.prototype.rebuild = function (year, month) {
+    var rr = this.rrule
+
+    if (year !== this.lastyear) {
+      this.yearlen = dateutil.isLeapYear(year) ? 366 : 365
+      this.nextyearlen = dateutil.isLeapYear(year + 1) ? 366 : 365
+      var firstyday = new Date(year, 0, 1)
+
+      this.yearordinal = dateutil.toOrdinal(firstyday)
+      this.yearweekday = dateutil.getWeekday(firstyday)
+
+      var wday = dateutil.getWeekday(new Date(year, 0, 1))
+
+      if (this.yearlen === 365) {
+        this.mmask = [].concat(M365MASK)
+        this.mdaymask = [].concat(MDAY365MASK)
+        this.nmdaymask = [].concat(NMDAY365MASK)
+        this.wdaymask = WDAYMASK.slice(wday)
+        this.mrange = [].concat(M365RANGE)
+      } else {
+        this.mmask = [].concat(M366MASK)
+        this.mdaymask = [].concat(MDAY366MASK)
+        this.nmdaymask = [].concat(NMDAY366MASK)
+        this.wdaymask = WDAYMASK.slice(wday)
+        this.mrange = [].concat(M366RANGE)
+      }
+
+      if (!plb(rr.options.byweekno)) {
+        this.wnomask = null
+      } else {
+        this.wnomask = repeat(0, this.yearlen + 7)
+        var no1wkst, firstwkst, wyearlen
+        no1wkst = firstwkst = pymod(7 - this.yearweekday + rr.options.wkst, 7)
+        if (no1wkst >= 4) {
+          no1wkst = 0
+          // Number of days in the year, plus the days we got
+          // from last year.
+          wyearlen = this.yearlen + pymod(this.yearweekday - rr.options.wkst, 7)
+        } else {
+          // Number of days in the year, minus the days we
+          // left in last year.
+          wyearlen = this.yearlen - no1wkst
+        }
+        var div = Math.floor(wyearlen / 7)
+        var mod = pymod(wyearlen, 7)
+        var numweeks = Math.floor(div + (mod / 4))
+        for (var n, i, j = 0; j < rr.options.byweekno.length; j++) {
+          n = rr.options.byweekno[j]
+          if (n < 0) {
+            n += numweeks + 1
+          } if (!(n > 0 && n <= numweeks)) {
+            continue
+          } if (n > 1) {
+            i = no1wkst + (n - 1) * 7
+            if (no1wkst !== firstwkst) {
+              i -= 7 - firstwkst
+            }
+          } else {
+            i = no1wkst
+          }
+          for (var k = 0; k < 7; k++) {
+            this.wnomask[i] = 1
+            i++
+            if (this.wdaymask[i] === rr.options.wkst) break
+          }
+        }
+
+        if (contains(rr.options.byweekno, 1)) {
+          // Check week number 1 of next year as well
+          // orig-TODO : Check -numweeks for next year.
+          i = no1wkst + numweeks * 7
+          if (no1wkst !== firstwkst) i -= 7 - firstwkst
+          if (i < this.yearlen) {
+            // If week starts in next year, we
+            // don't care about it.
+            for (j = 0; j < 7; j++) {
+              this.wnomask[i] = 1
+              i += 1
+              if (this.wdaymask[i] === rr.options.wkst) break
+            }
+          }
+        }
+
+        if (no1wkst) {
+          // Check last week number of last year as
+          // well. If no1wkst is 0, either the year
+          // started on week start, or week number 1
+          // got days from last year, so there are no
+          // days from last year's last week number in
+          // this year.
+          var lnumweeks
+          if (!contains(rr.options.byweekno, -1)) {
+            var lyearweekday = dateutil.getWeekday(new Date(year - 1, 0, 1))
+            var lno1wkst = pymod(7 - lyearweekday + rr.options.wkst, 7)
+            var lyearlen = dateutil.isLeapYear(year - 1) ? 366 : 365
+            if (lno1wkst >= 4) {
+              lno1wkst = 0
+              lnumweeks = Math.floor(52 +
+                pymod(lyearlen + pymod(lyearweekday - rr.options.wkst, 7), 7) / 4)
+            } else {
+              lnumweeks = Math.floor(52 + pymod(this.yearlen - no1wkst, 7) / 4)
+            }
+          } else {
+            lnumweeks = -1
+          }
+          if (contains(rr.options.byweekno, lnumweeks)) {
+            for (i = 0; i < no1wkst; i++) this.wnomask[i] = 1
+          }
+        }
+      }
+    }
+
+    if (plb(rr.options.bynweekday) && (month !== this.lastmonth || year !== this.lastyear)) {
+      var ranges = []
+      if (rr.options.freq === RRule.YEARLY) {
+        if (plb(rr.options.bymonth)) {
+          for (j = 0; j < rr.options.bymonth.length; j++) {
+            month = rr.options.bymonth[j]
+            ranges.push(this.mrange.slice(month - 1, month + 1))
+          }
+        } else {
+          ranges = [[0, this.yearlen]]
+        }
+      } else if (rr.options.freq === RRule.MONTHLY) {
+        ranges = [this.mrange.slice(month - 1, month + 1)]
+      }
+      if (plb(ranges)) {
+        // Weekly frequency won't get here, so we may not
+        // care about cross-year weekly periods.
+        this.nwdaymask = repeat(0, this.yearlen)
+
+        for (j = 0; j < ranges.length; j++) {
+          var rang = ranges[j]
+          var first = rang[0]
+          var last = rang[1]
+          last -= 1
+          for (k = 0; k < rr.options.bynweekday.length; k++) {
+            wday = rr.options.bynweekday[k][0]
+            n = rr.options.bynweekday[k][1]
+            if (n < 0) {
+              i = last + (n + 1) * 7
+              i -= pymod(this.wdaymask[i] - wday, 7)
+            } else {
+              i = first + (n - 1) * 7
+              i += pymod(7 - this.wdaymask[i] + wday, 7)
+            }
+            if (first <= i && i <= last) this.nwdaymask[i] = 1
+          }
+        }
+      }
+
+      this.lastyear = year
+      this.lastmonth = month
+    }
+
+    if (rr.options.byeaster !== null) {
+      this.eastermask = this.easter(year, rr.options.byeaster)
+    }
+  }
+
+  Iterinfo.prototype.ydayset = function (year, month, day) {
+    return [range(this.yearlen), 0, this.yearlen]
+  }
+
+  Iterinfo.prototype.mdayset = function (year, month, day) {
+    var set = repeat(null, this.yearlen)
+    var start = this.mrange[month - 1]
+    var end = this.mrange[month]
+    for (var i = start; i < end; i++) set[i] = i
+    return [set, start, end]
+  }
+
+  Iterinfo.prototype.wdayset = function (year, month, day) {
+    // We need to handle cross-year weeks here.
+    var set = repeat(null, this.yearlen + 7)
+    var i = dateutil.toOrdinal(new Date(year, month - 1, day)) - this.yearordinal
+    var start = i
+    for (var j = 0; j < 7; j++) {
+      set[i] = i
+      ++i
+      if (this.wdaymask[i] === this.rrule.options.wkst) break
+    }
+    return [set, start, i]
+  }
+
+  Iterinfo.prototype.ddayset = function (year, month, day) {
+    var set = repeat(null, this.yearlen)
+    var i = dateutil.toOrdinal(new Date(year, month - 1, day)) - this.yearordinal
+    set[i] = i
+    return [set, i, i + 1]
+  }
+
+  Iterinfo.prototype.htimeset = function (hour, minute, second, millisecond) {
+    var set = []
+    var rr = this.rrule
+    for (var i = 0; i < rr.options.byminute.length; i++) {
+      minute = rr.options.byminute[i]
+      for (var j = 0; j < rr.options.bysecond.length; j++) {
+        second = rr.options.bysecond[j]
+        set.push(new dateutil.Time(hour, minute, second, millisecond))
+      }
+    }
+    dateutil.sort(set)
+    return set
+  }
+
+  Iterinfo.prototype.mtimeset = function (hour, minute, second, millisecond) {
+    var set = []
+    var rr = this.rrule
+    for (var j = 0; j < rr.options.bysecond.length; j++) {
+      second = rr.options.bysecond[j]
+      set.push(new dateutil.Time(hour, minute, second, millisecond))
+    }
+    dateutil.sort(set)
+    return set
+  }
+
+  Iterinfo.prototype.stimeset = function (hour, minute, second, millisecond) {
+    return [new dateutil.Time(hour, minute, second, millisecond)]
+  }
+
+  // =============================================================================
+  // Results
+  // =============================================================================
+
+  /**
+   * This class helps us to emulate python's generators, sorta.
+   */
+  var IterResult = function (method, args) {
+    this.init(method, args)
+  }
+
+  IterResult.prototype = {
+    constructor: IterResult,
+    init: function (method, args) {
+      this.method = method
+      this.args = args
+      this.minDate = null
+      this.maxDate = null
+      this._result = []
+
+      if (method === 'between') {
+        this.maxDate = args.inc
+          ? args.before : new Date(args.before.getTime() - 1)
+        this.minDate = args.inc
+          ? args.after : new Date(args.after.getTime() + 1)
+      } else if (method === 'before') {
+        this.maxDate = args.inc ? args.dt : new Date(args.dt.getTime() - 1)
+      } else if (method === 'after') {
+        this.minDate = args.inc ? args.dt : new Date(args.dt.getTime() + 1)
+      }
+    },
+
+    /**
+     * Possibly adds a date into the result.
+     *
+     * @param {Date} date - the date isn't necessarly added to the result
+     *                      list (if it is too late/too early)
+     * @return {Boolean} true if it makes sense to continue the iteration
+     *                   false if we're done.
+     */
+    accept: function (date) {
+      var tooEarly = this.minDate && date < this.minDate
+      var tooLate = this.maxDate && date > this.maxDate
+
+      if (this.method === 'between') {
+        if (tooEarly) return true
+        if (tooLate) return false
+      } else if (this.method === 'before') {
+        if (tooLate) return false
+      } else if (this.method === 'after') {
+        if (tooEarly) return true
+        this.add(date)
+        return false
+      }
+
+      return this.add(date)
+    },
+
+    /**
+     *
+     * @param {Date} date that is part of the result.
+     * @return {Boolean} whether we are interested in more values.
+     */
+    add: function (date) {
+      this._result.push(date)
+      return true
+    },
+
+    /**
+     * 'before' and 'after' return only one date, whereas 'all'
+     * and 'between' an array.
+     * @return {Date,Array?}
+     */
+    getValue: function () {
+      var res = this._result
+      switch (this.method) {
+        case 'all':
+        case 'between':
+          return res
+        case 'before':
+        case 'after':
+          return res.length ? res[res.length - 1] : null
+      }
+    },
+
+    clone: function () {
+      return new IterResult(this.method, this.args)
+    }
+  }
+
+  /**
+   * IterResult subclass that calls a callback function on each add,
+   * and stops iterating when the callback returns false.
+   */
+  var CallbackIterResult = function (method, args, iterator) {
+    var allowedMethods = ['all', 'between']
+    if (!contains(allowedMethods, method)) {
+      throw new Error('Invalid method "' + method +
+        '". Only all and between works with iterator.')
+    }
+    this.add = function (date) {
+      if (iterator(date, this._result.length)) {
+        this._result.push(date)
+        return true
+      }
+      return false
+    }
+
+    this.init(method, args)
+  }
+  CallbackIterResult.prototype = IterResult.prototype
+
+  /**
+   *
+   * @param {Boolean?} noCache
+   *  The same stratagy as RRule on cache, default to false
+   * @constructor
+   */
+
+  var RRuleSet = function (noCache) {
+    // Let RRuleSet cacheable
+    this._cache = noCache ? null : {
+      all: false,
+      before: [],
+      after: [],
+      between: []
+    }
+    this._rrule = []
+    this._rdate = []
+    this._exrule = []
+    this._exdate = []
+  }
+
+  RRuleSet.prototype = {
+    constructor: RRuleSet,
+
+    /**
+    * @param {RRule}
+    */
+    rrule: function (rrule) {
+      if (!(rrule instanceof RRule)) {
+        throw new TypeError(String(rrule) + ' is not RRule instance')
+      }
+      if (!contains(this._rrule.map(String), String(rrule))) {
+        this._rrule.push(rrule)
+      }
+    },
+
+    /**
+    * @param {Date}
+    */
+    rdate: function (date) {
+      if (!(date instanceof Date)) {
+        throw new TypeError(String(date) + ' is not Date instance')
+      }
+      if (!contains(this._rdate.map(Number), Number(date))) {
+        this._rdate.push(date)
+        dateutil.sort(this._rdate)
+      }
+    },
+
+    /**
+    * @param {RRule}
+    */
+    exrule: function (rrule) {
+      if (!(rrule instanceof RRule)) {
+        throw new TypeError(String(rrule) + ' is not RRule instance')
+      }
+      if (!contains(this._exrule.map(String), String(rrule))) {
+        this._exrule.push(rrule)
+      }
+    },
+
+    /**
+    * @param {Date}
+    */
+    exdate: function (date) {
+      if (!(date instanceof Date)) {
+        throw new TypeError(String(date) + ' is not Date instance')
+      }
+      if (!contains(this._exdate.map(Number), Number(date))) {
+        this._exdate.push(date)
+        dateutil.sort(this._exdate)
+      }
+    },
+
+    valueOf: function () {
+      var result = []
+      if (this._rrule.length) {
+        this._rrule.forEach(function (rrule) {
+          result.push('RRULE:' + rrule)
+        })
+      }
+      if (this._rdate.length) {
+        result.push('RDATE:' + this._rdate.map(function (rdate) {
+          return dateutil.timeToUntilString(rdate)
+        }).join(','))
+      }
+      if (this._exrule.length) {
+        this._exrule.forEach(function (exrule) {
+          result.push('EXRULE:' + exrule)
+        })
+      }
+      if (this._exdate.length) {
+        result.push('EXDATE:' + this._exdate.map(function (exdate) {
+          return dateutil.timeToUntilString(exdate)
+        }).join(','))
+      }
+      return result
+    },
+
+    /**
+    * to generate recurrence field sush as:
+    *   ["RRULE:FREQ=YEARLY;COUNT=2;BYDAY=TU;DTSTART=19970902T010000Z","RRULE:FREQ=YEARLY;COUNT=1;BYDAY=TH;DTSTART=19970902T010000Z"]
+    */
+    toString: function () {
+      return JSON.stringify(this.valueOf())
+    },
+
+    _iter: function (iterResult) {
+      var _exdateHash = {}
+      var _exrule = this._exrule
+      var _accept = iterResult.accept
+
+      function evalExdate (after, before) {
+        _exrule.forEach(function (rrule) {
+          rrule.between(after, before, true).forEach(function (date) {
+            _exdateHash[Number(date)] = true
+          })
+        })
+      }
+
+      this._exdate.forEach(function (date) {
+        _exdateHash[Number(date)] = true
+      })
+
+      iterResult.accept = function (date) {
+        var dt = Number(date)
+        if (!_exdateHash[dt]) {
+          evalExdate(new Date(dt - 1), new Date(dt + 1))
+          if (!_exdateHash[dt]) {
+            _exdateHash[dt] = true
+            return _accept.call(this, date)
+          }
+        }
+        return true
+      }
+
+      if (iterResult.method === 'between') {
+        evalExdate(iterResult.args.after, iterResult.args.before)
+        iterResult.accept = function (date) {
+          var dt = Number(date)
+          if (!_exdateHash[dt]) {
+            _exdateHash[dt] = true
+            return _accept.call(this, date)
+          }
+          return true
+        }
+      }
+
+      for (var i = 0; i < this._rdate.length; i++) {
+        if (!iterResult.accept(new Date(this._rdate[i]))) break
+      }
+
+      this._rrule.forEach(function (rrule) {
+        rrule._iter(iterResult)
+      })
+
+      var res = iterResult._result
+      dateutil.sort(res)
+      switch (iterResult.method) {
+        case 'all':
+        case 'between':
+          return res
+        case 'before':
+          return (res.length && res[res.length - 1]) || null
+        case 'after':
+          return (res.length && res[0]) || null
+        default:
+          return null
+      }
+    },
+
+    /**
+    * Create a new RRuleSet Object completely base on current instance
+    */
+    clone: function () {
+      var rrs = new RRuleSet(!!this._cache)
+      var i
+      for (i = 0; i < this._rrule.length; i++) {
+        rrs.rrule(this._rrule[i].clone())
+      }
+      for (i = 0; i < this._rdate.length; i++) {
+        rrs.rdate(new Date(this._rdate[i]))
+      }
+      for (i = 0; i < this._exrule.length; i++) {
+        rrs.exrule(this._exrule[i].clone())
+      }
+      for (i = 0; i < this._exdate.length; i++) {
+        rrs.exdate(new Date(this._exdate[i]))
+      }
+      return rrs
+    }
+  }
+
+  /**
+   * Inherts method from RRule
+   *  add Read interface and set RRuleSet cacheable
+   */
+  var RRuleSetMethods = ['all', 'between', 'before', 'after', 'count', '_cacheAdd', '_cacheGet']
+  RRuleSetMethods.forEach(function (method) {
+    RRuleSet.prototype[method] = RRule.prototype[method]
+  })
+
+  /**
+   * RRuleStr
+   *  To parse a set of rrule strings
+   */
+
+  var RRuleStr = function () {}
+
+  RRuleStr.DEFAULT_OPTIONS = {
+    dtstart: null,
+    cache: false,
+    unfold: false,
+    forceset: false,
+    compatible: false,
+    ignoretz: false,
+    tzinfos: null
+  }
+
+  RRuleStr._freq_map = {
+    'YEARLY': RRule.YEARLY,
+    'MONTHLY': RRule.MONTHLY,
+    'WEEKLY': RRule.WEEKLY,
+    'DAILY': RRule.DAILY,
+    'HOURLY': RRule.HOURLY,
+    'MINUTELY': RRule.MINUTELY,
+    'SECONDLY': RRule.SECONDLY
+  }
+
+  RRuleStr._weekday_map = {
+    'MO': 0,
+    'TU': 1,
+    'WE': 2,
+    'TH': 3,
+    'FR': 4,
+    'SA': 5,
+    'SU': 6
+  }
+
+  RRuleStr.prototype = {
+    constructor: RRuleStr,
+
+    _handle_int: function (rrkwargs, name, value, options) {
+      rrkwargs[name.toLowerCase()] = parseInt(value, 10)
+    },
+
+    _handle_int_list: function (rrkwargs, name, value, options) {
+      rrkwargs[name.toLowerCase()] = value.split(',').map(function (x) {
+        return parseInt(x, 10)
+      })
+    },
+
+    _handle_FREQ: function (rrkwargs, name, value, options) {
+      rrkwargs['freq'] = RRuleStr._freq_map[value]
+    },
+
+    _handle_UNTIL: function (rrkwargs, name, value, options) {
+      try {
+        rrkwargs['until'] = dateutil.untilStringToDate(value)
+      } catch (error) {
+        throw new Error('invalid until date')
+      }
+    },
+
+    _handle_WKST: function (rrkwargs, name, value, options) {
+      rrkwargs['wkst'] = RRuleStr._weekday_map[value]
+    },
+
+    _handle_BYWEEKDAY: function (rrkwargs, name, value, options) {
+      // Two ways to specify this: +1MO or MO(+1)
+      var splt, i, j, n, w, wday
+      var l = []
+      var wdays = value.split(',')
+
+      for (i = 0; i < wdays.length; i++) {
+        wday = wdays[i]
+        if (wday.indexOf('(') > -1) {
+          // If it's of the form TH(+1), etc.
+          splt = wday.split('(')
+          w = splt[0]
+          n = parseInt(splt.slice(1, -1), 10)
+        } else {
+          // # If it's of the form +1MO
+          for (j = 0; j < wday.length; j++) {
+            if ('+-0123456789'.indexOf(wday[j]) === -1) break
+          }
+          n = wday.slice(0, j) || null
+          w = wday.slice(j)
+
+          if (n) n = parseInt(n, 10)
+        }
+
+        var weekday = new Weekday(RRuleStr._weekday_map[w], n)
+        l.push(weekday)
+      }
+      rrkwargs['byweekday'] = l
+    },
+
+    _parseRfcRRule: function (line, options) {
+      options = options || {}
+      options.dtstart = options.dtstart || null
+      options.cache = options.cache || false
+      options.ignoretz = options.ignoretz || false
+      options.tzinfos = options.tzinfos || null
+
+      var name, value, parts
+      if (line.indexOf(':') !== -1) {
+        parts = line.split(':')
+        name = parts[0]
+        value = parts[1]
+
+        if (name !== 'RRULE') throw new Error('unknown parameter name')
+      } else {
+        value = line
+      }
+
+      var i
+      var rrkwargs = {}
+      var pairs = value.split(';')
+
+      for (i = 0; i < pairs.length; i++) {
+        parts = pairs[i].split('=')
+        name = parts[0].toUpperCase()
+        value = parts[1].toUpperCase()
+
+        try {
+          this['_handle_' + name](rrkwargs, name, value, {
+            ignoretz: options.ignoretz,
+            tzinfos: options.tzinfos
+          })
+        } catch (error) {
+          throw new Error("unknown parameter '" + name + "':" + value)
+        }
+      }
+      rrkwargs.dtstart = rrkwargs.dtstart || options.dtstart
+      return new RRule(rrkwargs, !options.cache)
+    },
+
+    _parseRfc: function (s, options) {
+      if (options.compatible) {
+        options.forceset = true
+        options.unfold = true
+      }
+
+      s = s && s.toUpperCase().trim()
+      if (!s) throw new Error('Invalid empty string')
+
+      var i = 0
+      var line, lines
+
+      // More info about 'unfold' option
+      // Go head to http://www.ietf.org/rfc/rfc2445.txt
+      if (options.unfold) {
+        lines = s.split('\n')
+        while (i < lines.length) {
+          // TODO
+          line = lines[i] = lines[i].replace(/\s+$/g, '')
+          if (!line) {
+            lines.splice(i, 1)
+          } else if (i > 0 && line[0] === ' ') {
+            lines[i - 1] += line.slice(1)
+            lines.splice(i, 1)
+          } else {
+            i += 1
+          }
+        }
+      } else {
+        lines = s.split(/\s/)
+      }
+
+      var rrulevals = []
+      var rdatevals = []
+      var exrulevals = []
+      var exdatevals = []
+      var name, value, parts, parms, parm, dtstart, rset, j, k, datestrs, datestr
+
+      if (!options.forceset && lines.length === 1 && (s.indexOf(':') === -1 ||
+        s.indexOf('RRULE:') === 0)) {
+        return this._parseRfcRRule(lines[0], {
+          cache: options.cache,
+          dtstart: options.dtstart,
+          ignoretz: options.ignoretz,
+          tzinfos: options.tzinfos
+        })
+      } else {
+        for (i = 0; i < lines.length; i++) {
+          line = lines[i]
+          if (!line) continue
+          if (line.indexOf(':') === -1) {
+            name = 'RRULE'
+            value = line
+          } else {
+            parts = split(line, ':', 1)
+            name = parts[0]
+            value = parts[1]
+          }
+          parms = name.split(';')
+          if (!parms) throw new Error('empty property name')
+          name = parms[0]
+          parms = parms.slice(1)
+
+          if (name === 'RRULE') {
+            for (j = 0; j < parms.length; j++) {
+              parm = parms[j]
+              throw new Error('unsupported RRULE parm: ' + parm)
+            }
+            rrulevals.push(value)
+          } else if (name === 'RDATE') {
+            for (j = 0; j < parms.length; j++) {
+              parm = parms[j]
+              if (parm !== 'VALUE=DATE-TIME') {
+                throw new Error('unsupported RDATE parm: ' + parm)
+              }
+            }
+            rdatevals.push(value)
+          } else if (name === 'EXRULE') {
+            for (j = 0; j < parms.length; j++) {
+              parm = parms[j]
+              throw new Error('unsupported EXRULE parm: ' + parm)
+            }
+            exrulevals.push(value)
+          } else if (name === 'EXDATE') {
+            for (j = 0; j < parms.length; j++) {
+              parm = parms[j]
+              if (parm !== 'VALUE=DATE-TIME') {
+                throw new Error('unsupported RDATE parm: ' + parm)
+              }
+            }
+            exdatevals.push(value)
+          } else if (name === 'DTSTART') {
+            dtstart = dateutil.untilStringToDate(value)
+          } else {
+            throw new Error('unsupported property: ' + name)
+          }
+        }
+
+        if (options.forceset || rrulevals.length > 1 || rdatevals.length ||
+          exrulevals.length || exdatevals.length) {
+          rset = new RRuleSet(!options.cache)
+          for (j = 0; j < rrulevals.length; j++) {
+            rset.rrule(this._parseRfcRRule(rrulevals[j], {
+              dtstart: options.dtstart || dtstart,
+              ignoretz: options.ignoretz,
+              tzinfos: options.tzinfos
+            }))
+          }
+          for (j = 0; j < rdatevals.length; j++) {
+            datestrs = rdatevals[j].split(',')
+            for (k = 0; k < datestrs.length; k++) {
+              datestr = datestrs[k]
+              rset.rdate(dateutil.untilStringToDate(datestr))
+            }
+          }
+          for (j = 0; j < exrulevals.length; j++) {
+            rset.exrule(this._parseRfcRRule(exrulevals[j], {
+              dtstart: options.dtstart || dtstart,
+              ignoretz: options.ignoretz,
+              tzinfos: options.tzinfos
+            }))
+          }
+          for (j = 0; j < exdatevals.length; j++) {
+            datestrs = exdatevals[j].split(',')
+            for (k = 0; k < datestrs.length; k++) {
+              datestr = datestrs[k]
+              rset.exdate(dateutil.untilStringToDate(datestr))
+            }
+          }
+
+          if (options.campatiable && options.dtstart) rset.rdate(dtstart)
+          return rset
+        } else {
+          return this._parseRfcRRule(rrulevals[0], {
+            dtstart: options.dtstart || dtstart,
+            cache: options.cache,
+            ignoretz: options.ignoretz,
+            tzinfos: options.tzinfos
+          })
+        }
+      }
+    },
+
+    parse: function (s, options) {
+      options = options || {}
+
+      var invalid = []
+      var keys = Object.keys(options)
+      var defaultKeys = Object.keys(RRuleStr.DEFAULT_OPTIONS)
+
+      keys.forEach(function (key) {
+        if (!contains(defaultKeys, key)) invalid.push(key)
+      }, this)
+
+      if (invalid.length) throw new Error('Invalid options: ' + invalid.join(', '))
+
+      // Merge in default options
+      defaultKeys.forEach(function (key) {
+        if (!contains(keys, key)) options[key] = RRuleStr.DEFAULT_OPTIONS[key]
+      })
+
+      return this._parseRfc(s, options)
+    }
+  }
+
+  RRuleStr.prototype._handle_DTSTART = function (rrkwargs, name, value, options) {
+    rrkwargs[name.toLowerCase()] = dateutil.untilStringToDate(value)
+  }
+
+  RRuleStr.prototype._handle_BYDAY = RRuleStr.prototype._handle_BYWEEKDAY
+  RRuleStr.prototype._handle_INTERVAL = RRuleStr.prototype._handle_int
+  RRuleStr.prototype._handle_COUNT = RRuleStr.prototype._handle_int
+
+  ;[
+    '_handle_BYSETPOS', '_handle_BYMONTH', '_handle_BYMONTHDAY',
+    '_handle_BYYEARDAY', '_handle_BYEASTER', '_handle_BYWEEKNO',
+    '_handle_BYHOUR', '_handle_BYMINUTE', '_handle_BYSECOND'
+  ].forEach(function (method) {
+    RRuleStr.prototype[method] = RRuleStr.prototype._handle_int_list
+  })
+
+  // =============================================================================
+  // Export
+  // =============================================================================
+
+  // Only one RRuleStr instance for all rrule string parsing work.
+  var rruleStr = new RRuleStr()
+  var rrulestr = function () {
+    return rruleStr.parse.apply(rruleStr, arguments)
+  }
+
+  RRule.RRule = RRule
+  RRule.RRuleSet = RRuleSet
+  RRule.rrulestr = rrulestr
+  return RRule
+
+  function getnlp () {
+    // Lazy, runtime import to avoid circular refs.
+    if (!getnlp._nlp) {
+      if (root && root._getRRuleNLP) {
+        getnlp._nlp = root._getRRuleNLP(RRule)
+      } else if (typeof require === 'function') {
+        getnlp._nlp = require('./nlp')(RRule)
+      } else {
+        throw new Error('You need to include rrule/nlp.js for fromText/toText to work.')
+      }
+    }
+    return getnlp._nlp
+  }
+}))
diff --git a/modules/childs/child.html b/modules/childs/child.html
new file mode 100644 (file)
index 0000000..89085e4
--- /dev/null
@@ -0,0 +1,803 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+
+  <title>Détails - Enfant</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+  <link href="css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <!--<link href="css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="css/summernote.css" rel="stylesheet" type="text/css">
+  <link href="css/creorga.css" rel="stylesheet" type="text/css"><!-- Fav and touch icons -->
+</head>
+
+<body>
+    <div class="container-fluid">
+        <form name="frmchild" id="frmchild">
+          <input type="hidden" value="" id="childs_uuid">
+          <table>
+            <tr>
+              <td style="width: 500px;">
+                <div class="field">
+            <label for="childs_prename">Prénom</label> <input type="text" value="" id="childs_prename" class="form-control">
+          </div>
+
+          <div class="field">
+            <label for="childs_surname">Nom</label> <input type="text" value="" id="childs_surname" class="form-control">
+          </div>
+          <div class="field">
+            <label for="childs_checkservicenumber">No. Check Service</label> <input type="text" value="" id="childs_checkservicenumber" class="form-control">
+          </div>
+
+          <div class="field" id="date-container">
+            <label for="childs_checkserviceexpiration">Date d'expiration</label>
+
+            <div id="dt_childs_checkserviceexpiration" class="input-group date">
+              <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy" id="childs_checkserviceexpiration"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+            </div>
+          </div>
+              </td>
+              <td style="width: 500px;">
+                <div class="field" id="date-container">
+            <label for="childs_birthday">Date de naissance</label>
+
+            <div id="dt_childs_birthday" class="input-group date">
+              <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy" id="childs_birthday"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+            </div>
+          </div><div class="field" id="date-container">
+                      <label for="childs_entrydate">Date d'entrée</label>
+
+                      <div id="dt_childs_entrydate" class="input-group date">
+                        <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="childs_entrydate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                      </div>
+                    </div>
+
+                    <div class="field" id="date-container">
+                      <label for="childs_leavedate">Date de sortie</label>
+
+                      <div id="dt_childs_leavedate" class="input-group date">
+                        <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy" id="childs_leavedate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                      </div>
+                    </div>
+              </td>
+              <!--<td style="width: 200px;">
+                 <div class="form-group">
+                  <label for="childs_infoimportant">Info IMportant</label>
+                  <textarea class="summernote" type="text" id="childs_infoimportant"></textarea>
+                </div>
+              </td>-->
+            </tr>
+          </table>
+          <div class="tabbable">
+            <ul class="nav nav-tabs">
+              <li><a data-toggle="tab" href="#child">Adresse / Divers</a></li>
+              <li><a data-toggle="tab" href="#planning">Planification</a></li>
+              <li><a data-toggle="tab" href="#parents">Parents / Persones authorisées</a></li>
+              <li><a data-toggle="tab" href="#health">Santé</a></li>
+              <li><a data-toggle="tab" href="#lunch">Déjeuner</a></li>
+              <li><a data-toggle="tab" href="#caution">Caution</a></li>
+              <li><a data-toggle="tab" href="#myfiles">Fichiers</a></li>
+            </ul>
+
+            <div class="tab-content">
+              <div id="child" class="tab-pane active">
+                <table style="width: 100%;" class="table">
+                  <tbody>
+                    <tr>
+                      <td style="width: 50%">
+                        <div class="field">
+                          <label for="childs_clientnumber">No. Client</label> <input type="text" value="" id="childs_clientnumber" class="form-control">
+                        </div>
+                        <div class="field">
+                          <label for="childs_address">Addresse</label> <input type="text" value="" id="childs_address" class="form-control">
+                        </div>
+
+                        <div class="field">
+                          <label for="childs_city">Ville</label> <input type="text" value="" id="childs_city" class="form-control">
+                        </div>
+                        <div class="field">
+                          <label for="childs_zip">Code Postale</label> <input type="text" value="" id="childs_zip" class="form-control">
+                        </div>
+                        <div class="field">
+                          <label for="childs_country">Pays</label> <input type="text" value="" id="childs_country" class="form-control">
+                        </div>
+                        <div class="field">
+                          <label for="childs_nationality">Nationalité</label> <input type="text" value="" id="childs_nationality" class="form-control">
+                        </div>
+                        <div class="field">
+                          <label for="childs_nativelanguage">Langue maternelle</label> <input type="text" value="" id="childs_nativelanguage" class="form-control">
+                        </div>
+                      </td>
+
+                      <td style="width: 50%;"> 
+                        
+                        <div class="form-group">
+                          <label for="childs_remark">Remarque</label>
+                          <textarea class="summernote" type="text" id="childs_remark">
+</textarea>
+                        </div>
+                      </td>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
+
+              <div id="planning" class="tab-pane">
+                <div class="row">
+                  <div class="btn-group">
+                  <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+    <span class="glyphicons glyphicons-plus"></span>&nbsp;Ajouter Planification <span class="caret"></span>
+  </button>
+  <ul class="dropdown-menu" id="plantemplates">
+    <li style="font-weight: bold; padding-left: 5px;">multiple</li>
+    <li><a href="javascript:dlg_planning({'uuid':''},'insproposal');">Propose de planification</a></li>
+    <li role="separator" class="divider"></li>
+    <li style="font-weight: bold; padding-left: 5px;">simple</li>
+    <li><a href="javascript:dlg_planning({'uuid':''},'ins');">Plan Vide</a></li>
+  </ul>
+  </div>
+  <!--<button type="button" class="btn btn-primary" ><span class="glyphicons glyphicons-plus"></span>&nbsp;Planification vide</button>-->
+  <!--<button type="button" class="btn btn-primary" onclick="dlg_planning({'uuid':''},'insproposal');"><span class="glyphicon glyphicon-list"></span>&nbsp;Propose de planification</button>-->
+  <button type="button" class="btn btn-danger" onclick="dlg_planning({'uuid':''},'delall');"><span class="glyphicon glyphicon-remove"></span>&nbsp;Supprimer tous les planifications</button>
+  
+  
+
+  <!--<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+    Ajouter une planification <span class="caret"></span>
+  </button>
+  <ul class="dropdown-menu" id="btnaddchildplan" onclick="validate_plan_proposals();">
+    <li><a href="javascript:dlg_planning({'uuid':''},'ins');">Planification vide</a></li>
+    <li id="planproposal"><a href="javascrcelipt:dlg_planning({'uuid':''},'insproposal');">Propose de planification</a></li>
+  </ul>-->
+</div>
+                <br/>
+                <div id="tbl_planning_wrapper" class="dataTables_wrapper no-footer">
+                  <table id="tbl_planning" class="table table-striped dataTable no-footer" role="grid" style="width: 100%;">
+                    
+                  </table>
+                </div>
+              </div>
+
+              <div id="parents" class="tab-pane">
+                <a title="ajouter une personne authorisé" href="javascript:dlg_refperson({'uuid':''},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></a>
+
+                <div id="tbl_refperson_wrapper" class="dataTables_wrapper no-footer">
+                  <table id="tbl_refperson" class="display dataTable no-footer" role="grid">
+                    
+                  </table>
+                </div>
+              </div>
+              <div id="health" class="tab-pane">
+                <div class="form-group">
+                  <label for="childs_infohealth">Info Santé</label>
+                  <textarea class="summernote" type="text" id="childs_infohealth"></textarea>
+                </div>
+              </div>
+              <div id="lunch" class="tab-pane">
+                <div class="form-group">
+                  <label for="childs_infolunch">Info Déjeuner</label>
+                  <textarea class="summernote" type="text" id="childs_infolunch"></textarea>
+                </div>
+                
+              </div>
+              <div id="caution" class="tab-pane">
+                <table style="width: 100%;" class="table">
+                  <tbody>
+                    <tr><td style="width: 50%">
+                      <div class="field">
+                        <label for="childs_cautionamount">Somme caution</label>
+                        <div class="input-group number">
+                          <input type="number" value="" id="childs_cautionamount" style="text-align: right;" class="form-control">
+                          <div class="input-group-addon">€</div>
+                        </div>
+                      </div>
+                <div class="field">
+                  <label for="childs_bankaccount">IBAN parents</label> <input type="text" value="" id="childs_bankaccount" class="form-control">
+                </div>
+
+                <div class="field">
+                  <label for="childs_bankbic">BIC</label> <input type="text" value="" id="childs_bankbic" class="form-control">
+                </div>
+                <div class="field">
+                  <label for="childs_bankaccountowner">Tutulaire du compte</label> <input type="text" value="" id="childs_bankaccountowner" class="form-control">
+                </div>
+                <div class="form-group">
+                  <label for="childs_cautionremark">Remarque</label>
+                  <textarea class="summernote" type="text" rows="12" id="childs_cautionremark">
+</textarea>
+                </div>
+                
+                      </td><td style="width: 50%;">
+                      <button onclick="dlg_cautionstatus({'uuid':'0'},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> ajouter un transfer de caution</button>
+                <table id="tbl_cautionstatus" class="display dataTable" role="grid">
+                    
+                </table>
+                        
+                      </td></tr></tbody></table>
+              </div>
+              <div id="myfiles" class="tab-pane">
+                
+                <button  onclick="dlg_file();" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> ajouter fichier</button>
+                <table id="tbl_files" class="display dataTable no-footer" role="grid">
+                    
+                </table>
+              </div>
+            </div>
+          </div>
+        </form>
+
+        <div class="modal modal-wide fade" id="edit_planning">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Editer/Ajouter Plan</h4>
+              </div>
+
+              <div class="modal-body">
+                <div id="frmeditplanning">
+                  <input type="hidden" value="0" id="uuid">
+                  <div class="row">
+                  <div class="col-sm-4">
+                  <div class="field" id="date-container">
+                    <label for="datebegin">Date du</label>
+
+                    <div id="dt_datebegin" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="datebegin"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  </div>
+                  <div class="col-sm-4">
+                  <div class="field" id="date-container">
+                    <label for="dateend">jusqu'au</label>
+                      <div id="dt_dateend" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="dateend"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  </div>
+                  </div>
+                  <div class="row">
+                  <div class="col-sm-4">
+                  <div class="field">
+                    <label for="groupuuid">Groupe</label>
+
+                    <div class="input-group">
+                      <select id="groupuuid">
+                        
+                      </select>
+                    </div>
+                  </div>
+                  </div>
+                  </div>
+                  <div class="table-reponsive">
+                    <table class="table">
+                      <thead>
+                        <tr>
+                          <th></th>
+                          <th>Jours de semaine</th>
+                          <th><span class="glyphicon glyphicon-time" aria-hidden="true"></span> entrée</th>
+                          <th><span class="glyphicon glyphicon-time" aria-hidden="true"></span> sortie</th>
+                          <th><span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span></th>
+                        </tr>
+                      </thead>
+
+                      <tbody>
+                        <tr>
+                          <td><button  onclick="display_tblrow('mon');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Lundi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="montimebegin">
+                              </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="montimeend">
+                            </div>
+                          </td>
+                          <td>
+                              <input type="checkbox" id="monlunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+                            
+                          </td>
+                        </tr>
+                        <tr class="suprow" id="montime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('montime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="montimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="montimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- tue -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('tue');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Mardi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimeend">
+                              </div>
+                          </td>
+<td>
+
+                              <input type="checkbox" id="tuelunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+                          
+                        </tr>
+                        <tr class="suprow" id="tuetime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('tuetime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- wed -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('wed');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Mercredi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimeend">
+                              </div>
+                          </td>
+<td>
+
+                              <input type="checkbox" id="wedlunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+
+                        </tr>
+                        <tr class="suprow" id="wedtime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('wedtime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- thu -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('thu');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Jeudi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimeend">
+                              </div>
+                          </td>
+<td>
+                              <input type="checkbox" id="thulunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+                        </tr>
+                        <tr class="suprow" id="thutime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('thutime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- fri -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('fri');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Vendredi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimeend">
+                              </div>
+                          </td>
+<td>
+                              <input type="checkbox" id="frilunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+                        </tr>
+                        <tr class="suprow" id="fritime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('fritime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- sat -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('sat');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Samedi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimeend">
+                              </div>
+                          </td>
+<td>
+                              <input type="checkbox" id="satlunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+                        </tr>
+                        <tr class="suprow" id="sattime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('sattime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                      </tbody>
+                    </table>
+                  </div>
+                </div>
+              </div>
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_planning();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div class="modal fade" id="confirm_delete_planning">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Planification</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce plan?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_planning();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+        
+        <div class="modal fade" id="confirm_delete_allplanning">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Planifications</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer tous les plan?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_allplanning();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+        
+        <div class="modal fade" id="confirm_delete_refperson">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer personne authorisé </h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cet personne?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_refperson();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+        
+        <div class="modal fade" id="edit_refperson">
+          <div class="modal-dialog" style="width: 900px; max-width: 900px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Editer/Ajouter personne authorisée</h4>
+              </div>
+
+              <div class="modal-body">
+                <div id="frmeditrefperson">
+                  <table><tbody><tr><td style="vertical-align: top;">
+                  <input type="hidden" value="0" id="uuid">
+                  <div class="field">
+                    <label for="reftype" style="width: 100px;">Relation</label>
+                    <div class="input-group">
+                      <select id="reftype">
+                        
+                      </select>
+                    </div>
+                  </div>
+                  <div class="field">
+                    <label for="surname" style="width: 100px;">Nom</label>
+                    <input type="text" value="" id="surname" class="form-control">
+                  </div>
+                  <div class="field">
+                    <label for="prename" style="width: 100px;">Prénom</label>
+                    <input type="text" value="" id="prename" class="form-control">
+                  </div>
+                  <div class="field">
+                    <label for="address" style="width: 100px;">Addresse</label>
+                    <input type="text" value="" id="address" class="form-control">
+                  </div>
+                  <div class="field">
+                    <label for="zip" style="width: 100px;">CP</label>
+                    <input type="text" value="" id="zip" class="form-control" style="width: 100px;">
+                  </div>
+                  <div class="field">
+                    <label for="zip" style="width: 100px;">Ville</label>
+                    <input type="text" value="" id="city" class="form-control">
+                  </div>
+                  <div class="field">
+                    <label for="country" style="width: 100px;">Pays</label>
+                    <input type="text" value="" id="country" class="form-control">
+                  </div>
+              </td><td style="padding-left: 120px; vertical-align: top;">
+      
+                  <div class="field">
+                    <label for="priority" style="width: 100px;">Priorité</label>
+                    <input type="number" value="" id="priority" class="form-control" style="width: 40px; text-align: right;">
+                  </div>
+                  <div class="field">
+                    <label for="phone" style="width: 100px;">Tél.</label>
+                    <input type="text" value="" id="phone" class="form-control">
+                  </div>
+                  <div class="field">
+                    <label for="mobile" style="width: 100px;">GSM</label>
+                    <input type="text" value="" id="mobile" class="form-control">
+                  </div>
+                  <div class="field">
+                    <label for="workphone" style="width: 100px;">Tél. Travail</label>
+                    <input type="text" value="" id="workphone" class="form-control">
+                  </div>
+                  <div class="field">
+                    <label for="email" style="width: 100px;">E-Mail</label>
+                    <input type="text" value="" id="email" class="form-control">
+                  </div>
+                  <div class="field">
+                    <label for="job" style="width: 100px;">Profession</label>
+                    <input type="text" value="" id="job" class="form-control">
+                  </div>
+                  <div class="checkbox" style="margin-left: 130px;">
+                    <input type="checkbox" value="1" id="authsubscriber">
+                    <label for="authsubscriber">peut signer les contrat</label>
+                  </div>
+                  </td></tr>
+                  <tr><td colspan="2">
+                    <div class="form-group">
+                          <label for="remark">Remarque</label>
+                          <textarea class="summernote" type="text" id="remark"></textarea>
+                        </div>
+                  </td></tr></tbody></table>
+                </div>
+              </div>
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button>
+                <button onclick="save_refperson();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div class="modal fade" id="edit_cautionstatus">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button">
+                  <span aria-hidden="true">x</span><span class="sr-only">Close</span>
+                </button>
+                <h4 class="modal-title">Editer/Ajouter Transfer Caution</h4>
+              </div>
+
+              <div class="modal-body" style="min-height: 350px;">
+                <div id="frmeditcautionstatus">
+                  <input type="hidden" value="0" id="uuid">
+                  <div class="form-group" id="date-container">
+                    <label for="statusdate">Date</label>
+
+                    <div id="dt_statusdate" class="input-group date">
+                      <input type="date" class="form-control" value="" placeholder="dd.mm.yyyy"  id="statusdate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="form-group">
+                  <label for="amount">Montant</label>
+
+                  <div class="input-group number">
+                    <input type="number" value="" id="amount" style="text-align: right;" min="0" nullable="false" class="form-control">
+                    <div class="input-group-addon">€</div>
+                  </div>
+                </div>
+                  <div class="form-group">
+                    <label for="statementnumber">No. Extrait</label>
+                    <input type="text" value="" id="statementnumber"  nullable="true" class="form-control">
+                  </div>
+              </div>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_cautionstatus();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div class="modal fade" id="confirm_delete_cautionstatus">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Transaction Caution</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette transaction?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_cautionstatus();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+        
+        <div class="modal fade" id="confirm_delete_myfile" >
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce fichier?
+
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_file();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>  
+        
+        <div class="modal fade" id="edit_file">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Ajouter/Remplacer Fichier</h4>
+              </div>
+              <div class="modal-body">
+
+                <div id="frmeditfile">
+                  <input type="hidden" value="0" id="uuid" />
+                  
+                  
+                  <div class="form-group">
+                    <label for="name">Fichier</label>
+                    <input type="file" value="" id="file"  nullable="true" class="form-control">
+                  </div>
+                  <!--<div class="form-group">
+                    <label for="phone">Description</label>
+                    <input type="text" value="" id="description"  nullable="true" class="form-control">
+                  </div>-->
+                </div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_file();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+            </div>
+          </div>
+    </div>
+  <script src="js/jquery.min.js" type="text/javascript"></script>
+  <script src="js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="js/datatables.min.js" type="text/javascript"></script>
+  <script src="js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="js/summernote.min.js" type="text/javascript"></script>
+  <script src="js/lang/summernote-fr-FR.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="js/labels.js" type="text/javascript"></script>
+  <script src="js/creorga.js" type="text/javascript"></script>
+  <script src="js/child.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/childs/child.js b/modules/childs/child.js
new file mode 100644 (file)
index 0000000..3330e8d
--- /dev/null
@@ -0,0 +1,939 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {};
+var delplan = null;
+var delrefperson = null;
+var delcautionstatus = null;
+var delfile = null;
+var wh = window.innerHeight-380;
+var myfiles = [];
+var cruuid = null;
+function validate_plan_proposals() {
+  if (($("childs_birthday").val() != '') &&
+    ($("childs_entrydate").val() != '') &&
+    ($("childs_exitdate").val() != '')) {
+    $("planproposal").css("visibility", "visible");
+  } else {
+    $("planproposal").css("visibility", "hidden");
+  }
+}
+
+function initdata() {
+  
+  load_helpers();
+  curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+  var configdata = apppref.getpreference("pageconfig.child");
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  var cname = appdb.dbquery("select uuid from creche LIMIT 1;");
+  cruuid = cname.sqldata[0].uuid;
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'child';
+    apppref.setpreference("pageconfig.child",pconfig);
+  }
+  var cdatasql = "select uuid,clientnumber,prename,surname,strftime('%d.%m.%Y',birthday) as birthday,address,city,zip,country,strftime('%d.%m.%Y',entrydate) as entrydate,checkservicenumber,strftime('%d.%m.%Y',checkserviceexpiration) as checkserviceexpiration,strftime('%d.%m.%Y',leavedate) as leavedate,nationality,nativelanguage,bankaccount,bankbic,cautionamount,cautionremark,remark ,infohealth from childs  where uuid='" + pconfig.uuid + "';";
+  
+  var cdata = appdb.dbquery(cdatasql);
+  cdata = cdata.sqldata[0];
+  set_infoheader(cdata.prename + " " + cdata.surname);
+  for (var ci in cdata) {
+    if (document.getElementById("childs_" + ci)) {
+      if (document.getElementById("childs_" + ci).tagName == "TEXTAREA"){
+        document.getElementById("childs_" + ci).value=cdata[ci];
+      }
+      else {
+        document.getElementById("childs_" + ci).setAttribute('value', cdata[ci]);  
+      }
+    }
+  }
+  var edt_height = wh;
+  loadtextareas(edt_height);
+  //loadplantemplates();
+  //validate_plan_proposals();
+
+  if (pconfig && pconfig.activetab) {
+    $('a[href="#'+pconfig.activetab+'"]').tab('show');
+  }
+  $('#childs_checkservicenumber').on('blur',function(e){
+    var valchknum = $('#childs_checkservicenumber').val().replace(/\s/g,'');
+    if (valchknum.length < 10) {
+      return; 
+    }
+    var xcheck = $('#childs_checkservicenumber').val().replace(/\s/g,'').substring(0,8);
+
+    var bday = $('#childs_birthday').val();
+    var xcheckdate = xcheck.substring(6,8) + "." + xcheck.substring(4,6) +"."+xcheck.substring(0,4);
+    if (bday != xcheckdate) {
+      $('#childs_birthday').val(xcheckdate);
+      setborderdates();
+    }
+    setborderdates();
+  });
+  
+  $('#childs_birthday').on('blur',function(e){
+    setborderdates();
+
+  });
+  $('input[class^="time"]').on('keydown',function(e){
+    var keycode = e.keyCode || e.which; 
+    //jsdump(keycode);
+    if ( keycode == 9 ){
+          
+          $(this).next('input').focus();
+          //savetime(e);
+    }
+    
+});
+$('input[class^="time"]').focusout(function(e){
+    savetime($(this));
+});
+  
+}
+
+function savetime(obj){
+  var timeval = obj.val();
+  if (timeval != ''){
+    timeval = timeval.replace(/[^\d]/g, '') + "0000";
+  timeval = timeval.substring(0,2) + ":" + timeval.substring(2,4);
+  $("#" + obj.attr('id')).val(timeval);
+  }
+              
+  
+}
+
+function setborderdates() {
+  var minamonths = appdb.dbquery("select minage,maxage from creche LIMIT 1;");
+  var bday = encodeparam($('#childs_birthday').val(),'date').replace(/'/g,'');
+  var centrydate = encodeparam($('#childs_entrydate').val(),'date').replace(/'/g,'');
+  var cleavedate = encodeparam($('#childs_leavedate').val(),'date').replace(/'/g,'');
+  var dtbday = new Date(bday);
+  var dtminentrydate = new Date(dtbday.getFullYear(),dtbday.getMonth() + parseInt(minamonths.sqldata[0].minage), dtbday.getDate());
+  var today = new Date();
+  if (centrydate < dtminentrydate.toLocaleFormat("%Y-%m-%d") || (centrydate==cleavedate)) {
+
+    if (dtminentrydate > today) {
+      $('#childs_entrydate').val(dtminentrydate.toLocaleFormat("%d.%m.%Y"));
+    }else {
+      $('#childs_entrydate').val(today.toLocaleFormat("%d.%m.%Y"));
+    }
+    
+  }
+  var dtmaxleavedate = new Date(dtbday.getFullYear(),dtbday.getMonth() + parseInt(minamonths.sqldata[0].maxage), dtbday.getDate());
+  if (cleavedate > dtmaxleavedate.toLocaleFormat("%Y-%m-%d") || (centrydate==cleavedate)) {
+
+    $('#childs_leavedate').val(dtmaxleavedate.toLocaleFormat("%d.%m.%Y"));
+  }
+  centrydate = encodeparam($('#childs_entrydate').val(),'date').replace(/'/g,'');
+  cleavedate = encodeparam($('#childs_leavedate').val(),'date').replace(/'/g,'');
+  appdb.dbexec("update childs set birthday=date('"+bday+"'),entrydate=date('"+centrydate+"'),leavedate=date('"+cleavedate+"') where uuid='"+pconfig.uuid+"';");
+  //appdb.dbexec("update childs set birthday=date('"+$('#childs_birthday').val()+"'),entrydate=date('"+$('#childs_entrydate').val()+"'),leavedate=date('"+$('#childs_leavedate').val()+"') where childuuid='"+pconfig.uuid+"';");
+  //dlg_planning({'uuid':''},'insproposal');
+}
+
+$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+     var tn =  e.target.toString();
+     //dump(tn + "\n");
+     pconfig.activetab = tn.substring(tn.lastIndexOf("#")+1);
+     //dump(pconfig.activetab + "\n");
+     apppref.setpreference("pageconfig.child",pconfig);
+
+     if (pconfig.activetab == 'planning') {
+       load_table_presence();
+     }
+     if (pconfig.activetab == 'parents') {
+       load_table_refperson();
+     }
+     if (pconfig.activetab == 'myfiles') {
+       load_table_files();
+     }
+     if (pconfig.activetab == 'caution') {
+       load_table_caution();
+     }
+ });
+
+function load_table_presence() {
+  
+  var plandatasql = "SELECT '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_planning({''uuid'':''' || plan.uuid || '''},''upd'');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button> <button type=\"button\" class=\"btn btn-danger\" onclick=\"dlg_planning({''uuid'':''' || plan.uuid || '''},''del'');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button> ' AS action, grp.grpname, strftime('%d.%m.%Y',plan.datebegin) || ' - ' || strftime('%d.%m.%Y',plan.dateend) AS planningdaterange,";
+  var wda = ['mon','tue','wed','thu','fri','sat'];
+  var awda = [];
+  for (var w in wda){
+    awda.push("CASE WHEN plan."+wda[w]+"timebegin != plan."+wda[w]+"timeend THEN plan."+wda[w]+"timebegin || ' - ' || plan."+wda[w]+"timeend ELSE '' END || CASE WHEN plan."+wda[w]+"lunch='1' THEN ' (<span class=\"glyphicon glyphicon-cutlery\" aria-hidden=\"true\"></span>)' ELSE '' END || case when plan."+wda[w]+"timebegin2 is not null and plan."+wda[w]+"timeend2 is not null then '<br/>' || plan."+wda[w]+"timebegin2 || ' - ' || plan."+wda[w]+"timeend2 else '' end AS "+wda[w]+"planningtime");  
+  }
+  plandatasql += awda.join(',') + " FROM planning plan LEFT JOIN groups grp ON ( plan.groupuuid=grp.uuid) WHERE plan.childuuid='" + pconfig.uuid + "' ORDER BY plan.datebegin, plan.dateend;";
+  //dump("PLANDATA" + plandatasql + "\n");
+  var plandata = appdb.dbqueryarray(plandatasql);
+
+  var headerdata = getlabels(plandata.sqlhead.join(","));
+  dump("Header" + JSON.stringify(headerdata) + "\n");
+  $("#tbl_planning").html("");
+  var tblplan = $("#tbl_planning").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+    "data": plandata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "ordering": true,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+  loadplantemplates(plandata.sqldata.length);
+
+}
+
+function load_table_refperson() {
+  var labelx = getlabelswithkey('mother,father,tuteur,famillymember,famillyfriend');
+  var areftypes = new Array(); 
+  for (var l in labelx){
+    areftypes.push("select '"+ labelx[l].title +"' as refname, '"+labelx[l].keyname+"' as reftype");
+  }
+  var lblsql = areftypes.join(" UNION ");
+  var refperssql = "SELECT '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_refperson({''uuid'':''' || rp.uuid || '''},''upd'');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button> <button type=\"button\" class=\"btn btn-danger\" onclick=\"dlg_refperson({''uuid'':''' || rp.uuid || '''},''del'');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button> ' as action, rp.priority,rx.refname as reftype, coalesce(rp.surname,'') || ' ' || coalesce(rp.prename,'') as nameprename,  case when rp.phone is not null then '<span class=\"glyphicon glyphicon-earphone\" aria-hidden=\"true\"></span>: ' || rp.phone || '<br/>' else '' end || case when rp.mobile is not null then'<span class=\"glyphicon glyphicon-phone\" aria-hidden=\"true\"></span>: ' || rp.mobile || '<br/>' else '' end || case when rp.workphone is not null then '<span class=\"glyphicon glyphicon-phone-alt\" aria-hidden=\"true\"></span>: ' || rp.workphone || '<br/>' else '' end || case when rp.email is not null then '<span class=\"glyphicon glyphicon-envelope\" aria-hidden=\"true\"></span>: ' || email else '' end as phonemail, coalesce(rp.address,'') || '<br/>' || coalesce(rp.zip,'') || ' ' || coalesce(rp.city,'') || '<br/>' || coalesce(rp.country,'') as address, case when rp.authsubscriber then 'signataire: <span class=\"glyphicons glyphicons-check\"></span><br/>' else '' end || coalesce(rp.job || '<br/>','') as divers, coalesce(rp.remark ,'') as remark FROM refpersons rp join ("+ lblsql+") rx on (rp.reftype=rx.reftype)  where rp.childuuid='" + pconfig.uuid + "';";
+  var refpersondata = appdb.dbqueryarray(refperssql);
+
+  var headerdata = getlabels(refpersondata.sqlhead.join(","));
+  $("#tbl_refperson").html("");
+  var tblheader = '<tr>';
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+  tblacc = null;
+  $("#tbl_refperson").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_referson").append("<tbody>");
+  for (var i in refpersondata.sqldata){
+    var row = refpersondata.sqldata[i];
+    var tr = '<tr>';
+    for (var x in row){
+      //jsdump(x);
+      if (x == 7){
+        tr += "<td>"+ htmlUnescape(row[x])+"</td>";
+      } else {
+        tr += "<td>"+ row[x]+"</td>";
+      }
+    }
+    tr += "</tr>";
+    $("#tbl_refperson").append(tr);
+
+  }
+
+  
+  $("#tbl_refperson").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+    //"data": refpersondata.sqldata,
+    //"columns": headerdata,
+    "paging": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+}
+
+function load_table_caution(){
+  $("#tbl_cautionstatus").html("");
+  var cautionsql = "select '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_cautionstatus({''uuid'':''' || uuid || '''},''upd'');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button> <button type=\"button\" class=\"btn btn-danger\" onclick=\"dlg_cautionstatus({''uuid'':''' || uuid || '''},''del'');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button> ' as action, '<span style=\"display:none\">' || statusdate || '</span>' || strftime('%d.%m.%Y',statusdate) as daydate, amount || ' â‚¬' as amount,statementnumber from cautionstatus where childuuid='"+ pconfig.uuid+"' order by statusdate DESC;";
+  var caudata = appdb.dbqueryarray(cautionsql);
+  var headerdata = getlabels("action,daydate,amount,statementnumber");
+  $("#tbl_cautionstatus").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+    "data": caudata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+}
+
+function load_table_files(){
+  $("#tbl_files").html("");
+  var headerdata = getlabels("action,filename,description,daydate,filetype");
+  $("#tbl_files").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+    //"data": refpersondata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+}
+
+function dlg_cautionstatus(objuuid,type){
+  //TODO: dlg_addcautionstatus
+  //dump("Caution: " + type +" " + objuuid.uuid + +"\n");
+  if (type == 'upd' || type == 'ins') {
+    var caustatdata = appdb.dbquery("select '0' as uuid,strftime('%d.%m.%Y',date('now')) as statusdate,0 as amount,null as statementnumber");
+    if (type == 'upd') {
+      caustatdata = appdb.dbquery("SELECT uuid, strftime('%d.%m.%Y',statusdate) as statusdate, amount, statementnumber FROM cautionstatus where uuid='" + objuuid.uuid + "';");
+    }
+    $("#frmeditcautionstatus #uuid").val(objuuid.uuid);
+    caustatdata = caustatdata.sqldata[0];
+    //setrefpersontypes();
+
+    for (var r in caustatdata) {
+      if (document.getElementById(r)) {
+        
+          document.getElementById(r).value = caustatdata[r];
+        
+      }
+    }
+    $("#edit_cautionstatus").modal('show');
+  } else if (type == 'del') {
+    delcautionstatus= objuuid.uuid;
+    confirm_delete_cautionstatus();
+  }
+}
+
+function dlg_refperson(uuid, type) {
+  if (type == 'upd' || type == 'ins') {
+    var refpdata = appdb.dbquery("SELECT null as reftype, null as surname, null as prename, address, null as phone, null as mobile, null as job, null as email, null as workphone, zip, country, city, '0' as authsubscriber, null as uuid,lastmodified FROM childs where uuid='" + pconfig.uuid +"' union SELECT null as reftype, surname, null as prename, address, null as phone, null as mobile, null as job, null as email, null as workphone, zip, country, city, '0' as authsubscriber, null as uuid,lastmodified FROM refpersons where childuuid='"+pconfig.uuid +"' order by lastmodified DESC ");
+    if (type == 'upd') {
+      refpdata = appdb.dbquery("SELECT reftype, surname, prename, address, phone, mobile, job, email, workphone, zip, country, city, authsubscriber, uuid FROM refpersons where uuid='" + uuid.uuid + "';");
+    }
+    $("#frmeditrefperson #uuid").val(uuid.uuid);
+    refpdata = refpdata.sqldata[0];
+    setrefpersontypes();
+
+    for (var r in refpdata) {
+      if (document.getElementById(r)) {
+        if ($("#" + r).is(':checkbox')) {
+          if (refpdata[r] == '1') {
+            $("#" + r).prop("checked", true);
+          } else {
+            $("#" + r).prop("checked", false);
+          }
+        } else {
+          document.getElementById(r).value = refpdata[r];
+        }
+      }
+    }
+    $("#edit_refperson").modal('show');
+  } else if (type == 'del') {
+    delrefperson = uuid.uuid;
+    confirm_delete_refperson();
+  }
+}
+
+function setplanning_groups() {
+  var plangrps = appdb.dbquery("select uuid,grpname from groups order by minage,maxage;");
+  plangrps = plangrps.sqldata;
+  $("#groupuuid").html('');
+  $("#groupuuid").append('<option value=""></option>');
+  for (var g in plangrps) {
+    $("#groupuuid").append('<option value="' + plangrps[g].uuid + '">' + plangrps[g].grpname + '</option>');
+  }
+}
+
+function setrefpersontypes() {
+var labelx = getlabelswithkey('mother,father,tuteur,famillymember,famillyfriend');
+  var areftypes = new Array();
+  $("#reftype").html('');
+  for (var l in labelx){
+    $("#reftype").append('<option value="' + labelx[l].keyname + '">' + labelx[l].title + '</option>');
+  }
+}
+
+function dlg_planning(uuid, type, planuuid) {
+  //"dlg_planning" + uuid + " " + type + " " + planuuid + "\n");
+  if (type == 'upd') {
+    check_birthdate_valid();
+    setplanning_groups();
+    var plandata = appdb.dbquery("SELECT strftime('%d.%m.%Y',datebegin) as datebegin, strftime('%d.%m.%Y',dateend) as dateend, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch, sattimebegin, sattimeend, satlunch, suntimebegin, suntimeend, sunlunch, childuuid, uuid, groupuuid, montimebegin2, montimeend2, tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2, sattimebegin2, sattimeend2, suntimebegin2, suntimeend2 FROM planning where uuid='" + uuid.uuid + "';");
+    plandata = plandata.sqldata[0];
+
+    for (var p in plandata) {
+      if (document.getElementById(p)) {
+        if ($("#" + p).is(':checkbox')) {
+          if (plandata[p] == '1') {
+            $("#" + p).prop("checked", true);
+          } else {
+            $("#" + p).prop("checked", false);
+          }
+        } else {
+          if ((p.substr(p.length-1) == "2") && (p.indexOf("time") != -1) && (plandata[p] != "")){
+            $('#' + p.substr(0,3) + "time" + p.substr(p.length-1)).show();
+          }
+          if ((p.indexOf("time") != -1) && (plandata[p] == "")) {
+            document.getElementById(p).value = "";
+          } else {
+            document.getElementById(p).value = plandata[p];
+          }
+        }
+      }
+    }
+    $("#edit_planning").modal('show');
+  }
+  else if (type == 'del') {
+    delplan = uuid.uuid;
+    //"Launch confirm delete\n");
+    confirm_delete_planning();
+
+  }
+  else if (type == 'delall') {
+    //delplan = pconfig.uuid;
+    //"Launch confirm all delete\n");
+    confirm_delete_allplanning();
+
+  }
+  else if (type == 'ins') {
+    $("#frmeditplanning #uuid").val("0");
+    check_birthdate_valid();
+    setplanning_groups();
+    var timesql = "SELECT strftime('%d.%m.%Y',date('now')) as datebegin,strftime('%d.%m.%Y',date('now','+6 month')) as dateend ,null as montimebegin, null as montimeend, null as tuetimebegin, null as tuetimeend, null as wedtimebegin, null as wedtimeend, null as thutimebegin, null as thutimeend, null as fritimebegin, null  as fritimeend, null as sattimebegin, null as sattimeend;";  
+    if (planuuid){
+      timesql = "SELECT strftime('%d.%m.%Y',date('now')) as datebegin,strftime('%d.%m.%Y',date('now','+6 month')) as dateend ,montimebegin, montimeend, tuetimebegin, tuetimeend, wedtimebegin, wedtimeend, thutimebegin, thutimeend, fritimebegin, fritimeend, montimebegin2,montimeend2,tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2, sattimebegin2, sattimeend2 FROM planningtemplate where uuid='"+planuuid+"';";  
+    }
+    
+    var timeplan = appdb.dbquery(timesql);
+
+    timeplan = timeplan.sqldata[0];
+    $("#frmeditplanning #datebegin").val(timeplan.datebegin);
+    $("#frmeditplanning #dateend").val(timeplan.dateend);
+    for (var t in timeplan) {
+      if ((t.indexOf("time") != -1)) {
+        var tx = timeplan[t];
+        if (tx == "00:00" || tx== null) {
+          tx = "";
+        }
+
+        $("#" + t).val(tx);
+      }
+    }
+    $("#frmeditplanning :input").each(function() {
+      var input = $(this);
+      if (input.attr("type") == "checkbox") {
+        input.prop('checked', true);
+      }
+
+    });
+
+    $("#edit_planning").modal('show');
+  }
+  else if (type == 'insproposal') {
+    check_birthdate_valid();
+    setplanning_groups();
+    var curplan = appdb.dbquery("select count(*) as cnt,date(max(dateend),'+1 day') as maxdateto,(select birthday from childs where childs.uuid='" + pconfig.uuid + "') as birthday,(select entrydate from childs where childs.uuid='" + pconfig.uuid+"') as entrydate,(select leavedate from childs where childs.uuid='" + pconfig.uuid+"') as leavedate,date('now') as today from planning pl join childs ch on (ch.uuid=pl.childuuid) where pl.childuuid='" + pconfig.uuid + "'");
+    curplan = curplan.sqldata[0];
+    //dump("INSPROPOSAL:" + JSON.stringify(curplan) + "\n");
+    var plansql = "";
+    
+    if ((curplan.cnt == 0) || ( planuuid)){
+      //dump(curplan.today +"<-->" + curplan.birthday + "<-->" + curplan.entrydate + "\n") ;
+      
+      if (curplan.cnt > 0){
+         curplan.entrydate=curplan.maxdateto;
+      }
+       //if (curplan.today < curplan.entrydate) {
+         
+      //  plansql = "select date('"+ curplan.entrydate+"') as datebegin,date(birthday,'+' || maxage || ' months','-1 day') as dateend, pl.uuid as groupuuid, montimeopen as montimebegin,montimeclose as montimeend,tuetimeopen as tuetimebegin,tuetimeclose as tuetimeend,wedtimeopen as wedtimebegin,wedtimeclose as wedtimeend,thutimeopen as thutimebegin,thutimeclose as thutimeend,fritimeopen as fritimebegin,fritimeclose as fritimeend,null as montimebegin2, null as montimeend2, null as tuetimebegin2, null as tuetimeend2,   null as wedtimebegin2, null as wedtimeend2, null as thutimebegin2, null as thutimeend2, null as fritimebegin2, null as fritimeend2 from ( select uuid,minage,maxage,grpname,(select birthday from childs where childs.uuid='" + pconfig.uuid + "') as birthday from groups) pl join workinghours wk on (wk.datestart <= datebegin) group by groupuuid order by wk.datestart DESC,minage,maxage;";
+      //  if (planuuid){
+           //dump("today < entrydate PLANUUID: " + planuuid +"\n");
+      //  }
+      //} else {
+      //dump("INSPROPOSAL 2:" + JSON.stringify(curplan) + "\n");
+        //plansql = "select * from ( select CASE WHEN DATE(birthday,'+' || minage || ' months') < entrydate THEN entrydate ELSE DATE(birthday,'+' || minage || ' months') END AS datebegin, case when date(birthday,'+' || maxage || ' months') > leavedate then leavedate else date(birthday,'+' || maxage || ' months','-1 day') end as dateend, pl.uuid as groupuuid, montimeopen as montimebegin,montimeclose as montimeend,tuetimeopen as tuetimebegin,tuetimeclose as tuetimeend,wedtimeopen as wedtimebegin,wedtimeclose as wedtimeend,thutimeopen as thutimebegin,thutimeclose as thutimeend,fritimeopen as fritimebegin,fritimeclose as fritimeend,sattimeopen as sattimebegin,sattimeclose as sattimeend,null as montimebegin2, null as montimeend2, null as tuetimebegin2, null as tuetimeend2,   null as wedtimebegin2, null as wedtimeend2, null as thutimebegin2, null as thutimeend2, null as fritimebegin2, null as fritimeend2, null as sattimeend2,1 as monlunch,1 as tuelunch, 1 as wedlunch, 1 as thulunch, 1 as frilunch, 1 as satlunch from ( select uuid,minage,maxage,grpname,(select birthday from childs where childs.uuid='" + pconfig.uuid + "') as birthday,date('" + curplan.entrydate +"') AS entrydate,date('" + curplan.leavedate +"') AS leavedate from groups) pl join workinghours wk on (wk.datestart <= datebegin) group by groupuuid order by wk.datestart DESC,minage,maxage ) where datebegin!=dateend and dateend >= datebegin and order by datebegin,dateend;";
+        if (planuuid){
+          plansql = "select * from ( select CASE WHEN DATE(birthday,'+' || minage || ' months') < entrydate THEN entrydate ELSE DATE(birthday,'+' || minage || ' months') END AS datebegin, case when date(birthday,'+' || maxage || ' months') > leavedate then leavedate else date(birthday,'+' || maxage || ' months','-1 day') end as dateend, pl.uuid as groupuuid, plt.* from ( select uuid,minage,maxage,grpname,'"+pconfig.uuid+"' as chuuid,(select birthday from childs where childs.uuid='" + pconfig.uuid + "') as birthday, date('"+ curplan.entrydate+"') AS entrydate,date('" + curplan.leavedate +"') AS leavedate from groups) pl join workinghours wk on (wk.datestart <= datebegin) join (select '" + pconfig.uuid + "' as chuuid,* from planningtemplate where planningtemplate.uuid='"+planuuid+"') plt on (plt.chuuid=pl.chuuid) group by groupuuid order by wk.datestart DESC,minage,maxage ) where datebegin!=dateend and dateend >= datebegin order by datebegin,dateend;";
+          var plandata = appdb.dbquery(plansql);
+      
+      for (var pl in plandata.sqldata) {
+
+        var inssql = "INSERT INTO planning (uuid,childuuid, groupuuid,datebegin, dateend, montimebegin, montimeend,  tuetimebegin, tuetimeend,  wedtimebegin, wedtimeend, thutimebegin,thutimeend, fritimebegin, fritimeend,sattimebegin, sattimeend,montimebegin2, montimeend2,  tuetimebegin2, tuetimeend2,  wedtimebegin2, wedtimeend2, thutimebegin2,thutimeend2, fritimebegin2, fritimeend2,sattimebegin2, sattimeend2, monlunch, tuelunch,wedlunch,thulunch,frilunch,satlunch ) VALUES (";
+        inssql += "'" + appdb.generate_uuid() + "',";
+        inssql += "'" + pconfig.uuid + "',";
+        inssql += "'" + plandata.sqldata[pl].groupuuid + "',";
+        inssql += "'" + plandata.sqldata[pl].datebegin + "',";
+        inssql += "'" + plandata.sqldata[pl].dateend + "',";
+        inssql += "'" + plandata.sqldata[pl].montimebegin + "',";
+        inssql += "'" + plandata.sqldata[pl].montimeend + "',";
+        inssql += "'" + plandata.sqldata[pl].tuetimebegin + "',";
+        inssql += "'" + plandata.sqldata[pl].tuetimeend + "',";
+        inssql += "'" + plandata.sqldata[pl].wedtimebegin + "',";
+        inssql += "'" + plandata.sqldata[pl].wedtimeend + "',";
+        inssql += "'" + plandata.sqldata[pl].thutimebegin + "',";
+        inssql += "'" + plandata.sqldata[pl].thutimeend + "',";
+        inssql += "'" + plandata.sqldata[pl].fritimebegin + "',";
+        inssql += "'" + plandata.sqldata[pl].fritimeend + "',";
+        inssql += "'" + plandata.sqldata[pl].sattimebegin + "',";
+        inssql += "'" + plandata.sqldata[pl].sattimeend + "',";
+        inssql += ((plandata.sqldata[pl].montimebegin2 !== "")?"'" + plandata.sqldata[pl].montimebegin2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].montimeend2 !== "")?"'" + plandata.sqldata[pl].montimeend2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].tuetimebegin2 !== "")?"'" + plandata.sqldata[pl].tuetimebegin2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].tuetimeend2 !== "")?"'" + plandata.sqldata[pl].tuetimeend2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].wedtimebegin2 !== "")?"'" + plandata.sqldata[pl].wedtimebegin2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].wedtimeend2 !== "")?"'" + plandata.sqldata[pl].wedtimeend2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].thutimebegin2 !== "")?"'" + plandata.sqldata[pl].thutimebegin2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].thutimeend2 !== "")?"'" + plandata.sqldata[pl].thutimeend2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].fritimebegin2 !== "")?"'" + plandata.sqldata[pl].fritimebegin2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].fritimeend2 !== "")?"'" + plandata.sqldata[pl].fritimeend2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].sattimebegin2 !== "")?"'" + plandata.sqldata[pl].sattimebegin2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].sattimeend2 !== "")?"'" + plandata.sqldata[pl].sattimeend2 + "'":'null') +",";
+        inssql += ((plandata.sqldata[pl].monlunch == 1)?"'1'":'null') +",";
+        inssql += ((plandata.sqldata[pl].tuelunch == 1)?"'1'":'null') +",";
+        inssql += ((plandata.sqldata[pl].wedlunch == 1)?"'1'":'null') +",";
+        inssql += ((plandata.sqldata[pl].thulunch == 1)?"'1'":'null') +",";
+        inssql += ((plandata.sqldata[pl].frilunch == 1)?"'1'":'null') +",";
+        inssql += ((plandata.sqldata[pl].satlunch == 1)?"'1'":'null') +"";
+        inssql += ");";
+
+        appdb.dbexec(inssql);
+          }
+        }
+        //jsdump("plan SQL: " + plansql +"\n");
+        //if (curplan.cnt > 0){
+        //     plansql = plansql.replace(/%%WHERE%%/,"date('" + curplan.maxdateto+"') between datebegin and dateend or datebegin > date('" + curplan.maxdateto+"') ");
+        //}else {
+        //     plansql = plansql.replace(/%%WHERE%%/,"");
+        //}
+        
+      //}
+      //dump("PLANSQL: " +plansql + "\n");
+      
+      
+    }
+    if ((curplan.cnt >= 1) && (!planuuid)){
+
+      var plansql = "select * from ( select case when date(entrydate) < date(nextdate) then nextdate else entrydate end as datebegin, case when entrydate < date(nextdate) then date(nextdate) else date(birthday,'+' || maxage || ' months','-1 day') end as dateend, pl.uuid as groupuuid,birthday,nextdate,grpname from ( select uuid,minage,maxage,grpname, (select entrydate from childs where childs.uuid='" + pconfig.uuid + "') as entrydate ,(select birthday from childs where childs.uuid='" + pconfig.uuid + "') as birthday, (select date(max(dateend),'+1 day') from planning where planning.childuuid='" + pconfig.uuid + "') as nextdate from groups) pl group by groupuuid order by minage,maxage ) where datebegin<dateend;";
+    
+      var plan2sql = "select montimebegin,montimeend,monlunch,tuetimebegin,tuetimeend,tuelunch,wedtimebegin,wedtimeend,wedlunch,thutimebegin,thutimeend,thulunch,fritimebegin,fritimeend,frilunch,sattimebegin,sattimeend,satlunch,suntimebegin,suntimeend,montimebegin2,montimeend2,tuetimebegin2,tuetimeend2,wedtimebegin2,wedtimeend2,thutimebegin2,thutimeend2,fritimebegin2,fritimeend2,sattimebegin2,sattimeend2,suntimebegin2,suntimeend2 from planning where childuuid='" + pconfig.uuid + "' order by dateend DESC LIMIT 1;";
+      var plandata = appdb.dbquery(plansql);
+
+      var plan2data = appdb.dbquery(plan2sql);
+
+      for (var pl in plandata.sqldata) {
+
+        var inssql = "INSERT INTO planning (uuid,childuuid, groupuuid,datebegin, dateend, montimebegin, montimeend,  tuetimebegin, tuetimeend,  wedtimebegin, wedtimeend,  thutimebegin,thutimeend,  fritimebegin, fritimeend,sattimebegin, sattimeend, monlunch, tuelunch,wedlunch,thulunch,frilunch,satlunch  ) VALUES (";
+        inssql += "'" + appdb.generate_uuid() + "',";
+        inssql += "'" + pconfig.uuid + "',";
+        inssql += "'" + plandata.sqldata[pl].groupuuid + "',";
+        inssql += "'" + plandata.sqldata[pl].datebegin + "',";
+        inssql += "'" + plandata.sqldata[pl].dateend + "',";
+        inssql += "'" + plan2data.sqldata[0].montimebegin + "',";
+        inssql += "'" + plan2data.sqldata[0].montimeend + "',";
+        inssql += "'" + plan2data.sqldata[0].tuetimebegin + "',";
+        inssql += "'" + plan2data.sqldata[0].tuetimeend + "',";
+        inssql += "'" + plan2data.sqldata[0].wedtimebegin + "',";
+        inssql += "'" + plan2data.sqldata[0].wedtimeend + "',";
+        inssql += "'" + plan2data.sqldata[0].thutimebegin + "',";
+        inssql += "'" + plan2data.sqldata[0].thutimeend + "',";
+        inssql += "'" + plan2data.sqldata[0].fritimebegin + "',";
+        inssql += "'" + plan2data.sqldata[0].fritimeend + "',";
+        inssql += "'" + plan2data.sqldata[0].sattimebegin + "',";
+        inssql += "'" + plan2data.sqldata[0].sattimeend + "',";
+        inssql += "'" + plan2data.sqldata[0].monlunch + "',";
+        inssql += "'" + plan2data.sqldata[0].tuelunch + "',";
+        inssql += "'" + plan2data.sqldata[0].wedlunch + "',";
+        inssql += "'" + plan2data.sqldata[0].thulunch + "',";
+        inssql += "'" + plan2data.sqldata[0].frilunch + "'";
+        inssql += "'" + plan2data.sqldata[0].satlunch + "'";
+        inssql += ");";
+
+        appdb.dbexec(inssql);
+      }
+    }
+    load_table_presence();
+  }
+}
+
+function check_planning(){
+  if (encodeparam($("#frmeditplanning #datebegin").val(),'date') > encodeparam($("#frmeditplanning #dateend").val(),'date')){
+    errormsg("Erreur en dates!","La date de début ne peut pas Ãªtre supérieur Ã  la date de fin!\n");
+    return false;
+  }
+
+  if (($("#frmeditplanning #montimebegin").val() > $("#frmeditplanning #montimeend").val())  ||
+  ($("#frmeditplanning #tuetimebegin").val() > $("#frmeditplanning #tuetimeend").val()) ||
+  ($("#frmeditplanning #wedtimebegin").val() > $("#frmeditplanning #wedtimeend").val()) ||
+  ($("#frmeditplanning #thutimebegin").val() > $("#frmeditplanning #thutimeend").val()) ||
+  ($("#frmeditplanning #fritimebegin").val() > $("#frmeditplanning #fritimeend").val()) ||
+  ($("#frmeditplanning #sattimebegin").val() > $("#frmeditplanning #sattimeend").val()) ||
+  ($("#frmeditplanning #montimebegin2").val() > $("#frmeditplanning #montimeend2").val() && $("#montime2").is(':visible'))  ||
+  ($("#frmeditplanning #tuetimebegin2").val() > $("#frmeditplanning #tuetimeend2").val() && $("#tuetime2").is(':visible')) ||
+  ($("#frmeditplanning #wedtimebegin2").val() > $("#frmeditplanning #wedtimeend2").val() && $("#wedtime2").is(':visible')) ||
+  ($("#frmeditplanning #thutimebegin2").val() > $("#frmeditplanning #thutimeend2").val() && $("#thutime2").is(':visible')) ||
+  ($("#frmeditplanning #fritimebegin2").val() > $("#frmeditplanning #fritimeend2").val() && $("#fritime2").is(':visible')) ||
+  ($("#frmeditplanning #sattimebegin2").val() > $("#frmeditplanning #sattimeend2").val() && $("#sattime2").is(':visible')) ||
+  ($("#frmeditplanning #montimeend").val() > $("#frmeditplanning #montimebegin2").val() && $("#montime2").is(':visible')) ||
+  ($("#frmeditplanning #tuetimeend").val() > $("#frmeditplanning #tuetimebegin2").val() && $("#tuetime2").is(':visible')) ||
+  ($("#frmeditplanning #wedtimeend").val() > $("#frmeditplanning #wedtimebegin2").val() && $("#wedtime2").is(':visible')) ||
+  ($("#frmeditplanning #thutimeend").val() > $("#frmeditplanning #thutimebegin2").val() && $("#thutime2").is(':visible')) ||
+  ($("#frmeditplanning #fritimeend").val() > $("#frmeditplanning #fritimebegin2").val() && $("#fritime2").is(':visible')) ||
+  ($("#frmeditplanning #sattimeend").val() > $("#frmeditplanning #sattimebegin2").val() && $("#sattime2").is(':visible'))
+  ) 
+  {
+    errormsg("Erreur dans les heures d'entrée sortie!","l'heure d'entée ne peut pas Ãªtre suppérieur Ã  l'heure de sortie<br/>et<br/>une deuxième heure d'entrée d'un jour ne peut pas Ãªtre inférieur Ã  l'heure de la première sortie du jour!");
+    return false;
+  }
+  return true;
+}
+
+function save_planning() {
+
+  var sql1 = new Array();
+  var sql2 = new Array();
+
+  if (!check_planning()){
+    return;
+  };
+  var pluuid = null;
+  sql1.push("childuuid");
+
+  sql2.push("'" + pconfig.uuid + "'");
+  $("#frmeditplanning :input").each(function() {
+    var input = $(this);
+    if (input.attr("id")) {
+      sql1.push(input.attr("id"));
+      if (input.attr("id") == 'uuid') {
+        if (input.val() == "" || input.val() == "0") {
+          sql2.push("'" + appdb.generate_uuid() + "'");
+        } else {
+          sql2.push("'" + input.val() + "'");
+          pluuid = input.val();
+        }
+      } else if (input.attr("type") == "checkbox") {
+        sql2.push(((input.is(':checked')) ? "'1'" : "'0'"));
+      } else {
+        var ival = encodeparam(input.val(),input.attr('type'));
+        if ((input.attr("id").substring(input.attr("id").length-1) == "2") &&
+            $("#" + input.attr("id").substring(0,3) +"time" + input.attr("id").substring(input.attr("id").length-1)).is(":hidden"))  {
+                  ival = 'null';
+                }
+                if (ival == "''") {
+                  ival='null';
+                }
+                sql2.push(ival);
+
+      }
+    }
+
+  });
+
+  var sdatebegin = encodeparam($("#frmeditplanning #datebegin").val(),'date');
+  var sdateend = encodeparam($("#frmeditplanning #dateend").val(),'date');
+  var checkdatereplace = appdb.dbquery("select uuid from planning where datebegin >= "+sdatebegin+" and dateend <= "+sdateend+" and childuuid='"+pconfig.uuid+"';");
+  checkdatereplace = checkdatereplace.sqldata;
+  if (checkdatereplace.length > 0) {
+
+    var ruuid = new Array();
+    for (var i in checkdatereplace){
+      ruuid.push("'"+ checkdatereplace[i].uuid +"'");
+    }
+    appdb.dbexec("DELETE FROM planning where uuid in (" + ruuid.join(",") + ");");
+  }
+  var checkdatesplit = appdb.dbquery("select uuid,dateend from planning where datebegin <= "+sdatebegin+" and dateend >= "+sdateend+" and childuuid='"+pconfig.uuid+"';");
+  checkdatesplit = checkdatesplit.sqldata;
+  if (checkdatesplit.length == 1) {
+
+    var newuuid = appdb.generate_uuid();
+    appdb.dbexec("INSERT INTO planning (datebegin, dateend, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch, sattimebegin, sattimeend, satlunch, suntimebegin, suntimeend, sunlunch, childuuid, uuid, groupuuid, montimebegin2, montimeend2, tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2, sattimebegin2, sattimeend2, suntimebegin2, suntimeend2) SELECT date("+sdateend+",'+1 day'), dateend, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch, sattimebegin, sattimeend, satlunch, suntimebegin, suntimeend, sunlunch, childuuid, '"+newuuid+"', groupuuid, montimebegin2, montimeend2, tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2, sattimebegin2, sattimeend2, suntimebegin2, suntimeend2 FROM planning where uuid='"+ checkdatesplit[0].uuid +"';");
+    appdb.dbexec("UPDATE planning SET dateend=date("+sdatebegin+",'-1 day') where uuid='"+checkdatesplit[0].uuid+"'");
+  }
+  
+  var checkdatefrom = appdb.dbquery("select uuid from planning where datebegin between "+sdatebegin+" and "+sdateend+" and childuuid='"+pconfig.uuid+"';");
+  var checkdateto = appdb.dbquery("select uuid from planning where dateend between "+sdatebegin+" and "+sdateend+" and childuuid='"+pconfig.uuid+"';");
+  if (checkdatefrom.sqldata.length == 1) {
+
+    appdb.dbexec("update planning set datebegin=date("+encodeparam($("#frmeditplanning #dateend").val(),'date')+",'+1 day') where uuid='"+checkdatefrom.sqldata[0].uuid+"'");
+  }
+  if (checkdateto.sqldata.length == 1) {
+
+    appdb.dbexec("update planning set dateend=date("+encodeparam($("#frmeditplanning #datebegin").val(),'date')+",'-1 day') where uuid='"+checkdateto.sqldata[0].uuid+"'");
+  }
+  if (pluuid) {
+
+    appdb.dbexec("DELETE FROM planning where uuid='" + pluuid + "'");
+  }
+  var inssql = "INSERT INTO planning (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+  appdb.dbexec(inssql);
+  load_table_presence();
+  $("#edit_planning").modal('hide');
+}
+
+function save_refperson() {
+
+  var sql1 = new Array();
+  var sql2 = new Array();
+
+  sql1.push("childuuid");
+  sql2.push("'" + pconfig.uuid + "'");
+  var refuuid= null;
+  $("#frmeditrefperson :input").each(function() {
+    var input = $(this);
+
+    if (input.attr("id")) {
+      sql1.push(input.attr("id"));
+      if (input.attr("id") == 'uuid') {
+        if (input.val() == "" || input.val() == "0") {
+          sql2.push("'" + appdb.generate_uuid() + "'");
+        } else {
+          sql2.push("'" + input.val() + "'");
+        }
+        if (input.val() != "0") {
+          refuuid=input.val();
+        }
+      } else if (input.attr("type") == "checkbox") {
+
+        sql2.push(((input.is(':checked')) ? "'1'" : "'0'"));
+
+      } else {
+        var ival = input.val();
+        if (ival == "''") {
+          ival = 'null';
+        }
+        sql2.push(encodeparam(ival,'text'));
+
+      }
+    }
+  });
+
+  if (refuuid) {
+    appdb.dbexec("DELETE FROM refpersons where uuid='" + refuuid + "'");
+  }
+  var inssql = "INSERT INTO refpersons (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+  appdb.dbexec(inssql);
+
+  load_table_refperson();
+
+  $("#edit_refperson").modal('hide');
+
+  return false;
+}
+
+function save_cautionstatus(){
+  var sql1 = new Array();
+  var sql2 = new Array();
+
+  sql1.push("childuuid");
+  sql2.push("'" + pconfig.uuid + "'");
+  var cauuuid= null;
+  $("#frmeditcautionstatus :input").each(function() {
+    var input = $(this);
+
+    if (input.attr("id")) {
+      sql1.push(input.attr("id"));
+      if (input.attr("id") == 'uuid') {
+       //dump("caution uuid=" + input.val() +"\n");
+        if (input.val() === "" || input.val() === "0") {
+          sql2.push("'" + appdb.generate_uuid() + "'");
+        } else {
+          sql2.push("'" + input.val() + "'");
+        }
+        if (input.val() != "0") {
+          cauuuid=input.val();
+        }
+      } else {
+        var ival = encodeparam(input.val(),input.attr('type'));
+        if (ival == "''") {
+          ival = 'null';
+        }
+        sql2.push(ival);
+
+      }
+    }
+  });
+
+  if (cauuuid) {
+    appdb.dbexec("DELETE FROM cautionstatus where uuid='" + cauuuid + "'");
+  }
+  var inssql = "INSERT INTO cautionstatus (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+  //dump(inssql + "\n");
+  appdb.dbexec(inssql);
+
+  load_table_caution();
+
+  $("#edit_cautionstatus").modal('hide');
+
+  return false;
+}
+
+function confirm_delete_cautionstatus() {
+  $("#confirm_delete_cautionstatus").modal('show');
+  return false;
+}
+
+
+function confirm_delete_planning() {
+  $("#confirm_delete_planning").modal('show');
+  return false;
+}
+
+function confirm_delete_allplanning() {
+  $("#confirm_delete_allplanning").modal('show');
+  return false;
+}
+
+function confirm_delete_refperson() {
+  $("#confirm_delete_refperson").modal('show');
+  return false;
+}
+
+function delete_planning() {
+
+  appdb.dbexec("DELETE FROM planning where uuid='" + delplan + "'");
+  delplan = null;
+  load_table_presence();
+
+  $("#confirm_delete_planning").modal('hide');
+
+  return false;
+}
+
+function delete_allplanning() {
+
+  appdb.dbexec("DELETE FROM planning where childuuid='" + pconfig.uuid + "'");
+  delplan = null;
+  load_table_presence();
+
+  $("#confirm_delete_allplanning").modal('hide');
+
+  return false;
+}
+
+function delete_refperson() {
+
+  appdb.dbexec("DELETE FROM refpersons where uuid='" + delrefperson + "'");
+  delrefperson = null;
+  load_table_refperson();
+
+  $("#confirm_delete_refperson").modal('hide');
+
+  return false;
+}
+
+function delete_cautionstatus() {
+
+  appdb.dbexec("DELETE FROM cautionstatus where uuid='" + delcautionstatus + "'");
+  delcautionstatus = null;
+  load_table_caution();
+
+  $("#confirm_delete_cautionstatus").modal('hide');
+
+  return false;
+}
+
+function display_tblrow(trid) {
+    $('#' + trid + "time2").show();
+
+}
+
+function hide_tblrow(trid) {
+  $('#' + trid).hide();
+}
+
+function load_table_files(){
+      
+      myfiles = system.getChildFiles(cruuid,pconfig.uuid);
+      
+      var atbody = [];
+      for (var i=0;i<myfiles.length;i++){
+        var fname = system.getFileName(myfiles[i].path);
+        //dump(fname + "\n");
+        if (!fname.startsWith('.')){
+               var row = [];
+            row.push('<button onclick="preview_file(\'' + myfiles[i].path.replace(/\\/g,'\\\\') +'\');" class="btn btn-primary"><span class="glyphicon glyphicon-open" aria-hidden="true"></span></button>&nbsp;<button onclick="delete_report(\''+myfiles[i].path.replace(/\\/g,'\\\\')+'\');" class="btn btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>');
+            row.push(fname);
+            atbody.push(row);
+        }
+        
+  }
+
+  $("#tbl_files").html("");
+      var headerdata = getlabels("action,description");
+      $("#tbl_files").html("");
+      $("#tbl_files").dataTable({
+        "language": {
+          "url": "js/locale/datatable_fr.json"
+        },
+        "data": atbody,
+        "columns": headerdata,
+        "paging":   false,
+        "scrollY": wh + "px",
+        "scrollCollapse": true,
+        "ordering": true,
+        "info":     false,
+        "filter": false,
+        "destroy": true
+      });
+}
+
+function preview_file(fi){
+  //dump("open file: " + fi + "\n");
+  var ff = system.openFile(fi);
+  return false;
+}
+
+function delete_report(fi) {
+  //dump("delete" + fi + " ->"+ myfiles[delfile].path+"\n");
+  
+  //delfile = fi;
+  //dump(fi + "\n");
+  if (confirm("êtes vous sûre de supprimer ce fichier?")){
+    OS.File.remove(fi);
+    setTimeout(function(){load_table_files();},3000);
+  }
+
+  return false;
+
+}
+
+
+
+
+function dlg_file(){
+    $("#edit_file").modal('show');
+    return false;
+}
+  
+  
+function save_file(){
+  var file = $("#frmeditfile #file").val();
+  var path = FileUtils.File(curcfg.path.local  + system.sep() +"childs" + system.sep() +cruuid + system.sep() + pconfig.uuid);
+  var newlocation= path.path + system.sep() + system.getFileName(file);
+  OS.File.copy(file, newlocation);
+  setTimeout(function(){load_table_files();$("#edit_file").modal('hide');},3000);
+}
+
+function loadplantemplates(plarows){
+  //jsdump("plarows:" + plarows);
+  var xdata = appdb.dbquery("select uuid,templatename from planningtemplate order by templatename;");
+  xdata = xdata.sqldata;
+  if (xdata.length > 0){
+    $("#plantemplates").html("");
+    if ((!plarows) || (plarows == 0)){
+      $("#plantemplates").append('<li style="font-weight: bold; padding-left: 5px;">multiple</li>');
+      for (var i in xdata){
+        $("#plantemplates").append('<li><a href="javascript:dlg_planning({\'uuid\':\'\'},\'insproposal\',\''+xdata[i].uuid+'\');">'+ xdata[i].templatename+'</a></li>');  
+      } 
+    }
+    $("#plantemplates").append('<li role="separator" class="divider"></li>');
+    $("#plantemplates").append('<li style="font-weight: bold; padding-left: 5px;">simple</li>');
+    for (var i in xdata){
+      $("#plantemplates").append('<li><a href="javascript:dlg_planning({\'uuid\':\'\'},\'ins\',\''+xdata[i].uuid+'\');">'+ xdata[i].templatename+'</a></li>');  
+    }
+    $("#plantemplates").append('<li><a href="javascript:dlg_planning({\'uuid\':\'\'},\'ins\');">Plan Vide</a></li>');
+  } 
+}
\ No newline at end of file
diff --git a/modules/childs/filters.js b/modules/childs/filters.js
new file mode 100644 (file)
index 0000000..89769ef
--- /dev/null
@@ -0,0 +1,51 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var filters_fr = [
+{"sql":"select '%%ACTION%%' as action, checkservicenumber, prename,surname, '<span style=\"display: none;\">' || strftime('%Y-%m-%d',birthday) || '</span>' || strftime('%d.%m.%Y',birthday) as birthday from childs where leavedate >= date('now')",
+"heads":"action,checkservicenumber,prename,surname,birthday",
+"description":"courants (date actuelle <= date de sortie)"},
+// {"sql":"select '%%ACTION%%' as action, checkservicenumber, prename,surname, '<span style=\"display: none;\">' || strftime('%Y-%m-%d',birthday) || '</span>' || strftime('%d.%m.%Y',birthday) as birthday from childs where checkserviceexpiration >= date('now','-1 months')",
+// "heads":"action,checkservicenumber,prename,surname,birthday",
+// "description":"expiration checkservice (<= 1 mois)"},
+{"sql":"select '%%ACTION%%' as action, checkservicenumber, prename,surname, '<span style=\"display: none;\">' || strftime('%Y-%m-%d',birthday) || '</span>' || strftime('%d.%m.%Y',birthday) as birthday from childs where entrydate >= date('now')",
+"heads":"action,checkservicenumber,prename,surname,birthday",
+"description":"futur (date d'entrée >= date actuelle)"},
+{"sql":"select '%%ACTION%%' as action, checkservicenumber, prename,surname, '<span style=\"display: none;\">' || strftime('%Y-%m-%d',birthday) || '</span>' || strftime('%d.%m.%Y',birthday) as birthday from childs",
+"heads":"action,checkservicenumber,prename,surname,birthday",
+"description":"tous"},
+{"sql":"select '%%ACTION%%' as action, checkservicenumber, prename,surname, '<span style=\"display: none;\">' || strftime('%Y-%m-%d',birthday) || '</span>' || strftime('%d.%m.%Y',birthday) as birthday from childs where leavedate < date('now')",
+"heads":"action,checkservicenumber,prename,surname,birthday" ,
+"description":"anciens (date actuelle > date de sortie)"},
+// {"sql":"select '%%ACTION%%' as action, checkservicenumber, prename,surname, '<span style=\"display: none;\">' || strftime('%Y-%m-%d',birthday) || '</span>' || strftime('%d.%m.%Y',birthday) as birthday from childs where leavedate >= date('now','-2 months') and cautionamount is not null and cautionpayedback is null",
+// "heads":"action,checkservicenumber,prename,surname,birthday",
+// "description":"Caution Ã  rembourser (sorties < 2 mois)"},
+{"sql":"select '%%ACTION2%%' as action, coalesce(ch.prename,'') || ' ' || coalesce(ch.surname,'') || '<br/>' ||  '(' || coalesce(ch.checkservicenumber,'') || ')' as childname, rp.priority, "+
+" coalesce(rp.prename,'') || ' ' || coalesce(rp.surname,'') as nameprename, "+
+   " case when rp.phone is not null then '<span class=\"glyphicon glyphicon-earphone\" aria-hidden=\"true\"></span>: ' || rp.phone || '<br/>' else '' end || case when rp.mobile is not null then'<span class=\"glyphicon glyphicon-phone\" aria-hidden=\"true\"></span>: ' || rp.mobile || '<br/>' else '' end || case when rp.workphone is not null then '<span class=\"glyphicon glyphicon-phone-alt\" aria-hidden=\"true\"></span>: ' || rp.workphone || '<br/>' else '' end  as phone, coalesce(rp.address,'') || '<br/>' || coalesce(rp.zip,'') || ' ' || coalesce(rp.city,'') || '<br/>' || coalesce(rp.country,'') as address "+
+ " from childs ch left join refpersons rp on (ch.uuid=rp.childuuid) where ch.leavedate >= date('now') and ch.checkservicenumber is not null "+
+" order by ch.prename,ch.surname,rp.priority,rp.reftype DESC",
+"heads":"action,childname,priority,nameprename,phone,address",
+"description":"Parents / Personnes de référence"},
+{"sql":"select '%%ACTION2%%' as action,ch.checkservicenumber as checkservicenumber,ch.prename as prename,ch.surname as surname," +
+               "'<span style=\"display: none;\">' || strftime('%Y-%m-%d',plnow.datebegin) || '</span>' || strftime('%d.%m.%Y',plnow.datebegin) as datebeginnow,'<span style=\"display: none;\">' || strftime('%Y-%m-%d',plnow.dateend) || '</span>' || strftime('%d.%m.%Y',plnow.dateend) as dateendnow,gr.grpname as grpname, " +
+               "'<span style=\"display: none;\">' || strftime('%Y-%m-%d',plnext.nextdatebegin) || '</span>' || strftime('%d.%m.%Y',plnext.nextdatebegin) as datebeginnext, '<span style=\"display: none;\">' || strftime('%Y-%m-%d',plnext.nextdateend) || '</span>' || strftime('%d.%m.%Y',plnext.nextdateend) as dateendnext, gr2.grpname as nextgroup " +
+               "from (select uuid, prename,surname,checkservicenumber from childs where date('now') between entrydate and leavedate) ch left join (select * from planning where date('now') between datebegin and dateend) plnow on (ch.uuid=plnow.childuuid) left join groups gr on (plnow.groupuuid=gr.uuid) " +
+               "left join (select childuuid, groupuuid,max(datebegin) as nextdatebegin,max(dateend) as nextdateend from planning where datebegin > date('now') group by childuuid ) plnext on (ch.uuid=plnext.childuuid) left join groups gr2 on (plnext.groupuuid = gr2.uuid);",
+ "heads":"action,checkservicenumber,prename,surname,datebeginnow,dateendnow,grpname,datebeginnext,dateendnext,grpname",
+ "description":"Planification groupes courrant et prochain"
+}
+
+];
+
+function getallfilters(){
+  var ret = new Array();
+  for (var f=0;f<filters_fr.length;f++) {
+    ret.push(new Object(filters_fr[f]));
+  }
+  return ret;
+}
+
+function getfilter(fid){
+  return filters_fr[fid];
+}
+
diff --git a/modules/childs/index.html b/modules/childs/index.html
new file mode 100644 (file)
index 0000000..e2fcab1
--- /dev/null
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <title>Enfants</title>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="../../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../node_modules/bootstrap-table/dist/bootstrap-table.min.css" rel="stylesheet" type="text/css">
+  <link href="../../node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css" rel="stylesheet" type="text/css">
+  <link href="../../css/creorga.epic.css" rel="stylesheet" type="text/css">
+  <link href="../../css/app.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+  
+  <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
+    <a class="navbar-brand" href="#">Creorga</a>
+    <div class="ml-auto">
+      <div class="btn-group" role="group" aria-label="Basic example">
+          <button class="btn btn-primary" onclick="child_new();"><i class="fas fa-plus"></i><br/>nouv.</button>
+          <button class="btn btn-primary" onclick="child_edit();"><i class="fas fa-edit"></i><br/>édit.</button>
+          <button class="btn btn-primary" onclick="child_delete();"><i class="fas fa-trash"></i><br/>suppr.</button>
+      </div>
+    </div>
+  </nav>
+  <div class="cotainer-fluid" style="margin-top: 52px;">
+      <table id="tbl_childs" class="table table-bordered table-hover table-striped">
+          <thead class="thead-dark"> 
+                  <th data-checkbox="true"></th>
+                  <th data-sortable="true">Nom</th>
+                  <th data-sortable="true">Prénom</th>
+                  <th data-sortable="true">Check-Service</th>
+                  <th data-sortable="true">Date de Naissance</th>
+                  <th data-sortable="true">Date d'entrée</th>
+                  <th data-sortable="true">Date de sortie</th>
+          <tfoot></tfoot>
+          <tbody></tbody>
+      </table>
+      </div>
+  <script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
+  <script src="../../node_modules/jquery/dist/jquery.min.js"></script>
+  <script src="../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
+  <script src="../../node_modules/bootstrap-table/dist/bootstrap-table.min.js"></script>
+  <script src="../../node_modules/@fortawesome/fontawesome-free/js/all.min.js"></script>
+  <script src="../../js/moduleglobal.js"></script>
+  <script src="../../js/database.js"></script>
+  <script src="index.js"></script>
+  <script>if (window.module) module = window.module;</script>
+</body>
+</html>
diff --git a/modules/childs/index.js b/modules/childs/index.js
new file mode 100644 (file)
index 0000000..4acd282
--- /dev/null
@@ -0,0 +1,163 @@
+//Source-code licensed under EUPL v1.2 ( Copyright 2019 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+function initpage(){
+
+}
+var idfilter = null;
+var filter = null;
+var delchild = null;
+//var printchild = null;
+//var pagename = "childs";
+var pconfig = {};
+var childtbl = null;
+//var printchilddef = {};
+var wh= window.innerHeight -125;
+//var a = {};
+//var btnprintchild = "";
+var candelete = 0;
+function initdata(){
+  var configdata = apppref.getpreference("pageconfig.childs");
+  if (configdata !== '') {
+    pconfig = JSON.parse(configdata);
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.childs",pconfig);
+  }
+  if (system.appinfo().ID.indexOf("director") > 0){
+    candelete = 1;
+  }
+    var filters = getallfilters();
+    var strfilters = "";
+    for (var f in filters) {
+      if (pconfig.filterid === "") {
+        idfilter = 0;
+        filter = filters[0];
+        set_infoheader(filter.description);
+       
+        pconfig.idfilter = 0;
+        apppref.setpreference("pageconfig.childs",pconfig);
+      }
+      if (pconfig.filterid == f) {
+        idfilter = f;
+        filter = filters[f];
+        set_infoheader(filter.description);
+
+      }
+      strfilters += '<li><a href="javascript:setfilter(\'' + f + '\');">' + filters[f].description + '</a></li>';
+    }
+    
+  
+    $("#cmb_childsfilter").html(strfilters);
+
+  loadtable();
+}
+
+
+function loadtable() {
+  var actionbtnsql = "<button onclick=\"globelreq.send_request({page:''child'',data:{uuid:''' || uuid || '''},header:''Enfant''});\" class=\"btn btn-primary\"><span class=\"glyphicon glyphicon-pencil\" aria-hidden=\"true\"></span></button>";
+  if (candelete == 1){
+    actionbtnsql += "<button onclick=\"confirm_delete_child(''' || uuid || ''');\" class=\"btn btn-danger\"><span class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"></span></button>";
+  }
+  var sql = filter.sql;
+  sql = sql.replace('%%ACTION%%',actionbtnsql);
+  var actionbtnsql2 = "<button onclick=\"globelreq.send_request({page:''child'',data:{uuid:''' || ch.uuid || '''},header:''Enfant''});\" class=\"btn btn-primary\"><span class=\"glyphicon glyphicon-pencil\" aria-hidden=\"true\"></span></button>";
+  sql = sql.replace('%%ACTION2%%',actionbtnsql2);
+  var data = appdb.dbqueryarray(sql);
+  //dump("SQL:" + sql + "\n");
+  //dump(JSON.stringify(data) + "\n");
+  //dump(JSON.stringify(data.sqlhead) + "\n");
+  
+  var headerdata = null;
+  
+  headerdata = getlabels(data.sqlhead.join(","));
+
+  $("#tbl_childs").html("");
+  var nhd = [];
+  for (var i in headerdata){
+         nhd.push({"title":headerdata[i]["title"],"class":headerdata[i]["class"]}); 
+  }
+  
+  $("#tbl_childs").append();
+  childtbl = $("#tbl_childs").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+    "data": data.sqldata,
+    "columns": nhd,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "paging":   false,
+    "ordering": true,
+    "info":     true,
+    "filter": true,
+    "destroy": true
+  });
+  
+//  if (pconfig.filter) {
+//    childtbl.fnFilter(pconfig.filter);
+//  }
+  if (pconfig.order) {
+    childtbl.fnSort(pconfig.order);
+  }
+  
+}
+
+//$('#tbl_childs').on( 'search.dt', function () {
+//    pconfig.filter = childtbl.api().search();
+//    apppref.setpreference("pageconfig.childs",pconfig);
+//  } );
+
+  $('#tbl_childs').on( 'order.dt', function () {
+    pconfig.order= childtbl.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.childs",pconfig);
+  } );
+
+
+
+
+
+
+function setfilter(fid) {
+  idfilter = fid;
+  filter = getfilter(fid);
+  //cond = fnew.filtersql;
+  pconfig.filterid = fid;
+  apppref.setpreference("pageconfig.childs",pconfig);
+  globelreq.send_request({
+           page: 'childs',
+           data: null,
+           header: 'Enfants'
+         });
+  //set_infoheader(filter.description);
+  //loadtable();
+}
+
+function addchild() {
+  var newuuid = appdb.generate_uuid();
+  appdb.dbexec("insert into childs (uuid,birthday,entrydate,leavedate) VALUES ('" + newuuid + "',date('now','-2 months'),date('now'),date('now'));");
+  globelreq.send_request({
+    page: 'child',
+    data: {
+      "uuid": newuuid
+    },
+    header: 'Enfant'
+  });
+}
+
+function confirm_delete_child(myuuid) {
+  delchild = myuuid;
+  $("#confirm_delete_child").modal('show');
+}
+
+function delete_child() {
+  appdb.dbexec("DELETE from childslog where childuuid='"+delchild+"'");
+  appdb.dbexec("DELETE FROM presence where childuuid='" + delchild + "';");
+  appdb.dbexec("DELETE FROM refpersons where childuuid='" + delchild + "';");
+  appdb.dbexec("DELETE FROM planning where childuuid='" + delchild + "';");
+  appdb.dbexec("DELETE FROM childs where uuid='" + delchild + "';");
+  delchild = null;
+  loadtable();
+  $("#confirm_delete_child").modal('hide');
+}
+
+
diff --git a/modules/creche/creche.html b/modules/creche/creche.html
new file mode 100644 (file)
index 0000000..ed500d1
--- /dev/null
@@ -0,0 +1,753 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+
+  <title>Crèche</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="css/jquery.minicolors.css" rel="stylesheet" type="text/css">
+  <link href="css/creorga.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+    <div class="container-fluid">
+      <div id="main" class="main">
+        <!--<h2>Crèche</h2>-->
+        <br/>
+        <form name="frmcreche" id="frmcreche">
+          <input type="hidden" value="" id="creche_uuid">
+          <div class="field form-inline">
+            <label for="creche_crechename">Nom / Adresse</label> <input type="text" value="" id="creche_crechename" class="form-control"><input type="text" value="" id="creche_adress" class="form-control">
+          </div>
+
+          <div class="field form-inline">
+            <label for="creche_zip">CP / Ville / Pays</label> <input type="text" value="" size="6" id="creche_zip" class="form-control">
+             <input type="text" value="" size="30" id="creche_city" class="form-control"><input type="text" value="" id="creche_country" disabled="true" class="form-control">
+          </div>
+          <div class="field form-inline">
+            <label for="creche_idcheckservice">Identifiant Check-Service</label> <input type="text" value="" size="30" id="creche_idcheckservice" class="form-control">
+          </div>
+        </form>
+        <div class="tabbable">
+            <ul class="nav nav-tabs" id="tabgrouphead">
+              <li><a data-toggle="tab" href="#openinghours">Heures d'ouvertures</a></li>
+
+              <li><a data-toggle="tab" href="#groups">Groupes d'enfants</a></li>
+              <li><a data-toggle="tab" href="#planningtemplate">modèles planification</a></li>
+
+            </ul>
+
+            <div class="tab-content">
+              
+              <div id="openinghours" class="tab-pane active">
+                <button onclick="dlg_workinghours({'uuid':''},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp;heures d'ouvertures</button>
+                <div id="tbl_workinghours_wrapper" class="dataTables_wrapper no-footer">
+                    <table id="tbl_workinghours" class="table table-striped dataTable no-footer" role="grid"></table>
+                </div>
+              </div>
+              <div id="groups" class="tab-pane">
+                <div class="row">
+                  <div class="col-xs-4">
+                    <div class="field">
+                        <label for="creche_maxchilds">Maximum d'enfants authorisés</label>
+                        <div class="input-group number">
+                            <input type="number" value="58" id="creche_maxchilds" style="text-align: right;" max="200" min="1" nullable="false" class="form-control">
+                            <div class="input-group-addon"> Enfants</div>
+                        </div>
+                    </div>
+                  </div>
+                <div class="col-xs-4">
+        <div class="field">
+          <label for="creche_minage">Minimum age authorisés</label>
+
+          <div class="input-group number">
+            <input type="number" value="2" id="creche_minage" style="text-align: right;" max="144" min="2" nullable="false" class="form-control">
+            <div class="input-group-addon">Mois</div>
+          </div>
+        </div>
+        </div><div class="col-xs-4">
+        <div class="field">
+          <label for="creche_maxage">Maximum age authorisés</label>
+          <div class="input-group number">
+            <input type="number" value="84" id="creche_maxage" style="text-align: right;" max="144" min="2" nullable="false" class="form-control">
+            <div class="input-group-addon">Mois</div>
+          </div>
+        </div>
+        </div>
+        </div>
+        <button onclick="dlg_groups({'uuid':''},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp;groupe</button>
+  
+        <div id="tbl_groups_wrapper" class="dataTables_wrapper no-footer">
+        <table id="tbl_groups" class="table table-striped dataTable no-footer" role="grid">
+          
+        </table>
+        </div>
+              </div>
+        <div id="planningtemplate" class="tab-pane">
+        <button onclick="dlg_planningtemplate({'uuid':''},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp;Modèle</button>
+        <table id="tbl_planningtemplate" class="table table-striped dataTable no-footer" role="grid"></table>
+        </div>
+        
+            </div>  
+        
+      </div>
+      
+      <div class="modal fade" id="edit_workinghours">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Editer/Ajouter heures d'ouverture</h4>
+              </div>
+
+              <div class="modal-body">
+                <div id="frmeditworkinghours">
+                  <input type="hidden" value="0" id="uuid" />
+                  
+                  <div class="field" id="date-container">
+                    <label for="datestart">à partir de</label>
+
+                    <div id="dt_datestart" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy"  id="datestart"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+
+                  <div class="table-reponsive">
+                    <table class="table">
+                      <thead>
+                        <tr>
+                          <th>jour de semaine</th>
+
+                          <th>ouverture</th>
+
+                          <th>fermeture</th>
+                        </tr>
+                      </thead>
+
+                      <tbody>
+                        <tr>
+                          <td>Lundi</td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="montimeopen">
+                              </div>
+                            </div>
+                          </td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="montimeclose">
+                              </div>
+                            </div>
+                          </td>
+                        </tr>
+
+                        <tr>
+                          <td>Mardi</td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimeopen">
+                              </div>
+                            </div>
+                          </td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimeclose">
+                              </div>
+                            </div>
+                          </td>
+                        </tr>
+
+                        <tr>
+                          <td>Mercredi</td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimeopen">
+                              </div>
+                            </div>
+                          </td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimeclose">
+                              </div>
+                            </div>
+                          </td>
+                        </tr>
+
+                        <tr>
+                          <td>Jeudi</td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimeopen">
+                              </div>
+                            </div>
+                          </td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimeclose">
+                              </div>
+                            </div>
+                          </td>
+                        </tr>
+
+                        <tr>
+                          <td>Vendredi</td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimeopen">
+                              </div>
+                            </div>
+                          </td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimeclose">
+                              </div>
+                            </div>
+                          </td>
+                        </tr>
+                        <tr>
+                          <td>Samedi</td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimeopen">
+                              </div>
+                            </div>
+                          </td>
+
+                          <td>
+                            <div class="field">
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimeclose">
+                              </div>
+                            </div>
+                          </td>
+                        </tr>
+                      </tbody>
+                    </table>
+                  </div>
+                </div>
+              </div>
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_workinghours();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+      
+      <div class="modal fade" id="confirm_delete_workinghours">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer heure d'ouverture</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette heure d'ouverture?
+
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_workinghours();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+      <!-- PLANNING TEMPLATE  -->
+       <div class="modal modal-wide fade" id="edit_planning">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Editer/Ajouter Modèle</h4>
+              </div>
+
+              <div class="modal-body">
+                <div id="frmeditplanning">
+                  <input type="hidden" value="0" id="uuid">
+                  <div class="row">
+                  <div class="field">
+                    <label for="templatename">Nom</label>
+                    <input type="text" class="form-control" placeholder="" value="" id="templatename">
+                  </div>
+                  </div>
+                  <div class="table-reponsive">
+                    <table class="table">
+                      <thead>
+                        <tr>
+                          <th></th>
+                          <th>Jours de semaine</th>
+                          <th><span class="glyphicon glyphicon-time" aria-hidden="true"></span> entrée</th>
+                          <th><span class="glyphicon glyphicon-time" aria-hidden="true"></span> sortie</th>
+                          <th><span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span></th>
+                        </tr>
+                      </thead>
+
+                      <tbody>
+                        <tr>
+                          <td><button  onclick="display_tblrow('mon');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Lundi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="montimebegin">
+                              </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="montimeend">
+                            </div>
+                          </td>
+                          <td>
+                              <input type="checkbox" id="monlunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+                            
+                          </td>
+                        </tr>
+                        <tr class="suprow" id="montime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('montime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="montimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="montimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- tue -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('tue');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Mardi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimeend">
+                              </div>
+                          </td>
+<td>
+
+                              <input type="checkbox" id="tuelunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+                          
+                        </tr>
+                        <tr class="suprow" id="tuetime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('tuetime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="tuetimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- wed -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('wed');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Mercredi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimeend">
+                              </div>
+                          </td>
+<td>
+
+                              <input type="checkbox" id="wedlunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+
+                        </tr>
+                        <tr class="suprow" id="wedtime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('wedtime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="wedtimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- thu -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('thu');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Jeudi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimeend">
+                              </div>
+                          </td>
+<td>
+                              <input type="checkbox" id="thulunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+                        </tr>
+                        <tr class="suprow" id="thutime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('thutime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="thutimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- fri -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('fri');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Vendredi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimeend">
+                              </div>
+                          </td>
+<td>
+                              <input type="checkbox" id="frilunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+                        </tr>
+                        <tr class="suprow" id="fritime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('fritime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="fritimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                        <!-- fri -->
+                        <tr>
+                          <td><button  onclick="display_tblrow('sat');" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button></td>
+                          <td>Samedi</td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                                <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimebegin">
+                              </div>
+                          </td>
+                          <td>
+                              <div class="input-group bootstrap-timepicker time">
+                              <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimeend">
+                              </div>
+                          </td>
+<td>
+                              <input type="checkbox" id="satlunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+
+                          </td>
+                        </tr>
+                        <tr class="suprow" id="sattime2" style="display: none;">
+                          <td></td>
+                          <td><button onclick="hide_tblrow('sattime2');" class="btn btn-primary"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimebegin2">
+                            </div>
+                          </td>
+                          <td>
+                            <div class="input-group bootstrap-timepicker time">
+                            <input type="text" class="form-control timepicker" placeholder="" value="" id="sattimeend2">
+                            </div>
+                          </td>
+                          <td></td>
+                        </tr>
+                      </tbody>
+                    </table>
+                  </div>
+                </div>
+              </div>
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_planningtemplate();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div class="modal fade" id="confirm_delete_planningtemplate">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Modèle de Planification</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce modèle?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_planningtemplate();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+      
+      
+      
+      <!-- groups -->
+      
+      <div class="modal fade" id="edit_groups">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Editer/Ajouter Groupe</h4>
+              </div>
+
+              <div class="modal-body">
+                <div id="frmeditgroups">
+                  <input type="hidden" value="0" id="uuid">
+
+                  <div class="field">
+                    <label for="grpname">Nom</label> <input type="text" value="" id="grpname" class="form-control">
+                  </div>
+                  <div class="field" >
+                            <label for="color">Couleur</label>
+                            <div class="input-group">
+                            <input type="hidden" id="color" class="form-control " value="">
+                            </div>
+                        </div>
+                  <div class="field">
+                    <label for="maxchilds">Max. Enfants</label>
+
+                    <div class="input-group number">
+                      <input type="number" value="" id="maxchilds" style="text-align: right;" max="15" min="1" nullable="false" class="form-control">
+
+                      <div class="input-group-addon">
+                        Enfants
+                      </div>
+                    </div>
+                  </div>
+
+                  <div class="field">
+                    <label for="minage">Age min.</label>
+
+                    <div class="input-group number">
+                      <input type="number" value="" id="minage" style="text-align: right;" max="144" min="2" nullable="false" class="form-control">
+
+                      <div class="input-group-addon">
+                        Mois
+                      </div>
+                    </div>
+                  </div>
+
+                  <div class="field">
+                    <label for="maxage">Age max.</label>
+
+                    <div class="input-group number">
+                      <input type="number" value="" id="maxage" style="text-align: right;" max="144" min="2" nullable="false" class="form-control">
+
+                      <div class="input-group-addon">
+                        Mois
+                      </div>
+                    </div>
+                  </div>
+                  <div class="field">
+                    <label for="maxage">Nbr. Pers. requis</label>
+
+                    <div class="input-group number">
+                      <input type="number" value="" id="minstaff" style="text-align: right;" max="10" min="1" nullable="false" class="form-control">
+
+                      <div class="input-group-addon">
+                        personnes
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                
+              </div>
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_group();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+      
+      <div class="modal fade" id="confirm_delete_groups">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Groupe</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette groupe?
+
+                <div id="frmdeletegroup">
+                  <input type="hidden" value="" id="uuid"><input type="hidden" value="group" id="table"><input type="hidden" value="del" id="action">
+                </div>
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_groups();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+      <!-- end groups -->
+      
+      <!-- VACANCY -->
+      <div class="modal fade" id="edit_vacancy">
+        <div class="modal-dialog">
+          <div class="modal-content">
+            <div class="modal-header">
+              <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+              <h4 class="modal-title">Editer/Ajouter jours feriés</h4>
+            </div>
+
+            <div class="modal-body">
+              <div id="frmeditvacancy">
+                <div class="field" id="date-container">
+                    <label for="vacancydate">date</label>
+
+                    <div id="dt_vacancydate" class="input-group date">
+                      <input type="date" class="form-control" value="" placeholder="dd.mm.yyyy" id="vacancydate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                
+                <div class="field">
+                  <label for="vacancydescription">Nom/Description</label>
+
+                  <div class="input-group number">
+                    <input type="text" value="" id="vacancydescription"  nullable="false" class="form-control">
+                  </div>
+                </div>
+              </div>
+            </div>
+
+            <div class="modal-footer">
+              <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_vacancy();" class="btn btn-primary">OK</button>
+            </div>
+          </div>
+        </div>
+      </div>
+      
+      <div class="modal fade" id="confirm_delete_vacancy">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer jour ferié</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer de jour ferié?
+
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_vacancy();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+      
+      <!-- end vacancy -->
+    </div>
+  </div>
+  <script src="js/jquery.min.js" type="text/javascript"></script>
+  <script src="js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="js/jquery.minicolors.min.js" type="text/javascript"></script>
+  <script src="js/datatables.min.js" type="text/javascript"></script>
+  <script src="js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+
+<script src="js/creorga.js" type="text/javascript"></script>
+<script src="js/labels.js" type="text/javascript"></script>
+<script src="js/creche.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/creche/creche.js b/modules/creche/creche.js
new file mode 100644 (file)
index 0000000..6f6c9aa
--- /dev/null
@@ -0,0 +1,510 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var crident = null;
+var pconfig = {};
+var delwkhours = null;
+var delplanning = null;
+var delgroups = null;
+var winh = window.innerHeight - 360;
+var weekdays = ['mon','tue','wed','thu','fri','sat'];
+
+function initdata() {
+  load_helpers();
+  var sql = "SELECT uuid,crechename, adress, city, country, zip,maxchilds,minage,maxage,stafflist,idcheckservice FROM creche LIMIT 1;";
+  var crdata = appdb.dbquery(sql);
+  set_infoheader("");
+  //dump(JSON.stringify(crdata) + "\n");
+  if (crdata.sqldata.length == 0){
+      check_defaultdata();
+      crdata = appdb.dbquery(sql);
+  }
+  crident = crdata.sqldata[0].uuid;
+  cdata = crdata.sqldata[0];
+  for (var ci in cdata) {
+
+    if (document.getElementById("creche_" + ci)) {
+        if (ci == "stafflist"){
+               $("#creche_stafflist").prop('checked', true);
+        } else {
+               document.getElementById("creche_" + ci).setAttribute('value', cdata[ci]);
+        }
+
+    }
+  }
+  var configdata = apppref.getpreference("pageconfig.creche");
+
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+
+  $('#tabgrouphead a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
+    var tn = e.target.toString();
+    pconfig.activetab = tn.substring(tn.lastIndexOf("#") + 1);
+    apppref.setpreference("pageconfig.creche", pconfig);
+
+    if (pconfig.activetab == 'openinghours') {
+      load_table_workinghours();
+    }
+    if (pconfig.activetab == 'groups') {
+      load_table_groups();
+    }
+    if (pconfig.activetab == 'planningtemplate') {
+      load_table_planningtemplate();
+    }
+
+  });
+  $('#frmeditgroups #color').minicolors({theme:'bootstrap',position: 'bottom right'});
+  if (pconfig && pconfig.activetab) {
+    $('#tabgrouphead a[href="#' + pconfig.activetab + '"]').tab('show');
+  } else {
+    $('#tabgrouphead a[href="#openinghours"]').tab('show');
+  }
+}
+
+$('#creche_stafflist').on('change', function() {
+    // From the other examples
+    if (this.checked) {
+        appdb.dbexec("update creche set stafflist='1';");
+    } else {
+       appdb.dbexec("update creche set stafflist=null;");
+    }
+});
+
+function load_table_workinghours() {
+
+  var whsql1 = "select count(*) as cnt from workinghours;";
+  var wdata1 = appdb.dbquery(whsql1);
+  var delbtn = "<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_workinghours({''uuid'':''' || uuid || '''},''del'');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>";
+  if (wdata1.sqldata[0].cnt == 1) {
+    delbtn = '';
+  }
+  var whsql = "SELECT '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_workinghours({''uuid'':''' || uuid || '''},''upd'');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button> " + delbtn + "' as action, strftime('%d.%m.%Y',datestart) as startdate, case when montimeopen is null then 'fermé' else montimeopen || ' - ' || montimeclose end as monday, case when tuetimeopen is null then 'fermé' else tuetimeopen || ' - ' || tuetimeclose end as tuesday, case when wedtimeopen is null then 'fermé' else wedtimeopen || ' - ' || wedtimeclose end as wednesday, case when thutimeopen is null then 'fermé' else thutimeopen || ' - ' || thutimeclose end as thursday, case when fritimeopen is null then 'fermé' else fritimeopen || ' - ' || fritimeclose end as friday, case when sattimeopen is null then 'fermé' else sattimeopen || ' - ' || sattimeclose end as saturday FROM workinghours order by datestart ASC;";
+
+  var whdata = appdb.dbqueryarray(whsql);
+
+  var headerdata = getlabels(whdata.sqlhead.join(","));
+  $("#tbl_workinghours").html("");
+  $("#tbl_workinghours").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+    "data": whdata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "scrollY": winh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+
+}
+
+function load_table_groups() {
+  var grpsql1 = "select count(*) as cnt from groups;";
+  var grpcnt = appdb.dbquery(grpsql1);
+  var grpdel = "|| case when groupchildcount = 0 then '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_groups({''uuid'':''' || uuid || '''},''del'');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button> ' else '' end";
+  if (grpcnt.sqldata[0].cnt <= 1) {
+    grpdel = '';
+  }
+  var grsql = "select '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_groups({''uuid'':''' || uuid || '''},''upd'');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>' " + grpdel + " as action, grpname,case when color is not null then '<div style=\"width: 50px; height: 30px;background-color: ' || color ||';\"></div><br/>' else null end as color, maxchilds, minage, maxage,coalesce(minstaff,1) as minstaff from ( select grp.uuid,grp.grpname,grp.color,grp.maxchilds,grp.minage,grp.maxage,grp.minstaff, count(plan.uuid) as groupchildcount from groups grp left join planning plan on (grp.uuid=plan.groupuuid) group by grp.uuid,grp.grpname,grp.maxchilds,grp.minage,grp.maxage order by grp.minage,grp.maxage) order by minage,maxage;";
+
+  var grdata = appdb.dbqueryarray(grsql);
+
+  var headerdata = getlabels(grdata.sqlhead.join(","));
+  $("#tbl_groups").html("");
+  var dtbl_groups = $("#tbl_groups").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+    "data": grdata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "scrollY": winh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+}
+
+function load_table_planningtemplate() {
+
+  var plansql = "SELECT '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_planningtemplate({''uuid'':''' || uuid || '''},''upd'');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button>" +
+  "<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_planningtemplate({''uuid'':''' || uuid || '''},''del'');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>' as action," + 'templatename as name,';
+  var xplan = [];
+  for (var i in weekdays){
+
+
+    xplan.push("case when "+ weekdays[i] +"timebegin is null or "+ weekdays[i] +"timeend is null or "+ weekdays[i] +"timebegin = "+ weekdays[i] +"timeend  then '' else "+ weekdays[i] +"timebegin || ' - ' || "+ weekdays[i] +"timeend end || (case when "+ weekdays[i] +"lunch then ' (<span class=\"glyphicons glyphicons-cutlery\"></span>)' else  '' end) || case when "+ weekdays[i] +"timebegin2 = "+ weekdays[i] +"timeend2 or "+ weekdays[i] +"timebegin2 is null or "+ weekdays[i] +"timeend2 is null then '' else '<br/>' || "+ weekdays[i] +"timebegin2 || ' - ' || "+ weekdays[i] +"timeend2 end as "+ weekdays[i] +"");
+  }
+  plansql += xplan.join(',') + ' from planningtemplate order by templatename;';
+  //dump("PLANSQL:" + plansql + "\n");
+  var tmpldata = appdb.dbqueryarray(plansql);
+
+  var headerdata = getlabels("action,name,mon,tue,wed,thu,fri,sat");
+  $("#tbl_planningtemplate").html("");
+  $("#tbl_planningtemplate").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+    "data": tmpldata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "scrollY": winh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+}
+
+function dlg_workinghours(uuid, type) {
+  if ((type == 'upd') || (type == 'ins')) {
+    var cwhsql = "SELECT  '0' as uuid,strftime('%d.%m.%Y',date('now')) as datestart, montimeopen, montimeclose, tuetimeopen, tuetimeclose, wedtimeopen, wedtimeclose, thutimeopen, thutimeclose, fritimeopen, fritimeclose FROM workinghours order by datestart DESC LIMIT 1;";
+    if (type == 'upd') {
+      cwhsql = "SELECT uuid,strftime('%d.%m.%Y',datestart) as datestart, montimeopen, montimeclose, tuetimeopen, tuetimeclose, wedtimeopen, wedtimeclose, thutimeopen, thutimeclose, fritimeopen, fritimeclose, sattimeopen FROM workinghours  where uuid='" + uuid.uuid + "';";
+    }
+    var cwhdata = appdb.dbquery(cwhsql);
+    cwhdata = cwhdata.sqldata[0];
+    for (var w in cwhdata) {
+      if ($("#frmeditworkinghours #" + w)) {
+
+        $("#frmeditworkinghours #" + w).val(cwhdata[w]);
+      }
+    }
+    $("#edit_workinghours").modal('show');
+  } else if (type == 'del') {
+    delwkhours = uuid.uuid;
+    confirm_delete_workinghours();
+  }
+}
+
+function dlg_planningtemplate(uuid, type) {
+  for (var i in weekdays){
+    $("#frmeditplanning #" + weekdays[i] + "time2").hide();
+  }
+  if ((type == 'upd') || (type == 'ins')) {
+    //var grpsql = "SELECT strftime('%d.%m.%Y',date('now')) as startdate, '0,00' as costsperhour,'0,00' as costperhourfallback, '0' as weeklyhourslimit, '0' as dailylunchcosts, '0' as uuid;";
+    var hdata = {templatename:"nouveau modèle",uuid:"0",
+    montimebegin:"00:00",montimeend:"00:00",monlunch:"0",montimebegin2: "00:00",montimeend2: "00:00",
+    tuetimebegin:"00:00",tuetimeend:"00:00",tuelunch:"0",tuetimebegin2: "00:00",tuetimeend2: "00:00",
+    wedtimebegin:"00:00",wedtimeend:"00:00",wedlunch:"0",wedtimebegin2: "00:00",wedtimeend2: "00:00",
+    thutimebegin:"00:00",thutimeend:"00:00",thulunch:"0",thutimebegin2: "00:00",thutimeend2: "00:00",
+    fritimebegin:"00:00",fritimeend:"00:00",frilunch:"0",fritimebegin2: "00:00",fritimeend2: "00:00"
+    };
+    if (type == 'upd') {
+      var plxsql = "SELECT uuid, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch,sattimebegin, sattimeend, satlunch, montimebegin2, montimeend2, tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2,sattimebegin2, sattimeend2, templatename FROM planningtemplate where uuid='" + uuid.uuid + "';";
+      var hdbdata = appdb.dbquery(plxsql);
+      hdata = hdbdata.sqldata[0];
+    }
+    //JSON.stringify(hdata) + "\n");
+    $("#frmeditplanning #uuid").val(hdata.uuid);
+    for (var p in hdata) {
+
+      if ($("#frmeditplanning #"+p)) {
+        //dump("found:" + p + "\n");
+        if ($("#" + p).is(':checkbox')) {
+          if (hdata[p] == '1') {
+            $("#" + p).prop("checked", true);
+          } else {
+            $("#" + p).prop("checked", false);
+          }
+        } else {
+          if ((p.substr(p.length-1) == "2") && (p.indexOf("time") !== -1) && (hdata[p.substr(0,3) + "timebegin2"] !== hdata[p.substr(0,3) + "timeend2"])){
+            //dump("p:" + p +'#' + p.substr(0,3) + "time" + p.substr(p.length-1) + " show\n");
+            $('#' + p.substr(0,3) + "time" + p.substr(p.length-1)).show();
+          }
+          if ((p.indexOf("time") !== -1) && (hdata[p] === "")) {
+            document.getElementById(p).value = "00:00";
+          } else {
+            document.getElementById(p).value = hdata[p];
+          }
+        }
+      }
+    }
+    //"curuuid" + $("#frmeditplanning #uuid").val()+"\n");
+
+    $("#edit_planning").modal('show');
+  } else if (type == 'del') {
+    delplanning = uuid.uuid;
+    confirm_delete_planningtemplate();
+  }
+}
+
+function dlg_groups(uuid, type) {
+  if ((type == 'upd') || (type == 'ins')) {
+    var grpsql = "SELECT '0' as uuid,'nouvelle groupe' as grpname, case when maxchilds > 15 then 15 else maxchilds end as maxchilds, minage, maxage, 1 as minstaff FROM creche LIMIT 1;";
+    if (type == 'upd') {
+      grpsql = "SELECT grpname, maxchilds, minage, maxage,minstaff, uuid,color FROM groups where uuid='" + uuid.uuid + "';"
+    }
+    var grpdata = appdb.dbquery(grpsql);
+    grpdata = grpdata.sqldata[0];
+    for (var g in grpdata) {
+
+      if ($("#frmeditgroups #" + g)) {
+        $("#frmeditgroups #" + g).val(grpdata[g]);
+        if (g == 'color'){
+          $('#frmeditgroups #color').minicolors('value',{color: grpdata[g]});
+        }
+      }
+    }
+    $("#edit_groups").modal('show');
+  } else if (type == 'del') {
+    delgroups = uuid.uuid;
+    confirm_delete_groups();
+  }
+}
+
+function save_workinghours() {
+  var sql1 = new Array();
+  var sql2 = new Array();
+  var type = 'ins';
+  var cuuid = "";
+  if ($("#frmeditworkinghours #uuid").val() != 0) {
+    type = 'upd';
+    cuuid = $("#frmeditworkinghours #uuid").val();
+  }
+  $("#frmeditworkinghours :input").each(function() {
+    var input = $(this);
+    if (input.attr("id")) {
+      if (type == 'ins') {
+        sql1.push('"' + input.attr("id") + '"');
+        if (input.attr("id") == 'uuid') {
+          if (input.val() == "" || input.val() == "0") {
+            sql2.push("'" + appdb.generate_uuid() + "'");
+          } else {
+            sql2.push("'" + input.val() + "'");
+          }
+        } else {
+          var ival = encodeparam(input.val(), input.attr('type'));
+          sql2.push(ival);
+        }
+      } else {
+        if (input.attr("id") != 'uuid') {
+          var ival = encodeparam(input.val(), input.attr('type'));
+          sql2.push('"' + input.attr("id") + '"=' + ival);
+        }
+      }
+
+
+    }
+
+  });
+  var xsql = "";
+  if (type == 'upd') {
+    xsql = "UPDATE workinghours SET " + sql2.join(',') + " where \"uuid\"='" + cuuid + "';";
+  } else {
+    xsql = "INSERT INTO workinghours (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+  }
+
+  appdb.dbexec(xsql);
+  load_table_workinghours();
+  $("#frmeditworkinghours #uuid").val("0");
+  $("#edit_workinghours").modal('hide');
+}
+
+function save_planningtemplate() {
+  var sql1 = [];
+  var sql2 = [];
+  var cuuid = "";
+  //"save planning!\n");
+  if ($("#frmeditplanning #uuid").val() !== "0") {
+    cuuid = $("#frmeditplanning #uuid").val();
+  }
+  //$("#frmeditplanning :input").each(function() {
+    //var input = $(this);
+    sql1.push('"templatename"');
+    sql2.push(encodeparam($('#frmeditplanning #templatename').val(), "text"));
+    for (var i in weekdays){
+      if ($('#frmeditplanning #' + weekdays[i] + "timebegin").val() !== $('#frmeditplanning #' + weekdays[i] + "timeend").val()){
+          sql1.push('"' + weekdays[i] + "timebegin" + '"');
+          sql1.push('"' + weekdays[i] + "timeend" + '"');
+          sql2.push(encodeparam($('#frmeditplanning #' + weekdays[i] + "timebegin").val(), "text"));
+          sql2.push(encodeparam($('#frmeditplanning #' + weekdays[i] + "timeend").val(), "text"));
+          if ($('#frmeditplanning #' + weekdays[i] + "lunch").is(':checked')){
+            sql1.push('"' + weekdays[i] + "lunch" + '"');
+            sql2.push("'1'");
+          }
+      }
+      if ($('#frmeditplanning #' + weekdays[i] + "timebegin2").val() !== $('#frmeditplanning #' + weekdays[i] + "timeend2").val()){
+          sql1.push('"' + weekdays[i] + "timebegin2" + '"');
+          sql1.push('"' + weekdays[i] + "timeend2" + '"');
+          sql2.push(encodeparam($('#frmeditplanning #' + weekdays[i] + "timebegin2").val(), "text"));
+          sql2.push(encodeparam($('#frmeditplanning #' + weekdays[i] + "timeend2").val(), "text"));
+      }
+    }
+    if (cuuid !== '') {
+      appdb.dbexec("DELETE  FROM planningtemplate where \"uuid\"='" + cuuid + "';");
+      sql1.push('"uuid"');
+      sql2.push("'"+cuuid+"'");
+    }else {
+      sql1.push('"uuid"');
+      sql2.push("'"+appdb.generate_uuid()+"'");
+    }
+    var xsql = "INSERT INTO planningtemplate (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+    //"EXEC planning SQL:"+ xsql + "\n");
+    appdb.dbexec(xsql);
+    load_table_planningtemplate();
+    $("#frmeditplanning #uuid").val("0");
+    $("#edit_planning").modal('hide');
+}
+
+function save_group() {
+  var sql1 = new Array();
+  var sql2 = new Array();
+  var type = 'ins';
+  var cuuid = "";
+
+  if ($("#frmeditgroups #uuid").val() != 0) {
+    type = 'upd';
+    cuuid = $("#frmeditgroups #uuid").val();
+  }
+  $("#frmeditgroups :input").each(function() {
+    var input = $(this);
+    if (input.attr("id")) {
+      if (type == 'ins') {
+        sql1.push('"' + input.attr("id") + '"');
+        if (input.attr("id") == 'uuid') {
+          if (input.val() == "" || input.val() == "0") {
+            sql2.push("'" + appdb.generate_uuid() + "'");
+          } else {
+            sql2.push("'" + input.val() + "'");
+          }
+        } else {
+          var ival = encodeparam(input.val(), input.attr('type'));
+          sql2.push(ival);
+        }
+      } else {
+        if (input.attr("id") != 'uuid') {
+          var ival = encodeparam(input.val(), input.attr('type'));
+          sql2.push('"' + input.attr("id") + '"=' + ival);
+        }
+      }
+
+
+    }
+
+  });
+  var xsql = "";
+  if (type == 'upd') {
+    xsql = "UPDATE groups SET " + sql2.join(',') + " where \"uuid\"='" + cuuid + "';";
+  } else {
+    xsql = "INSERT INTO groups (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+  }
+
+  appdb.dbexec(xsql);
+  load_table_groups();
+  $("#frmeditgroups #uuid").val("0");
+  $("#edit_groups").modal('hide');
+}
+
+function confirm_delete_workinghours() {
+  $("#confirm_delete_workinghours").modal('show');
+  return false;
+}
+
+function confirm_delete_planningtemplate() {
+  $("#confirm_delete_planningtemplate").modal('show');
+  return false;
+}
+
+function confirm_delete_groups() {
+  $("#confirm_delete_groups").modal('show');
+  return false;
+}
+
+
+
+function delete_groups() {
+
+  appdb.dbexec("DELETE FROM groups where uuid='" + delgroups + "';");
+  delgroups = null;
+  load_table_groups();
+
+  $("#confirm_delete_groups").modal('hide');
+
+  return false;
+}
+
+function delete_workinghours() {
+  var delsql = "DELETE FROM workinghours where uuid='" + delwkhours + "';";
+  appdb.dbexec(delsql);
+  delwhours = null;
+  load_table_workinghours();
+
+  $("#confirm_delete_workinghours").modal('hide');
+
+  return false;
+}
+
+function delete_planningtemplate() {
+
+  appdb.dbexec("DELETE FROM planningtemplate where uuid='" + delplanning + "'");
+  delplanning = null;
+  load_table_planningtemplate();
+
+  $("#confirm_delete_planningtemplate").modal('hide');
+
+  return false;
+}
+
+function display_tblrow(trid) {
+    $('#frmeditplanning #' + trid + "time2").show();
+
+}
+
+function hide_tblrow(trid) {
+  //trid.substring(0,3)+ "\n ");
+  $('#frmeditplanning #' + trid.substr(0,3)+"timebegin2").val("00:00");
+  $('#frmeditplanning #' + trid.substr(0,3)+"timeend2").val("00:00");
+  $('#frmeditplanning #' + trid).hide();
+}
+
+function check_defaultdata() {
+       curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+       var tables = ['creche','groups','workinghours','vacancy','planningtemplate'];
+       for (var t in tables) {
+               var sql = "select count(*) as cnt from "+ tables[t]+";";
+
+               var res = appdb.dbquery(sql);
+
+               if ((res) && (res.sqldata[0].cnt == '0')) {
+       
+var inssql = [];
+if (tables[t] == 'creche') {
+  inssql.push("INSERT INTO creche (crechename, adress, city, country, zip, maxchilds, uuid, minage, maxage) VALUES ('Crèche', '', '', 'Luxembourg', '', 28, '"+ curcfg.uuid +"', 2, 84);");
+} else if (tables[t] == 'groups') {
+  var sinssql = "INSERT INTO groups (grpname, maxchilds, minage, maxage, uuid) VALUES ";
+  sinssql +=  "('Groupe Bébé', 6, 2, 12, '"+ appdb.generate_uuid() +"'),";
+  sinssql +=  "('Groupe plus 1 an ', 6, 12, 24, '"+ appdb.generate_uuid() +"'),";
+  sinssql +=  "('Groupe de 2 ans Ã  3 ans', 8, 24, 36, '"+ appdb.generate_uuid() +"'),";
+  sinssql +=  "('Groupe de 3 Ã  4 ans ', 8, 36, 48, '"+ appdb.generate_uuid() +"'),";
+  sinssql +=  "('Groupe plus 4 ans ( Scolaires)', 11, 48, 84, '"+ appdb.generate_uuid() +"');"
+  inssql.push(sinssql);
+} else if (tables[t] == 'workinghours') {
+  inssql.push("INSERT INTO workinghours (uuid, datestart, montimeopen, montimeclose, tuetimeopen, tuetimeclose, wedtimeopen, wedtimeclose, thutimeopen, thutimeclose, fritimeopen, fritimeclose, sattimeopen, sattimeclose, suntimeopen, suntimeclose, crecheuuid) VALUES ('"+appdb.generate_uuid()+"', strftime(\"%Y\",date('now','-1 year')) || '-01-01', '07:00', '19:00', '07:00', '19:00', '07:00', '19:00', '07:00', '19:00', '07:00', '19:00', null, null, null, null, '"+ curcfg.uuid+"');");
+
+}
+
+else if (tables[t] == 'planningtemplate') {
+
+  var sinssql = "INSERT INTO planningtemplate (uuid, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch, templatename) VALUES ";
+  sinssql += "('"+ appdb.generate_uuid()+"', '08:00', '18:00', 1, '08:00', '18:00', 1, '08:00', '18:00', 1, '08:00', '18:00', 1, '08:00', '18:00',1, 'plain temps (60h)'),";
+  sinssql += "('"+ appdb.generate_uuid()+"', '08:00', '13:00', 1, '08:00', '13:00', 1, '08:00', '13:00', 1, '08:00', '13:00', 1, '08:00', '13:00',1,'matin (30h)'),";
+  sinssql += "('"+ appdb.generate_uuid()+"', '13:00', '18:00', 1, '13:00', '18:00', 1, '13:00', '18:00', 1, '13:00', '18:00', 1, '13:00', '18:00',1, 'après-midi (30h)');";
+  inssql.push(sinssql);
+
+}
+for (var i in inssql){
+
+       appdb.dbexec(inssql[i]);
+}
+
+
+}
+}
+}
diff --git a/modules/dashboard/index.html b/modules/dashboard/index.html
new file mode 100644 (file)
index 0000000..f84c768
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <title>Dashboard</title>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="../../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../node_modules/bootstrap-table/dist/bootstrap-table.min.css" rel="stylesheet" type="text/css">
+  <link href="../../node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css" rel="stylesheet" type="text/css">
+  <link href="../../css/creorga.epic.css" rel="stylesheet" type="text/css">
+  <link href="../../css/app.css" rel="stylesheet" type="text/css">
+  </head>
+  <body>
+    <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
+      <a class="navbar-brand" href="#">Creorga</a>
+      <div class="ml-auto">
+        <div class="btn-group" role="group" aria-label="Basic example">
+        </div>
+      </div>
+    </nav>
+    <div class="cotainer-fluid" style="margin-top: 52px;">
+      
+      <div class="row">
+        <div class="col-sm-12">
+          <div class="card">
+            <div class="card-heading">
+              <h3 class="cadr-title">&nbsp;Informations Utiles</h3>
+            </div>
+            <div class="card-body" id="infopanel">
+              pas d'informations utiles pour l'instant!
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
+    <script src="../../node_modules/jquery/dist/jquery.min.js" type="text/javascript"></script>
+    <script src="../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
+    <script src="../../node_modules/bootstrap-table/dist/bootstrap-table.min.js"></script>
+    <script src="../../node_modules/@fortawesome/fontawesome-free/js/all.min.js"></script>
+    <script src="../../js/moduleglobal.js"></script>
+    <script src="../../js/database.js"></script>
+    <!--<script src="chrome://creorga/content/js/tools.js" type="text/javascript"></script>-->
+    <!-- <script src="js/creorga.js" type="text/javascript"></script> -->
+    <!-- <script src="js/labels.js" type="text/javascript"></script> -->
+    <script src="index.js" type="text/javascript"></script>
+    <script>if (window.module) module = window.module;</script>
+  </body>
+</html>
+
diff --git a/modules/dashboard/index.js b/modules/dashboard/index.js
new file mode 100644 (file)
index 0000000..ab68dc1
--- /dev/null
@@ -0,0 +1,17 @@
+function initpage(){
+
+}
+// var lastpageopened = {};
+
+// function initdata(){
+//   set_infoheader("");
+// }
+
+// var strlp = apppref.getpreference("pageconfig.lastpage");
+// if (strlp !== '') {
+//   lastpageopened = JSON.parse(strlp);
+// }
+
+// if ((lastpageopened) && (lastpageopened.view != "")  && (lastpageopened.view != "home")){
+//   globelreq.send_request({page:lastpageopened.view,module:lastpageopened.module,header:lastpageopened.header},null);
+// }
diff --git a/modules/forms/forms.html b/modules/forms/forms.html
new file mode 100644 (file)
index 0000000..52753ab
--- /dev/null
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+
+  <title>Creorga - Creche</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+    <div class="container-fluid" style="padding-top: 5px;">
+        <!--<span class="pagehead" id="pagehead">Formulaires</span>&nbsp;-->
+        <button  onclick="dlg_addform();" id="btnadd" class="btn btn-primary" type="button">
+  <span class="glyphicon glyphicon-plus"></span>
+</button>
+  
+   
+    <!--<button onclick="return globelreq.send_request({foo: 1}, something.callback)">send {foo: 1} with callback</button>-->
+    <!--<button onclick="return globelreq.send_request({baz: 3}, something.callback)">send {baz: 3} with callback</button>-->
+    <table id="tbl_forms" class="table table-striped">
+      
+    </table>
+    
+      </div>
+    <div class="modal fade" id="edit_forms">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Ajouter/Remplacer Fichier</h4>
+              </div>
+              <div class="modal-body">
+
+                <div id="frmeditforms">
+                  <input type="hidden" value="0" id="uuid" />
+                  
+                  
+                  <div class="form-group">
+                    <label for="name">Fichier</label>
+                    <input type="file" value="" id="file"  nullable="true" class="form-control">
+                  </div>
+                  <!--<div class="form-group">
+                    <label for="phone">Description</label>
+                    <input type="text" value="" id="description"  nullable="true" class="form-control">
+                  </div>-->
+                </div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_forms();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+          </div>
+        </div>
+      
+      <div class="modal fade" id="confirm_delete_forms">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce fichier?
+
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_forms();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>  
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+
+<script src="../../web/js/creorga.js" type="text/javascript"></script>
+<script src="../../web/js/labels.js" type="text/javascript"></script>
+<script src="js/forms.js" type="text/javascript"></script>
+  </body>
+</html>
+
diff --git a/modules/forms/forms.xul b/modules/forms/forms.xul
new file mode 100644 (file)
index 0000000..54eeef0
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_forms" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton class="btn btn-default" id="tbb_forms" insertbefore="tbb_space" label="Formulaires" image="modules/forms/img/doc.png" orient="vertical" oncommand="navigation.load_appview('forms','forms',null,'Formulaires');"/>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/forms/img/doc.png b/modules/forms/img/doc.png
new file mode 100644 (file)
index 0000000..32dbbec
Binary files /dev/null and b/modules/forms/img/doc.png differ
diff --git a/modules/forms/img/form.png b/modules/forms/img/form.png
new file mode 100644 (file)
index 0000000..0de6475
Binary files /dev/null and b/modules/forms/img/form.png differ
diff --git a/modules/forms/js/forms.js b/modules/forms/js/forms.js
new file mode 100644 (file)
index 0000000..5ca9c3a
--- /dev/null
@@ -0,0 +1,93 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var wh= window.screen.height -400;
+var myfiles = null;
+var delform = null;
+var cruuid = null;
+var candelete = 0;
+function initdata(){
+      curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+      load_table_forms();
+      set_infoheader("");
+      if (system.appinfo().ID.indexOf("director")){
+        candelete = 1;
+      }
+    }
+
+function load_table_forms(){
+      var cname = appdb.dbquery("select uuid from creche LIMIT 1;");
+      cruuid = cname.sqldata[0].uuid;
+
+      myfiles = system.getReports(cruuid);
+      var atbody = new Array();
+      for (var i=0;i<myfiles.length;i++){
+       
+        var fname = system.getFileName(myfiles[i].path);
+        if (!fname.startsWith('.')){
+               var row = new Array();
+          var btndelete = "";  
+            //if (candelete == 1){
+              btndelete = '<button onclick="delete_report('+i+');" class="btn btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>';
+            //}
+            row.push('<button onclick="preview_report(' + i +');" class="btn btn-primary"><span class="glyphicon glyphicon-open" aria-hidden="true"></span></button>' + btndelete);
+            row.push(fname);
+            atbody.push(row);
+        }
+        
+  }
+
+  $("#tbl_forms").html("");
+      
+
+      var headerdata = getlabels("action,description");
+      $("#tbl_forms").html("");
+      $("#tbl_forms").dataTable({
+        "language": {
+          "url": "js/locale/datatable_fr.json"
+        },
+        "data": atbody,
+        "columns": headerdata,
+        "paging":   false,
+        "scrollY": wh + "px",
+        "scrollCollapse": true,
+        "ordering": true,
+        "info":     false,
+        "filter": false,
+        "destroy": true
+      });
+}
+
+function preview_report(fi){
+  var ff = system.openFile(myfiles[fi].path);
+}
+
+
+function delete_report(fi) {
+  delform = fi;
+  confirm_delete_forms();
+}
+
+function dlg_addform(){
+      $("#edit_forms").modal('show');
+}
+    
+function confirm_delete_forms(){
+  $("#confirm_delete_forms").modal('show');
+  return false;
+}
+  
+function delete_forms(){
+  OS.File.remove(myfiles[delform].path);
+  setTimeout(function(){load_table_forms();$("#confirm_delete_forms").modal('hide');},3000);
+  delform = null;
+  return false;
+}
+  
+function save_forms(){
+  var file = $("#frmeditforms #file").val();
+  var path = FileUtils.File(curcfg.path.local  + system.sep() +"reports" + system.sep() + cruuid);
+  var newlocation= path.path + system.sep() + system.getFileName(file);
+  OS.File.copy(file, newlocation);
+  setTimeout(function(){load_table_forms();$("#edit_forms").modal('hide');},3000);
+}
diff --git a/modules/logbook/img/logbook.png b/modules/logbook/img/logbook.png
new file mode 100644 (file)
index 0000000..a8c9914
Binary files /dev/null and b/modules/logbook/img/logbook.png differ
diff --git a/modules/logbook/js/logactivity.js b/modules/logbook/js/logactivity.js
new file mode 100644 (file)
index 0000000..9b0711d
--- /dev/null
@@ -0,0 +1,326 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+var winh= window.innerHeight -170;
+var tbllog = null;
+var crecheuuid = null;
+var initdate = new Date();
+var deluuid = "";
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre', 'Octobre','Novembre', 'Décembre'];
+var myhostname = system.hostname();
+
+function initdata(){
+       
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.logactivity");
+  //dump("cfdata:" + configdata +"\n");
+  if ((configdata) && (configdata !== '')){
+    pconfig = JSON.parse(configdata);
+  }
+  //dump("logactivity Page new loaded!\n");
+  //if (!pconfig.printlayout) {
+    pconfig.printlayout = 'book';
+    apppref.setpreference("pageconfig.logactivity",pconfig);
+  //}
+  var ccreche = appdb.dbquery("select uuid from creche LIMIT 1;");
+  crecheuuid = ccreche.sqldata[0].uuid;
+  var edith = 270;
+  loadtextareas(edith);
+  myhostname = system.hostname();
+   if (pconfig.logmonth) {
+
+    initdate = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+    $("#logmonth").val(pconfig.logmonth);
+  } else {
+    $("#logmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    
+    pconfig.logmonth=initdate.toLocaleFormat("%m.%Y");
+    apppref.setpreference("pageconfig.logactivity",pconfig);
+  }
+  var acttitle = "";
+  if (pconfig.activityuuid){
+    var chdata = appdb.dbquery("select logtitle from activitylog where uuid='"+ pconfig.activityuuid +"'");
+    if (chdata.sqldata.length > 0){
+      acttitle = chdata.sqldata[0].logtitle + " - "; 
+    }
+  }
+  //dump(JSON.stringify(pconfig) + "\n");
+  set_infoheader(acttitle + " Mois: " + amonth[parseInt(pconfig.logmonth.substring(0, 3))] + " " + pconfig.logmonth.substring(3, 8));
+  
+  $('#logmonth').on('dp.hide', function(e) {
+    set_logmonth();
+  });
+  $("#btnedit").hide();
+  $("#btnprotection").hide();
+  $("#btndelete").hide();
+  load_logactivity_table();
+}
+
+
+
+function load_logactivity_table(){
+  var mins = initdate.getTimezoneOffset() * -1;//dump("cur timezoneoffset:" + + "\n");
+  if (mins > 0){
+    mins = '+' + mins;
+  }
+  var logsql = "SELECT uuid, logtitle, strftime('%d.%m.%Y',logdatefrom) as logdatefrom, strftime('%d.%m.%Y',logdateto) as logdateto,'<span style=\"display:none\">' || lastmodified || '</span>' || strftime('%d.%m.%Y %H:%M',lastmodified,'"+mins+" minutes') as lastmodified,editor  FROM activitylog where date(logdatefrom) between date('"+initdate.toLocaleFormat("%Y-%m")+"-01') and date('"+initdate.toLocaleFormat("%Y-%m")+"-01','+1 month','-1 day') or logdateto between date('"+initdate.toLocaleFormat("%Y-%m")+"-01') and date('"+initdate.toLocaleFormat("%Y-%m")+"-01','+1 month','-1 day');";
+  var logdata = appdb.dbquery(logsql);
+  var headerdata = getlabels("activity,lastmodified,editor");
+  $("#tbl_logactivity").html("");
+
+  var tblheader = '<tr>';
+
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+
+  
+  $("#tbl_logactivity").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_logactivity").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_logactivity").append("<tbody>");
+
+  for (var i in logdata.sqldata){
+    var sel = "";
+    var row = logdata.sqldata[i];
+    if (pconfig.activityuuid && row.uuid == pconfig.activityuuid) {
+      sel = "selected";
+      load_activitylog();
+    }
+        //<td><button type="button" class="btn btn-danger" onclick="confirm_delete_logactivity(\''+ row.uuid +'\');" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button></td>
+    //!= '')?'<button class="btn btn-danger" id="btnprotection" onclick="confirm_delete_protection();" style="display: none;"><span class="glyphicon glyphicon-remove"></span></button>':'') +row.editor    
+    var tr = '<tr data-activity="'+ row.uuid+'" data-editor="'+row.editor+'" class="'+ sel+'"><td>' + row.logtitle + '<br/><i>' + row.logdatefrom +' - ' + row.logdateto + '</i></td>'+
+        '<td>'+ row.lastmodified+'</td>'+'<td>'+ row.editor +'</td>'+
+        '</tr>';
+        
+        $("#tbl_logactivity").append(tr);
+    }
+    
+  $("#tbl_logactivity").append("</tbody>");
+
+
+  tbllog = $("#tbl_logactivity").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": false,
+        "destroy": true,
+      });
+  
+
+
+  $('#tbl_logactivity').on( 'order.dt', function () {
+    pconfig.order= tbllog.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.logactivity",pconfig);
+  } );
+
+  if (pconfig.order) {
+    
+    tbllog.fnSort(pconfig.order);
+  }
+  
+  $('#tbl_logactivity tbody').on( 'click', 'tr', function () {
+      //dump("select activity\n");
+      if ( $(this).hasClass('selected') ) {
+         // $(this).removeClass('selected');
+      }
+      else {
+          //dump("select activity\n");
+         $("#btnedit").hide();
+         $("#btnprotection").hide();
+         $("#btndelete").hide();
+          tbllog.$('tr.selected').removeClass('selected');
+          $(this).addClass('selected');
+          var curactivity = $(this).attr('data-activity');
+          pconfig.activityuuid = curactivity;
+          var actlogsql = "SELECT editor FROM activitylog where uuid='"+ pconfig.activityuuid+"';";
+          var adata = appdb.dbquery(actlogsql);
+          
+          if (adata.sqldata[0].editor == '' || adata.sqldata[0].editor == myhostname){
+           $("#btnedit").show();
+           $("#btndelete").show();
+               }
+               if (adata.sqldata[0].editor != '' && adata.sqldata[0].editor != myhostname){
+                       $("#btnprotection").show();
+               }
+          //setforeigneditor($(this).attr('data-editor'));
+          apppref.setpreference("pageconfig.logactivity",pconfig);
+          load_activitylog();
+      }
+  } );
+  
+}
+
+
+
+function newlogactivity(){
+  var nuuid = appdb.generate_uuid();
+  var sql = "INSERT INTO activitylog (uuid,logtitle,logdatefrom,logdateto) VALUES ('"+nuuid+"','nouvelle Activité',date('"+initdate.toLocaleFormat('%Y-%m-%d')+"'),date('"+initdate.toLocaleFormat('%Y-%m-%d')+"'));";
+  appdb.dbexec(sql);
+  pconfig.activityuuid=nuuid;
+  apppref.setpreference("pageconfig.logactivity",pconfig);
+  edit_activitylog();
+  //load_logactivity_table();
+}
+
+function load_activitylog(){
+         $("#btnedit").hide();
+         $("#btnprotection").hide();
+         $("#btndelete").hide();
+  var actlogsql = "SELECT uuid, strftime('%d.%m.%Y',logdatefrom) as logdatefrom, strftime('%d.%m.%Y',logdateto) as logdateto, logtitle, logmessage,editor FROM activitylog where uuid='"+ pconfig.activityuuid+"';";
+  var adata = appdb.dbquery(actlogsql);
+  var inftitle = "";
+  if (adata.sqldata.length > 0){
+    $("#activityloguuid").val(adata.sqldata[0].uuid);
+    $("#activitylogmessage").html(htmlUnescape(adata.sqldata[0].logmessage))
+    $("#activitylogtitle").html(adata.sqldata[0].logtitle);
+    $("#activitylogdatefrom").html(adata.sqldata[0].logdatefrom);
+    $("#activitylogdateto").html(adata.sqldata[0].logdateto);
+    if (adata.sqldata[0].editor == '' || adata.sqldata[0].editor == myhostname){
+           $("#btnedit").show();
+           $("#btndelete").show();
+       }
+       if (adata.sqldata[0].editor != '' && adata.sqldata[0].editor != myhostname){
+           $("#btnprotection").show();
+       }
+
+    inftitle=adata.sqldata[0].logtitle;
+  }else {
+    $("#activityloguuid").val(0);
+    $("#activitylogmessage").html("");
+    $("#activitylogtitle").html('');
+    $("#activitylogdatefrom").html('');
+    $("#activitylogdateto").html('');
+  }
+  
+  set_infoheader(inftitle + " Mois: " + amonth[parseInt(pconfig.logmonth.substring(0, 3))] + " " + pconfig.logmonth.substring(3, 8));
+
+}
+
+function edit_activitylog(){
+       var actlogsql = "SELECT uuid, strftime('%d.%m.%Y',logdatefrom) as logdatefrom, strftime('%d.%m.%Y',logdateto) as logdateto, logtitle, logmessage,editor FROM activitylog where uuid='"+ pconfig.activityuuid+"';";
+       
+       var adata = appdb.dbquery(actlogsql);
+    //dump("EDIT: " + JSON.stringify(chdata) + "\n");
+    if ((adata.sqldata[0].editor != '') && (adata.sqldata[0].editor != myhostname)){
+       system.popup("cette activité est bloqué par l'editeur: " + adata.sqldata[0].editor);
+       load_logactivity_table();
+       return;
+    }
+       seteditorhost();
+    if (adata.sqldata.length > 0){
+       $('#frmeditactivitylog #loguuid').val(adata.sqldata[0].uuid);
+       $("#frmeditactivitylog #logtitle").val(adata.sqldata[0].logtitle);
+    $("#frmeditactivitylog #logdatefrom").val(adata.sqldata[0].logdatefrom);
+    $("#frmeditactivitylog #logdateto").val(adata.sqldata[0].logdateto);
+       $("#frmeditactivitylog #logmessage").summernote('reset');
+       $("#frmeditactivitylog #logmessage").summernote('code',htmlUnescape(adata.sqldata[0].logmessage));
+    }
+    $("#edit_activitylog").modal('show');
+}
+
+function save_activitylog(){
+    var lsql = "";
+    //dump($('#frmeditactivitylog #logdateto').val() + " - " + $('#frmeditactivitylog #logdatefrom').val() + "\n");
+       $("#activityloguuid").val($("#frmeditactivitylog #loguuid").val());
+       //var tmpdate = encodeparam(pconfig.logdate, 'date').replace(/'/g, '');
+       var dt = encodeparam($("#frmeditactivitylog #logdateto").val(),"date");
+       var df = encodeparam($("#frmeditactivitylog #logdatefrom").val(),"date");
+       var ltitle = encodeparam($('#frmeditactivitylog #logtitle').val(),"text");
+       var lmessage = encodeparam($('#frmeditactivitylog #logmessage').val(),"richtextarea");
+       var uid = $("#frmeditactivitylog #loguuid").val();
+       //dump(df + " - " + dt + "\n");
+       var lsql = "UPDATE activitylog set logtitle="+ltitle+
+       ",logmessage="+lmessage+
+       ",logdatefrom=date("+df+")"+
+       ",logdateto=date("+dt+") where uuid='"+uid+"';";
+       //dump(lsql + "\n");
+    appdb.dbexec(lsql);
+    removeeditorhost();
+    load_logactivity_table();
+    //load_activitylog();
+    $("#edit_activitylog").modal('hide');
+}
+
+function confirm_delete_activity() {
+
+  deluuid = $("#activityloguuid").val();
+  $('#confirm_delete_logactivity').modal('show');
+}
+
+function delete_logactivity() {
+  appdb.dbexec("delete from activitylog where uuid='"+ deluuid+"';");
+  load_logactivity_table();
+  $('#confirm_delete_logactivity').modal('hide');
+}
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.logmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.logactivity", pconfig);
+  globelreq.send_request({
+    page: 'logactivity',
+    module: 'logbook',
+    header: 'Livret des activités'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.logmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.logactivity", pconfig);
+  globelreq.send_request({
+    page: 'logactivity',
+    module: 'logbook',
+    header: 'Livret des activités'
+  }, null);
+}
+
+function set_logmonth(){
+      pconfig.logmonth =$("#logmonth").val();
+      apppref.setpreference("pageconfig.logactivity",pconfig);
+      globelreq.send_request({
+            page: 'logactivity',
+            module: 'logbook',
+            header: 'Livret des activités'
+      });
+}
+
+function seteditorhost(){
+       appdb.dbexec("UPDATE activitylog set editor=null where editor='"+myhostname+"';");
+       appdb.dbexec("UPDATE activitylog set editor='"+myhostname+"' where uuid='"+$('#activityloguuid').val()+"';");
+}
+
+function removeeditorhost(){
+       appdb.dbexec("UPDATE activitylog set editor=null where editor='"+myhostname+"';");
+}
+
+
+function confirm_delete_protection(){
+       $("#confirm_delete_protection").modal('show');
+}
+
+function delete_protection(){
+       appdb.dbexec("UPDATE activitylog set editor=null where uuid='"+$('#activityloguuid').val()+"';");
+       $('#editorhost').html('');
+       $('#btneditorhost').removeClass('btn-danger');
+       $('#btneditorhost').addClass('btn-default');
+       $('#btnprotection').hide();
+       load_logactivity_table();
+       $("#confirm_delete_protection").modal('hide');
+}
\ No newline at end of file
diff --git a/modules/logbook/js/logactivity_basic.js b/modules/logbook/js/logactivity_basic.js
new file mode 100644 (file)
index 0000000..887a475
--- /dev/null
@@ -0,0 +1,282 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+var winh= window.innerHeight -170;
+var tbllog = null;
+var crecheuuid = null;
+var initdate = new Date();
+var deluuid = "";
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre', 'Octobre','Novembre', 'Décembre'];
+var myhostname = system.hostname();
+
+function initdata(){
+       
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.logactivity");
+  //dump("cfdata:" + configdata +"\n");
+  if ((configdata) && (configdata !== '')){
+    pconfig = JSON.parse(configdata);
+  }
+  //dump("logactivity Page new loaded!\n");
+  //if (!pconfig.printlayout) {
+    pconfig.printlayout = 'book';
+    apppref.setpreference("pageconfig.logactivity",pconfig);
+  //}
+  var ccreche = appdb.dbquery("select uuid from creche LIMIT 1;");
+  crecheuuid = ccreche.sqldata[0].uuid;
+  var edith = 270;
+  loadtextareas(edith);
+  myhostname = system.hostname();
+   if (pconfig.logmonth) {
+
+    initdate = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+    $("#logmonth").val(pconfig.logmonth);
+  } else {
+    $("#logmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    
+    pconfig.logmonth=initdate.toLocaleFormat("%m.%Y");
+    apppref.setpreference("pageconfig.logactivity",pconfig);
+  }
+  var acttitle = "";
+  if (pconfig.activityuuid){
+    var chdata = appdb.dbquery("select logtitle from activitylog where uuid='"+ pconfig.activityuuid +"'");
+    if (chdata.sqldata.length > 0){
+      acttitle = chdata.sqldata[0].logtitle + " - "; 
+    }
+  }
+  //dump(JSON.stringify(pconfig) + "\n");
+  set_infoheader(acttitle + " Mois: " + amonth[parseInt(pconfig.logmonth.substring(0, 3))] + " " + pconfig.logmonth.substring(3, 8));
+  
+  $('#logmonth').on('dp.hide', function(e) {
+    set_logmonth();
+  });
+  $("#btnedit").hide();
+
+  load_logactivity_table();
+}
+
+
+
+function load_logactivity_table(){
+  var mins = initdate.getTimezoneOffset() * -1;//dump("cur timezoneoffset:" + + "\n");
+  if (mins > 0){
+    mins = '+' + mins;
+  }
+  var logsql = "SELECT uuid, logtitle, strftime('%d.%m.%Y',logdatefrom) as logdatefrom, strftime('%d.%m.%Y',logdateto) as logdateto,'<span style=\"display:none\">' || lastmodified || '</span>' || strftime('%d.%m.%Y %H:%M',lastmodified,'"+mins+" minutes') as lastmodified,editor  FROM activitylog where date(logdatefrom) between date('"+initdate.toLocaleFormat("%Y-%m")+"-01') and date('"+initdate.toLocaleFormat("%Y-%m")+"-01','+1 month','-1 day') or logdateto between date('"+initdate.toLocaleFormat("%Y-%m")+"-01') and date('"+initdate.toLocaleFormat("%Y-%m")+"-01','+1 month','-1 day');";
+  var logdata = appdb.dbquery(logsql);
+  var headerdata = getlabels("activity,lastmodified,editor");
+  $("#tbl_logactivity").html("");
+
+  var tblheader = '<tr>';
+
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+
+  
+  $("#tbl_logactivity").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_logactivity").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_logactivity").append("<tbody>");
+
+  for (var i in logdata.sqldata){
+    var sel = "";
+    var row = logdata.sqldata[i];
+    if (pconfig.activityuuid && row.uuid == pconfig.activityuuid) {
+      sel = "selected";
+      load_activitylog();
+    }
+       
+    var tr = '<tr data-activity="'+ row.uuid+'" data-editor="'+row.editor+'" class="'+ sel+'"><td>' + row.logtitle + '<br/><i>' + row.logdatefrom +' - ' + row.logdateto + '</i></td>'+
+        '<td>'+ row.lastmodified+'</td>'+'<td>'+ row.editor +'</td>'+
+        '</tr>';
+        
+        $("#tbl_logactivity").append(tr);
+    }
+    
+  $("#tbl_logactivity").append("</tbody>");
+
+
+  tbllog = $("#tbl_logactivity").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": false,
+        "destroy": true,
+      });
+  
+
+
+  $('#tbl_logactivity').on( 'order.dt', function () {
+    pconfig.order= tbllog.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.logactivity",pconfig);
+  } );
+
+  if (pconfig.order) {
+    
+    tbllog.fnSort(pconfig.order);
+  }
+  
+  $('#tbl_logactivity tbody').on( 'click', 'tr', function () {
+      //dump("select activity\n");
+      if ( $(this).hasClass('selected') ) {
+         // $(this).removeClass('selected');
+      }
+      else {
+          //dump("select activity\n");
+         $("#btnedit").hide();
+          tbllog.$('tr.selected').removeClass('selected');
+          $(this).addClass('selected');
+          var curactivity = $(this).attr('data-activity');
+          var actlogsql = "SELECT editor FROM activitylog where uuid='"+ pconfig.activityuuid+"';";
+          var adata = appdb.dbquery(actlogsql);
+          pconfig.activityuuid = curactivity;
+          if (adata.sqldata[0].editor == '' || adata.sqldata[0].editor == myhostname){
+           $("#btnedit").show();
+               }
+          //setforeigneditor($(this).attr('data-editor'));
+          apppref.setpreference("pageconfig.logactivity",pconfig);
+          load_activitylog();
+      }
+  } );
+  
+}
+
+
+
+function newlogactivity(){
+  var nuuid = appdb.generate_uuid();
+  var sql = "INSERT INTO activitylog (uuid,logtitle,logdatefrom,logdateto) VALUES ('"+nuuid+"','nouvelle Activité',date('"+initdate.toLocaleFormat('%Y-%m-%d')+"'),date('"+initdate.toLocaleFormat('%Y-%m-%d')+"'));";
+  appdb.dbexec(sql);
+  pconfig.activityuuid=nuuid;
+  apppref.setpreference("pageconfig.logactivity",pconfig);
+  edit_activitylog();
+  //load_logactivity_table();
+}
+
+function load_activitylog(){
+         $("#btnedit").hide();
+  var actlogsql = "SELECT uuid, strftime('%d.%m.%Y',logdatefrom) as logdatefrom, strftime('%d.%m.%Y',logdateto) as logdateto, logtitle, logmessage,editor FROM activitylog where uuid='"+ pconfig.activityuuid+"';";
+  var adata = appdb.dbquery(actlogsql);
+  var inftitle = "";
+  if (adata.sqldata.length > 0){
+    $("#activityloguuid").val(adata.sqldata[0].uuid);
+    $("#activitylogmessage").html(htmlUnescape(adata.sqldata[0].logmessage))
+    $("#activitylogtitle").html(adata.sqldata[0].logtitle);
+    $("#activitylogdatefrom").html(adata.sqldata[0].logdatefrom);
+    $("#activitylogdateto").html(adata.sqldata[0].logdateto);
+    if (adata.sqldata[0].editor == '' || adata.sqldata[0].editor == myhostname){
+           $("#btnedit").show();
+       }
+
+    inftitle=adata.sqldata[0].logtitle;
+  }else {
+    $("#activityloguuid").val(0);
+    $("#activitylogmessage").html("");
+    $("#activitylogtitle").html('');
+    $("#activitylogdatefrom").html('');
+    $("#activitylogdateto").html('');
+  }
+  
+  set_infoheader(inftitle + " Mois: " + amonth[parseInt(pconfig.logmonth.substring(0, 3))] + " " + pconfig.logmonth.substring(3, 8));
+
+}
+
+function edit_activitylog(){
+       var actlogsql = "SELECT uuid, strftime('%d.%m.%Y',logdatefrom) as logdatefrom, strftime('%d.%m.%Y',logdateto) as logdateto, logtitle, logmessage,editor FROM activitylog where uuid='"+ pconfig.activityuuid+"';";
+       var adata = appdb.dbquery(actlogsql);
+       if ((adata.sqldata[0].editor != '') && (adata.sqldata[0].editor != myhostname)){
+               system.popup("cette activité est bloqué par l'editeur: " + adata.sqldata[0].editor);
+               return;
+           }
+    //dump("EDIT: " + JSON.stringify(chdata) + "\n");
+    seteditorhost();
+    if (adata.sqldata.length > 0){
+       $('#frmeditactivitylog #loguuid').val(adata.sqldata[0].uuid);
+       $("#frmeditactivitylog #logtitle").val(adata.sqldata[0].logtitle);
+    $("#frmeditactivitylog #logdatefrom").val(adata.sqldata[0].logdatefrom);
+    $("#frmeditactivitylog #logdateto").val(adata.sqldata[0].logdateto);
+       $("#frmeditactivitylog #logmessage").summernote('reset');
+       $("#frmeditactivitylog #logmessage").summernote('code',htmlUnescape(adata.sqldata[0].logmessage));
+    }
+    $("#edit_activitylog").modal('show');
+}
+
+function save_activitylog(){
+    var lsql = "";
+    //dump($('#frmeditactivitylog #logdateto').val() + " - " + $('#frmeditactivitylog #logdatefrom').val() + "\n");
+       $("#activityloguuid").val($("#frmeditactivitylog #loguuid").val());
+       //var tmpdate = encodeparam(pconfig.logdate, 'date').replace(/'/g, '');
+       var dt = encodeparam($("#frmeditactivitylog #logdateto").val(),"date");
+       var df = encodeparam($("#frmeditactivitylog #logdatefrom").val(),"date");
+       var ltitle = encodeparam($('#frmeditactivitylog #logtitle').val(),"text");
+       var lmessage = encodeparam($('#frmeditactivitylog #logmessage').val(),"richtextarea");
+       var uid = $("#frmeditactivitylog #loguuid").val();
+       //dump(df + " - " + dt + "\n");
+       var lsql = "UPDATE activitylog set logtitle="+ltitle+
+       ",logmessage="+lmessage+
+       ",logdatefrom=date("+df+")"+
+       ",logdateto=date("+dt+") where uuid='"+uid+"';";
+       //dump(lsql + "\n");
+    appdb.dbexec(lsql);
+    removeeditorhost();
+    load_logactivity_table();
+    //load_activitylog();
+    $("#edit_activitylog").modal('hide');
+}
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.logmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.logactivity", pconfig);
+  globelreq.send_request({
+    page: 'logactivity_basic',
+    module: 'logbook',
+    header: 'Livret des activités'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.logmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.logactivity", pconfig);
+  globelreq.send_request({
+    page: 'logactivity_basic',
+    module: 'logbook',
+    header: 'Livret des activités'
+  }, null);
+}
+
+function set_logmonth(){
+      pconfig.logmonth =$("#logmonth").val();
+      apppref.setpreference("pageconfig.logactivity",pconfig);
+      globelreq.send_request({
+            page: 'logactivity_basic',
+            module: 'logbook',
+            header: 'Livret des activités'
+      });
+}
+
+function seteditorhost(){
+       appdb.dbexec("UPDATE activitylog set editor=null where editor='"+myhostname+"';");
+       appdb.dbexec("UPDATE activitylog set editor='"+myhostname+"' where uuid='"+$('#loguuid').val()+"';");
+}
+
+function removeeditorhost(){
+       appdb.dbexec("UPDATE activitylog set editor=null where editor='"+myhostname+"';");
+}
diff --git a/modules/logbook/js/logchild.js b/modules/logbook/js/logchild.js
new file mode 100644 (file)
index 0000000..73f3284
--- /dev/null
@@ -0,0 +1,359 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+var winh= window.innerHeight -170;
+var tbllog = null;
+var crecheuuid = null;
+var initdate = new Date();
+var myhostname = system.hostname();
+
+function initdata(){
+
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.logchild");
+
+  if ((configdata) && (configdata !== '')){
+    pconfig = JSON.parse(configdata);
+  }
+  //dump(JSON.stringify(pconfig) + "\n");
+  //if (!pconfig.printlayout) {
+    pconfig.printlayout = 'logchild';
+    apppref.setpreference("pageconfig.logchild",pconfig);
+  //}
+  var ccreche = appdb.dbquery("select uuid from creche LIMIT 1;");
+  crecheuuid = ccreche.sqldata[0].uuid;
+
+  loadtextareas(winh);
+  $("#logdate").on("dp.hide", function () {
+    set_logdate();
+  });
+  myhostname = system.hostname();
+  if (pconfig.logdate) {
+
+    initdate = new Date(encodeparam(pconfig.logdate, 'date').replace(/'/g, ''));
+    $("#logdate").val(pconfig.logdate);
+  } else {
+    $("#logdate").val(initdate.toLocaleFormat('%d.%m.%Y'));
+    pconfig.logdate = initdate.toLocaleFormat('%d.%m.%Y');
+  }
+  var childname = "";
+  if (pconfig.childuuid){
+    var chdata = appdb.dbquery("select prename || ' ' || surname AS childname from childs where uuid='"+ pconfig.childuuid +"'");
+    if (chdata.sqldata.length > 0){
+      childname = chdata.sqldata[0].childname + " - "; 
+    }
+  }
+  set_infoheader(childname + " Date du: " + pconfig.logdate);
+  load_logchild_table();
+  
+}
+
+
+
+
+
+function load_logchild_table(){
+  var mins = initdate.getTimezoneOffset() * -1;//dump("cur timezoneoffset:" + + "\n");
+  if (mins > 0){
+    mins = '+' + mins;
+  }
+  var sqlchilds = "select distinct(ch.uuid) as uuid, ch.prename || ' ' || ch.surname AS childname, ch.checkservicenumber,gr.grpname,'<span style=\"display:none\">' || cl.lastmodified || '</span>' || strftime('%d.%m.%Y %H:%M',cl.lastmodified,'"+mins+" minutes') as lastmodified,cl.editor as editor from childs ch left join planning pl on (ch.uuid=pl.childuuid) left join groups gr on (pl.groupuuid=gr.uuid) left join childslog cl on (ch.uuid=cl.childuuid and logdate=date('"+initdate.toLocaleFormat('%Y-%m-%d')+"')) where date('"+ initdate.toLocaleFormat('%Y-%m-%d')+"') between pl.datebegin and pl.dateend order by childname;"; 
+  //dump("SQLChilds:" + sqlchilds + "\n");
+  var logdata = appdb.dbquery(sqlchilds);  
+  //dump("load childs Log!\n");
+  var headerdata = getlabels("childname,grpname,lastmodified,editor");
+
+  $("#tbl_logchild").html("");
+  //if (tbllog) {tbllog.destroy();}
+  var tblheader = '<tr>';
+
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+    if ((pconfig.hidden_columns) && (pconfig.hidden_columns.indexOf(headerdata[h].keyname) != -1)) {
+      if (headerdata[h].class.indexOf('colhidden') == -1) {
+        headerdata[h].class += " colhidden"; 
+      }
+    }else {
+      headerdata[h].class.replace("colhidden","");
+    }
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+
+  
+  $("#tbl_logchild").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_logchild").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_logchild").append("<tbody>");
+  //var curchld = "";
+
+  for (var i in logdata.sqldata){
+    var row = logdata.sqldata[i];
+    var sel = "";
+    if (pconfig.childuuid && row.uuid == pconfig.childuuid) {
+      sel = "selected";
+      load_childlog();
+    }
+        var tr = '<tr data-child="'+ row.uuid+'" class="'+ sel +'">';
+        //tr += '<td class="noprint"></td>';
+        tr += '<td>' + row.childname +'<br/>('+ row.checkservicenumber+ ')'+ "</td>";
+        tr += '<td>' + row.grpname + "</td>";
+        tr += '<td>' + row.lastmodified + "</td>";
+        tr += '<td>' + row.editor + "</td>";
+        tr += "</tr>";
+        $("#tbl_logchild").append(tr);
+    }
+    
+  $("#tbl_logchild").append("</tbody>");
+
+
+  tbllog = $("#tbl_logchild").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": false,
+        "destroy": true,
+      });
+  
+//  $('#tbl_logchild').on( 'search.dt', function () {
+//    pconfig.filter = tbllog.api().search();
+//    apppref.setpreference("pageconfig.logchild",pconfig);
+//  } );
+
+  $('#tbl_logchild').on( 'order.dt', function () {
+    pconfig.order= tbllog.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.logchild",pconfig);
+  } );
+//  if (pconfig.filter) {
+//    tbllog.fnFilter(pconfig.filter);
+//  }
+  if (pconfig.order) {
+  
+    tbllog.fnSort(pconfig.order);
+  }
+  
+  
+
+$('#tbl_logchild tbody').on( 'click', 'tr', function () {
+        if ( $(this).hasClass('selected') ) {
+           // $(this).removeClass('selected');
+        }
+        else {
+            tbllog.$('tr.selected').removeClass('selected');
+            $(this).addClass('selected');
+            var curchild = $(this).attr('data-child');
+            pconfig.childuuid = curchild;
+            var chsel = appdb.dbquery("select lastmodified,editor from childslog where childuuid='"+pconfig.childuuid+"' and logdate=date('"+initdate.toLocaleFormat('%Y-%m-%d')+"');");
+            //dump(JSON.stringify(chsel) + "\n");
+            $("#btnadd").hide();
+           $("#btnedit").hide();
+           $("#btnprotection").hide();
+            if (chsel.sqldata.length > 0){
+               if (chsel.sqldata[0].editor == '' || chsel.sqldata[0].editor == myhostname){
+                   $("#btnedit").show();
+               }
+               if (chsel.sqldata[0].editor != '' && chsel.sqldata[0].editor != myhostname){
+                   $("#btnprotection").show();
+               }
+               
+               
+               load_childlog();        
+            } else {
+               $("#childlogmessage").html("");
+               $("#btnadd").show();
+            }
+            apppref.setpreference("pageconfig.logchild",pconfig);
+            
+        }
+    } );
+}
+
+function load_childlog(){
+  //$("#childlogmessage").summernote('disable');
+  var tmpdate = encodeparam(pconfig.logdate, 'date').replace(/'/g, '');
+  var childlogsql = "select uuid,logmessage,childuuid,lastmodified,editor from childslog where logdate=date('" + tmpdate + "') and childuuid='"+ pconfig.childuuid+"';";
+  var chdata = appdb.dbquery(childlogsql);
+  $("#btnadd").hide();
+  $("#btnedit").hide();
+  $("#btnprotection").hide();
+  //dump(childlogsql + " -> " +JSON.stringify(chdata) + "\n");
+  $("#childlogmessage").html("");
+  if (chdata.sqldata.length > 0){
+      if (chdata.sqldata[0].editor == '' || chdata.sqldata[0].editor == myhostname){
+           $("#btnedit").show();
+       }
+       if (chdata.sqldata[0].editor != '' && chdata.sqldata[0].editor != myhostname){
+           $("#btnprotection").show();
+       }
+    //dump("load data from db\n");
+    $("#childloguuid").val(chdata.sqldata[0].uuid);
+    $("#childlogmessage").html(htmlUnescape(chdata.sqldata[0].logmessage));
+  }else {
+       //$("#childlogmessage").html("");
+      $("#btnadd").show();
+  }
+  var childname = "";
+  if (pconfig.childuuid){
+    var chxdata = appdb.dbquery("select prename || ' ' || surname AS childname from childs where uuid='"+ pconfig.childuuid +"'");
+    if (chxdata.sqldata.length > 0){
+      childname = chxdata.sqldata[0].childname + " - "; 
+    }
+  }
+  set_infoheader(childname + " Date du: " + pconfig.logdate);
+}
+
+
+function edit_childlog(){
+    var childlogsql = "select uuid,logmessage,childuuid,editor from childslog where uuid='"+$("#childloguuid").val()+"';";
+    var chdata = appdb.dbquery(childlogsql);
+    if ((chdata.sqldata[0].editor != '') && (chdata.sqldata[0].editor != myhostname)){
+       system.popup("cette fiche d'évaluation est bloqué par l'editeur: " + chdata.sqldata[0].editor);
+       load_logchild_table()();
+       return;
+    }
+    //dump("EDIT: " + JSON.stringify(chdata) + "\n");
+    seteditorhost();
+    if (chdata.sqldata.length > 0){
+       //$('#frmeditchildlog #logmessage').summernote('reset');
+       $('#frmeditchildlog #uuid').val(chdata.sqldata[0].uuid);
+       $('#frmeditchildlog #childuuid').val(chdata.sqldata[0].childuuid);
+       $("#frmeditchildlog #logmessage").summernote('reset');
+       $("#frmeditchildlog #logmessage").summernote('code',htmlUnescape(chdata.sqldata[0].logmessage));
+       //$('#frmeditchildlog #logmessage').val(htmlUnescape(chdata.sqldata[0].logmessage));
+    }
+    $("#edit_childlog").modal('show');
+}
+
+function save_childlog(){
+    var lsql = "";
+    if ($('#frmeditchildlog #uuid').val() == '0'){
+       //new childlog
+       var nuuid = appdb.generate_uuid();
+       $("#childloguuid").val(nuuid);
+       var tmpdate = encodeparam(pconfig.logdate, 'date').replace(/'/g, '');
+       lsql = "INSERT INTO childslog (uuid,childuuid,logmessage,logdate) VALUES ('"+nuuid+"','"+pconfig.childuuid+"'," + encodeparam($('#frmeditchildlog #logmessage').val(),"richtextarea")+",date('"+tmpdate+"'));";
+    }else {
+       //update childlog;
+       lsql = "UPDATE childslog set logmessage="+encodeparam($('#frmeditchildlog #logmessage').val(),"richtextarea")+" where uuid='"+$("#frmeditchildlog  #uuid").val()+"';";
+    }
+    appdb.dbexec(lsql);
+    removeeditorhost();
+    load_logchild_table();
+    load_childlog();
+    $("#edit_childlog").modal('hide');
+}
+//$('#childlogmessage').on('summernote.focus', function() {
+//     seteditorhost();
+//     $("#childlogmessage").summernote('enable');
+//     });
+//
+//
+//$('#childlogmessage').on('summernote.blur', function() {
+//  //dump("New Data\n");
+//  var lsql = "";
+//  if ($("#childloguuid").val() != "0"){
+//    //UPDATE
+//    lsql = "UPDATE childslog set logmessage="+encodeparam($('#childlogmessage').val(),"richtextarea")+" where uuid='"+$("#childloguuid").val()+"';";
+//    //dump("UPDATE:" + lsql + "\n");
+//  } else {
+//    //INSERT
+//    var nuuid = appdb.generate_uuid();
+//    $("#childloguuid").val(nuuid);
+//    var tmpdate = encodeparam(pconfig.logdate, 'date').replace(/'/g, '');
+//    lsql = "INSERT INTO childslog (uuid,childuuid,logmessage,logdate) VALUES ('"+nuuid+"','"+pconfig.childuuid+"'," + encodeparam($('#childlogmessage').val(),"richtextarea")+",date('"+tmpdate+"'));";
+//    //dump("INSERT:" + lsql + "\n");
+//  }
+//  appdb.dbexec(lsql);
+//  removeeditorhost();
+//  //load_logchild_table();
+//  
+//});
+
+function addchildlog(){
+    var nuuid = appdb.generate_uuid();
+    var tmpdate = encodeparam(pconfig.logdate, 'date').replace(/'/g, '');
+    $("#childloguuid").val(nuuid);
+    var lsql = "INSERT INTO childslog (uuid,childuuid,logmessage,logdate) VALUES ('"+nuuid+"','"+pconfig.childuuid+"',null,date('"+tmpdate+"'));";
+    appdb.dbexec(lsql);
+    edit_childlog();
+
+}
+
+
+function set_logdate(){
+      pconfig.logdate =$("#logdate").val();
+      //dump("set_logdate:" + JSON.stringify(pconfig) + "\n");
+      apppref.setpreference("pageconfig.logchild",pconfig);
+      removeeditorhost();
+      globelreq.send_request({
+            page: 'logchild',
+            module: 'logbook',
+            data: null,
+            header: 'Livret d\'évaluation des enfants par date'
+      });
+}
+
+
+function onnextdate() {
+  var tmpmonth = new Date(encodeparam(pconfig.logdate, 'date').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth(), tmpmonth.getDate()+1);
+  pconfig.logdate = nmonth.toLocaleFormat('%d.%m.%Y');
+  apppref.setpreference("pageconfig.logchild", pconfig);
+  removeeditorhost();
+  globelreq.send_request({
+    page: 'logchild',
+    module: 'logbook',
+    header: 'Livret d\'évaluation des enfants par date'
+  }, null);
+}
+
+function onpreviousdate() {
+  var tmpmonth = new Date(encodeparam(pconfig.logdate, 'date').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth(), tmpmonth.getDate()-1);
+  pconfig.logdate = nmonth.toLocaleFormat('%d.%m.%Y');
+  apppref.setpreference("pageconfig.logchild", pconfig);
+  removeeditorhost();
+  globelreq.send_request({
+    page: 'logchild',
+    module: 'logbook',
+    header: 'Livret d\'évaluation des enfants par date'
+  }, null);
+}
+
+function seteditorhost(){
+       //dump('BLOCK editor '+ myhostname +"->"+ $('#childloguuid').val() +"\n");
+       appdb.dbexec("UPDATE childslog set editor=null where editor='"+myhostname+"';");
+       appdb.dbexec("UPDATE childslog set editor='"+myhostname+"' where uuid='"+$('#childloguuid').val()+"';");
+       //load_logchild_table();
+}
+//
+function removeeditorhost(){
+       appdb.dbexec("UPDATE childslog set editor=null where editor='"+myhostname+"';");
+       //load_logchild_table();
+}
+
+
+
+function confirm_delete_protection(){
+       $("#confirm_delete_protection").modal('show');
+}
+
+function delete_protection(){
+       appdb.dbexec("UPDATE childslog set editor=null where uuid='"+$('#childloguuid').val()+"';");
+       $('#editorhost').html('');
+       $('#btneditorhost').removeClass('btn-danger');
+       $('#btneditorhost').addClass('btn-default');
+       $('#btnprotection').hide();
+       load_logchild_table();
+       $("#confirm_delete_protection").modal('hide');
+}
diff --git a/modules/logbook/js/logcominterne.js b/modules/logbook/js/logcominterne.js
new file mode 100644 (file)
index 0000000..c814574
--- /dev/null
@@ -0,0 +1,328 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+var winh= window.innerHeight -170;
+var tbllog = null;
+var crecheuuid = null;
+var initdate = new Date();
+var xcurdate = new Date();
+var deluuid = "";
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre', 'Octobre','Novembre', 'Décembre'];
+var myhostname = system.hostname();
+
+function initdata(){
+
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.logcominterne");
+  //dump("cfdata:" + configdata +"\n");
+  if ((configdata) && (configdata !== '')){
+    pconfig = JSON.parse(configdata);
+  }
+
+  pconfig.printlayout = 'book';
+  apppref.setpreference("pageconfig.logcominterne",pconfig);
+
+  var ccreche = appdb.dbquery("select uuid from creche LIMIT 1;");
+  crecheuuid = ccreche.sqldata[0].uuid;
+  var edith = 270;
+  myhostname = system.hostname();
+  //dump("Current Hostname:" + myhostname + "\n");
+  loadtextareas(edith);
+   if (pconfig.logmonth) {
+
+    initdate = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+    $("#logmonth").val(pconfig.logmonth);
+  } else {
+    $("#logmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    
+    pconfig.logmonth=initdate.toLocaleFormat("%m.%Y");
+    apppref.setpreference("pageconfig.logcominterne",pconfig);
+  }
+  var acttitle = "";
+  if (pconfig.activityuuid){
+    var chdata = appdb.dbquery("select logtitle from messagelog where uuid='"+ pconfig.messageuuid +"'");
+    if (chdata.sqldata.length > 0){
+      acttitle = chdata.sqldata[0].logtitle + " - "; 
+    }
+  }
+  if (xcurdate.toLocaleFormat("%m.%Y") == pconfig.logmonth){
+         $('#btnaddmessage').show();
+  } else{
+         $('#btnaddmessage').hide();
+  }
+  set_infoheader(acttitle + " Mois: " + amonth[parseInt(pconfig.logmonth.substring(0, 3))] + " " + pconfig.logmonth.substring(3, 8));
+  $('#logmonth').on('dp.hide', function(e) {
+    set_logmonth();
+  });
+  $("#btnedit").hide();
+  $("#btnprotection").hide();
+  $("#btndelete").hide();
+  load_logmessage_table();
+  
+}
+
+function seteditorhost(){
+       //dump('BLOCK editor '+ myhostname +"->"+ $('#loguuid').val() +"\n");
+       appdb.dbexec("UPDATE messagelog set editor=null where editor='"+myhostname+"';");
+       appdb.dbexec("UPDATE messagelog set editor='"+myhostname+"' where uuid='"+$('#cominterneloguuid').val()+"';");
+       load_logmessage_table();
+}
+
+function removeeditorhost(){
+       appdb.dbexec("UPDATE messagelog set editor=null where editor='"+myhostname+"';");
+       load_logmessage_table();
+}
+
+
+function load_logmessage_table(){
+  var mins = initdate.getTimezoneOffset() * -1;//dump("cur timezoneoffset:" + + "\n");
+  if (mins > 0){
+    mins = '+' + mins;
+  }
+  var logsql = "SELECT uuid, logtitle,'<span style=\"display:none\">' || logdate || '</span>' || strftime('%d.%m.%Y',logdate) as logdate,'<span style=\"display:none\">' || lastmodified || '</span>' || strftime('%d.%m.%Y %H:%M',lastmodified,'"+mins+" minutes') as lastmodified,editor  FROM messagelog where date(logdate) between date('"+initdate.toLocaleFormat("%Y-%m")+"-01') and date('"+initdate.toLocaleFormat("%Y-%m")+"-01','+1 month','-1 day');";
+  var logdata = appdb.dbquery(logsql);
+  var headerdata = getlabels("subject,daydate,lastmodified,editor");
+  $("#tbl_logcominterne").html("");
+  //tbllog = null;
+  var tblheader = '<tr>';
+
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+
+  
+  $("#tbl_logcominterne").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_logcominterne").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_logcominterne").append("<tbody>");
+
+  for (var i in logdata.sqldata){
+    var sel = "";
+    var row = logdata.sqldata[i];
+    if (pconfig.messageuuid && row.uuid == pconfig.messageuuid) {
+      sel = "selected";
+      load_messagelog();
+    }
+    
+        var tr = '<tr data-message="'+ row.uuid+'" class="'+ sel+'"><td>' + row.logtitle + '</td>'+
+        '<td>' + row.logdate + '</td>'+
+        '<td>'+ row.lastmodified+'</td>'+
+        '<td>'+ row.editor +'</td>'+
+        '</tr>';
+        
+        $("#tbl_logcominterne").append(tr);
+    }
+    
+  $("#tbl_logcominterne").append("</tbody>");
+
+
+  tbllog = $("#tbl_logcominterne").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": false,
+        "destroy": true,
+      });
+  
+
+
+  $('#tbl_logcominterne').on( 'order.dt', function () {
+    pconfig.order= tbllog.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.logcominterne",pconfig);
+  } );
+
+  if (pconfig.order) {
+  
+    tbllog.fnSort(pconfig.order);
+  }
+  
+  
+
+$('#tbl_logcominterne tbody').on( 'click', 'tr', function () {
+        //dump("select activity\n");
+        if ( $(this).hasClass('selected') ) {
+           // $(this).removeClass('selected');
+        }
+        else {
+               $("#btnedit").hide();
+         $("#btnprotection").hide();
+         $("#btndelete").hide();
+            tbllog.$('tr.selected').removeClass('selected');
+            $(this).addClass('selected');
+            var curmessage = $(this).attr('data-message');
+            //setforeigneditor($(this).attr('data-editor'));
+            pconfig.messageuuid = curmessage;
+            var cilogsql = "SELECT editor FROM messagelog where uuid='"+ pconfig.messageuuid+"';";
+            var cdata = appdb.dbquery(cilogsql);
+            if (cdata.sqldata[0].editor == '' || cdata.sqldata[0].editor == myhostname){
+                   $("#btnedit").show();
+                   $("#btndelete").show();
+                       }
+                       if (cdata.sqldata[0].editor != '' && cdata.sqldata[0].editor != myhostname){
+                               $("#btnprotection").show();
+                       }
+            apppref.setpreference("pageconfig.logcominterne",pconfig);
+            load_messagelog();
+        }
+    } );
+}
+
+function newlogmessage(){
+  var nuuid = appdb.generate_uuid();
+  var sql = "INSERT INTO messagelog (uuid,logtitle,logdate) VALUES ('"+nuuid+"','nouveau message',date('"+xcurdate.toLocaleFormat('%Y-%m-%d')+"'));";
+  //dump(sql + "\n");
+  appdb.dbexec(sql);
+  pconfig.messageuuid=nuuid;
+  apppref.setpreference("pageconfig.logcominterne",pconfig);
+  edit_cominternelog();
+}
+
+function edit_cominternelog(){
+       var actlogsql = "SELECT uuid, strftime('%d.%m.%Y',logdate) as logdate,  logtitle, logmessage,editor FROM messagelog where uuid='"+ pconfig.messageuuid+"';";
+       var adata = appdb.dbquery(actlogsql);
+    //dump("EDIT: " + JSON.stringify(chdata) + "\n");
+       if ((adata.sqldata[0].editor != '') && (adata.sqldata[0].editor != myhostname)){
+       system.popup("cette communication est bloqué par l'editeur: " + adata.sqldata[0].editor);
+       load_logmessage_table();
+       return;
+       }
+    seteditorhost();
+    if (adata.sqldata.length > 0){
+       $('#frmeditcominterne #loguuid').val(adata.sqldata[0].uuid);
+       $("#frmeditcominterne #logtitle").val(adata.sqldata[0].logtitle);
+    $("#frmeditcominterne #logdate").val(adata.sqldata[0].logdate);
+       $("#frmeditcominterne #logmessage").summernote('reset');
+       $("#frmeditcominterne #logmessage").summernote('code',htmlUnescape(adata.sqldata[0].logmessage));
+    }
+    $("#edit_cominternelog").modal('show');
+}
+
+function load_messagelog(){
+       $("#btnedit").hide();
+         $("#btnprotection").hide();
+         $("#btndelete").hide();
+  var actlogsql = "SELECT uuid, strftime('%d.%m.%Y',logdate) as logdate,  logtitle, logmessage,editor FROM messagelog where uuid='"+ pconfig.messageuuid+"';";
+  var adata = appdb.dbquery(actlogsql);
+  //dump(childlogsql + " -> " +JSON.stringify(chdata) + "\n");
+  var inftitle = "";
+  if (adata.sqldata.length > 0){
+    //dump("load data from db\n");
+    $("#cominterneloguuid").val(adata.sqldata[0].uuid);
+    $("#cominternelogmessage").html(htmlUnescape(adata.sqldata[0].logmessage));
+    $("#cominternelogtitle").html(adata.sqldata[0].logtitle);
+    $("#cominternelogdate").html(adata.sqldata[0].logdate);
+    if (adata.sqldata[0].editor == '' || adata.sqldata[0].editor == myhostname){
+           $("#btnedit").show();
+           $("#btndelete").show();
+       }
+       if (adata.sqldata[0].editor != '' && adata.sqldata[0].editor != myhostname){
+           $("#btnprotection").show();
+       }
+    inftitle=adata.sqldata[0].logtitle;
+  }else {
+    //dump("set data to empty fields\n");
+         $("#cominterneloguuid").val('0');
+           $("#cominternelogmessage").html("");
+           $("#cominternelogtitle").html("");
+           $("#cominternelogdate").html("");
+       
+  }
+  
+  set_infoheader(inftitle + " Mois: " + amonth[parseInt(pconfig.logmonth.substring(0, 3))] + " " + pconfig.logmonth.substring(3, 8));
+
+}
+
+function save_cominternelog(){
+       var ld = encodeparam($("#frmeditcominterne #logdate").val(),"date");
+       $("#cominterneloguuid").val($("#frmeditcominterne #loguuid").val());
+       //var tmpdate = encodeparam(pconfig.logdate, 'date').replace(/'/g, '');
+       var lsql = "UPDATE messagelog set logtitle="+encodeparam($('#frmeditcominterne #logtitle').val(),"text")+
+       ",logmessage="+encodeparam($('#frmeditcominterne #logmessage').val(),"richtextarea")+
+       ",logdate=date("+ld+") where uuid='"+$("#frmeditcominterne #loguuid").val()+"';";
+       //dump("SV cominterne: "+ lsql + "\n");
+    appdb.dbexec(lsql);
+    removeeditorhost();
+    $("#edit_cominternelog").modal('hide');
+    //load_logmessage_table();
+    load_messagelog();
+    
+}
+
+function confirm_delete_cominterne() {
+
+  deluuid = $("#cominterneloguuid").val();
+  $('#confirm_delete_logcominterne').modal('show');
+}
+
+function delete_logcominterne() {
+  appdb.dbexec("delete from messagelog where uuid='"+ deluuid+"';");
+  load_logmessage_table();
+  $('#confirm_delete_logcominterne').modal('hide');
+}
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.logmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.logcominterne", pconfig);
+  removeeditorhost();
+  //dump("Next Month:" +JSON.stringify(pconfig) + "\n");
+  globelreq.send_request({
+    page: 'logcominterne',
+    module: 'logbook',
+    header: 'Communication interne'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.logmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.logcominterne", pconfig);
+  removeeditorhost();
+  //dump("previous Month:" +JSON.stringify(pconfig) + "\n");
+  globelreq.send_request({
+    page: 'logcominterne',
+    module: 'logbook',
+    header: 'Communication interne'
+  }, null);
+}
+
+function set_logmonth(){
+      pconfig.logmonth =$("#logmonth").val();
+      apppref.setpreference("pageconfig.logcominterne",pconfig);
+      removeeditorhost();
+      //dump("Set Month:" +JSON.stringify(pconfig) + "\n");
+      globelreq.send_request({
+            page: 'logcominterne',
+            module: 'logbook',
+            header: 'Communication interne'
+      });
+}
+
+function confirm_delete_protection(){
+       $("#confirm_delete_protection").modal('show');
+}
+
+function delete_protection(){
+       //dump("DELPROT: UPDATE messagelog set editor=null where uuid='"+$('#loguuid').val()+"';\n");
+       appdb.dbexec("UPDATE messagelog set editor=null where uuid='"+$('#cominterneloguuid').val()+"';");
+       $('#editorhost').html('');
+       $('#btneditorhost').removeClass('btn-danger');
+       $('#btneditorhost').addClass('btn-default');
+       $('#btnprotection').hide();
+       load_logmessage_table();
+       $("#confirm_delete_protection").modal('hide');
+}
\ No newline at end of file
diff --git a/modules/logbook/js/logcominterne_basic.js b/modules/logbook/js/logcominterne_basic.js
new file mode 100644 (file)
index 0000000..27d3135
--- /dev/null
@@ -0,0 +1,296 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+var winh= window.innerHeight -170;
+var tbllog = null;
+var crecheuuid = null;
+var initdate = new Date();
+var xcurdate = new Date();
+var deluuid = "";
+var amonth = ['', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre', 'Octobre','Novembre', 'Décembre'];
+var myhostname = system.hostname();
+
+function initdata(){
+
+  load_helpers();
+  var configdata = apppref.getpreference("pageconfig.logcominterne");
+  //dump("cfdata:" + configdata +"\n");
+  if ((configdata) && (configdata !== '')){
+    pconfig = JSON.parse(configdata);
+  }
+
+  pconfig.printlayout = 'book';
+  apppref.setpreference("pageconfig.logcominterne",pconfig);
+
+  var ccreche = appdb.dbquery("select uuid from creche LIMIT 1;");
+  crecheuuid = ccreche.sqldata[0].uuid;
+  var edith = 270;
+  myhostname = system.hostname();
+  //dump("Current Hostname:" + myhostname + "\n");
+  loadtextareas(edith);
+   if (pconfig.logmonth) {
+
+    initdate = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+    $("#logmonth").val(pconfig.logmonth);
+  } else {
+    $("#logmonth").val(initdate.toLocaleFormat('%m.%Y'));
+    
+    pconfig.logmonth=initdate.toLocaleFormat("%m.%Y");
+    apppref.setpreference("pageconfig.logcominterne",pconfig);
+  }
+  var acttitle = "";
+  if (pconfig.activityuuid){
+    var chdata = appdb.dbquery("select logtitle from messagelog where uuid='"+ pconfig.messageuuid +"'");
+    if (chdata.sqldata.length > 0){
+      acttitle = chdata.sqldata[0].logtitle + " - "; 
+    }
+  }
+  if (xcurdate.toLocaleFormat("%m.%Y") == pconfig.logmonth){
+         $('#btnaddmessage').show();
+  } else{
+         $('#btnaddmessage').hide();
+  }
+  set_infoheader(acttitle + " Mois: " + amonth[parseInt(pconfig.logmonth.substring(0, 3))] + " " + pconfig.logmonth.substring(3, 8));
+  $('#logmonth').on('dp.hide', function(e) {
+    set_logmonth();
+  });
+  $("#btnedit").hide();
+  load_logmessage_table();
+  
+}
+
+function seteditorhost(){
+       //dump('BLOCK editor '+ myhostname +"->"+ $('#loguuid').val() +"\n");
+       appdb.dbexec("UPDATE messagelog set editor=null where editor='"+myhostname+"';");
+       appdb.dbexec("UPDATE messagelog set editor='"+myhostname+"' where uuid='"+$('#loguuid').val()+"';");
+       load_logmessage_table();
+}
+
+function removeeditorhost(){
+       appdb.dbexec("UPDATE messagelog set editor=null where editor='"+myhostname+"';");
+       load_logmessage_table();
+}
+
+
+function load_logmessage_table(){
+  var mins = initdate.getTimezoneOffset() * -1;//dump("cur timezoneoffset:" + + "\n");
+  if (mins > 0){
+    mins = '+' + mins;
+  }
+  var logsql = "SELECT uuid, logtitle,'<span style=\"display:none\">' || logdate || '</span>' || strftime('%d.%m.%Y',logdate) as logdate,'<span style=\"display:none\">' || lastmodified || '</span>' || strftime('%d.%m.%Y %H:%M',lastmodified,'"+mins+" minutes') as lastmodified,editor  FROM messagelog where date(logdate) between date('"+initdate.toLocaleFormat("%Y-%m")+"-01') and date('"+initdate.toLocaleFormat("%Y-%m")+"-01','+1 month','-1 day');";
+  var logdata = appdb.dbquery(logsql);
+  var headerdata = getlabels("subject,daydate,lastmodified,editor");
+  $("#tbl_logcominterne").html("");
+  //tbllog = null;
+  var tblheader = '<tr>';
+
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+
+  
+  $("#tbl_logcominterne").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_logcominterne").append("<tfoot>" + tblheader + "</tfoot>");
+  $("#tbl_logcominterne").append("<tbody>");
+
+  for (var i in logdata.sqldata){
+    var sel = "";
+    var row = logdata.sqldata[i];
+    if (pconfig.messageuuid && row.uuid == pconfig.messageuuid) {
+      sel = "selected";
+      load_messagelog();
+    }
+    
+        var tr = '<tr data-message="'+ row.uuid+'" class="'+ sel+'"><td>' + row.logtitle + '</td>'+
+        '<td>' + row.logdate + '</td>'+
+        '<td>'+ row.lastmodified+'</td>'+
+        '<td>'+ row.editor +'</td>'+
+        '</tr>';
+        
+        $("#tbl_logcominterne").append(tr);
+    }
+    
+  $("#tbl_logcominterne").append("</tbody>");
+
+
+  tbllog = $("#tbl_logcominterne").dataTable({
+        "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+        "paging":   false,
+        "ordering": true,
+        "bAutoWidth": false,
+        "scrollY": winh + "px",
+        "scrollCollapse": true,
+        "info":     false,
+        "filter": false,
+        "destroy": true,
+      });
+  
+
+
+  $('#tbl_logcominterne').on( 'order.dt', function () {
+    pconfig.order= tbllog.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.logcominterne",pconfig);
+  } );
+
+  if (pconfig.order) {
+  
+    tbllog.fnSort(pconfig.order);
+  }
+  
+  
+
+$('#tbl_logcominterne tbody').on( 'click', 'tr', function () {
+        //dump("select activity\n");
+        if ( $(this).hasClass('selected') ) {
+           // $(this).removeClass('selected');
+        }
+        else {
+               $("#btnedit").hide();
+            tbllog.$('tr.selected').removeClass('selected');
+            $(this).addClass('selected');
+            var curmessage = $(this).attr('data-message');
+            //setforeigneditor($(this).attr('data-editor'));
+            pconfig.messageuuid = curmessage;
+            var cilogsql = "SELECT editor FROM messagelog where uuid='"+ pconfig.messageuuid+"';";
+            var cdata = appdb.dbquery(cilogsql);
+            if (cdata.sqldata[0].editor == '' || cdata.sqldata[0].editor == myhostname){
+                   $("#btnedit").show();
+
+                       }
+
+            apppref.setpreference("pageconfig.logcominterne",pconfig);
+            load_messagelog();
+        }
+    } );
+}
+
+function newlogmessage(){
+  var nuuid = appdb.generate_uuid();
+  var sql = "INSERT INTO messagelog (uuid,logtitle,logdate) VALUES ('"+nuuid+"','nouveau message',date('"+xcurdate.toLocaleFormat('%Y-%m-%d')+"'));";
+  //dump(sql + "\n");
+  appdb.dbexec(sql);
+  pconfig.messageuuid=nuuid;
+  apppref.setpreference("pageconfig.logcominterne",pconfig);
+  edit_cominternelog();
+}
+
+function edit_cominternelog(){
+       var actlogsql = "SELECT uuid, strftime('%d.%m.%Y',logdate) as logdate,  logtitle, logmessage,editor FROM messagelog where uuid='"+ pconfig.messageuuid+"';";
+       var adata = appdb.dbquery(actlogsql);
+       if ((adata.sqldata[0].editor != '') && (adata.sqldata[0].editor != myhostname)){
+           system.popup("cette communication est bloqué par l'editeur: " + adata.sqldata[0].editor);
+           load_logmessage_table();
+           return;
+       }
+    //dump("EDIT: " + JSON.stringify(chdata) + "\n");
+    seteditorhost();
+    if (adata.sqldata.length > 0){
+       $('#frmeditcominterne #loguuid').val(adata.sqldata[0].uuid);
+       $("#frmeditcominterne #logtitle").val(adata.sqldata[0].logtitle);
+    $("#frmeditcominterne #logdate").val(adata.sqldata[0].logdate);
+       $("#frmeditcominterne #logmessage").summernote('reset');
+       $("#frmeditcominterne #logmessage").summernote('code',htmlUnescape(adata.sqldata[0].logmessage));
+    }
+    $("#edit_cominternelog").modal('show');
+}
+
+function load_messagelog(){
+       $("#btnedit").hide();
+         $("#btnprotection").hide();
+         $("#btndelete").hide();
+  var actlogsql = "SELECT uuid, strftime('%d.%m.%Y',logdate) as logdate,  logtitle, logmessage,editor FROM messagelog where uuid='"+ pconfig.messageuuid+"';";
+  var adata = appdb.dbquery(actlogsql);
+  //dump(childlogsql + " -> " +JSON.stringify(chdata) + "\n");
+  var inftitle = "";
+  if (adata.sqldata.length > 0){
+    //dump("load data from db\n");
+    $("#cominterneloguuid").val(adata.sqldata[0].uuid);
+    $("#cominternelogmessage").html(htmlUnescape(adata.sqldata[0].logmessage));
+    $("#cominternelogtitle").html(adata.sqldata[0].logtitle);
+    $("#cominternelogdate").html(adata.sqldata[0].logdate);
+    if (adata.sqldata[0].editor == '' || adata.sqldata[0].editor == myhostname){
+           $("#btnedit").show();
+           $("#btndelete").show();
+       }
+       if (adata.sqldata[0].editor != '' && adata.sqldata[0].editor != myhostname){
+           $("#btnprotection").show();
+       }
+    inftitle=adata.sqldata[0].logtitle;
+  }else {
+    //dump("set data to empty fields\n");
+         $("#cominterneloguuid").val('0');
+           $("#cominternelogmessage").html("");
+           $("#cominternelogtitle").html("");
+           $("#cominternelogdate").html("");
+       
+  }
+  
+  set_infoheader(inftitle + " Mois: " + amonth[parseInt(pconfig.logmonth.substring(0, 3))] + " " + pconfig.logmonth.substring(3, 8));
+
+}
+
+function save_cominternelog(){
+       var ld = encodeparam($("#frmeditcominterne #logdate").val(),"date");
+       $("#cominterneloguuid").val($("#frmeditcominterne #loguuid").val());
+       //var tmpdate = encodeparam(pconfig.logdate, 'date').replace(/'/g, '');
+       var lsql = "UPDATE messagelog set logtitle="+encodeparam($('#frmeditcominterne #logtitle').val(),"text")+
+       ",logmessage="+encodeparam($('#frmeditcominterne #logmessage').val(),"richtextarea")+
+       ",logdate=date("+ld+") where uuid='"+$("#frmeditcominterne #loguuid").val()+"';";
+       //dump("SV cominterne: "+ lsql + "\n");
+    appdb.dbexec(lsql);
+    removeeditorhost();
+    $("#edit_cominternelog").modal('hide');
+    //load_logmessage_table();
+    load_messagelog();
+    
+}
+
+function onnextmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() + 1, tmpmonth.getDate());
+  pconfig.logmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.logcominterne", pconfig);
+  removeeditorhost();
+  //dump("Next Month:" +JSON.stringify(pconfig) + "\n");
+  globelreq.send_request({
+    page: 'logcominterne_basic',
+    module: 'logbook',
+    header: 'Communication interne'
+  }, null);
+}
+
+function onpreviousmonth() {
+  var tmpmonth = new Date(encodeparam(pconfig.logmonth, 'month').replace(/'/g, ''));
+  var nmonth = new Date(tmpmonth.getFullYear(), tmpmonth.getMonth() - 1, tmpmonth.getDate());
+  pconfig.logmonth = nmonth.toLocaleFormat('%m.%Y');
+  apppref.setpreference("pageconfig.logcominterne", pconfig);
+  removeeditorhost();
+  //dump("previous Month:" +JSON.stringify(pconfig) + "\n");
+  globelreq.send_request({
+    page: 'logcominterne_basic',
+    module: 'logbook',
+    header: 'Communication interne'
+  }, null);
+}
+
+function set_logmonth(){
+      pconfig.logmonth =$("#logmonth").val();
+      apppref.setpreference("pageconfig.logcominterne",pconfig);
+      removeeditorhost();
+      //dump("Set Month:" +JSON.stringify(pconfig) + "\n");
+      globelreq.send_request({
+            page: 'logcominterne_basic',
+            module: 'logbook',
+            header: 'Communication interne'
+      });
+}
+
diff --git a/modules/logbook/js/logstaff.js b/modules/logbook/js/logstaff.js
new file mode 100644 (file)
index 0000000..5b33b73
--- /dev/null
@@ -0,0 +1 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
\ No newline at end of file
diff --git a/modules/logbook/logactivity.html b/modules/logbook/logactivity.html
new file mode 100644 (file)
index 0000000..41fbda3
--- /dev/null
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Livret des activités</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/summernote.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: 15px;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="container-fluid"  style="padding-top: 5px;">
+    <div class="form-inline" >
+      <div class="input-group month btn-group">
+            <span class="input-group-addon">du mois:</span>
+            <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="logmonth">
+            <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+          </div>
+            <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+            <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+      <button class="btn btn-primary" onclick="newlogactivity();"><span class="glyphicon glyphicon-plus"></span> Activité</button>
+    
+   </div>
+   <div>
+    <table style="height: calc(100vh - 100px); width: 100%; ">
+      <tbody>
+        <tr>
+          <td style="width: 550px; vertical-align: top;"><table class="display dataTable cell-border" style="width: 100%;" id="tbl_logactivity" role="grid"></table></td>
+          <td style="vertical-align: top; margin-left: 30px;">
+            <div class="form-inline" style="margin-top: 15px; margin-bottom: 10px; margin-left: 10px;">
+                               <button class="btn btn-success" onclick="edit_activitylog();" id="btnedit"><span class="glyphicon glyphicon-pencil"></span> Ã©diter</button>
+                       <button class="btn btn-danger" onclick="confirm_delete_activity();" id="btndelete"><span class="glyphicon glyphicon-remove"></span> supprimer</button>
+                       <button class="btn btn-warning" onclick="confirm_delete_protection();" id="btnprotection"><span class="glyphicon glyphicon-remove"></span> Protection</button>
+               </div>
+               <input type="hidden" id="activityloguuid" value="0">
+               
+                <div><strong>Titre:</strong> <span  id="activitylogtitle"></span></div>
+                       <div><strong>Date: </strong><span id="activitylogdatefrom"></span> <strong>au</strong> <span id="activitylogdateto"></span></div>
+               
+          <div style="width: 100%; height: calc(100vh - 200px); background-color: #fff; border: 1px solid grey; border-radius: 10px; display: block; overflow-y: auto; padding: 5px; margin: 5px;" id="activitylogmessage"></div></td>
+        </tr>
+      </tbody>
+    </table>
+   </div>
+   <div class="modal fade" id="confirm_delete_logactivity">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Activité</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette activité?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_logactivity();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+  </div>
+  <div class="modal fade" id="confirm_delete_protection">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Protection</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette protection?<br>
+                (possibilité de perdre des données pas sauvegardées)
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_protection();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+  </div>
+  <div class="modal fade" id="edit_activitylog">
+          <div class="modal-dialog"  style="width: 1000px; min-width: 1000px;">
+            <div class="modal-content" >
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer activité</h4>
+              </div>
+              <div class="modal-body" style=" height: 80vh; max-height: height: 80vh; ">
+
+                <div id="frmeditactivitylog">
+                  <input type="hidden" id="loguuid" value="0">
+          <div class="row form-inline" style="margin-left: 30px;">
+                          <label for="logtitle">Titre</label> <input type="text" value="" style="width: 80%;" id="logtitle" class="form-control">
+          </div>
+          <div class="row" style="margin-left: 30px;">
+             <div class="form-inline" id="date-container">
+                          <label for="logdatefrom" style="width: 200px;">Date début / fin</label>
+                          <div id="dt_logdatefrom" class="input-group date">
+                            <input type="date" class="form-control" value="00.00.0000" limits="0" placeholder="dd.mm.yyyy"  id="logdatefrom"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        
+                          <div id="dt_logdateto" class="input-group date">
+                            <input type="date" class="form-control" value="00.00.0000" limits="0" placeholder="dd.mm.yyyy" id="logdateto"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        </div>
+
+          </div>
+          <textarea class="summernote" type="text" style="width: 100%;" id="logmessage">
+</textarea>
+                                       
+                </div>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" onclick="removeeditorhost();" class="btn">Annuler</button> <button onclick="save_activitylog();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+          </div>
+   </div>
+   
+  
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="../../web/js/summernote.min.js" type="text/javascript"></script>
+  <script src="../../web/js/lang/summernote-fr-FR.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/logactivity.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/logbook/logactivity_basic.html b/modules/logbook/logactivity_basic.html
new file mode 100644 (file)
index 0000000..b68930b
--- /dev/null
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Livret des activités</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/summernote.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: 15px;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="container-fluid"  style="padding-top: 5px;">
+    <div class="form-inline" >
+      <div class="input-group month btn-group">
+            <span class="input-group-addon">du mois:</span>
+            <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="logmonth">
+            <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+          </div>
+            <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+            <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+      <button class="btn btn-primary" onclick="newlogactivity();"><span class="glyphicon glyphicon-plus"></span> Activité</button>
+     
+   </div>
+   <div>
+    <table style="height: calc(100vh - 100px); width: 100%; ">
+      <tbody>
+        <tr>
+          <td style="width: 550px; vertical-align: top;"><table class="display dataTable cell-border" style="width: 100%;" id="tbl_logactivity" role="grid"></table></td>
+          <td style="vertical-align: top; margin-left: 30px;">
+            <div class="form-inline" style="margin-top: 15px; margin-bottom: 10px; margin-left: 10px;">
+                               <button class="btn btn-success" onclick="edit_activitylog();" id="btnedit"><span class="glyphicon glyphicon-pencil"></span> Ã©diter</button>
+                       </div>
+               <input type="hidden" id="activityloguuid" value="0">
+               
+                <div><strong>Titre:</strong> <span  id="activitylogtitle"></span></div>
+                       <div><strong>Date début: </strong><span id="activitylogdatefrom"></span> <strong>au</strong> <span id="activitylogdateto"></span></div>
+               
+          <div style="width: 100%; height: calc(100vh - 200px); background-color: #fff; border: 1px solid grey; border-radius: 10px; display: block; overflow-y: auto; padding: 5px; margin: 5px;" id="activitylogmessage"></div></td>
+        </tr>
+      </tbody>
+    </table>
+   </div>
+  <div class="modal fade" id="edit_activitylog">
+          <div class="modal-dialog"  style="width: 1000px; min-width: 1000px;">
+            <div class="modal-content" >
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer activité</h4>
+              </div>
+              <div class="modal-body" style=" height: 80vh; max-height: height: 80vh; ">
+
+                <div id="frmeditactivitylog">
+                  <input type="hidden" id="loguuid" value="0">
+          <div class="row form-inline" style="margin-left: 30px;">
+                          <label for="logtitle">Titre</label> <input type="text" value="" style="width: 80%;" id="logtitle" class="form-control">
+          </div>
+          <div class="row" style="margin-left: 30px;">
+             <div class="form-inline" id="date-container">
+                          <label for="logdatefrom" style="width: 200px;">Date début / fin</label>
+                          <div id="dt_logdatefrom" class="input-group date">
+                            <input type="date" class="form-control" value="00.00.0000" limits="0" placeholder="dd.mm.yyyy"  id="logdatefrom"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        
+                          <div id="dt_logdateto" class="input-group date">
+                            <input type="date" class="form-control" value="00.00.0000" limits="0" placeholder="dd.mm.yyyy" id="logdateto"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        </div>
+
+          </div>
+          <textarea class="summernote" type="text"  style="width: 100%;" id="logmessage">
+</textarea>
+                                       
+                </div>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" onclick="removeeditorhost();" class="btn">Annuler</button> <button onclick="save_activitylog();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+          </div>
+   </div>
+   </div>
+   
+  
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="../../web/js/summernote.min.js" type="text/javascript"></script>
+  <script src="../../web/js/lang/summernote-fr-FR.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/logactivity.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/logbook/logbook.xul b/modules/logbook/logbook.xul
new file mode 100644 (file)
index 0000000..559a5b5
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_logbook" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton type="menu" class="btn btn-default" id="tbb_logbook" insertafter="tbb_forms" label="Livrets de bord" image="modules/logbook/img/logbook.png" orient="vertical">
+    <menupopup class="tlbpopup" style="text-align: left;">
+      
+      <label value="Enfants" style="font-weight: bold;"/>
+      <menuitem label="Livret d'évaluation par date" oncommand="navigation.load_appview('logchild','logbook',null,'Livret d Ã©valuation des enfants par date');"  id="mnulogchild"/>
+      <menuseparator />
+      <label value="Crèche" style="font-weight: bold;"/>
+      <menuitem label="Livret des activités" oncommand="navigation.load_appview('logactivity','logbook',null,'Livret des activités');"  id="mnulogactivity"/>
+      <menuitem label="Communication Interne" oncommand="navigation.load_appview('logcominterne','logbook',null,'Communication Interne');"  id="mnulogmessage"/>
+      
+    </menupopup>
+    </toolbarbutton>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/logbook/logbook_basic.xul b/modules/logbook/logbook_basic.xul
new file mode 100644 (file)
index 0000000..802382e
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_logbook" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton type="menu" class="btn btn-default" id="tbb_logbook" insertafter="tbb_forms" label="Livrets de bord" image="modules/logbook/img/logbook.png" orient="vertical">
+    <menupopup class="tlbpopup" style="text-align: left;">
+      
+      <label value="Enfants" style="font-weight: bold;"/>
+      <menuitem label="Livret d'évaluation par date" oncommand="navigation.load_appview('logchild','logbook',null,'Livret d Ã©valuation des enfants par date');"  id="mnulogchild"/>
+      <menuseparator />
+      <label value="Crèche" style="font-weight: bold;"/>
+      <menuitem label="Livret des activités" oncommand="navigation.load_appview('logactivity_basic','logbook',null,'Livret des activités');"  id="mnulogactivity"/>
+      <menuitem label="Communication Interne" oncommand="navigation.load_appview('logcominterne_basic','logbook',null,'Communication Interne');"  id="mnulogmessage"/>
+    </menupopup>
+    </toolbarbutton>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/logbook/logchild.html b/modules/logbook/logchild.html
new file mode 100644 (file)
index 0000000..b8c316b
--- /dev/null
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Livret d'évaluation des enfants</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/summernote.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: 15px;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="container-fluid"  style="padding-top: 5px;">
+    <div class="form-inline" >
+      <div class="input-group date btn-group">
+            <span class="input-group-addon">date du:</span>
+            <input type="date" class="form-control" value="" placeholder="dd.mm.yyyy" style="width: 120px;" id="logdate" onchange="set_logdate();">
+            <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+          </div>
+          <button class="btn btn-primary" onclick="onpreviousdate();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+          <button class="btn btn-primary" onclick="onnextdate();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+          <!--<button class="btn btn-default" id="btneditorhost">Editeur: <span id="editorhost"></span></button>
+          <button class="btn btn-danger" id="btnprotection" onclick="confirm_delete_protection();" style="display: none;"><span class="glyphicon glyphicon-remove"></span> protection</button>-->
+   </div>
+   <div>
+    <table style="height: calc(100vh - 100px); width: 100%;">
+      <tbody>
+        <tr>
+          <td style="width: 600px; vertical-align: top; padding-top: 0px;"><table class="display dataTable cell-border" style="width: 100%;" id="tbl_logchild" role="grid"></table></td>
+          <td style="vertical-align: top; padding-top: 0px; ">
+               <input type="hidden" id="childloguuid" value="0">
+               <div class="form-inline" style="margin-top: 15px; margin-bottom: 10px; margin-left: 10px;">
+                       <button class="btn btn-primary" onclick="addchildlog();" id="btnadd"><span class="glyphicon glyphicon-plus"></span> ajouter</button>
+                       <button class="btn btn-success" onclick="edit_childlog();" id="btnedit"><span class="glyphicon glyphicon-pencil"></span> Ã©diter</button>
+                       <button class="btn btn-warning" onclick="confirm_delete_protection();" id="btnprotection"><span class="glyphicon glyphicon-remove"></span> Protection</button>
+               </div>
+               <div   style="width: 100%; height: calc(100vh - 150px); background-color: #fff; border: 1px solid grey; border-radius: 10px; display: block; overflow-y: auto; padding: 5px; margin: 5px;" id="childlogmessage"></div>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    
+   </div>
+   <div class="modal fade" id="confirm_delete_protection">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Protection</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette protection?<br>
+                (possibilité de perdre des données pas sauvegardées)
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_protection();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+  </div>
+  <div class="modal fade" id="edit_childlog">
+          <div class="modal-dialog"  style="width: 1000px; min-width: 1000px;">
+            <div class="modal-content" >
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer livret d'évaluation</h4>
+              </div>
+              <div class="modal-body" style=" height: 700px; max-height: 700px ">
+
+                <div id="frmeditchildlog">
+                  <input type="hidden" value="0" id="uuid" />
+                  <input type="hidden" value="0" id="childuuid" />
+                  <textarea style="height: 600px;" class="summernote" type="text"  id="logmessage"></textarea>
+                                       
+                </div>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" onclick="removeeditorhost();" class="btn">Annuler</button> <button onclick="save_childlog();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+          </div>
+   </div>
+  
+  
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="../../web/js/summernote.min.js" type="text/javascript"></script>
+  <script src="../../web/js/lang/summernote-fr-FR.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/logchild.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/logbook/logcominterne.html b/modules/logbook/logcominterne.html
new file mode 100644 (file)
index 0000000..79ddc8d
--- /dev/null
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Communication interne</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/summernote.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: 15px;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="container-fluid"  style="padding-top: 5px;">
+    <div class="form-inline" >
+      <div class="input-group month btn-group">
+            <span class="input-group-addon">du mois:</span>
+            <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="logmonth">
+            <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+          </div>
+            <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+            <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+      <button class="btn btn-primary" onclick="newlogmessage();" id="btnaddmessage"><span class="glyphicon glyphicon-plus"></span> Message</button>
+         <!--<button class="btn btn-default" id="btneditorhost">Editeur: <span id="editorhost"></span></button>
+         <button class="btn btn-danger" id="btnprotection" onclick="confirm_delete_protection();" style="display: none;"><span class="glyphicon glyphicon-remove"></span> protection</button>-->
+   </div>
+   <div>
+    <table style="height: calc(100vh - 100px); width: 100%; ">
+      <tbody>
+        <tr>
+          <td style="width: 550px; vertical-align: top;"><table class="display dataTable cell-border" style="width: 100%;" id="tbl_logcominterne" role="grid"></table></td>
+          <td style="vertical-align: top; margin-left: 30px;">
+               <div class="form-inline" style="margin-top: 15px; margin-bottom: 10px; margin-left: 10px;">
+                               <button class="btn btn-success" onclick="edit_cominternelog();" id="btnedit"><span class="glyphicon glyphicon-pencil"></span> Ã©diter</button>
+                       <button class="btn btn-danger" onclick="confirm_delete_cominterne();" id="btndelete"><span class="glyphicon glyphicon-remove"></span> supprimer</button>
+                       <button class="btn btn-warning" onclick="confirm_delete_protection();" id="btnprotection"><span class="glyphicon glyphicon-remove"></span> Protection</button>
+               </div>
+               <input type="hidden" id="cominterneloguuid" value="0">
+               <div><strong>Titre:</strong> <span  id="cominternelogtitle"></span></div>
+                       <div><strong>Date: </strong><span id="cominternelogdate"></span></div>
+               
+          <div style="width: 100%; height: calc(100vh - 200px); background-color: #fff; border: 1px solid grey; border-radius: 10px; display: block; overflow-y: auto; padding: 5px; margin: 5px;" id="cominternelogmessage"></div>
+          
+          </td>
+        </tr>
+      </tbody>
+    </table>
+   </div>
+   <div class="modal fade" id="confirm_delete_logcominterne">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Message</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce message?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_logcominterne();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+  </div>
+  <div class="modal fade" id="confirm_delete_protection">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Protection</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette protection?<br>
+                (possibilité de perdre des données pas sauvegardées)
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_protection();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+  </div>
+  <div class="modal fade" id="edit_cominternelog">
+          <div class="modal-dialog"  style="width: 1000px; min-width: 1000px;">
+            <div class="modal-content" >
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer communication</h4>
+              </div>
+              <div class="modal-body" style=" height: 80vh; max-height: height: 80vh; ">
+
+                <div id="frmeditcominterne">
+                  <input type="hidden" id="loguuid" value="0">
+          <div class="row form-inline" style="margin-left: 30px;">
+                          <label for="logtitle">Titre</label> <input type="text" value=""  style="width: 80%;" id="logtitle" class="form-control">
+          </div>
+          <div class="row" style="margin-left: 30px;">
+             <div class="form-inline" id="date-container">
+                          <label for="logtimestamp" style="width: 100px;">Date</label>
+                          <div id="dt_logdate" class="input-group date">
+                            <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="logdate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        
+                          
+                        </div>
+
+          </div>
+          <textarea class="summernote"  style="width: 100%;" id="logmessage">
+</textarea>
+                                       
+                </div>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" onclick="removeeditorhost();" class="btn">Annuler</button> <button onclick="save_cominternelog();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+          </div>
+   </div>
+   
+  
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="../../web/js/summernote.min.js" type="text/javascript"></script>
+  <script src="../../web/js/lang/summernote-fr-FR.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/logcominterne.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/logbook/logcominterne_basic.html b/modules/logbook/logcominterne_basic.html
new file mode 100644 (file)
index 0000000..0d82130
--- /dev/null
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Communication interne</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/bootstrap-multiselect.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/summernote.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: 15px;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="container-fluid"  style="padding-top: 5px;">
+    <div class="form-inline" >
+      <div class="input-group month btn-group">
+            <span class="input-group-addon">du mois:</span>
+            <input type="date" class="form-control" value="" placeholder="mm.yyyy" style="width: 80px;" id="logmonth">
+            <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+          </div>
+            <button class="btn btn-primary" onclick="onpreviousmonth();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+            <button class="btn btn-primary" onclick="onnextmonth();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+      <button class="btn btn-primary" onclick="newlogmessage();" id="btnaddmessage"><span class="glyphicon glyphicon-plus"></span> Message</button>
+         <!--<button class="btn btn-default" id="btneditorhost">Editeur: <span id="editorhost"></span></button>
+         <button class="btn btn-danger" id="btnprotection" onclick="confirm_delete_protection();" style="display: none;"><span class="glyphicon glyphicon-remove"></span> protection</button>-->
+   </div>
+   <div>
+    <table style="height: calc(100vh - 100px); width: 100%; ">
+      <tbody>
+        <tr>
+          <td style="width: 550px; vertical-align: top;"><table class="display dataTable cell-border" style="width: 100%;" id="tbl_logcominterne" role="grid"></table></td>
+          <td style="vertical-align: top; margin-left: 30px;">
+               <div class="form-inline" style="margin-top: 15px; margin-bottom: 10px; margin-left: 10px;">
+                               <button class="btn btn-success" onclick="edit_cominternelog();" id="btnedit"><span class="glyphicon glyphicon-pencil"></span> Ã©diter</button>
+                       </div>
+               <input type="hidden" id="cominterneloguuid" value="0">
+               <div><strong>Titre:</strong> <span  id="cominternelogtitle"></span></div>
+                       <div><strong>Date: </strong><span id="cominternelogdate"></span></div>
+               
+          <div style="width: 100%; height: calc(100vh - 200px); background-color: #fff; border: 1px solid grey; border-radius: 10px; display: block; overflow-y: auto; padding: 5px; margin: 5px;" id="cominternelogmessage"></div>
+          
+          </td>
+        </tr>
+      </tbody>
+    </table>
+   </div>
+   <div class="modal fade" id="confirm_delete_logcominterne">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Message</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce message?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_logcominterne();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+  </div>
+  <div class="modal fade" id="confirm_delete_protection">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Protection</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette protection?<br>
+                (possibilité de perdre des données pas sauvegardées)
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_protection();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+  </div>
+  <div class="modal fade" id="edit_cominternelog">
+          <div class="modal-dialog"  style="width: 1000px; min-width: 1000px;">
+            <div class="modal-content" >
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer communication</h4>
+              </div>
+              <div class="modal-body" style=" height: 80vh; max-height: height: 80vh; ">
+
+                <div id="frmeditcominterne">
+                  <input type="hidden" id="loguuid" value="0">
+          <div class="row form-inline" style="margin-left: 30px;">
+                          <label for="logtitle">Titre</label> <input type="text" value=""  style="width: 80%;" id="logtitle" class="form-control">
+          </div>
+          <div class="row" style="margin-left: 30px;">
+             <div class="form-inline" id="date-container">
+                          <label for="logtimestamp" style="width: 100px;">Date</label>
+                          <div id="dt_logdate" class="input-group date">
+                            <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="logdate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        
+                          
+                        </div>
+
+          </div>
+          <textarea class="summernote"  style="width: 100%;" id="logmessage">
+</textarea>
+                                       
+                </div>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" onclick="removeeditorhost();" class="btn">Annuler</button> <button onclick="save_cominternelog();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+          </div>
+   </div>
+   
+  
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="../../web/js/summernote.min.js" type="text/javascript"></script>
+  <script src="../../web/js/lang/summernote-fr-FR.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/logcominterne.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
diff --git a/modules/logbook/logstaff.html b/modules/logbook/logstaff.html
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/presences/dailypresences.html b/modules/presences/dailypresences.html
new file mode 100644 (file)
index 0000000..30fdcc6
--- /dev/null
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  
+  <title>Présences par jour</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <!--<link href="css/glyphicons-bootstrap.css" rel="stylesheet">-->
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/glyphicons.css" rel="stylesheet">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: -86px;
+    }
+    .tab-pane {
+      margin-top: 0px;
+      padding-top: 0px;
+    }
+  </style>
+</head>
+
+<body>
+    <div class="container-fluid" style="padding-top: 5px;">
+    <!--<span class="pagehead" id="pagehead">Présences</span>&nbsp;-->
+    <div class="btn-group" style=" margin-bottom: 10px;">
+  
+  <div class="input-group date btn-group">
+    <span class="input-group-addon">Date du:</span>
+    <input type="date" class="form-control" value="" style="width: 100px;" limits="1" placeholder="dd.mm.yyyy" id="presday"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+  </div>
+  <button class="btn btn-primary" onclick="onpreviousday();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+  <button class="btn btn-primary" onclick="onnextday();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+  <!--<button title="imprimer" onclick="print_report();" id="btnprintreport" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-print" aria-hidden="true"></span> </button>-->
+  <button onclick="setalltopresent();" class="btn btn-success" id="btnreload"><span class="glyphicons glyphicons-check" aria-hidden="true"></span></button>
+  <div class="dropdown btn-group">
+  <button class="btn btn-primary dropdown-toggle" type="button" id="mnulegend" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+   Légende
+    <span class="caret"></span>
+  </button>
+  <ul class="dropdown-menu" aria-labelledby="mnulegend">
+    <li><button class="btn btn-default" style="width: 100%;"><span class="glyphicons glyphicons-circle-question-mark" aria-hidden="true"></span> non configuré</button></li>
+    <li><button class="btn btn-success" style="width: 100%;"><span class="glyphicons glyphicons-ok" aria-hidden="true"></span> présent</button></li>
+    <li><button class="btn btn-warning" style="width: 100%;"><span class="glyphicons glyphicons-stethoscope" aria-hidden="true"></span> malade</button></li>
+    <li><button class="btn btn-danger" style="width: 100%;"><span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span> absence non verifé</button></li>
+    <li><button class="btn btn-absent2" style="width: 100%;"><span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span> absence verifié</button></li>
+    <li><button class="btn btn-info" style="width: 100%;"><span class="glyphicon glyphicon-plane" aria-hidden="true"></span> vacances</button></li>
+    <li><button class="btn btn-primary" style="width: 100%;"><span class="glyphicons glyphicons-circle-question-mark" aria-hidden="true"></span> essaie</button></li>
+  </ul>
+</div>
+    </div>
+    <div>
+       <table class="display dataTable cell-border" style="width: 100%;" id="tbldailypresences" role="grid"><thead></thead><tfoot></tfoot><tbody></tbody></table>  
+    </div>
+    
+  <!--  <div class="tabbable">
+            <ul class="nav nav-tabs" id="tabgrouphead">
+              
+              
+            </ul>
+
+            <div class="tab-content" id="tabgroupbody">
+              
+            </div>
+  </div>-->
+  
+  </div>
+  <div class="modal fade" id="dlg_addplanning">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Ajouter planification pour un jour</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body" style="overflow: hidden;">
+                <form id="planning">
+                  <input type="hidden" id="childuuid" value="" />
+                  <input type="hidden" id="plandate" value="" />
+                  <input type="hidden" id="planday" value="" />
+                  <div class="row">
+                    <div class="col-md-3">
+                    <span class="glyphicon glyphicon-time" aria-hidden="true"></span> de:
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timebegin">
+                    </div>
+                      </div>
+                      <div class="col-md-3">
+                    <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Ã :
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timeend">
+                    </div></div>
+                      <div class="col-md-3">
+                      déjeuner:<br/>
+                    <input type="checkbox" id="lunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+                  </div>
+                  </div>
+                </form>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_planning();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+  
+  <div class="modal fade" id="dlg_changegrp">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Changer le groupe de l'enfant</h4>
+              </div>
+
+              <div class="modal-body" style=" height: 350px; max-height: 350px ">
+                <form id="planning">
+                  <input type="hidden" id="childuuid" value="" />
+                  <input type="hidden" id="curgrp" value="" />
+                  <div class="row col-md-12">
+                    <label for="datebegin">à partir de </label>
+
+                    <div id="dt_dategrpchange" class="input-group date" style="z-index: 300;">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="dategrpchange"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                    <label for="groupuuid">Groupe</label>
+
+                    <div class="input-group">
+                      <select id="groupuuid">
+                        
+                      </select>
+                    </div>
+                    
+                  </div>
+                  <div class="row col-md-12" id="curgrpdata">
+                    
+                  </div>
+                </form>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_grpchange();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/dailypresences.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/presences/img/presence.png b/modules/presences/img/presence.png
new file mode 100644 (file)
index 0000000..545d90b
Binary files /dev/null and b/modules/presences/img/presence.png differ
diff --git a/modules/presences/js/dailypresences.js b/modules/presences/js/dailypresences.js
new file mode 100644 (file)
index 0000000..6efc6ce
--- /dev/null
@@ -0,0 +1,400 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {
+      "groupuuid": null,
+      "presday": null
+};
+var weekdates = null;
+var initdate = new Date();
+var cdate = initdate.toLocaleFormat('%Y-%m-%d');
+var wh= window.innerHeight -190;
+//var groups = {}; 
+var tableheadssql = "";
+var weekday = initdate.getDay();
+
+var presencedropdown = '';
+
+var wdays = ["sun","mon","tue","wed","thu","fri","sat"];
+
+var presences = {
+      "btn-default": 0,
+      "btn-success": 1,
+      "btn-warning": 2,
+      "btn-danger": 3,
+      "btn-absent2": 31,
+      "btn-info": 4,
+      "btn-primary": 5
+};
+
+var presenceids = {
+       0: {
+                       text: "default",
+            class: "btn-default",
+            icon: '<span class="glyphicons glyphicons-circle-question-mark"></span>'
+            
+      },
+      1: {
+               text: "success",
+            class: "btn-success",
+            icon: '<span class="glyphicons glyphicons-check"></span>'
+            
+      },
+      2: {
+               text: "warning",
+            class: "btn-warning",
+            icon: '<span class="glyphicons glyphicons-stethoscope"></span>'
+      },
+      3: {
+               text: "danger",
+            class: "btn-danger",
+            icon: '<span class="glyphicons glyphicons-eye-close"></span>'
+      },
+      31: {
+            text: "absent2",
+            class: "btn-absent2",
+            icon: '<span class="glyphicons glyphicons-eye-close"></span>'
+      },
+      4: {
+               text: "info",
+            class: "btn-info",
+            icon: '<span class="glyphicon glyphicon-plane"></span>'
+      },
+      5: {
+               text: "primary",
+            class: "btn-primary",
+            icon: '<span class="glyphicons glyphicons-circle-ok"></span>'
+      }
+};
+
+function initdata() {
+      load_helpers();
+      $('input').on("click", function () {
+            $(this).select();
+          });
+      var pdata = apppref.getpreference("pageconfig.dailypresences");
+      if (pdata !== '') {
+        pconfig = JSON.parse(pdata);
+      }
+        pconfig.printlayout = 'multilist';
+        apppref.setpreference("pageconfig.dailypresences",pconfig);
+
+      if (pconfig.presday) {
+            initdate = new Date(encodeparam(pconfig.presday, 'date').replace(/'/g, ''));
+
+            $("#presday").val(pconfig.presday);
+      }else{
+            $("#presday").val(initdate.toLocaleFormat('%d.%m.%Y'));
+      }
+      $("#presday").on("dp.hide", function () {
+        change_day();
+      });
+      set_infoheader("");
+      cdate = initdate.toLocaleFormat('%Y-%m-%d');
+      var daygroupsql = "SELECT ch.uuid as childuuid, ch.prename || ' ' || ch.surname AS childname, "+
+            "gr.uuid as groupuuid, gr.grpname as grpname, " +
+            "pr.begintime1 as begintime1, pr.endtime1 as endtime1, pr.begintime2 as begintime2, pr.endtime2 as endtime2, pr.status as status, pr.lunch as lunch, "+
+            wdays[weekday]+"timebegin as plantimebegin, "+wdays[weekday]+"timeend as plantimeend, "+
+            wdays[weekday]+"timebegin2 as plantimebegin2, "+wdays[weekday]+"timeend2 as plantimeend2, "+wdays[weekday]+"lunch as planlunch , "+
+            "case when pr.childuuid is not null then 'upd' else 'ins' end as ddltype "+
+            "from childs ch "+
+            "LEFT JOIN presence pr ON (pr.childuuid = ch.uuid and pr.daydate = date('"+cdate+"')) "+
+            "left join planning pl on (pl.childuuid = ch.uuid and date('"+cdate+"') between pl.datebegin and pl.dateend ) "+
+            "LEFT JOIN groups gr ON (pl.groupuuid = gr.uuid) "+
+            " where ch.entrydate <= date('"+cdate+"') and ch.leavedate >= date('"+cdate+"')";
+       set_infoheader("Date du " + initdate.toLocaleFormat("%d.%m.%Y"));
+       //jsdump("DAY GROUP SQL");
+      //jsdump(daygroupsql);
+      var dpresdata = appdb.dbquery(daygroupsql);
+            var headerdata = getlabels("act,grpname,childname,effectiftime,status,plannedtime");
+
+            var headdata = "";
+            for (var h=0;h<headerdata.length;h++){
+              if (h !== 0) {
+                headdata += '<th>'+ headerdata[h].title +'</th>';
+              }
+            }
+            $("#tbldailypresences > thead").append('<tr>' + headdata+ '</tr>');
+            var dpdata = dpresdata.sqldata;
+            
+            for (var b in dpdata){
+              var row = dpdata[b];
+              var rdata = '<td>'+ row.grpname +'</td><td>'+row.childname+'</td>';
+   
+              rdata += '<td style="min-width: 350px;max-width: 350px;"><div class="form-inline" id="frm_'+ row.childuuid +'" style="white-space: nowrap; '+ ((row.status != 0 && row.status != 1 && row.status != 5)?"display: none":"")+'">'+
+            '<span class="glyphicon glyphicon-time" aria-hidden="true"></span> de: '+
+                    '<div class="input-group bootstrap-timepicker time" style="width: 70px;"> ' +
+                      '<input type="text" class="form-control timepicker dailypresence" placeholder="00:00" value="'+ row.begintime1+'" id="txtbegintime1_'+row.childuuid+'" onClick="timefocus(this);"></div> '+
+                    ' Ã : '+
+                    '<div class="input-group bootstrap-timepicker time" style="width: 70px;">'+
+                      '<input type="text" class="form-control timepicker dailypresence" placeholder="00:00" value="'+row.endtime1+'" id="txtendtime1_'+row.childuuid+'" data-ddltype="'+row.ddltype+'" onClick="timefocus(this);"></div>' +
+                      'et de: '+
+                      '<div class="input-group bootstrap-timepicker time" style="width: 70px;"> ' +
+                        '<input type="text" class="form-control timepicker dailypresence" placeholder="00:00" value="'+ row.begintime2+'" id="txtbegintime2_'+row.childuuid+'" data-ddltype="'+row.ddltype+'" onClick="timefocus(this);"></div> '+
+                      ' Ã : '+
+                      '<div class="input-group bootstrap-timepicker time" style="width: 70px;">'+
+                        '<input type="text" class="form-control timepicker dailypresence" placeholder="00:00" value="'+row.endtime2+'" id="txtendtime2_'+row.childuuid+'" data-ddltype="'+row.ddltype+'" onClick="timefocus(this);"></div>' +
+                    '</div><br/><span id="'+row.childuuid+'_ddltype" style="display: none;">'+row.ddltype+'</span></td>';
+              rdata += '<td>'+ 
+              '<div class="btn-group"><button type="button" class="btn btn-default dropdown-toggle" data-status="'+ row.status+'"  id="btn_' + row.childuuid + '" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="glyphicons glyphicons-circle-question-mark" ></span></button>' +
+              '<div class="dropdown-menu dropdown-menu-right" style="width: 290px;top: 0px; left: -290px;">' +
+              '<button class="btn btn-default" onclick="setpresence(\'' + row.childuuid + '\',0);"><span class="glyphicons glyphicons-circle-question-mark"></span></button>' +
+              '<button class="btn btn-primary" onclick="setpresence(\'' + row.childuuid + '\',5);"><span class="glyphicons glyphicons-circle-ok"></span></button>' +
+              '<button class="btn btn-info" onclick="setpresence(\'' + row.childuuid + '\',4);"><span class="glyphicon glyphicon-plane"></span></button>' +
+              '<button class="btn btn-danger" onclick="setpresence(\'' + row.childuuid + '\',3);"><span class="glyphicons glyphicons-eye-close"></span></button>' +
+              '<button class="btn btn-absent2" onclick="setpresence(\'' + row.childuuid + '\',31);"><span class="glyphicons glyphicons-eye-close"></span></button>' +
+              '<button class="btn btn-warning" onclick="setpresence(\'' + row.childuuid + '\',2);"><span class="glyphicons glyphicons-stethoscope" ></span></button>' +
+              '<button class="btn btn-success" onclick="setpresence(\'' + row.childuuid + '\',1);"><span class="glyphicons glyphicons-check" ></span></button>' +
+            '</div>' +'</div>' +
+              '<div class="btn-group"><button type="button" class="btn btn-default dropdown-toggle" id="btn_' + row.childuuid + '_lunch" data-lunch="'+ row.lunch+'" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="display: none;"><span class="glyphicons glyphicons-cutlery"></span></button>' +
+              '<div class="dropdown-menu dropdown-menu-left" style="width: 60px; top: 0px; left: 30px;">' +
+              '<button class="btn btn-success" onclick="setlunch(\'' + row.childuuid + '\',1);"><span class="glyphicons glyphicons-cutlery"></span> oui</button>' +
+              '<button class="btn btn-default" onclick="setlunch(\'' + row.childuuid + '\',0);"><span class="glyphicons glyphicons-cutlery"></span> non</button>' +
+              
+              '</div></td>';
+              rdata += '<td><span id="planbegintime1_'+ row.childuuid+'">'+row.plantimebegin +'</span> - <span id="planendtime1_'+ row.childuuid+'">' + row.plantimeend + '</span><span id="planlunch_'+ row.childuuid+'">'+ ((row.planlunch == "1")?' (<span class="glyphicons glyphicons-cutlery" ></span>)':'')+'</span>'+
+              ((row.plantimebegin2 != '')?'<br/><span id="planbegintime2_'+ row.childuuid+'">'+row.plantimebegin2 +'</span> - <span id="planendtime2_'+ row.childuuid+'">' + row.plantimeend2 + '</span>':'')+
+              '</td>';
+              
+
+              $("#tbldailypresences > tbody").append('<tr >'+rdata+'</tr>');
+            }
+      //      //
+            $("#tbldailypresences").dataTable({
+              "language": {
+                "url": "js/locale/datatable_fr.json"
+              },
+              "paging": false,
+              "scrollY": wh + "px",
+              "scrollCollapse": true,
+              "info": false,
+              "ordering": true,
+              "filter": true,
+              "destroy": true
+            });
+            
+            $('input[id^="txt"]').on('keydown',function(e){
+                  var keycode = e.keyCode || e.which; 
+                  //jsdump(keycode);
+                  if ( keycode == 9 ){
+                        
+                        $(this).next('input').focus();
+                        //savetime(e);
+                  }
+                  
+            });
+            $('input[id^="txt"]').focusout(function(e){
+                  savetime($(this));
+            });
+
+      setallpresences();
+
+}
+
+
+function savetime(obj){
+      var fdata =obj.attr('id').split("_");
+                  var timeval = obj.val();
+                  var ddltype = $("#" + fdata[1]+ "_ddltype").html();
+
+                  var psqltime = "";
+                  if (timeval == ''){
+                          timeval='null';
+                  }else{
+                        timeval = timeval.replace(/[^\d]/g, '') + "0000";
+                        timeval = timeval.substring(0,2) + ":" + timeval.substring(2,4);
+                        $("#" + obj.attr('id')).val(timeval);
+                        timeval = "'" + timeval + "'";
+                  }
+                  
+                  
+                  if (ddltype == 'upd'){
+                         
+                         if (fdata[0] == "txtbegintime1"){
+                                 psqltime = "update presence set begintime1="+timeval+" where childuuid='"+fdata[1]+"' and daydate=date('"+initdate.toLocaleFormat('%Y-%m-%d')+"');";
+                         } else if (fdata[0] == "txtendtime1"){
+                                 psqltime = "update presence set endtime1="+timeval+" where childuuid='"+fdata[1]+"' and daydate=date('"+initdate.toLocaleFormat('%Y-%m-%d')+"');";
+                         } else if (fdata[0] == "txtbegintime2"){
+                                 psqltime = "update presence set begintime2="+timeval+" where childuuid='"+fdata[1]+"' and daydate=date('"+initdate.toLocaleFormat('%Y-%m-%d')+"');";
+                         } else if (fdata[0] == "txtendtime2") {
+                                 psqltime = "update presence set endtime2="+timeval+" where childuuid='"+fdata[1]+"' and daydate=date('"+initdate.toLocaleFormat('%Y-%m-%d')+"');";
+                         } else {
+                        return false;
+                         }
+                  } else if (ddltype == 'ins'){
+                         var xfield = fdata[0].substring(3);
+                         var psqltime = "INSERT INTO presence (status,childuuid,daydate,lunch,"+xfield+") VALUES ";
+                         psqltime +=  "(1,'" + fdata[1] + "',date('" + initdate.toLocaleFormat("%Y-%m-%d") + "')," + 
+                         ((($("#planlunch_" + fdata[1]).exists()) && ($("#planlunch_" + fdata[1]).html() != ''))?"'1'":'null') + ","+timeval+");";
+                  }
+                  if (psqltime !== ""){
+
+                        appdb.dbexec(psqltime);
+                        if (ddltype == 'ins'){
+                               $("#" + fdata[1]+ "_ddltype").html('upd');
+                        }
+                  }
+}
+
+function setlunch(childuuid,status) {
+      
+      var lunch = 'null';
+      if (status == 1) {
+            $("#btn_" +  childuuid+ "_lunch").removeClass('btn-default');
+            $("#btn_" +  childuuid+ "_lunch").addClass('btn-success');
+            lunch = "'1'";
+      } else {
+            $("#btn_" +  childuuid+ "_lunch").removeClass('btn-success');
+            $("#btn_" +  childuuid+ "_lunch").addClass('btn-default');
+            lunch = "'0'";
+      }
+
+      appdb.dbexec("update presence set lunch=" + lunch + " where daydate=date('" + initdate.toLocaleFormat("%Y-%m-%d") + "') and childuuid='" + childuuid + "';");
+
+}
+
+function setpresence(childuuid,newstatus) {
+       
+      var ddltype = $("#" + childuuid + "_ddltype").html();
+      
+      var usql = "";
+      if (newstatus == 0){
+         $("#btn_" + childuuid + "_lunch").css("display", "none");
+      } else {
+         $("#btn_" + childuuid + "_lunch").css("display", "");
+      }
+      if ((ddltype=='ins') && (newstatus != 0)){
+         
+         usql = "INSERT INTO presence (status,childuuid,daydate,lunch) "+
+         "VALUES (" + newstatus + ",'" + childuuid + "',date('" + initdate.toLocaleFormat("%Y-%m-%d") + "')," + 
+         ((($("#planlunch_" + childuuid).exists()) && ($("#planlunch_" + childuuid).html() != '') && newstatus==1)?"'1'":'null') + ");";
+         
+      } else if (newstatus == 0) {
+           
+            usql = "DELETE FROM presence where childuuid='" + childuuid + "' and daydate=date('" + initdate.toLocaleFormat("%Y-%m-%d") + "');";
+            $("#txtbegintime1_" + childuuid).val('');
+            $("#txtendtime1_" + childuuid).val('');
+            $("#txtbegintime2_" + childuuid).val('');
+            $("#txtendtime2_" + childuuid).val('');
+            $("#btn_" +  childuuid+ "_lunch").removeClass('btn-success');
+            $("#btn_" +  childuuid+ "_lunch").addClass('btn-default');
+      
+      } else {
+         var usql = "UPDATE presence SET status=" + newstatus + " where childuuid='" + childuuid + "' and daydate=date('" + initdate.toLocaleFormat("%Y-%m-%d") + "');";
+         
+      }
+      appdb.dbexec(usql);
+      $("#" + childuuid + "_ddltype").html("upd");
+      $("#btn_" +  childuuid).attr("class","btn " + presenceids[newstatus].class + " dropdown-toggle");
+      $("#btn_" +  childuuid).html(presenceids[newstatus].icon);
+
+      if (newstatus != 0 && newstatus != 1 && newstatus != 5){
+        $("#frm_" + childuuid).css("display","none");
+      }else {
+        $("#frm_" + childuuid).css("display",""); 
+      }
+      
+      if (($("#planlunch_" + childuuid).exists()) && ($("#planlunch_" + childuuid).html() != '') && newstatus == 1){
+             setlunch(childuuid,1);
+         }
+
+}
+
+function setalltopresent(){
+  $('body').css('cursor','wait');
+
+      $("button[id^=btn_]").each(
+            function(){
+                  if (($(this).attr("id").indexOf("lunch") == -1) && ($(this).attr("class").indexOf("btn-default") != -1)) {
+                      var btnspl =$(this).attr("id").split("_");
+                      setpresence(btnspl[1],1);
+                  }
+                  
+            }
+      );
+  $('body').css('cursor','auto');
+}
+
+function change_day() {
+      pconfig.presday = $('#presday').val();
+      
+      apppref.setpreference("pageconfig.dailypresences",pconfig);
+      globelreq.send_request({
+            page: 'dailypresences',
+            module: 'presences',
+            data: null,
+            header: 'Présences par jour'
+      });
+}
+
+function setallpresences() {
+      var prsql = "select daydate,childuuid,status,lunch from presence where daydate = date('" +initdate.toLocaleFormat("%Y-%m-%d") + "');";
+      var presdata = appdb.dbquery(prsql);
+      presdata = presdata.sqldata;
+      if (presdata) {
+        for (var p in presdata) {
+            if ($("#btn_" + presdata[p].childuuid ).exists()) {
+                  $("#btn_" + presdata[p].childuuid).attr("class","btn " + presenceids[presdata[p].status].class + " dropdown-toggle");
+                  $("#btn_" + presdata[p].childuuid).html(presenceids[presdata[p].status].icon);
+                  $("#btn_" + presdata[p].childuuid + "_lunch").css("display","");
+            }
+               if (presdata[p].lunch == 1){
+                       $("#btn_" + presdata[p].childuuid + "_lunch").attr("class","btn btn-success dropdown-toggle");
+
+               }
+
+
+        }
+      }
+}
+
+function onpreviousday() {
+  pconfig.presday = $('#presday').val();
+  var tmpweek = new Date(encodeparam(pconfig.presday, 'date').replace(/'/g, ''));
+  var nweek = new Date(tmpweek.getFullYear(), tmpweek.getMonth(), tmpweek.getDate()-1);
+  if (nweek.getDay() == 0){
+      nweek = new Date(tmpweek.getFullYear(), tmpweek.getMonth(), tmpweek.getDate()-2);
+  }
+//   if (nweek.getDay() == 6){
+//       nweek = new Date(tmpweek.getFullYear(), tmpweek.getMonth(), tmpweek.getDate()-2);
+//   }
+  pconfig.presday = nweek.toLocaleFormat('%d.%m.%Y');
+      apppref.setpreference("pageconfig.dailypresences",pconfig);
+      globelreq.send_request({
+            page: 'dailypresences',
+            module: 'presences',
+            data: null,
+            header: 'Présences par jour'
+      });
+}
+
+function onnextday() {
+  pconfig.presday = $('#presday').val();
+  var tmpweek = new Date(encodeparam(pconfig.presday, 'date').replace(/'/g, ''));
+  var nweek = new Date(tmpweek.getFullYear(), tmpweek.getMonth(), tmpweek.getDate()+1);
+   if (nweek.getDay() == 0){
+      nweek = new Date(tmpweek.getFullYear(), tmpweek.getMonth(), tmpweek.getDate()+2);
+  }
+//   if (nweek.getDay() == 6){
+//       nweek = new Date(tmpweek.getFullYear(), tmpweek.getMonth(), tmpweek.getDate()+3);
+//   }
+  pconfig.presday = nweek.toLocaleFormat('%d.%m.%Y');
+      apppref.setpreference("pageconfig.dailypresences",pconfig);
+      globelreq.send_request({
+            page: 'dailypresences',
+            module: 'presences',
+            data: null,
+            header: 'Présences par jour'
+      });
+}
+
+function timefocus(obj){
+      if (!obj.value || obj.value == ''){
+            var currentdate = new Date(); 
+            obj.value=currentdate.toLocaleFormat("%H:%M");
+      }
+      obj.select();
+}
+
+
+
diff --git a/modules/presences/js/weeklypresences.js b/modules/presences/js/weeklypresences.js
new file mode 100644 (file)
index 0000000..2a280ca
--- /dev/null
@@ -0,0 +1,464 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {
+      "groupuuid": null,
+      "presweek": null
+};
+var weekdates = null;
+var initdate = new Date();
+var cdate = initdate.toLocaleFormat('%Y-%m-%d');
+var wh= window.innerHeight -190;
+var groups = {}; 
+var tableheadssql = "";
+
+var presences = {
+      "btn-default": {
+            class: "btn-success",
+            icon: '<span class="glyphicons glyphicons-check" aria-hidden="true"></span>',
+            nextdata: 1
+      },
+      "btn-success": {
+            class: "btn-warning",
+            icon: '<span class="glyphicons glyphicons-stethoscope" aria-hidden="true"></span>',
+            nextdata: 2
+      },
+      "btn-warning": {
+            class: "btn-danger",
+            icon: '<span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span>',
+            nextdata: 3
+      },
+      "btn-absent2": {
+            class: "btn-absent2",
+            icon: '<span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span>',
+            nextdata: 31
+      },
+      "btn-danger": {
+            class: "btn-info",
+            icon: '<span class="glyphicon glyphicon-plane" aria-hidden="true"></span>',
+            nextdata: 4
+      },
+      "btn-info": {
+            class: "btn-primary",
+            icon: '<span class="glyphicons glyphicons-circle-ok" aria-hidden="true"></span>',
+            nextdata: 5
+      },
+      "btn-primary": {
+            class: "btn-default",
+            icon: '<span class="glyphicons glyphicons-circle-question-mark" aria-hidden="true"></span>',
+            nextdata: null
+      }
+};
+
+var presenceids = {
+      1: {
+            class: "btn-success",
+            icon: '<span class="glyphicons glyphicons-check" aria-hidden="true"></span>',
+            nextdata: 1
+      },
+      2: {
+            class: "btn-warning",
+            icon: '<span class="glyphicons glyphicons-stethoscope" aria-hidden="true"></span>',
+            nextdata: 2
+      },
+      3: {
+            class: "btn-danger",
+            icon: '<span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span>',
+            nextdata: 3
+      },
+      31: { 
+            class: "btn-absent2",
+            icon: '<span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span>',
+            nextdata: 31
+      },
+      4: {
+            class: "btn-primary",
+            icon: '<span class="glyphicons glyphicons-circle-ok" aria-hidden="true"></span>',
+            nextdata: 4
+      },
+      5: {
+            class: "btn-info",
+            icon: '<span class="glyphicon glyphicon-plane" aria-hidden="true"></span>',
+            nextdata: 5
+      }
+};
+
+function initdata() {
+      load_helpers();
+      var pdata = apppref.getpreference("pageconfig.weeklypresences");
+      if (pdata !== '') {
+        pconfig = JSON.parse(pdata);
+      }
+        pconfig.printlayout = 'multilist';
+        apppref.setpreference("pageconfig.weeklypresences",pconfig);
+
+      if (pconfig.presweek) {
+            initdate = new Date(encodeparam(pconfig.presweek, 'date').replace(/'/g, ''));
+
+            $("#presweek").val(pconfig.presweek);
+      }else{
+            $("#presweek").val(initdate.toLocaleFormat('%d.%m.%Y'));
+      }
+      $("#presweek").on("dp.hide", function () {
+        change_week();
+      });
+      set_infoheader("");
+      cdate = initdate.toLocaleFormat('%Y-%m-%d');
+      
+      weekdates = appdb.dbquery("select weekdaybegin as mon, date(weekdaybegin,'+1 day') as tue, date(weekdaybegin,'+2 days') as wed, date(weekdaybegin,'+3 days') as thu, date(weekdaybegin,'+4 days') as fri from (select case when strftime('%w','" + cdate + "') = '1' then strftime('%Y-%m-%d','" + cdate + "') else strftime('%Y-%m-%d', date(date('" + cdate + "','-7 days'),'weekday 1')) end as weekdaybegin) ");
+
+      tableheadssql = "select 'Lundi, ' || strftime('%d.%m.%Y',weekdaybegin) as monday, 'Mardi, ' || strftime('%d.%m.%Y',date(weekdaybegin,'+1 day')) as tuesday, 'Mercredi, ' || strftime('%d.%m.%Y',date(weekdaybegin,'+2 days')) as wednesday, 'Jeudi, ' || strftime('%d.%m.%Y',date(weekdaybegin,'+3 days')) as thursday, 'Vendredi, ' || strftime('%d.%m.%Y',date(weekdaybegin,'+4 days')) as friday from (select case when strftime('%w','" + cdate + "') = '1' then strftime('%Y-%m-%d','" + cdate + "') else strftime('%Y-%m-%d', date(date('" + cdate + "','-7 days'),'weekday 1')) end as weekdaybegin);";
+
+      var tblheads = appdb.dbquery(tableheadssql);
+      weekdates = weekdates.sqldata[0];
+      
+      groups = appdb.dbquery("select grpname,uuid as groupuuid,minage,maxage  from groups UNION select 'Pas de groupe' as grpname,null as uuid,(select max(maxage) from creche) as minage,(select max(maxage) from creche) as maxage order by minage,maxage");
+      set_infoheader("Semaine du " + tblheads.sqldata[0].monday + " au " + tblheads.sqldata[0].friday);
+      groups = groups.sqldata;
+      
+      var tblgrpsql = "SELECT childname, MAX(monplan) AS monplan, MAX(monlunchplan) AS monlunchplan, MAX(tueplan) AS tueplan, MAX(tuelunchplan) AS tuelunchplan, MAX(wedplan) AS wedplan, MAX(wedlunchplan) AS wedlunchplan, MAX(thuplan) AS thuplan, MAX(thulunchplan) AS thulunchplan, MAX(friplan) AS friplan, MAX(frilunchplan) AS frilunchplan FROM ( SELECT '<button type=\"button\" class=\"btn btn-primary\" id=\"btn_changegrp_' || ch.uuid || '\"  onclick=\"dlgchangegrp(this);\"><span class=\"glyphicons glyphicons-group\" aria-hidden=\"true\"></button>&nbsp;' || ch.prename || ' ' || ch.surname AS childname, ";
+      var vacdates = appdb.dbqueryarray("select CAST(strftime(\"%w\",vacancydate) as INT)-1 as wdnum from vacancy where vacancydate between '"+weekdates.mon+"' and '"+weekdates.fri+"' and vacancydateto is null;" );
+      var vacrem = "";
+      if (vacdates) {
+        vacdates = vacdates.sqldata;
+        vacrem = vacdates.join(',');
+      }
+      var wda = ['mon','tue','wed','thu','fri','sat'];
+      var wdsa = [];
+      for (var w in wda){
+        
+        if (vacrem.indexOf(w) != -1) {
+          wdsa.push("null as "+wda[w]+"plan,null AS "+wda[w]+"lunchplan");
+        } else {
+            
+          wdsa.push(" CASE WHEN pl."+wda[w]+"timebegin != '00:00' AND '" + weekdates[wda[w]] + "' BETWEEN pl.datebegin AND pl.dateend THEN '<button type=\"button\" class=\"btn btn-default 2\" id=\"btn_' || ch.uuid || '_"+wda[w]+"\"  onclick=\"setpresence(this);\"><span class=\"glyphicons glyphicons-circle-question-mark\" aria-hidden=\"true\"></button>' ELSE '<button type=\"button\" class=\"btn btn-primary 1\" id=\"btn_edit_' || ch.uuid || '_"+wda[w]+"\"  onclick=\"configure_presence(this);\"><span class=\"glyphicons glyphicons-settings\" aria-hidden=\"true\"></button>' END AS "+wda[w]+"plan, " +
+          " CASE WHEN pl."+wda[w]+"timebegin != '00:00' AND '" + weekdates[wda[w]] + "' BETWEEN pl.datebegin AND pl.dateend THEN '<button type=\"button\" class=\"btn btn-' || CASE WHEN pl."+wda[w]+"lunch = 1 THEN 'default' ELSE 'default' END || '\" id=\"btn_' || ch.uuid || '_"+wda[w]+"lunch\" onclick=\"setlunch(this);\" disabled=\"disabled\"><span class=\"glyphicons glyphicons-cutlery\" ></span></button>' ELSE NULL END AS "+wda[w]+"lunchplan" );
+        }
+        
+      }
+      tblgrpsql += wdsa.join(",") +
+      " FROM planning pl LEFT JOIN childs ch ON ( pl.childuuid=ch.uuid) LEFT JOIN groups gr ON ( pl.groupuuid=gr.uuid) WHERE gr.uuid%%goupuuid%% AND (( pl.datebegin <= '" + weekdates.mon + "' AND pl.dateend >= '" + weekdates.mon + "') OR ( pl.datebegin <= '" + weekdates.tue + "' AND pl.dateend >= '" + weekdates.tue + "') OR ( pl.datebegin <= '" + weekdates.wed + "' AND pl.dateend >= '" + weekdates.wed + "') OR ( pl.datebegin <= '" + weekdates.thu + "' AND pl.dateend >= '" + weekdates.thu + "') OR ( pl.datebegin <= '" + weekdates.fri + "' AND pl.dateend >= '" + weekdates.fri + "') ) ) chpr GROUP BY childname ORDER BY childname";
+      for (var g in groups) {
+            if (groups[g].groupuuid !== '') {
+              $("#dlg_changegrp #groupuuid").append('<option value="'+ groups[g].groupuuid +'">'+groups[g].grpname+'</option>');
+            }
+            
+            $("#tabgrouphead").append('<li><a data-toggle="tab" href="#tabgrp_' + groups[g].groupuuid + '">' + groups[g].grpname + '</a></li>');
+            $("#tabgroupbody").append('<div id="tabgrp_' + groups[g].groupuuid + '" class="tab-pane"></div>');
+            var cgrpsql = tblgrpsql.replace('%%goupuuid%%', "='" +groups[g].groupuuid + "'");
+            if (groups[g].groupuuid === '') {
+              cgrpsql = tblgrpsql.replace('%%goupuuid%%', " is null");
+            }
+
+            var grpdata = appdb.dbqueryarray(cgrpsql);
+
+            var headerdata = getlabels(grpdata.sqlhead.join(","));
+
+            $("#tabgrp_" + groups[g].groupuuid).append('<table class="display dataTable cell-border" style="width: 100%;" id="tblgrp_' + groups[g].groupuuid + '" role="grid"><thead></thead><tfoot></tfoot><tbody></tbody></table>');
+   
+            $("#tblgrp_" + groups[g].groupuuid + " > thead").append('<tr><th rowspan="2">Enfant</th><th colspan="2">' + tblheads.sqldata[0].monday + '</th><th colspan="2">' + tblheads.sqldata[0].tuesday + '</th><th colspan="2">' + tblheads.sqldata[0].wednesday + '</th><th colspan="2">' + tblheads.sqldata[0].thursday + '</th><th colspan="2">' + tblheads.sqldata[0].friday + '</th></tr>');
+            var headdata = "";
+            for (var h=0;h<headerdata.length;h++){
+              if (h !== 0) {
+                headdata += '<th>'+ headerdata[h].title +'</th>';
+              }
+            }
+            $("#tblgrp_" + groups[g].groupuuid + " > thead").append('<tr>' + headdata+ '</tr>');
+            grpdata = grpdata.sqldata;
+            for (var b in grpdata){
+              var xdata = grpdata[b];
+              $("#tblgrp_" + groups[g].groupuuid + " > tbody").append('<tr><td>'+xdata.join('</td><td>')+'</td></tr>');
+            }
+            //
+            $("#tblgrp_" + groups[g].groupuuid).dataTable({
+              "language": {
+                "url": "js/locale/datatable_fr.json"
+              },
+              "paging": false,
+              "scrollY": wh + "px",
+              "scrollCollapse": true,
+              "info": false,
+              "ordering": true,
+              "filter": true,
+              "destroy": true
+            });
+      }
+
+      setallpresences();
+      $('#tabgrouphead a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+        var tn =  e.target.toString();
+        pconfig.groupuuid = tn.substring(tn.lastIndexOf("#")+8);
+        pconfig.activetab = 'tblgrp_' +pconfig.groupuuid;
+        apppref.setpreference("pageconfig.weeklypresences",pconfig);
+       
+      $("#tblgrp_" + pconfig.groupuuid).dataTable({
+              "language": {
+                "url": "js/locale/datatable_fr.json"
+              },
+              "paging": false,
+              "scrollY": wh + "px",
+              "scrollCollapse": true,
+              "info": false,
+              "ordering": true,
+              "filter": true,
+              "destroy": true
+            });
+      });
+      if (!pconfig.groupuuid) {
+            $('#tabgrouphead a[href="#tabgrp_' + groups[0].groupuuid + '"]').tab('show');
+            pconfig.groupuuid = groups[0].groupuuid;
+            pconfig.activetab = '#tabgrp_' + groups[0].groupuuid;
+            apppref.setpreference("pageconfig.weeklypresences",pconfig);
+      } else {
+            $('#tabgrouphead a[href="#tabgrp_' + pconfig.groupuuid + '"]').tab('show');
+            pconfig.activetab = '#tabgrp_' + groups[0].groupuuid;
+            apppref.setpreference("pageconfig.weeklypresences",pconfig);
+      }
+      
+      
+}
+
+function setlunch(btn) {
+      
+      var clb = $(btn).attr('class').split(' ');
+      var ident = $(btn).attr('id').split('_');
+
+      var lunch = 'null';
+      if (clb[1] == 'btn-default') {
+            $(btn).removeClass('btn-default');
+            $(btn).addClass('btn-success');
+            lunch = "'1'";
+      } else {
+            $(btn).removeClass('btn-success');
+            $(btn).addClass('btn-default');
+            lunch = "'0'";
+      }
+
+      appdb.dbexec("update presence set lunch=" + lunch + " where daydate='" + weekdates[ident[2].substring(0, 3)] + "' and childuuid='" + ident[1] + "';");
+
+}
+
+function setpresence(btn) {
+      $(btn).removeClass('2');
+      var clx = $(btn).attr('class');
+      var clb = clx.split(' ');
+      
+      var ident = $(btn).attr('id').split('_');
+      if ((ident[0] == 'btn') && ((ident[1] == 'edit') || (ident[1] == 'changegrp'))) {
+        return;
+      }
+      var clblunch = $("#" + $(btn).attr('id') + 'lunch').attr('class').split(' ');
+      var usql = "UPDATE presence SET status=" + presences[clb[1]].nextdata + " where childuuid='" + ident[1] + "' and daydate=date('" + weekdates[ident[2]] + "');";
+
+      if (presences[clb[1]].nextdata == 1) {
+            usql = "INSERT INTO presence (status,childuuid,daydate,lunch) VALUES (" + presences[clb[1]].nextdata + ",'" + ident[1] + "',date('" + weekdates[ident[2]] + "')," + ((clblunch[1] == 'default') ? 0 : 1) + ");";
+
+      } else if (!presences[clb[1]].nextdata) {
+            usql = "DELETE FROM presence where childuuid='" + ident[1] + "' and daydate='" + weekdates[ident[2]] + "';";
+      }
+
+      appdb.dbexec(usql);
+      $(btn).removeClass(clb[1]);
+      $(btn).addClass(presences[clb[1]].class);
+      $(btn).html(presences[clb[1]].icon);
+      if ((presences[clb[1]].nextdata == 1) || (presences[clb[1]].nextdata == 5)) {
+            $("#" + $(btn).attr("id") + "lunch").removeClass('btn-default');
+            $("#" + $(btn).attr("id") + "lunch").addClass('btn-success');
+            $("#" + $(btn).attr("id") + "lunch").prop("disabled", false);
+      } else {
+            $("#" + $(btn).attr("id") + "lunch").removeClass('btn-success');
+            $("#" + $(btn).attr("id") + "lunch").addClass('btn-default');
+            $("#" + $(btn).attr("id") + "lunch").prop("disabled", true);
+      }
+}
+
+function setalltopresent(){
+  $('body').css('cursor','wait');
+
+      $("button[id^=btn_]").each(
+            function(){
+                  if ((this.id.indexOf("lunch") == -1) && (this.getAttribute("class").indexOf("btn-default") != -1)) {
+                    setpresence(this);
+                  }
+                  
+            }
+      );
+  $('body').css('cursor','auto');
+}
+
+function change_week() {
+      pconfig.presweek = $('#presweek').val();
+      
+      apppref.setpreference("pageconfig.weeklypresences",pconfig);
+      globelreq.send_request({
+            page: 'weeklypresences',
+            module: 'presences',
+            data: null,
+            header: 'Présences par semaine'
+      });
+}
+
+function setallpresences() {
+      var prsql = "select daydate,childuuid,status,lunch,case ";
+      var wda = ['','mon','tue','wed','thu','fri','sat'];
+      var dd = [];
+      for (var i=1;i<=wda.length;i++){
+            dd.push("when weekday='"+i+"' then '"+ wda[i]+"'");
+      }
+       prsql += dd.join(',') +  " else null end as weekday from (select daydate,childuuid,status,lunch,strftime('%w',daydate) as weekday from presence where daydate >= date('" + weekdates.mon + "') and daydate <=date('" + weekdates.fri + "')) group by childuuid,daydate;";
+      var presdata = appdb.dbquery(prsql);
+      presdata = presdata.sqldata;
+      if (presdata) {
+        for (var p in presdata) {
+            if ($("#btn_" + presdata[p].childuuid + "_" + presdata[p].weekday)) {
+                  $("#btn_" + presdata[p].childuuid + "_" + presdata[p].weekday).removeClass("btn-default");
+                  $("#btn_" + presdata[p].childuuid + "_" + presdata[p].weekday).addClass(presenceids[presdata[p].status].class);
+                  $("#btn_" + presdata[p].childuuid + "_" + presdata[p].weekday).html(presenceids[presdata[p].status].icon);
+            if ((presdata[p].status == 1) || (presdata[p].status == 5)) {
+                  $("#btn_" + presdata[p].childuuid + "_" + presdata[p].weekday + "lunch").prop("disabled", false);
+            }
+            }
+            if ($("#btn_" + presdata[p].childuuid + "_" + presdata[p].weekday + "lunch")) {
+                  $("#btn_" + presdata[p].childuuid + "_" + presdata[p].weekday + "lunch").removeClass("btn-default");
+                  $("#btn_" + presdata[p].childuuid + "_" + presdata[p].weekday + "lunch").addClass("btn-success");
+
+            }
+        }
+      }
+}
+
+function configure_presence(obj) {
+  var xx = obj.id.split("_");
+  var chid = xx[2];
+  //var lblcday=getlabels(xx[3]);
+  var cfgdate = new Date(weekdates[xx[3]]).toLocaleFormat("%Y-%m-%d");
+  $('#planning > #plandate').val(cfgdate);
+  $('#planning > #childuuid').val(chid);
+  $('#planning > #planday').val(xx[3]);
+  $('#dlg_addplanning').modal('show');
+}
+
+
+function save_planning() {
+  var newplandata = {};
+  $("#planning :input").each(function() {
+    var input = $(this);
+    
+    if (input.attr("id")) {
+
+      if ((input.attr("type") == "checkbox") && input.attr("checked")){
+        newplandata[input.attr("id")] = input.val();
+      }
+      else if (input.attr("type") != "checkbox"){
+        newplandata[input.attr("id")] = input.val();
+      }
+    }
+  });
+
+  if ((newplandata.timebegin=='00:00') || (newplandata.timeend=='00:00') || (newplandata.timebegin==newplandata.timeend)) {
+    return;                                     
+  }
+  
+  var checkdatesplit = appdb.dbquery("select * from planning where datebegin <= '"+newplandata.plandate+"' and dateend >= '"+newplandata.plandate+"' and childuuid='"+newplandata.childuuid+"';");
+  checkdatesplit = checkdatesplit.sqldata;
+  if (checkdatesplit.length == 1) {
+  //
+    var newuuid = appdb.generate_uuid();
+    appdb.dbexec("INSERT INTO planning (datebegin, dateend, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch, sattimebegin, sattimeend, satlunch, suntimebegin, suntimeend, sunlunch, childuuid, uuid, groupuuid, montimebegin2, montimeend2, tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2, sattimebegin2, sattimeend2, suntimebegin2, suntimeend2) SELECT date('"+newplandata.plandate+"','+1 day'), dateend, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch, sattimebegin, sattimeend, satlunch, suntimebegin, suntimeend, sunlunch, childuuid, '"+newuuid+"', groupuuid, montimebegin2, montimeend2, tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2, sattimebegin2, sattimeend2, suntimebegin2, suntimeend2 FROM planning where uuid='"+ checkdatesplit[0].uuid +"';");
+    appdb.dbexec("UPDATE planning SET dateend=date('"+newplandata.plandate+"','-1 day') where uuid='"+checkdatesplit[0].uuid+"'");
+    newuuid = appdb.generate_uuid();
+    appdb.dbexec("INSERT INTO planning (datebegin,dateend, "+newplandata.planday+"timebegin,"+newplandata.planday+"timeend,"+newplandata.planday+"lunch,childuuid,uuid,groupuuid) VALUES ('"+newplandata.plandate+"','"+newplandata.plandate+"','"+newplandata.timebegin+"','"+newplandata.timeend+"',"+((newplandata.lunch)?"'1'":'null')+",'"+newplandata.childuuid+"','"+newuuid+"','"+checkdatesplit[0].groupuuid+"');");
+  }
+  $('#dlg_addplanning').modal('hide');
+  globelreq.send_request({
+            page: 'weeklypresences',
+            module: 'presences',
+            data: null,
+            header: 'Présences par semaine'
+      });
+}
+
+
+function onpreviousweek() {
+  pconfig.presweek = $('#presweek').val();
+  var tmpweek = new Date(encodeparam(pconfig.presweek, 'date').replace(/'/g, ''));
+  var nweek = new Date(tmpweek.getFullYear(), tmpweek.getMonth(), tmpweek.getDate()-7);
+  pconfig.presweek = nweek.toLocaleFormat('%d.%m.%Y');
+      apppref.setpreference("pageconfig.weeklypresences",pconfig);
+      globelreq.send_request({
+            page: 'weeklypresences',
+            module: 'presences',
+            data: null,
+            header: 'Présences par semaine'
+      });
+}
+
+function onnextweek() {
+  pconfig.presweek = $('#presweek').val();
+  var tmpweek = new Date(encodeparam(pconfig.presweek, 'date').replace(/'/g, ''));
+  var nweek = new Date(tmpweek.getFullYear(), tmpweek.getMonth(), tmpweek.getDate()+7);
+  pconfig.presweek = nweek.toLocaleFormat('%d.%m.%Y');
+      apppref.setpreference("pageconfig.weeklypresences",pconfig);
+      globelreq.send_request({
+            page: 'weeklypresences',
+            module: 'presences',
+            data: null,
+            header: 'Présences par semaine'
+      });
+}
+
+function dlgchangegrp(obj) {
+  var xx = obj.id.split("_");
+  var chid = xx[2];
+  
+  var chldnames = appdb.dbquery("SELECT prename || ' ' || surname as childname from childs where uuid='"+chid+"';");
+  var grps = appdb.dbquery("SELECT '<strong>' || gr.grpname ||  '</strong>:  ' || strftime(\"%d.%m.%Y\",datebegin) || ' - ' || strftime(\"%d.%m.%Y\",dateend) as strdates,strftime(\"%d.%m.%Y\",dateend) from planning pl left join groups gr on (pl.groupuuid=gr.uuid) where pl.childuuid='"+chid+"' and (datebegin between '"+ weekdates.mon+"' and '"+ weekdates.fri+"' or dateend between '"+ weekdates.mon+"' and '"+ weekdates.fri+"' or (datebegin <= '"+ weekdates.mon+"' and dateend >= '"+ weekdates.fri+"'));");
+  if (grps.sqldata) {
+    grps = grps.sqldata;
+  }
+  
+  var strgrp = "";
+  if (grps) {
+    dgrpc = grps[0].dateend;
+    for (var f in grps){
+      strgrp += grps[f].strdates + '<br/>';
+    }
+  }
+  
+  $('#dlg_changegrp #dategrpchange').val(new Date(weekdates.mon).toLocaleFormat('%d.%m.%Y'));
+  $('#dlg_changegrp #childuuid').val(chid);
+  $('#dlg_changegrp #groupuuid').val(pconfig.groupuuid);
+  $('#dlg_changegrp #curgrp').val(pconfig.groupuuid);
+  $('#dlg_changegrp #curgrpdata').html("<br/><br/><strong>Enfant</strong>: " + chldnames.sqldata[0].childname+'</strong><br/>'+ strgrp);
+  $('#dlg_changegrp').modal('show');
+}
+
+function save_grpchange() {
+    var newgrpplan = {};
+    $("#dlg_changegrp :input").each(function() {
+      var input = $(this);
+    
+      if (input.attr("id")) {
+      
+        newgrpplan[input.attr("id")] = input.val();
+      }
+    });
+    newgrpplan.dategrpchange = encodeparam(newgrpplan.dategrpchange,'date').replace(/'/g,'');
+    
+    if (newgrpplan.curgrp != newgrpplan.groupuuid) {
+      var checkdatesplit = appdb.dbquery("select * from planning where date('"+newgrpplan.dategrpchange+"') between datebegin and dateend and childuuid='"+newgrpplan.childuuid+"';");
+      checkdatesplit = checkdatesplit.sqldata;
+      if (checkdatesplit.length == 1) {
+        var newuuid = appdb.generate_uuid();
+        appdb.dbexec("INSERT INTO planning (datebegin, dateend, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch, sattimebegin, sattimeend, satlunch, suntimebegin, suntimeend, sunlunch, childuuid, uuid, groupuuid, montimebegin2, montimeend2, tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2, sattimebegin2, sattimeend2, suntimebegin2, suntimeend2) SELECT date('"+newgrpplan.dategrpchange+"'), dateend, montimebegin, montimeend, monlunch, tuetimebegin, tuetimeend, tuelunch, wedtimebegin, wedtimeend, wedlunch, thutimebegin, thutimeend, thulunch, fritimebegin, fritimeend, frilunch, sattimebegin, sattimeend, satlunch, suntimebegin, suntimeend, sunlunch, childuuid, '"+newuuid+"', '"+newgrpplan.groupuuid+"', montimebegin2, montimeend2, tuetimebegin2, tuetimeend2, wedtimebegin2, wedtimeend2, thutimebegin2, thutimeend2, fritimebegin2, fritimeend2, sattimebegin2, sattimeend2, suntimebegin2, suntimeend2 FROM planning where uuid='"+ checkdatesplit[0].uuid +"';");
+        appdb.dbexec("UPDATE planning SET dateend=date('"+newgrpplan.dategrpchange+"','-1 day') where uuid='"+checkdatesplit[0].uuid+"'");
+        $('#dlg_changegrp').modal('hide');
+        globelreq.send_request({
+            page: 'weeklypresences',
+            module: 'presences',
+            data: null,
+            header: 'Présences par semaine'
+      });
+      }
+  }  
+
+}
diff --git a/modules/presences/presences.xul b/modules/presences/presences.xul
new file mode 100644 (file)
index 0000000..1f25e88
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_logbook" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <!--<toolbarbutton type="menu" class="btn btn-default" id="tbb_logbook" insertafter="tbb_forms" label="Livrets de bord" image="modules/logbook/img/logbook.png" orient="vertical">-->
+    <toolbarbutton type="menu" class="btn btn-default" id="tbb_presences" insertafter="tbb_childs" label="Présences" image="modules/presences/img/presence.png" orient="vertical">
+    <menupopup class="tlbpopup" style="text-align: left;">
+      <menuitem label="Présences par par jour" oncommand="navigation.load_appview('dailypresences','presences',null,'Présences par jour');"  id="mnudailypresences"/>
+      <menuitem label="Présences par semaine" oncommand="navigation.load_appview('weeklypresences','presences',null,'Présences par semaine');"  id="mnuweeklypresences"/>
+      
+      
+      <!--<menuseparator />
+      <label value="Personnel" style="font-weight: bold;"/>
+      <menuitem label="Livret d'évaluation" oncommand="navigation.load_appview('logstaff','logbook',null,'Livret d Ã©valuation');"  id="mnulogstaff"/>-->
+    </menupopup>
+    </toolbarbutton>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/presences/weeklypresences.html b/modules/presences/weeklypresences.html
new file mode 100644 (file)
index 0000000..0ee1f1c
--- /dev/null
@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  
+  <title>Présences par semaine</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <!--<link href="css/glyphicons-bootstrap.css" rel="stylesheet">-->
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/glyphicons.css" rel="stylesheet">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+  <style type="text/css">
+    .dataTables_filter {
+      margin-top: -86px;
+    }
+    .tab-pane {
+      margin-top: 0px;
+      padding-top: 0px;
+    }
+  </style>
+</head>
+
+<body>
+    <div class="container-fluid" style="padding-top: 5px;">
+    <!--<span class="pagehead" id="pagehead">Présences</span>&nbsp;-->
+    <div class="btn-group" style=" margin-bottom: 10px;">
+  
+  <div class="input-group week btn-group">
+    <span class="input-group-addon">Semaine du:</span>
+    <input type="date" class="form-control" value="" style="width: 100px;" placeholder="dd.mm.yyyy" id="presweek"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+  </div>
+  <button class="btn btn-primary" onclick="onpreviousweek();"><span class="glyphicon glyphicon-chevron-left"></span></button>
+  <button class="btn btn-primary" onclick="onnextweek();"><span class="glyphicon glyphicon-chevron-right"></span></button>
+  <!--<button title="imprimer" onclick="print_report();" id="btnprintreport" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-print" aria-hidden="true"></span> </button>-->
+  <button onclick="setalltopresent();" class="btn btn-success" id="btnreload"><span class="glyphicons glyphicons-check" aria-hidden="true"></span></button>
+    <div class="dropdown btn-group">
+  <button class="btn btn-primary dropdown-toggle" type="button" id="mnulegend" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+   Légende
+    <span class="caret"></span>
+  </button>
+  <ul class="dropdown-menu" aria-labelledby="mnulegend">
+    <li class="btn-primary"><span class="glyphicons glyphicons-circle-question-mark" aria-hidden="true"></span> non configuré</li>
+    <li class="btn-success"><span class="glyphicons glyphicons-ok" aria-hidden="true"></span> présent</li>
+    <li class="btn-warning"><span class="glyphicons glyphicons-stethoscope" aria-hidden="true"></span> malade</li>
+    <li class="btn-danger"><span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span> absence non verifé</li>
+    <li class="btn-absent2"><span class="glyphicons glyphicons-eye-close" aria-hidden="true"></span> absence verifié</li>
+    <li class="btn-info"><span class="glyphicon glyphicon-plane" aria-hidden="true"></span> vacences</li>
+    <li class="btn-primary"><span class="glyphicons glyphicons-circle-question-mark" aria-hidden="true"></span> essaie</li>
+  </ul>
+</div>
+    </div>
+    <div>
+      
+    </div>
+  <div class="tabbable">
+            <ul class="nav nav-tabs" id="tabgrouphead">
+              
+              
+            </ul>
+
+            <div class="tab-content" id="tabgroupbody">
+              
+            </div>
+  </div>
+  
+  </div>
+  <div class="modal fade" id="dlg_addplanning">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Ajouter planification pour un jour</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body" style="overflow: hidden;">
+                <form id="planning">
+                  <input type="hidden" id="childuuid" value="" />
+                  <input type="hidden" id="plandate" value="" />
+                  <input type="hidden" id="planday" value="" />
+                  <div class="row">
+                    <div class="col-md-3">
+                    <span class="glyphicon glyphicon-time" aria-hidden="true"></span> de:
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timebegin">
+                    </div>
+                      </div>
+                      <div class="col-md-3">
+                    <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Ã :
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timeend">
+                    </div></div>
+                      <div class="col-md-3">
+                      déjeuner:<br/>
+                    <input type="checkbox" id="lunch"> <span class="glyphicon glyphicon-cutlery" aria-hidden="true"></span>
+                  </div>
+                  </div>
+                </form>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_planning();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+  
+  <div class="modal fade" id="dlg_changegrp">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Changer le groupe de l'enfant</h4>
+              </div>
+
+              <div class="modal-body" style=" height: 350px; max-height: 350px ">
+                <form id="planning">
+                  <input type="hidden" id="childuuid" value="" />
+                  <input type="hidden" id="curgrp" value="" />
+                  <div class="row col-md-12">
+                    <label for="datebegin">à partir de </label>
+
+                    <div id="dt_dategrpchange" class="input-group date" style="z-index: 300;">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="dategrpchange"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                    <label for="groupuuid">Groupe</label>
+
+                    <div class="input-group">
+                      <select id="groupuuid">
+                        
+                      </select>
+                    </div>
+                    
+                  </div>
+                  <div class="row col-md-12" id="curgrpdata">
+                    
+                  </div>
+                </form>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_grpchange();" class="btn btn-primary">OK</button>
+              </div>
+            </div>
+          </div>
+        </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/weeklypresences.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/reports/css/print.css b/modules/reports/css/print.css
new file mode 100644 (file)
index 0000000..a3c54fc
--- /dev/null
@@ -0,0 +1,138 @@
+body {
+  font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+  font-size: 11px;
+  line-height: 1.42857;
+  background-color: #fff;
+}
+h2 {
+  font-size: 18px;
+  font-weight: bold;
+  margin-top: 0px;
+  margin-bottom: 5px;
+}
+
+h3 {
+  font-size: 14px;
+  font-style: italic;
+  margin-top: 0px;
+  margin-bottom: 5px;
+}
+
+.dataTables_filter {
+  height: 0px;
+  width: 0px;
+}
+
+/*.dataTable > thead > tr > th {*/
+/*  padding-top: 70px;*/
+/*}*/
+
+/*.dataTable > tfoot > tr > th {
+  padding-bottom: 40px;
+}*/
+
+/*tfoot { display: table-footer-group;*/
+/*                 position: absolute;        */
+/*                 bottom: 0; }*/
+
+.alignright{
+        text-align: right;
+}
+
+.alignleft {
+        text-align: left;
+}
+
+.noprint {
+  display: none;
+}
+
+
+
+@media print {
+
+@page {
+  margin-left: 2cm;
+  margin-right: 1cm;
+  margin-top: 1cm;
+  margin-bottom: 1cm;
+}
+
+tfoot {
+  display: table-row-group;
+}
+
+table {
+  width: 100% !Important;
+    border-spacing: 0;
+    border-collapse: collapse;
+}
+
+table.dataTable td {
+  white-space: nowrap;
+  overflow: hidden;
+}
+
+table.dataTable > thead > th > td {
+  white-space: nowrap;
+  overflow: hidden;
+}
+table.dataTable tr {
+               page-break-inside: avoid;
+               page-break-after: auto;
+           }
+
+table.dataTable tfoot {
+               page-break-inside: avoid;
+               page-break-after: auto;
+           }
+
+table.dataTable tfoot > th > td {
+  font-size: 2vw;
+}
+table.dataTable {
+  width: 100% !Important;
+    border-spacing: 0;
+    border-collapse: collapse;
+}
+
+#print-head {
+  display: block;
+  position: fixed;
+  font-family: Arial,Helvetica, sans-serif;
+  z-index: 10;
+  top: 0pt;
+  left:0pt;
+  right: 0pt;
+  background-color: #fff;
+  text-align: center;
+  }
+
+/*#print-foot {
+  display: block;
+  position: fixed;
+  width: 100%;
+  padding-top: 5px; 
+  bottom: 0pt;
+  text-align: center;
+  right: auto;
+  left: auto;
+  font-family: Arial,Helvetica, sans-serif;
+  }*/
+
+/*#print-foot:after {
+  content: counter(page);
+  counter-increment: page;
+  }*/
+
+
+.dataTables_filter {
+  height: 0px;
+  width: 0px;
+}
+
+.dataTable {
+    width: 100% !Important;
+}
+  
+}
\ No newline at end of file
diff --git a/modules/reports/dlg/dlgpdfviewer.xul b/modules/reports/dlg/dlgpdfviewer.xul
new file mode 100644 (file)
index 0000000..255bb8c
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!DOCTYPE dialog PUBLIC "-//MOZILLA//DTD XUL V1.0//EN" "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+
+<dialog id="dlgprdfviewer" title="PDF Viewer"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        persist="screenX screenY width height"
+        buttons="accept"
+        buttonlabelaccept="Fermer"
+        ondialogaccept="return OK();"
+        >
+    <script type="application/javascript" src="chrome://creorga/content/js/system.js" />
+    <vbox flex="1">
+        <browser id="pdfviewer" flex="1" src="chrome://creorga/web/pdfjs/web/viewer.html" type="content-primary" style="background-color: #fff;"/>
+    </vbox>
+<script><![CDATA[
+      
+      
+      function OK() {
+          window.close();
+      }
+
+
+      if (window.arguments[0]. in != null) {
+        var appd = OS.Path.split(system.appdir());
+        var len = appd.components.length-1;
+        var npath = new Array();
+        for (var i=0; i<len;i++){
+            npath.push("..");
+        }
+        var abspath= window.arguments[0].in.uri.substring(8);
+        //dump("PDF URI: "+ abspath + "\n");
+        //npath.join("/") +
+        //?file=" +abspath file:///
+        
+          document.getElementById("pdfviewer").loadURI("chrome://creorga/content/web/pdfjs/web/viewer.html?file=" +abspath, null, 'UTF-8');
+
+      }
+]]>
+</script>
+</dialog>
diff --git a/modules/reports/dlg/dlgprint.xul b/modules/reports/dlg/dlgprint.xul
new file mode 100644 (file)
index 0000000..0817914
--- /dev/null
@@ -0,0 +1,164 @@
+<?xml version="1.0"?>
+<!DOCTYPE dialog PUBLIC "-//MOZILLA//DTD XUL V1.0//EN" "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+
+<dialog id="dlgprint" title="Impression"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        persist="screenX screenY width height"
+        buttons="accept"
+        buttonlabelaccept="Fermer"
+        ondialogaccept="return OK();"
+        minwidth="1020"
+        minheight="600"
+        >
+    <script type="application/javascript" src="chrome://global/content/printUtils.js"/>
+    <script type="application/javascript" src="chrome://creorga/content/js/system.js" />
+    <vbox flex="1">
+        <toolbox id="previewtoolbox">
+<toolbar>
+<toolbarbutton label="Configuration" id="cmd_pageSetup" image="../img/settings.png" orient="vertical" oncommand="showpagesetup();"/>
+<toolbarbutton label="Imprimer" id="cmd_print" image="../img/print.png" orient="vertical" oncommand="PrintUtils.print(document.getElementById('print_browser').contentWindowAsCPOW, document.getElementById('print_browser'));" />
+</toolbar>
+</toolbox>
+        <browser id="print_browser" src="about:blank" type="content-primary" style="height: 0px;" autoscroll="true"/>
+        <browser id="preview_browser" src="about:blank" type="content-primary" flex="1" autoscroll="true" />
+    </vbox>
+<script><![CDATA[
+  var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"].getService(Components.interfaces.nsIPrintSettingsService);
+  var printSettings = PSSVC.newPrintSettings; printSettings.printerName = PSSVC.printerName;
+  if (system.os == "WINNT") {
+    //code
+  
+    if (!printSettings.printerName) {
+        printSettings.printerName = PSSVC.defaultPrinterName;
+    }
+    PSSVC.initPrintSettingsFromPrinter(printSettings.printerName, printSettings);
+    PSSVC.initPrintSettingsFromPrefs(printSettings, true, printSettings.kInitSaveAll);
+    }
+  if (system.os == "WINNT") {
+    var printPreviewTB = {
+      inititalize: function() {
+      },
+      updateToolbar: function() {
+      }
+    };
+
+    var PrintPreviewListener = {
+      getPrintPreviewBrowser: function() {
+        return document.getElementById('preview_browser');
+      },
+      getSourceBrowser: function() {
+        return document.getElementById('print_browser');
+      },
+      getNavToolbox: function() {
+        return document.getElementById('previewtoolbox');
+      },
+      onEnter: function() {
+        //gInPrintPreviewMode = true;
+        this._toggleAffectedChrome();
+
+      },
+      onExit: function() {
+        this._toggleAffectedChrome();
+        this._printPreviewTab = null;
+      }
+    }
+  }
+
+
+  function OK() {
+    window.close();
+  }
+
+  function reload() {
+    //var orientval = ((printSettings.orientation == 1) ? "landscape" : "portrait");
+    window.arguments[0].out = {
+      reload: true
+    };
+    window.close();
+  }
+
+  function savedocument() {
+    var sdoc = document.getElementById("print_browser").contentDocument;
+    var webBrowserPersist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
+      .createInstance(Components.interfaces.nsIWebBrowserPersist);
+    var localFile = Components.classes["@mozilla.org/file/local;1"]
+      .createInstance(Components.interfaces.nsILocalFile);
+    localFile.initWithPath(system.tmpdir() + system.sep() + 'test' + system.sep() + 'test.html');
+    //"File saved to: " + system.tmpdir() + system.sep() + 'test' + system.sep() + 'test.html' + "\n");
+    var localDir = Components.classes["@mozilla.org/file/local;1"]
+      .createInstance(Components.interfaces.nsILocalFile);
+    localDir.initWithPath(system.tmpdir() + system.sep() + 'test' + system.sep() + 'testdata');
+    
+    webBrowserPersist.saveDocument(sdoc, localFile, localDir, null, null, null);
+  }
+
+  function showpagesetup() {
+    try {
+      var x = PrintUtils.showPageSetup();
+    } catch (e) {} finally {
+      reload();
+    }
+  }
+
+  function resize() {
+    var ww = 1020;
+    if (printSettings.orientation == 1) {
+      ww = 1430;
+    }
+    if (ww > window.screen.width) {
+      ww = window.screen.width;
+    }
+    window.resizeTo(ww, window.screen.availHeight);
+  }
+  if (window.arguments[0].in != null) {
+    document.getElementById("print_browser").loadURI(window.arguments[0].in.uri, null, 'UTF-8');
+    printSettings.printBGColors = true;
+    printSettings.printBGImages = true;
+    printSettings.unwriteableMarginTop = 0.5;
+    printSettings.unwriteableMarginLeft = 0.5;
+    printSettings.unwriteableMarginBottom = 0.5;
+    printSettings.unwriteableMarginRight = 0.5;
+    printSettings.marginTop = 0.2; /*  these are in inches */
+    printSettings.marginLeft = 0.2;
+    printSettings.marginBottom = 0.2;
+    printSettings.marginRight = 0.2;
+    //printSettings.shrinkToFit;
+    printSettings.paperName = "iso_a4"; /* name of paper */
+    printSettings.paperSizeType = 1; /* use native data or is defined here */
+    //printSettings.paperData = 9;     /* native data value */
+    if (printSettings.orientation == 1) {
+      printSettings.paperWidth = 297.0; /* width of the paper in inches or mm */
+      printSettings.paperHeight = 210.0; /* height of the paper in inches or mm */
+
+    } else {
+      printSettings.paperWidth = 210.0; /* width of the paper in inches or mm */
+      printSettings.paperHeight = 297.0; /* height of the paper in inches or mm */
+    }
+    printSettings.paperSizeUnit = 1; /* paper is in inches or mm */
+    //lets hide those ugly default headers
+    printSettings.footerStrCenter = '';
+    printSettings.footerStrLeft = '';
+    printSettings.footerStrRight = '';
+    printSettings.headerStrCenter = '';
+    printSettings.headerStrLeft = '';
+    printSettings.headerStrRight = '';
+    
+    PSSVC.savePrintSettingsToPrefs(printSettings, true, printSettings.kInitSaveAll);
+    gBrowser = document.getElementById("preview_browser");
+    gBrowser.selectedBrowser = document.getElementById("preview_browser");
+    if (system.os == "WINNT") {
+      PSSVC.savePrintSettingsToPrefs(printSettings, true, printSettings.kInitSavePrinterName);
+      PrintUtils.printPreview(PrintPreviewListener);
+      resize();
+    } else {
+      document.getElementById("preview_browser").setAttribute("hidden", true);
+      document.getElementById("print_browser").removeAttribute("style");
+      document.getElementById("print_browser").setAttribute("flex", "1");
+      //document.getElementById("cmd_save").setAttribute("hidden", true);
+    }
+  }
+  ]]>
+</script>
+</dialog>
diff --git a/modules/reports/img/logoprint.png b/modules/reports/img/logoprint.png
new file mode 100644 (file)
index 0000000..8c760e8
Binary files /dev/null and b/modules/reports/img/logoprint.png differ
diff --git a/modules/reports/img/print.png b/modules/reports/img/print.png
new file mode 100644 (file)
index 0000000..335f482
Binary files /dev/null and b/modules/reports/img/print.png differ
diff --git a/modules/reports/img/save.png b/modules/reports/img/save.png
new file mode 100644 (file)
index 0000000..ef5ba59
Binary files /dev/null and b/modules/reports/img/save.png differ
diff --git a/modules/reports/img/settings.png b/modules/reports/img/settings.png
new file mode 100644 (file)
index 0000000..3a8b3b3
Binary files /dev/null and b/modules/reports/img/settings.png differ
diff --git a/modules/reports/js/print.js b/modules/reports/js/print.js
new file mode 100644 (file)
index 0000000..4ae6ede
--- /dev/null
@@ -0,0 +1,64 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+document.onreadystatechange = function () {
+  if (document.readyState == "complete") {
+    try {
+      initdata();
+    }catch(e){
+      //dump("Print.js No initdata function!\n");
+    }
+  }
+}
+
+function encodeparam(string,type){
+    if (type == "text") {
+        if (string == "") {
+            string = 'null';
+        }else {
+            string = string.replace('<','&lt;','g');
+            string = string.replace('>','&gt;','g');
+            string = string.replace('&','&amp;','g');
+            string = string.replace('"','&quot','g');
+            string = string.replace("'","''",'g');
+            string = "'"+ string+"'";
+        }
+    }else if(type == "date"){
+      var re = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/i;
+        if (!string.match(re)) {
+            string = 'null';
+        }else{
+           var dspl=string.split('.');
+            string = "'"+dspl[2]+'-'+dspl[1]+'-'+dspl[0]+"'";
+        }
+    }else if(type == "number"){
+        if (string == "") {
+            string = 'null';
+        }else {
+            string.replace(',','.');
+            string = parseFloat(string);
+        }
+    }else if(type == "boolean"){
+        if (string == "") {
+          string = 'null';
+        }
+        string= string.replace('true',"'1'");
+        string= string.replace('false',"'0'");
+    }else if(type == "month"){
+      var re = /^(\d{1,2})\.(\d{4})$/i;
+        if (!string.match(re)) {
+            string = 'null';
+        }else{
+           var dspl=string.split('.');
+            string = "'"+dspl[1]+'-'+dspl[0]+"-01'"
+        }
+    }
+    else {
+        string = string.replace('<','&lt;','g');
+        string = string.replace('>','&gt;','g');
+        string = string.replace('&','&amp;','g');
+        string = string.replace('"','&quot','g');
+        string = string.replace("'","''",'g');
+        string = "'"+ string+"'";
+    }
+    
+    return string;
+}
\ No newline at end of file
diff --git a/modules/reports/js/print_book.js b/modules/reports/js/print_book.js
new file mode 100644 (file)
index 0000000..7f3632d
--- /dev/null
@@ -0,0 +1,41 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+
+function initdata(){
+    var configdata = apppref.getpreference("pageconfig.logactivity");
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  //"Book Ident Data:" + JSON.stringify(pconfig) + "\n");
+  var windowMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+      var winmain = windowMediator.getMostRecentWindow("xulcreorga");
+      var maindoc = winmain.document.getElementById("brw_application").contentDocument;
+
+      //var xdate = new Date();
+      //$("#printdatetime").html(xdate.toLocaleFormat("%d.%m.%Y %H:%M:%S"));
+      $("#title_sub").html(winmain.document.getElementById("infoheader").value);
+
+      $("#title_main").html(maindoc.title);
+      //$("#tbl_list").css("margin-top","100px");
+      var crn = appdb.dbquery("select crechename,adress,city,country,zip from creche;");
+      crn = crn.sqldata[0];
+      $("#creche_name").html(crn.crechename);
+      $("#creche_address").html(crn.adress);
+      $("#creche_zip").html(crn.zip);
+      $("#creche_city").html(crn.city);
+      loadactivitydata();
+}
+
+function loadactivitydata(){
+  var actdatasql = "SELECT strftime('%d.%m.%Y',logdatefrom) || ' - ' || strftime('%d.%m.%Y',logdateto) as daterange, logtitle, logmessage FROM activitylog where uuid='"+ pconfig.activityuuid+"';";
+  //dump(actdatasql + "\n");
+  var data = appdb.dbquery(actdatasql);
+  $("#bookdata").append('<h2>'+ data.sqldata[0].logtitle+'</h2>');
+  $("#bookdata").append('<h4>'+ data.sqldata[0].daterange+'</h4>');
+  $("#bookdata").append('<div>'+ data.sqldata[0].logmessage+'</div>');
+}
+
+
+
diff --git a/modules/reports/js/print_calendar.js b/modules/reports/js/print_calendar.js
new file mode 100644 (file)
index 0000000..7e6e2f8
--- /dev/null
@@ -0,0 +1,35 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+function initdata(){
+  var windowMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+      var winmain = windowMediator.getMostRecentWindow("xulcreorga");
+
+      var maindoc = winmain.document.getElementById("brw_application").contentDocument;
+      
+      var xdate = new Date();
+      $("#printdatetime").html(xdate.toLocaleFormat("%d.%m.%Y %H:%M:%S"));
+      $("#title_sub").html(winmain.document.getElementById("infoheader").value);
+      $("#title_main").html(maindoc.title);
+      //$("#cal_month").css("margin-top","100px");
+      var crn = appdb.dbquery("select crechename,adress,city,country,zip from creche;");
+      crn = crn.sqldata[0];
+      $("#creche_name").html(crn.crechename);
+      $("#creche_address").html(crn.adress);
+      $("#creche_zip").html(crn.zip);
+      $("#creche_city").html(crn.city);
+      
+      var elx = maindoc.querySelectorAll('table[id^="cal_"]');
+      
+      for (var i in elx) {
+        //dump(elx[i].id + "\n");
+        if (elx[i].id) {
+          var elementdata = maindoc.getElementById(elx[i].id).innerHTML;
+          
+          //elementdata = elementdata.replace(/height:\ 0px;/g,'');
+          //elementdata = elementdata.replace(/height:0;/g,'');
+          $("#cal_month").append(elementdata);
+          //$("#tbl_list th:first-child").remove();
+          //$("#tbl_list td:first-child").remove();
+        }
+      }
+}
\ No newline at end of file
diff --git a/modules/reports/js/print_child.js b/modules/reports/js/print_child.js
new file mode 100644 (file)
index 0000000..d704637
--- /dev/null
@@ -0,0 +1,155 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+function initdata(){
+    var configdata = apppref.getpreference("pageconfig.child");
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  var windowMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+      var winmain = windowMediator.getMostRecentWindow("xulcreorga");
+      var maindoc = winmain.document.getElementById("brw_application").contentDocument;
+
+      //var xdate = new Date();
+      //$("#printdatetime").html(xdate.toLocaleFormat("%d.%m.%Y %H:%M:%S"));
+      $("#title_sub").html(winmain.document.getElementById("infoheader").value);
+
+      $("#title_main").html(maindoc.title);
+      //$("#tbl_list").css("margin-top","100px");
+      var crn = appdb.dbquery("select crechename,adress,city,country,zip from creche;");
+      crn = crn.sqldata[0];
+      $("#creche_name").html(crn.crechename);
+      $("#creche_address").html(crn.adress);
+      $("#creche_zip").html(crn.zip);
+      $("#creche_city").html(crn.city);
+
+  var cdatasql = "select child.uuid,child.clientnumber,child.prename,child.surname,strftime('%d.%m.%Y',child.birthday) as birthday,child.address,child.city,child.zip,child.country,strftime('%d.%m.%Y',child.entrydate) as entrydate,child.checkservicenumber,strftime('%d.%m.%Y',child.checkserviceexpiration) as checkserviceexpiration,strftime('%d.%m.%Y',child.leavedate) as leavedate,child.nationality,child.nativelanguage,child.bankaccount,child.bankbic,child.cautionamount,child.cautionpayed,child.cautionremark,child.cautionpayedback,child.cautionstatusdate,child.remark,child.uuid,health.docname, health.docphone,health.docaddress,health.doczip, health.doccity,health.doccountry,health.healthinfo,health.uuid as docuuid from childs child join health health on (child.uuid=health.childuuid)  where child.uuid='" + pconfig.uuid + "';";
+  var cdata = appdb.dbquery(cdatasql);
+  $('#financedata').hide();
+  if (cdata) {
+    cdata = cdata.sqldata[0];
+   var hx = true;
+  for (var ci in cdata) {
+    if (document.getElementById("childs_" + ci)) {
+      $("#childs_" + ci).html(cdata[ci]);
+    }
+    if (document.getElementById("health_" + ci)) {
+      if (cdata[ci] != '') {
+        hx = false;
+        $("#health_" + ci).html(cdata[ci]);
+      }else {
+        $("#health_" + ci).hide();
+      }
+      
+    }
+
+  }
+  if (hx) {
+    $('#healthdata').hide();
+  }
+  }
+  
+   load_table_presence();
+    load_table_parents();
+    load_table_refpersons();
+  var cdatea = new Date();
+  //$("#printdatetime").html(cdatea.toLocaleFormat("%d.%m.%Y %H:%M:%S"));
+  //$("#accmonth").html(myfilter.description);
+  var crn = appdb.dbquery("select crechename,adress,city,country,zip from creche;");
+  crn = crn.sqldata[0];
+  $("#creche_name").html(crn.crechename);
+  $("#creche_address").html(crn.adress);
+  $("#creche_zip").html(crn.zip);
+  $("#creche_city").html(crn.city);
+}
+
+function load_table_presence(){
+    var plandatasql = "SELECT grp.grpname, strftime('%d.%m.%Y',plan.datebegin) || ' - ' || strftime('%d.%m.%Y',plan.dateend) AS planningdaterange, plan.montimebegin || ' - ' || plan.montimeend || CASE WHEN plan.monlunch='1' THEN ' (<span class=\"glyphicon glyphicon-cutlery\" aria-hidden=\"true\"></span>)' ELSE '' END || case when plan.montimebegin2 is not null and plan.montimeend2 is not null then '<br/>' || plan.montimebegin2 || ' - ' || plan.montimeend2 else '' end AS monplanningtime, plan.tuetimebegin || ' - ' || plan.tuetimeend || CASE WHEN plan.tuelunch='1' THEN ' (<span class=\"glyphicon glyphicon-cutlery\" aria-hidden=\"true\"></span>)' ELSE '' END || case when plan.tuetimebegin2 is not null and plan.tuetimeend2 is not null then '<br/>' || plan.tuetimebegin2 || ' - ' || plan.tuetimeend2 else '' end AS tueplanningtime, plan.wedtimebegin || ' - ' || plan.wedtimeend || CASE WHEN plan.wedlunch='1' THEN ' (<span class=\"glyphicon glyphicon-cutlery\" aria-hidden=\"true\"></span>)' ELSE '' END || case when plan.wedtimebegin2 is not null and plan.wedtimeend2 is not null then '<br/>' || plan.wedtimebegin2 || ' - ' || plan.wedtimeend2 else '' end AS wedplanningtime, plan.thutimebegin || ' - ' || plan.thutimeend || CASE WHEN plan.thulunch='1' THEN ' (<span class=\"glyphicon glyphicon-cutlery\" aria-hidden=\"true\"></span>)' ELSE '' END || case when plan.thutimebegin2 is not null and plan.thutimeend2 is not null then '<br/>' || plan.thutimebegin2 || ' - ' || plan.thutimeend2 else '' end AS thuplanningtime, plan.fritimebegin || ' - ' || plan.fritimeend || CASE WHEN plan.frilunch='1' THEN ' (<span class=\"glyphicon glyphicon-cutlery\" aria-hidden=\"true\"></span>)' ELSE '' END || case when plan.fritimebegin2 is not null and plan.fritimeend2 is not null then '<br/>' || plan.fritimebegin2 || ' - ' || plan.fritimeend2 else '' end AS friplanningtime FROM planning plan LEFT JOIN groups grp ON ( plan.groupuuid=grp.uuid) WHERE plan.childuuid='" + pconfig.uuid + "' ORDER BY plan.datebegin, plan.dateend;";
+  var plandata = appdb.dbqueryarray(plandatasql);
+  if (plandata) {
+    var headerdata = getlabels(plandata.sqlhead.join(","));
+  $("#tbl_planning").html("");
+  var tblplan = $("#tbl_planning").dataTable({
+    "language": {
+          "url": "L../../web/js/locale/datatable_fr.json"
+        },
+    "data": plandata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "ordering": false,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+  }else {
+    $('#planningdata').hide();
+  }
+}
+
+function load_table_parents() {
+  var labelx = getlabelswithkey('mother,father');
+  var areftypes = new Array(); 
+  for (var l in labelx){
+    areftypes.push("select '"+ labelx[l].title +"' as refname, '"+labelx[l].keyname+"' as reftype");
+  }
+  var lblsql = areftypes.join(" UNION "); 
+  var parentssql = "SELECT rx.refname as reftype, coalesce(rp.surname,'') || ' ' || coalesce(rp.prename,'') as nameprename, coalesce(rp.address,'') || '<br/>' || coalesce(rp.zip,'') || ' ' || coalesce(rp.city,'') || '<br/>' || coalesce(rp.country,'') as address, case when rp.phone is not null then '<span class=\"glyphicon glyphicon-earphone\" aria-hidden=\"true\"></span>: ' || rp.phone || '<br/>' else '' end || case when rp.mobile is not null then'<span class=\"glyphicon glyphicon-phone\" aria-hidden=\"true\"></span>: ' || rp.mobile || '<br/>' else '' end || case when rp.workphone is not null then '<span class=\"glyphicon glyphicon-phone-alt\" aria-hidden=\"true\"></span>: ' || rp.workphone || '<br/>' else '' end || case when rp.email is not null then '<span class=\"glyphicon glyphicon-envelope\" aria-hidden=\"true\"></span>: ' || email else '' end as phonemail, rp.job, rp.authsubscriber FROM refpersons rp join ("+lblsql+") rx on (rp.reftype=rx.reftype)  where rp.childuuid='" + pconfig.uuid + "' and rp.reftype in ('mother','father');";
+  
+  var parentsdata = appdb.dbqueryarray(parentssql);
+  if (parentsdata) {
+    var headerdata = getlabels(parentsdata.sqlhead.join(","));
+  $("#tbl_parents").html("");
+  $("#tbl_parents").dataTable({
+"language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+    "data": parentsdata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "ordering": false,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+  }else {
+    $('#parentdata').hide();
+  }
+  
+  
+  
+}
+
+function load_table_refpersons() {
+   var labelx = getlabelswithkey('tuteur,famillymember,famillyfriend');
+  var areftypes = new Array(); 
+  for (var l in labelx){
+    areftypes.push("select '"+ labelx[l].title +"' as refname, '"+labelx[l].keyname+"' as reftype");
+  }
+  var lblsql = areftypes.join(" UNION "); 
+   var refpersonsql = "SELECT rx.refname as reftype, coalesce(rp.surname,'') || ' ' || coalesce(rp.prename,'') as nameprename, coalesce(rp.address,'') || '<br/>' || coalesce(rp.zip,'') || ' ' || coalesce(rp.city,'') || '<br/>' || coalesce(rp.country,'') as address, case when rp.phone is not null then '<span class=\"glyphicon glyphicon-earphone\" aria-hidden=\"true\"></span>: ' || rp.phone || '<br/>' else '' end || case when rp.mobile is not null then'<span class=\"glyphicon glyphicon-phone\" aria-hidden=\"true\"></span>: ' || rp.mobile || '<br/>' else '' end || case when rp.workphone is not null then '<span class=\"glyphicon glyphicon-phone-alt\" aria-hidden=\"true\"></span>: ' || rp.workphone || '<br/>' else '' end || case when rp.email is not null then '<span class=\"glyphicon glyphicon-envelope\" aria-hidden=\"true\"></span>: ' || email else '' end as phonemail, rp.job, rp.authsubscriber FROM refpersons rp join ("+lblsql+") rx on (rp.reftype=rx.reftype)  where rp.childuuid='" + pconfig.uuid + "' and rp.reftype not in ('mother','father');";
+
+  var refpersonsdata = appdb.dbqueryarray(refpersonsql);
+  if (refpersonsdata) {
+    var headerdata = getlabels(refpersonsdata.sqlhead.join(","));
+  $("#tbl_refpersons").html("");
+  $("#tbl_refpersons").dataTable({
+    "language": {
+          "url": "../../web/js/locale/datatable_fr.json"
+        },
+    "data": refpersonsdata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "ordering": false,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+  }else {
+    $('#refpersondata').hide();
+  }
+  
+  
+  
+}
+
diff --git a/modules/reports/js/print_loaddata.js b/modules/reports/js/print_loaddata.js
new file mode 100644 (file)
index 0000000..48c9de8
--- /dev/null
@@ -0,0 +1,67 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+function initdata(){
+      var windowMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+      var winmain = windowMediator.getMostRecentWindow("xulcreorga");
+      var maindoc = winmain.document.getElementById("brw_application").contentDocument;
+
+      $("#title_sub").html(winmain.document.getElementById("infoheader").value);
+
+      $("#title_main").html(maindoc.title);
+      var crn = appdb.dbquery("select crechename,adress,city,country,zip from creche;");
+      crn = crn.sqldata[0];
+      $("#creche_name").html(crn.crechename);
+      $("#creche_address").html(crn.adress);
+      $("#creche_zip").html(crn.zip);
+      $("#creche_city").html(crn.city);
+      
+      var elx = maindoc.querySelectorAll('div[id^="tbl"]');
+      //var elx = maindoc.querySelectorAll('tfoot');
+      
+      var tcols = 1;
+      var strlp = apppref.getpreference("pageconfig.lastpage");
+      var lp = JSON.parse(strlp);
+      var strcp = apppref.getpreference("pageconfig." + lp.view);
+      var cp = JSON.parse(strcp);
+      var ctab = "";
+      //"print_loaddata.js \n");
+      if (cp.activetab) {
+        ctab = cp.activetab; 
+      }
+      for (var i in elx) {
+        //dump(elx[i].id)
+        if ((elx[i].id ) && (elx[i].id.indexOf(ctab+"_wrapper") != -1)) {
+   
+          var elementdata = maindoc.getElementById(elx[i].id).innerHTML;
+          
+          elementdata = elementdata.replace(/height:\ 0px;/g,'');
+          elementdata = elementdata.replace(/height:0;/g,'');
+          elementdata = elementdata.replace(/colspan="1" rowspan="1"/g,'');
+          elementdata = elementdata.replace(/style="width:\s\d+px;"/g,'');
+
+          var thead = elementdata.substring(elementdata.indexOf('<thead>'),elementdata.indexOf('</thead>')).replace('<thead>','');
+          var tbody = elementdata.substring(elementdata.indexOf('<tbody>'),elementdata.indexOf('</tbody>')).replace('<tbody>','');
+          var tfoot = elementdata.substring(elementdata.lastIndexOf('<tfoot>'),elementdata.lastIndexOf('</tfoot>')).replace('<tfoot>','');
+
+          tcols = thead.split('</th>');
+
+          
+          
+          $("#tbl_list > thead").append(thead);
+          $("#tbl_list > tbody").append(tbody);
+          $("#tbl_list > tfoot").append(tfoot);
+           
+        }
+      }
+      //$("#tbl_list").removeClass("dataTable");
+      // $("#tbl_list").dataTable({
+      //  "language": {
+      //    "url": "../../../web/js/locale/datatable_fr.json"
+      //  },
+      //  "paging":   false,
+      //  "ordering": false,
+      //  "info":     false,
+      //  "filter": false,
+      //  "destroy": true
+      //});
+}
\ No newline at end of file
diff --git a/modules/reports/js/print_logchild.js b/modules/reports/js/print_logchild.js
new file mode 100644 (file)
index 0000000..9fd5b9a
--- /dev/null
@@ -0,0 +1,45 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+var initdate = new Date();
+
+function initdata(){
+    
+    var configdata = apppref.getpreference("pageconfig.logchild");
+  if (configdata != '') {
+    pconfig = JSON.parse(configdata);
+  }
+  var windowMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+      var winmain = windowMediator.getMostRecentWindow("xulcreorga");
+      var maindoc = winmain.document.getElementById("brw_application").contentDocument;
+      initdate = new Date(encodeparam(pconfig.logdate, 'date').replace(/'/g, ''));
+      //var xdate = new Date();
+      //$("#printdatetime").html(xdate.toLocaleFormat("%d.%m.%Y %H:%M:%S"));
+     
+      $("#title_sub").html(pconfig.logdate);
+
+      $("#title_main").html(maindoc.title);
+      //$("#tbl_list").css("margin-top","100px");
+      var crn = appdb.dbquery("select crechename,adress,city,country,zip from creche;");
+      crn = crn.sqldata[0];
+      $("#creche_name").html(crn.crechename);
+      $("#creche_address").html(crn.adress);
+      $("#creche_zip").html(crn.zip);
+      $("#creche_city").html(crn.city);
+      
+      load_table_logchilds();
+}
+
+function load_table_logchilds(){
+    var logsql = "select  ch.prename || ' ' || ch.surname AS childname, ch.checkservicenumber,lc.logmessage from childs ch left join planning pl on (ch.uuid=pl.childuuid) left join childslog lc on (lc.childuuid=ch.uuid) where date('"+ initdate.toLocaleFormat('%Y-%m-%d')+"') between pl.datebegin and pl.dateend and lc.logmessage is not null and lc.logmessage != '' order by childname;";
+    
+    var logdata = appdb.dbquery(logsql);
+    
+    for (var i in logdata.sqldata){
+        var row = logdata.sqldata[i];
+        //"initdata print_logchild! " + JSON.stringify(row)+"\n");
+        var divd = '<div class="row panel panel-default"><div class="panel-heading"><strong>'+ row.childname + '</strong> ('+ row.checkservicenumber + ')'+'</div>';
+        divd += '<div class="panel-body">'+ row.logmessage+'</div></div>';
+        $("#div_data").append(divd);
+    }
+}
\ No newline at end of file
diff --git a/modules/reports/js/print_multilist.js b/modules/reports/js/print_multilist.js
new file mode 100644 (file)
index 0000000..605dc5a
--- /dev/null
@@ -0,0 +1,75 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+function initdata(){
+      var windowMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+      var winmain = windowMediator.getMostRecentWindow("xulcreorga");
+      var maindoc = winmain.document.getElementById("brw_application").contentDocument;
+
+      $("#title_sub").html(winmain.document.getElementById("infoheader").value);
+
+      $("#title_main").html(maindoc.title);
+      var crn = appdb.dbquery("select crechename,adress,city,country,zip from creche;");
+      crn = crn.sqldata[0];
+      $("#creche_name").html(crn.crechename);
+      $("#creche_address").html(crn.adress);
+      $("#creche_zip").html(crn.zip);
+      $("#creche_city").html(crn.city);
+      
+      var elx = maindoc.querySelectorAll('div[id^="tbl"]');
+      //var elx = maindoc.querySelectorAll('tfoot');
+      //"print_multilist.js \n");
+      var tcols = 1;
+      var strlp = apppref.getpreference("pageconfig.lastpage");
+      var lp = JSON.parse(strlp);
+      var strcp = apppref.getpreference("pageconfig." + lp.view);
+      var cp = JSON.parse(strcp);
+      var ctab = "";
+      //dump(JSON.stringify(cp) + "\n");
+      var getpagedesign=$("#allpages").html();
+      //dump(getpagedesign + "\n===============\n");
+      var cnt = 1;
+      $("#allpages").html("");
+      for (var i in elx) {
+      //  //dump(elx[i].id)
+        if ((elx[i].id ) && (elx[i].id.indexOf(ctab+"_wrapper") != -1)) {
+          var npage = getpagedesign.replace(/_xxnum/g,cnt);
+          
+          var elementdata = maindoc.getElementById(elx[i].id).innerHTML;
+          //
+          elementdata = elementdata.replace(/height:\ 0px;/g,'');
+          elementdata = elementdata.replace(/height:0;/g,'');
+          elementdata = elementdata.replace(/colspan="1" rowspan="1"/g,'');
+          elementdata = elementdata.replace(/style="width:\s\d+px;"/g,'');
+          //
+          var thead = elementdata.substring(elementdata.indexOf('<thead>'),elementdata.indexOf('</thead>')).replace('<thead>','');
+          var tbody = elementdata.substring(elementdata.indexOf('<tbody>'),elementdata.indexOf('</tbody>')).replace('<tbody>','');
+          var tfoot = elementdata.substring(elementdata.lastIndexOf('<tfoot>'),elementdata.lastIndexOf('</tfoot>')).replace('<tfoot>','');
+          //
+          //tcols = thead.split('</th>');
+          //dump(tbody + "\n========\n");
+          //
+          //
+          if (tbody.indexOf("dataTables_empty") == -1) {
+            $("#allpages").append(npage);
+            $("#tbl_list"+cnt+" > thead").append(thead);
+            $("#tbl_list"+cnt+" > tbody").append(tbody);
+            $("#tbl_list"+cnt+" > tfoot").append(tfoot);
+            
+            $("#tbl_list" + cnt).dataTable({
+              "language": {
+                "url": "../../../web/js/locale/datatable_fr.json"
+              },
+              "paging":   false,
+              "ordering": false,
+              "info":     false,
+              "filter": false,
+              "destroy": true
+            });
+            cnt++;
+          }
+          
+        }
+      }
+      $('[id$="lunch"]').removeClass('btn-success');
+      $('[id$="lunch"]').addClass('btn-default');
+}
\ No newline at end of file
diff --git a/modules/reports/js/print_table.js b/modules/reports/js/print_table.js
new file mode 100644 (file)
index 0000000..525aeb5
--- /dev/null
@@ -0,0 +1,92 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+function initdata(){
+      var windowMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+                     .getService(Components.interfaces.nsIWindowMediator);
+      var winmain = windowMediator.getMostRecentWindow("xulcreorga");
+      var maindoc = winmain.document.getElementById("brw_application").contentDocument;
+
+      $("#title_sub").html(winmain.document.getElementById("infoheader").value);
+
+      $("#title_main").html(maindoc.title);
+      var crn = appdb.dbquery("select crechename,adress,city,country,zip from creche;");
+      crn = crn.sqldata[0];
+      $("#creche_name").html(crn.crechename);
+      $("#creche_address").html(crn.adress);
+      $("#creche_zip").html(crn.zip);
+      $("#creche_city").html(crn.city);
+      
+      var elx = maindoc.querySelectorAll('table[id="tbl_timetable"]');
+      //var elx = maindoc.querySelectorAll('tfoot');
+      
+      var tcols = 1;
+      var strlp = apppref.getpreference("pageconfig.lastpage");
+      var lp = JSON.parse(strlp);
+      var strcp = apppref.getpreference("pageconfig." + lp.view);
+      var cp = JSON.parse(strcp);
+      var ctab = "";
+      //dump(JSON.stringify(cp) + "\n");
+      //if (cp.activetab) {
+      //  ctab = cp.activetab; 
+      //}
+      //var elx = maindoc.querySelectorAll('table[id^="cal_"]');
+      for (var i in elx) {
+        if (elx[i].id) {
+          var elementdata = maindoc.getElementById(elx[i].id).innerHTML;
+          //elementdata = elementdata.replace(/height:\ 0px;/g,'');
+          //elementdata = elementdata.replace(/height:0;/g,'');
+          $("#tbl_list").append(elementdata);
+          //$("#tbl_list th:first-child").remove();
+          //$("#tbl_list td:first-child").remove();
+        }
+      }
+      
+      //$('td').each(function(){
+      //  if($(this).attr('colspan') > 1){
+      //    var ccol = $(this).attr('colspan');
+      //    $(this).attr('colspan',ccol -1);
+      //  }
+      //});
+      //$('th').each(function(){
+      //  if($(this).attr('colspan') > 1){
+      //    var ccol = $(this).attr('colspan');
+      //    $(this).attr('colspan',ccol -1);
+      //  }
+      //});
+
+
+      //for (var i in elx) {
+      //  //dump(elx[i].id)
+      //  if ((elx[i].id ) && (elx[i].id.indexOf(ctab+"_wrapper") != -1)) {
+      //
+      //    var elementdata = maindoc.getElementById(elx[i].id).innerHTML;
+      //    
+      //    elementdata = elementdata.replace(/height:\ 0px;/g,'');
+      //    elementdata = elementdata.replace(/height:0;/g,'');
+      //    elementdata = elementdata.replace(/colspan="1" rowspan="1"/g,'');
+      //    elementdata = elementdata.replace(/style="width:\s\d+px;"/g,'');
+      //
+      //    var thead = elementdata.substring(elementdata.indexOf('<thead>'),elementdata.indexOf('</thead>')).replace('<thead>','');
+      //    var tbody = elementdata.substring(elementdata.indexOf('<tbody>'),elementdata.indexOf('</tbody>')).replace('<tbody>','');
+      //    var tfoot = elementdata.substring(elementdata.lastIndexOf('<tfoot>'),elementdata.lastIndexOf('</tfoot>')).replace('<tfoot>','');
+      //
+      //    tcols = thead.split('</th>');
+      //
+      //    
+      //    
+      //    $("#tbl_list > thead").append(thead);
+      //    $("#tbl_list > tbody").append(tbody);
+      //    $("#tbl_list > tfoot").append(tfoot);
+      //     
+      //  }
+      //}
+      // $("#tbl_list").dataTable({
+      //  "language": {
+      //    "url": "../../../web/js/locale/datatable_fr.json"
+      //  },
+      //  "paging":   false,
+      //  "ordering": false,
+      //  "info":     false,
+      //  "filter": false,
+      //  "destroy": true
+      //});
+}
\ No newline at end of file
diff --git a/modules/reports/js/printpdf.js b/modules/reports/js/printpdf.js
new file mode 100644 (file)
index 0000000..c178594
--- /dev/null
@@ -0,0 +1,85 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var printpdf = {
+  //onLoad: function() {
+  //  // initialization code
+  //  this.initialized = true;
+  //  this.strings     = document.getElementById("printpdf-strings");
+  //  this.prefs       = Components.classes["@mozilla.org/preferences-service;1"]
+  //                            .getService(Components.interfaces.nsIPrefBranch).getBranch("extensions.printpdf@pavlov.");
+  //},
+  onMenuItemCommand: function(fpath,fname,e) {
+    var nsIFilePicker = Components.interfaces.nsIFilePicker;
+    var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+    picker.init(window, "Save Document as PDF", nsIFilePicker.modeSave);
+    picker.appendFilter("PDF", "*.pdf");
+    picker.defaultExtension = "pdf";
+    picker.defaultString = content.document.title;
+
+    picker.show();
+
+    var webBrowserPrint = window.content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+    .getInterface(Components.interfaces.nsIWebBrowserPrint);
+
+    var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
+    .getService(Components.interfaces.nsIPrintSettingsService);
+    
+    var printSettings = PSSVC.newPrintSettings;
+    
+    printSettings.printToFile = true;
+    printSettings.toFileName  = picker.file.path;
+    printSettings.printSilent = true;
+    printSettings.outputFormat = Components.interfaces.nsIPrintSettings.kOutputFormatPDF;
+    
+    // Added by bho
+    //var myPrintPrefs  = printpdf.getPrintingPrefs();
+    printSettings.printBGColors = true;
+    printSettings.printBGImages = true;
+    printSettings.unwriteableMarginTop = 0.5;
+    printSettings.unwriteableMarginLeft = 0.5;
+    printSettings.unwriteableMarginBottom = 0.5;
+    printSettings.unwriteableMarginRight = 0.5;
+    printSettings.marginTop = 0.2; /*  these are in inches */
+    printSettings.marginLeft = 0.2;
+    printSettings.marginBottom = 0.2;
+    printSettings.marginRight = 0.2;
+    //printSettings.shrinkToFit;
+    printSettings.paperName = "iso_a4"; /* name of paper */
+    printSettings.paperSizeType = 1; /* use native data or is defined here */
+    //printSettings.paperData = 9;     /* native data value */
+    printSettings.orientation = 1;
+    //"PDF Orientation:" + printSettings.orientation + "\n");
+    if (printSettings.orientation == 1) {
+      printSettings.paperWidth = 297.0; /* width of the paper in inches or mm */
+      printSettings.paperHeight = 210.0; /* height of the paper in inches or mm */
+
+    } else {
+      printSettings.paperWidth = 210.0; /* width of the paper in inches or mm */
+      printSettings.paperHeight = 297.0; /* height of the paper in inches or mm */
+    }
+    printSettings.paperSizeUnit = 1; /* paper is in inches or mm */
+    //lets hide those ugly default headers
+    printSettings.footerStrCenter = '';
+    printSettings.footerStrLeft = '';
+    printSettings.footerStrRight = '';
+    printSettings.headerStrCenter = '';
+    printSettings.headerStrLeft = '';
+    printSettings.headerStrRight = '';
+    //}
+    // END: Added by bho
+
+    webBrowserPrint.print(printSettings, null);
+  }
+  //onToolbarButtonCommand: function(e) {
+  //  // just reuse the function above.  you can change this, obviously!
+  //  printpdf.onMenuItemCommand(e);
+  //},
+  //getPrintingPrefs: function (){
+  //    return {
+  //        showBGColor: this.prefs.getBoolPref("print.showBGColors"),
+  //        showBGImages: this.prefs.getBoolPref("print.showBGImages"),
+  //        showHeaders: this.prefs.getBoolPref("print.showHeaders")
+  //    };
+  //}
+
+};
+//window.addEventListener("load", function(e) { printpdf.onLoad(e); }, false);
diff --git a/modules/reports/js/printutils.js b/modules/reports/js/printutils.js
new file mode 100644 (file)
index 0000000..d3ac722
--- /dev/null
@@ -0,0 +1,41 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var printmanager = {
+  onprint: function() {
+    var sprdata = apppref.getpreference("pageconfig.lastpage");
+    var prdata = JSON.parse(sprdata);
+    var spldata = apppref.getpreference("pageconfig." + prdata.view);
+    var pldata = JSON.parse(spldata);
+    if (!pldata.printlayout) {
+      //dump(prdata.module +" "+prdata.view+": Sorry, no printlayout defined!\n");
+    }else {
+       //dump(JSON.stringify(pldata) + "\n");
+       printmanager.load_printpreview("chrome://creorga/content/modules/reports/print_" +pldata.printlayout + ".html");
+    }
+  },
+  load_pdf: function(data){
+    var params = { in : {
+        "uri": data.uri
+      },
+      out: null
+    };
+    var dlg = window.openDialog("chrome://creorga/content/modules/reports/dlg/dlgpdfviewer.xul", "dlgpdfviewer",
+      "chrome,centerscreen,resizable,scrollbars", params).focus();
+    if (params.out) {
+      //code
+    }
+  },
+  load_printpreview: function(path) {
+    var params = { in : {
+        "uri": path
+    },
+      out: null
+    };
+    var dlg = window.openDialog("chrome://creorga/content/modules/reports/dlg/dlgprint.xul", "dlgprint",
+      "chrome,centerscreen,resizable,scrollbars,modal", params).focus();
+    if (params.out) {
+      if (params.out.reload == true) {
+        printmanager.load_printpreview(params.in.uri,params.in.type);
+      }
+    }
+  },
+}
\ No newline at end of file
diff --git a/modules/reports/print_book.html b/modules/reports/print_book.html
new file mode 100644 (file)
index 0000000..248f817
--- /dev/null
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>Creorga - Enfant</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="cache-control" content="max-age=0" />
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="expires" content="0" />
+    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+    <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+    <link href="../../web/css/jquery.dataTables.min.css" rel="stylesheet" type="text/css">
+    <link href="../../web/css/jquery.dataTables_themeroller.css" rel="stylesheet" type="text/css">
+    <link href="css/print.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+    <div style="width: 100%;">
+      <table style="width: 100%;" id="pagehead"><tr><td style="width: 200px; text-align: left; ">
+                <img src="img/logoprint.png" />
+                </td>
+      <td style="text-align: center;"><h2 id="title_main"></h2><h3 id="title_sub"></h3></td>
+                <td style="text-align: right;">
+                  <div style="text-align: left;"><span id="creche_name">Creche</span><br/>
+                  <span id="creche_address">address</span><br/>
+                  <span id="creche_zip">CP</span>&nbsp;<span id="creche_city">City</span></div>
+                </td>
+                </tr>
+                </table>
+    </div>
+    <div id="bookdata">
+      
+    </div>
+    <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+    <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    <script src="js/print.js" type="text/javascript"></script>
+    <script src="js/print_book.js" type="text/javascript"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/modules/reports/print_calendar.html b/modules/reports/print_calendar.html
new file mode 100644 (file)
index 0000000..c834e6f
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>Creorga - Printing - List</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="cache-control" content="max-age=0" />
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="expires" content="0" />
+    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+    <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+    <link href="../../web/css/jquery.dataTables.min.css" rel="stylesheet" type="text/css">
+    <!--<link href="../../web/css/jquery.dataTables_themeroller.css" rel="stylesheet" type="text/css">-->
+    <link href="css/print.css" rel="stylesheet" type="text/css">
+    <link href="../../web/css/calendar.css" rel="stylesheet" type="text/css">
+    <style>
+      .panel-daybody {
+  height: 10.5vh;
+  max-height: 10.5vh;
+  overflow-y: auto;
+  padding: 3px;
+}
+    </style>
+</head>
+
+<body>
+  <div style="width: 100%;">
+      <table style="width: 100%;" id="pagehead"><tr><td style="width: 200px; text-align: left;">
+                <img src="img/logoprint.png" />
+                </td>
+      <td style="text-align: center;"><h2 id="title_main"></h2><h3 id="title_sub"></h3></td>
+                <td style="text-align: right; ">
+                  <div style="text-align: left;"><span id="creche_name">Creche</span><br/>
+                  <span id="creche_address">address</span><br/>
+                  <span id="creche_zip">CP</span>&nbsp;<span id="creche_city">City</span></div>
+                </td>
+                </tr>
+                </table>
+    </div>
+  <table class="table table-bordered" id="cal_month" style="width: 100%;">
+    </table>
+    
+    <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+    <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    <script src="js/print.js" type="text/javascript"></script>
+    <script src="js/print_calendar.js" type="text/javascript"></script>
+    <script src="../../web/js/labels.js" type="text/javascript"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/modules/reports/print_child.html b/modules/reports/print_child.html
new file mode 100644 (file)
index 0000000..4e2c4d6
--- /dev/null
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>Creorga - Enfant</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="cache-control" content="max-age=0" />
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="expires" content="0" />
+    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+    <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+    <link href="../../web/css/jquery.dataTables.min.css" rel="stylesheet" type="text/css">
+    <link href="../../web/css/jquery.dataTables_themeroller.css" rel="stylesheet" type="text/css">
+    <link href="css/print.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+    <div style="width: 100%;">
+      <table style="width: 100%;" id="pagehead"><tr><td style="width: 200px; text-align: left; ">
+                <img src="img/logoprint.png" />
+                </td>
+      <td style="text-align: center;"><h2 id="title_main"></h2><h3 id="title_sub"></h3></td>
+                <td style="text-align: right;">
+                  <div style="text-align: left;"><span id="creche_name">Creche</span><br/>
+                  <span id="creche_address">address</span><br/>
+                  <span id="creche_zip">CP</span>&nbsp;<span id="creche_city">City</span></div>
+                </td>
+                </tr>
+                </table>
+    </div>
+    <div id="childdata" style="margin-top: 20px;">
+        <h2>Données de base</h2>
+        <table class="table table-striped">
+            <tbody>
+                <tr><td>Prénom</td><th id="childs_prename"></th></tr>
+                <tr><td>Nom</td><th id="childs_surname"></th></tr>
+                <tr><td>Date de naissance</td><th id="childs_birthday"></th></tr>
+                <tr><td>No. Check Service</td><th id="childs_checkservicenumber"></th></tr>
+                <tr><td>Date d'expiration</td><th id="childs_checkserviceexpiration"></th></tr>
+                <tr><td>No. Client</td><th id="childs_clientnumber"></th></tr>
+                <tr><td>Addresse</td><th id="childs_address"></th></tr>
+                <tr><td>Code Postale</td><th id="childs_zip"></th></tr>
+                <tr><td>Ville</td><th id="childs_city"></th></tr>
+                <tr><td>Pays</td><th id="childs_country"></th></tr>
+                <tr><td>Nationalité</td><th id="childs_nationality"></th></tr>
+                <tr><td>Langue maternelle</td><th id="childs_nativelanguage"></th></tr>
+                <tr><td>Remarque</td><th id="childs_remark"></th></tr>
+            </tbody>
+        </table>
+    </div>
+    
+    <div  id="parentdata" style="padding-top: 20px;">
+        <h2>Données parents / personnes de référence</h2>
+        <div id="tbl_parents_wrapper" class="dataTables_wrapper" style="width: 100%;">
+            
+            <table class="display dataTable cell-border" style="width: 100%;" id="tbl_parents" role="grid">
+              
+            </table>
+          </div>
+    </div>
+
+    <div  id="refpersondata" style="padding-top: 20px;">
+        <h2>Données personnes de réferences/authorisées</h2>
+        <div id="tbl_refpersons_wrapper" class="dataTables_wrapper" style="width: 100%;">
+            
+            <table class="display dataTable cell-border" style="width: 100%;" id="tbl_refpersons" role="grid">
+              
+            </table>
+          </div>
+    </div>
+
+    <div id="planningdata" style="padding-top: 20px;">
+        <h2>Info Planning</h2>
+        <table>
+            <tbody>
+                <tr><td>Date d'entrée</td><td id="childs_entrydate"></td></tr>
+                <tr><td>Date de sortie</td><td id="childs_leavedate"></td></tr>
+                
+            </tbody>
+        </table>
+        <div id="tbl_planning_wrapper" class="dataTables_wrapper" style="width: 100%;">
+            
+            <table class="display dataTable cell-border" style="width: 100%;" id="tbl_planning" role="grid">
+              
+            </table>
+          </div>
+    </div>
+
+    <div id="healthdata" style="padding-top: 20px;">
+        <h2>Info Santé</h2>
+        <table class="table table-striped">
+            <tbody>
+                <tr><td>Médecin de famille</td><th id="health_docname"></th></tr>
+                <tr><td>Téléphone</td><th id="health_docphone"></th></tr>
+                <tr><td>Adr. cabinet</td><th id="health_docaddress"></th></tr>
+                <tr><td>Code Postale</td><th id="health_doczip"></th></tr>
+                <tr><td>Ville</td><th id="health_doccity"></th></tr>
+                <tr><td>Pays</td><th id="health_doccountry"></th></tr>
+                <tr><td>Info Santé</td><th id="health_healthinfo"></th></tr>
+            </tbody>
+        </table>    
+    </div>
+   
+    <div id="financedata" style="padding-top: 20px;">
+        <h2>Info fincances/caution</h2>
+        <table class="table table-striped">
+            <tbody>
+                <tr><td>Somme totale</td><td id="health_docname"></td></tr>
+                <tr><td>Somme payé</td><td id="health_docphone"></td></tr>
+                <tr><td>Somme remboursé</td><td id="health_docaddress"></td></tr>
+                <tr><td>Date Status</td><td id="health_doczip"></td></tr>
+                <tr><td>Compte bancaire</td><td id="health_doccity"></td></tr>
+                <tr><td>BIC</td><td id="health_doccountry"></td></tr>
+                <tr><td>Remarque</td><td id="health_healthinfo"></td></tr>
+            </tbody>
+        </table>   
+    </div>
+    
+    
+    
+    <!--<div id="print-foot">
+      Date: <span id="printdatetime">00.00.0000 00:00</span>&nbsp;&nbsp;-&nbsp;Page: 
+    </div>-->
+    <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+    <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    <script src="js/print.js" type="text/javascript"></script>
+    <script src="js/print_child.js" type="text/javascript"></script>
+    <script src="../../web/js/labels.js" type="text/javascript"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/modules/reports/print_list.html b/modules/reports/print_list.html
new file mode 100644 (file)
index 0000000..13a8de5
--- /dev/null
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>Creorga - Printing - List</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="cache-control" content="max-age=0" />
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="expires" content="0" />
+    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+    <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+    <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+    <link href="../../web/css/glyphicons.css" rel="stylesheet">
+    <!--<link href="../../web/css/jquery.dataTables_themeroller.css" rel="stylesheet" type="text/css">-->
+    <link href="css/print.css" rel="stylesheet" type="text/css">
+    <link href="../../web/css/calendar.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+    <div style="width: 100%;">
+      <table style="width: 100%;" id="pagehead"><tr><td style="width: 200px; text-align: left;">
+                <img src="img/logoprint.png" />
+                </td>
+      <td style="text-align: center;"><h2 id="title_main"></h2><h3 id="title_sub"></h3></td>
+                <td style="text-align: right; ">
+                  <div style="text-align: left;"><span id="creche_name">Creche</span><br/>
+                  <span id="creche_address">address</span><br/>
+                  <span id="creche_zip">CP</span>&nbsp;<span id="creche_city">City</span></div>
+                </td>
+                </tr>
+                </table>
+    </div>
+    <table class="dataTable row-border cell-border stripe" tyle="width: 100%;" id="tbl_list" role="grid">
+    <thead style="margin-top: 200px;"></thead>
+    <tbody>
+      
+    </tbody>
+    <tfoot>
+      
+    </tfoot>
+    </table>
+    <!--<div id="print-head" style="width: 100%;">
+      <table style="width: 100%;" id="pagehead"><tr><td style="width: 200px; text-align: left;">
+                <img src="img/logoprint.png" />
+                </td>
+      <td style="text-align: center;"><h2 id="title_main"></h2><h3 id="title_sub"></h3></td>
+                <td style="text-align: right; ">
+                  <div style="text-align: left;"><span id="creche_name">Creche</span><br/>
+                  <span id="creche_address">address</span><br/>
+                  <span id="creche_zip">CP</span>&nbsp;<span id="creche_city">City</span></div>
+                </td>
+                </tr>
+                </table>
+    </div>-->
+    <!--<div id="print-foot">
+      Date: <span id="printdatetime">00.00.0000 00:00</span>&nbsp;&nbsp;-&nbsp;Page:&nbsp;
+    </div>-->
+    <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+    <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+    <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    <script src="js/print.js" type="text/javascript"></script>
+    <script src="js/print_loaddata.js" type="text/javascript"></script>
+    <script src="../../web/js/labels.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/reports/print_logchild.html b/modules/reports/print_logchild.html
new file mode 100644 (file)
index 0000000..f41f7bf
--- /dev/null
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>Creorga - Logbook</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="cache-control" content="max-age=0" />
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="expires" content="0" />
+    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+    <link href="css/print.css" rel="stylesheet" type="text/css">
+    <style>
+        .panel-heading {
+            background-color: #969696 !important;
+    }
+    </style>
+</head>
+
+<body>
+    <div style="width: 100%;">
+      <table style="width: 100%;" id="pagehead"><tr><td style="width: 200px; text-align: left; ">
+                <img src="img/logoprint.png" />
+                </td>
+      <td style="text-align: center;"><h2 id="title_main"></h2><h3 id="title_sub"></h3></td>
+                <td style="text-align: right;">
+                  <div style="text-align: left;"><span id="creche_name">Creche</span><br/>
+                  <span id="creche_address">address</span><br/>
+                  <span id="creche_zip">CP</span>&nbsp;<span id="creche_city">City</span></div>
+                </td>
+                </tr>
+                </table>
+    </div>
+    <div id="div_data" style="margin-top: 20px;"></div>
+    <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+    <!--<script src="../../web/js/datatables.min.js" type="text/javascript"></script>-->
+    <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    <script src="js/print.js" type="text/javascript"></script>
+    <script src="js/print_logchild.js" type="text/javascript"></script>
+    <script src="../../web/js/labels.js" type="text/javascript"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/modules/reports/print_multilist.html b/modules/reports/print_multilist.html
new file mode 100644 (file)
index 0000000..8b7a52b
--- /dev/null
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>Creorga - Printing - MultiList</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="cache-control" content="max-age=0" />
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="expires" content="0" />
+    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+    <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+    <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+    <!--<link href="../../web/css/glyphicons.css" rel="stylesheet">-->
+    <!--<link href="../../web/css/jquery.dataTables_themeroller.css" rel="stylesheet" type="text/css">-->
+    <link href="css/print.css" rel="stylesheet" type="text/css">
+    <style>
+      .mpage {
+        page-break-after: always;
+      }
+    </style>
+</head>
+
+<body>
+    <div id="allpages">
+    <div id="page_xxnum" class="mpage">
+    <div style="width: 100%;">
+      <table style="width: 100%;" id="pagehead"><tr><td style="width: 200px; text-align: left;">
+                <img src="img/logoprint.png" />
+                </td>
+      <td style="text-align: center;"><h2 id="title_main"></h2><h3 id="title_sub"></h3></td>
+                <td style="text-align: right; ">
+                  <div style="text-align: left;"><span id="creche_name">Creche</span><br/>
+                  <span id="creche_address">address</span><br/>
+                  <span id="creche_zip">CP</span>&nbsp;<span id="creche_city">City</span></div>
+                </td>
+                </tr>
+                </table>
+    </div>
+    <h2 id="page_title"></h2>
+    <table class="dataTable row-border cell-border stripe" tyle="width: 100%;" id="tbl_list_xxnum" role="grid">
+    <thead style="margin-top: 200px;"></thead>
+    <tbody>
+      
+    </tbody>
+    <tfoot>
+      
+    </tfoot>
+    
+    </table>
+    </div>
+    </div>
+    <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+    <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+    <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    <script src="js/print.js" type="text/javascript"></script>
+    <script src="js/print_multilist.js" type="text/javascript"></script>
+    <script src="../../web/js/labels.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/reports/print_table.html b/modules/reports/print_table.html
new file mode 100644 (file)
index 0000000..d4a0374
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>Creorga - Printing - Table</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="cache-control" content="max-age=0" />
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="expires" content="0" />
+    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+    <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+    <!--<link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">-->
+    <link href="../../web/css/glyphicons.css" rel="stylesheet">
+    <!--<link href="../../web/css/jquery.dataTables_themeroller.css" rel="stylesheet" type="text/css">-->
+    <link href="css/print.css" rel="stylesheet" type="text/css">
+    <link href="../../web/css/calendar.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+    <div style="width: 100%;">
+      <table style="width: 100%;" id="pagehead"><tr><td style="width: 200px; text-align: left;">
+                <img src="img/logoprint.png" />
+                </td>
+      <td style="text-align: center;"><h2 id="title_main"></h2><h3 id="title_sub"></h3></td>
+                <td style="text-align: right; ">
+                  <div style="text-align: left;"><span id="creche_name">Creche</span><br/>
+                  <span id="creche_address">address</span><br/>
+                  <span id="creche_zip">CP</span>&nbsp;<span id="creche_city">City</span></div>
+                </td>
+                </tr>
+                </table>
+    </div>
+    <table class="table table-bordered table-striped" style="width: 100%;" id="tbl_list" role="grid">
+
+    </table>
+    <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+    <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+    <script src="js/print.js" type="text/javascript"></script>
+    <script src="js/print_table.js" type="text/javascript"></script>
+    <script src="../../web/js/labels.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/reports/reports.xul b/modules/reports/reports.xul
new file mode 100644 (file)
index 0000000..7f9abec
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_reports" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <script type="application/javascript" src="chrome://creorga/content/modules/reports/js/printutils.js" />
+  <script type="application/javascript" src="chrome://creorga/content/modules/reports/js/printpdf.js" />
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton class="btn btn-default" id="tbb_print" insertafter="tbb_space" label="Impression" image="modules/reports/img/print.png" orient="vertical" oncommand="printmanager.onprint();"/>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/settings/db.html b/modules/settings/db.html
new file mode 100644 (file)
index 0000000..4eadb91
--- /dev/null
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <title>Database - Settings</title>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="../../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../node_modules/bootstrap-table/dist/bootstrap-table.min.css" rel="stylesheet" type="text/css">
+  <link href="../../node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css" rel="stylesheet" type="text/css">
+  <link href="../../css/creorga.epic.css" rel="stylesheet" type="text/css">
+  <link href="../../css/app.css" rel="stylesheet" type="text/css">
+  </head>
+  <body>
+    <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
+      <button class="btn btn-primary" onclick="parent.userapp.loadmodule('settings');"><i class="fas fa-chevron-left"></i><br/>retour</button>
+      <a class="navbar-brand" href="#">Configuration - Base de donnée</a>
+      <div class="ml-auto">
+        <div class="btn-group" role="group" aria-label="Basic example">
+            <button class="btn btn-primary" onclick="db_test();"><i class="fas fa-plus"></i><br/>Tester Connection</button>
+            <button class="btn btn-primary" onclick="db_save();"><i class="fas fa-plus"></i><br/>Sauvegarder</button>
+            <button class="btn btn-primary" onclick="db_import();"><i class="fas fa-plus"></i><br/>importer</button>
+            <button class="btn btn-primary" onclick="db_export();"><i class="fas fa-plus"></i><br/>exporter</button>
+        </div>
+      </div>
+    </nav>
+    <div class="cotainer-fluid" style="margin-top: 52px;">
+    <div class="row justify-content-center">
+        <div class="col-md-6">
+            <div class="form-group">
+                <label for="name">Nom</label>
+                <input type="text" id="name"  name="name" class="form-control">
+            </div>
+            <div class="form-group">
+                <label for="name">Type</label>
+                <select id="type" name="type" class="form-control">
+                    <option value="http">LAN</option>
+                    <option value="https">Cloud</option>
+                </select>
+            </div>
+            <div class="form-group">
+                <label for="name">Server</label>
+                <input type="text" id="server"  name="server" class="form-control">
+            </div>
+            <div class="form-group">
+                <label for="name">Base de donnée</label>
+                <input type="text" id="db"  name="db" class="form-control">
+            </div>
+            <div class="form-group">
+                <label for="login">Login</label>
+                <input type="text" id="login"  name="login" class="form-control">
+            </div>
+            <div class="form-group">
+                <label for="login">Mot de passe</label>
+                <input type="password" id="pwd"  name="pwd" class="form-control">
+            </div>
+        </div>
+    </div>
+      <!-- <div class="row">
+        <div class="col-sm-12">
+          <div class="card">
+            <div class="card-heading">
+              <h3 class="cadr-title">&nbsp;Informations Utiles</h3>
+            </div>
+            <div class="card-body" id="infopanel">
+              pas d'informations utiles pour l'instant!
+            </div>
+          </div>
+        </div>
+      </div> -->
+    </div>
+    <script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
+    <script src="../../node_modules/jquery/dist/jquery.min.js" type="text/javascript"></script>
+    <script src="../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
+    <script src="../../node_modules/bootstrap-table/dist/bootstrap-table.min.js"></script>
+    <script src="../../node_modules/@fortawesome/fontawesome-free/js/all.min.js"></script>
+    <script src="../../js/moduleglobal.js"></script>
+    <!-- <script src="../../js/database.js"></script> -->
+    <!--<script src="chrome://creorga/content/js/tools.js" type="text/javascript"></script>-->
+    <!-- <script src="js/creorga.js" type="text/javascript"></script> -->
+    <!-- <script src="js/labels.js" type="text/javascript"></script> -->
+    <script src="dbconfig.js" type="text/javascript"></script>
+    <script>if (window.module) module = window.module;</script>
+  </body>
+</html>
+
diff --git a/modules/settings/dbconfig.js b/modules/settings/dbconfig.js
new file mode 100644 (file)
index 0000000..361a038
--- /dev/null
@@ -0,0 +1,7 @@
+function initpage(){
+    
+}
+
+var dbconfig = {
+
+} 
\ No newline at end of file
diff --git a/modules/settings/index.html b/modules/settings/index.html
new file mode 100644 (file)
index 0000000..f9a2741
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <title>Dashboard</title>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link href="../../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../node_modules/bootstrap-table/dist/bootstrap-table.min.css" rel="stylesheet" type="text/css">
+  <link href="../../node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css" rel="stylesheet" type="text/css">
+  <link href="../../css/creorga.epic.css" rel="stylesheet" type="text/css">
+  <link href="../../css/app.css" rel="stylesheet" type="text/css">
+  </head>
+  <body>
+    <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
+      <a class="navbar-brand" href="#">Configuration</a>
+      <div class="ml-auto">
+        <div class="btn-group" role="group" aria-label="Basic example">
+                <button class="btn btn-primary" onclick="db_import();"><i class="fas fa-plus"></i><br/>importer</button>
+                <button class="btn btn-primary" onclick="db_export();"><i class="fas fa-plus"></i><br/>exporter</button>
+                <button class="btn btn-primary" onclick="db_new();"><i class="fas fa-plus"></i><br/>nouv.</button>
+                <button class="btn btn-primary" onclick="db_edit();"><i class="fas fa-edit"></i><br/>édit.</button>
+                <button class="btn btn-primary" onclick="db_delete();"><i class="fas fa-trash"></i><br/>suppr.</button>
+                <button class="btn btn-primary" onclick="db_test();"><i class="fas fa-plus"></i><br/>Tester Connection</button>
+        </div>
+      </div>
+    </nav>
+    <div class="cotainer-fluid" style="margin-top: 52px;">
+            <table id="tbl_childs" class="table table-bordered table-hover table-striped">
+                    <thead class="thead-dark">
+                            <th data-checkbox="true"></th>
+                            <th data-sortable="true">Nom</th>
+                            <th data-sortable="true">Type</th>
+                            <th data-sortable="true">VPN</th>
+                            <th data-sortable="true">URL</th>
+                            <th data-sortable="true">Status</th>
+                    <tfoot></tfoot>
+                    <tbody></tbody>
+                </table>
+      <!-- <div class="row">
+        <div class="col-sm-12">
+          <div class="card">
+            <div class="card-heading">
+              <h3 class="cadr-title">&nbsp;Informations Utiles</h3>
+            </div>
+            <div class="card-body" id="infopanel">
+              pas d'informations utiles pour l'instant!
+            </div>
+          </div>
+        </div>
+      </div> -->
+    </div>
+    <script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
+    <script src="../../node_modules/jquery/dist/jquery.min.js" type="text/javascript"></script>
+    <script src="../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
+    <script src="../../node_modules/bootstrap-table/dist/bootstrap-table.min.js"></script>
+    <script src="../../node_modules/@fortawesome/fontawesome-free/js/all.min.js"></script>
+    <script src="../../js/moduleglobal.js"></script>
+    <!-- <script src="../../js/database.js"></script> -->
+    <!--<script src="chrome://creorga/content/js/tools.js" type="text/javascript"></script>-->
+    <!-- <script src="js/creorga.js" type="text/javascript"></script> -->
+    <!-- <script src="js/labels.js" type="text/javascript"></script> -->
+    <script src="index.js" type="text/javascript"></script>
+    <script src="dbconfig.js" type="text/javascript"></script>
+    <script>if (window.module) module = window.module;</script>
+  </body>
+</html>
+
diff --git a/modules/settings/index.js b/modules/settings/index.js
new file mode 100644 (file)
index 0000000..f4a8bae
--- /dev/null
@@ -0,0 +1,7 @@
+function initpage(){
+    console.log("Loading Settings!");
+}
+
+function db_new(){
+    parent.userapp.loadmodulepage('settings','db',null);
+}
\ No newline at end of file
diff --git a/modules/settings/js/multisite_reader.js b/modules/settings/js/multisite_reader.js
new file mode 100644 (file)
index 0000000..a8cb8c9
--- /dev/null
@@ -0,0 +1,58 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var multisite_reader = {
+  
+  getsites: function(){
+    var childnames = apppref.branch.getChildList("",{});
+               var clmsel = document.getElementsByClassName("clmultisite");
+    var cnum = apppref.getpreference("support.database.currentdb.num");
+    var xx = document.getElementById("pop_multisites");
+    while(xx.hasChildNodes()){
+      xx.removeChild(xx.firstChild);
+    }
+    for (var i in childnames){
+      if ((childnames[i].substring(0,16) == 'support.database') && (childnames[i].indexOf("currentdb") == -1) && (childnames[i].indexOf("currentsite") == -1)) {
+        //dump("gsites:" +  childnames[i] + "\n");
+        var sitecfg = JSON.parse(apppref.getpreference(childnames[i]));
+        //dump("Creche loader: " + JSON.stringify(sitecfg) + "A: "+system.fileexists( sitecfg.path.local ) + system.sep() + sitecfg.uuid + ".sqlite")+ "\n");
+               //if (system.fileexists( sitecfg.path.local  + system.sep() + sitecfg.uuid + ".sqlite")){
+        if (!document.getElementById("mnumultisite_" + sitecfg.dbnum))
+        {
+        var  item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem");
+                                               item.setAttribute("label", sitecfg.name);
+                                               item.setAttribute("id", "mnumultisite_" + sitecfg.dbnum);
+                                               item.setAttribute("value", sitecfg.dbnum);
+                                               item.setAttribute("class","clmultisite");
+                                               item.setAttribute("oncommand","multisite_reader.setcurrent('"+ sitecfg.dbnum +"');");
+                                               document.getElementById("pop_multisites").appendChild(item);
+               }else {
+            document.getElementById("mnumultisite_" + sitecfg.dbnum).setAttribute("label", sitecfg.name);
+            if (sitecfg.dbnum == cnum) {
+              document.getElementById("curcreche").value=sitecfg.name;
+            }
+        }
+               //}
+                               
+      }
+    }
+  },
+  setcurrent:function(num){
+    if (!num) {
+      return;
+    }
+    apppref.setpreference("support.database.currentdb.num",num);
+    
+               curcfg.loadconfig(num);
+    //appdb.check_defaultdata();
+    ///dump("creche loaded: " + curcfg.dbfile.local +"\ndbnum: " + curcfg.dbnum + "\nName: " + curcfg.name + "\n");
+    if (system.fileexists(curcfg.dbfile.local)) {
+                       navigation.update_dbname(curcfg.name);
+                       var lastpageopened = JSON.parse(apppref.getpreference("pageconfig.lastpage"));
+                       if (lastpageopened.view != "") {
+                               navigation.load_appview(lastpageopened.view,lastpageopened.module,null,lastpageopened.header);
+                       } 
+    } else {
+                       //dump("File : '" + curdb + "' does not exist!\n");
+               }
+               
+  }
+}
\ No newline at end of file
diff --git a/modules/settings/multisite.xul b/modules/settings/multisite.xul
new file mode 100644 (file)
index 0000000..bdcdc3e
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_multisite" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <script type="application/javascript" src="chrome://creorga/content/modules/multisite/js/multisite_reader.js" />
+  <!--<script type="application/javascript" src="chrome://POSDABAudio/content/js/category.js" />-->
+  <!--<script type="application/javascript" src="chrome://POSDABAudio/content/js/virtualcategory.js" />-->
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton class="btn btn-default" id="tbb_multisite" type="menu" insertbefore="tbb_about" label="Change Site" image="modules/multisite/img/profile.png" orient="vertical" onload="multisite_reader.getsites();">
+      <menupopup class="tlbpopup" id="pop_multisites">
+        
+        <!--<menuseparator />-->
+      </menupopup>
+    </toolbarbutton>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/settings/support/js/multisite.js b/modules/settings/support/js/multisite.js
new file mode 100644 (file)
index 0000000..c69a88a
--- /dev/null
@@ -0,0 +1,385 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {};
+var wh= window.screen.height -200;
+var delms = null;
+var tblmultisite = null;
+var sitenum = 0;
+var maxsites = 1;
+var shared = false;
+var newrsite = false;
+var higestdbnum = 0;
+var checkdb = 0;
+function initdata(){
+  //load_helpers();
+  var pdata = apppref.getpreference("pageconfig.multisite");
+  //maxsites = apppref.getpreference("support.sites");
+  //shared = apppref.getpreference("support.sharesites");
+  var strvpnpref= null;
+  if (system.os == "Darwin"){
+         strvpnpref = apppref.getpreference("support.vpn.data");
+  } else {
+         strvpnpref = apppref.getpreference("support.openvpn.data");
+  }
+  
+  if (!strvpnpref){
+         $('#btnvpnconnection').hide();
+  }
+  if (pdata != '') {
+    pconfig = JSON.parse(pdata);
+  }
+  set_infoheader("");
+  curcfg.loadconfig(apppref.getpreference("support.database.currentdb.num"));
+  //$('#btncheckdb').hide();
+  if (system.os == "Darwin"){
+    if (system.fileexists(system.toolsdir() + system.sep() + "creorgadb")){
+      checkdb = 1;
+    }
+  } else {
+         if (system.fileexists(system.toolsdir() + system.sep() + "creorgadb.exe")){
+      checkdb = 1;
+    }
+      
+  }
+  //$('#btnsyncconfig').show();
+  load_multisite_table();
+  //$("#remoteshared").on('change',function(){
+  //
+  //    if ($("#remoteshared").is(':checked')){
+  //      $('#sharedfolderdata').show();
+  //    }else {
+  //      $('#sharedfolderdata').hide();
+  //    }
+  //});
+}
+
+
+
+function load_multisite_table(){
+  sitenum = 0;
+       $("#tbl_multisite").html("");
+       $("#tbl_multisite").append("<thead><tr><th>Action</th><th>Nom du Site</th><th>Base de données</th></thead>");
+
+       var childnames = apppref.branch.getChildList("",{});
+    var tbodydata = '<tbody>';
+    
+   
+               for (var i in childnames){
+      if ((childnames[i].substring(0,16) == 'support.database')   && (childnames[i].indexOf("currentdb") == -1) && (childnames[i].indexOf("currentsite") == -1)){
+        var sitecfg = JSON.parse(apppref.getpreference(childnames[i]));
+        sitenum++;
+
+        //var ltype = "private";
+        //if (sitecfg.path.local == system.commondir()) {
+        //  ltype = "localshare";
+        //}
+        
+        //dump(JSON.stringify(sitecfg) + "\n");
+        if (higestdbnum < sitecfg.dbnum){
+          higestdbnum = sitecfg.dbnum;
+        }
+               var btndel ='';
+        var btnshare = '';
+        //var btnvpn = '';
+               var msgaccess = '';
+        if (curcfg.dbnum != sitecfg.dbnum) {
+          btndel = "<button type=\"button\" class=\"btn btn-danger\" onclick=\"confirm_delete_multisite('"+sitecfg.dbnum +"');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button>";  
+        }
+    if (system.fileexists(sitecfg.path.local + system.sep() +sitecfg.uuid+".sqlite")){
+                       btnshare = "<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_remotesite('"+sitecfg.dbnum +"');\" title=\"partager\"><span class=\"glyphicons glyphicons-folder-open\"></span></button>";
+               } else {
+                       msgaccess = "<span style=\"color: red;\">cette base de donnée n'est pas accessible! Vérifiez l'access au répertoire (et/ou la VPN)</span>";
+    }
+    var msgcheckdb = "";
+    if (checkdb == 1){
+      var msgcheckdb = '<button onclick="dbcheck(\''+sitecfg.dbnum +'\');" class="btn btn-info" type="button" id="btncheckdb"><span class="glyphicons glyphicons-database" aria-hidden="true"></span></button>';
+    }
+        
+        tbodydata += "<tr><td>"+btndel+btnshare+msgcheckdb+"</td><td>"+sitecfg.name+"</td><td><input type=\"text\" style=\"width: 90%;\" readonly=\"true\" value=\""+ sitecfg.path.local + system.sep() +sitecfg.uuid+".sqlite\"/>"+
+        ((msgaccess != "")?'<br/>' + msgaccess:"")
+        +"</td>";
+        tbodydata +="</tr>";
+        
+      }
+    }
+               tbodydata += '</tbody>';
+               $("#tbl_multisite").append(tbodydata);
+    if (system.appinfo().ID.indexOf("director") > 0){
+      $("#btnnewsite").show();  
+    } else {
+      $("#btnnewsite").hide();
+    }
+    
+    
+    $("#btnremotesite").show();
+
+  tblmultisite = $("#tbl_multisite").dataTable({
+    "paging": false,
+    "ordering": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+   
+}
+
+function getremotefolder() {
+  var r = system.selectdirectory('',"selectionner le répertoire");
+  if (r) {
+    $('#sharedfolder').val(r.path);
+  }
+}
+
+function vpnconnection(){
+       if (system.fileexists(system.profilerootdir() + system.sep() + 'vpncfg.txt')){
+       if (system.os == "Darwin"){
+               system.runcmdline("/bin/bash",[system.toolsdir() + system.sep() + "vpnconnect.sh",system.profilerootdir() + system.sep() + 'vpncfg.txt']);
+       } else {
+               system.runcmdline(system.toolsdir() + system.sep() + "ovpn.exe",["--connect"],function(data){
+                         system.popup("Info","démarrage VPN!\n");
+                       });
+                
+       }
+       }
+}
+
+function getremotefile() {
+    var r = system.selectfile('',"selectionner la base de donnée (*.sqlite)");
+    if (r) {
+      $('#sharedfile').val(r.path);
+    } 
+}
+
+function getvpnfile() {
+    var r = system.selectvpnfile('',"selectionner le fichier (*.privkey)");
+    if (r) {
+      $('#vpnkeyfile').val(r.path);
+    } 
+}
+
+//function run_vpncheck(vpnapp){
+//     var ff = system.openFile(vpnapp);
+//}
+
+function dlg_remotesite(sitenum){
+    //dump("Remote site:" + sitenum + "\n");
+      if (sitenum > 0){
+        var strsitepref = apppref.getpreference("support.database." +sitenum);  
+        var sitepref;
+        if (strsitepref.length > 0){
+          sitepref = JSON.parse(strsitepref);
+          $("#sharedfolder").val(sitepref.path.local);
+          $("#oldfolder").val(sitepref.path.local);
+          if (sitepref.vpncheck){
+                 $("#vpnfile").val(sitepref.vpncheck);
+          }else {
+                 $("#vpnfile").val("");
+          }
+          $("#dbnum").val(sitepref.dbnum);
+          $("#gluuid").val(sitepref.uuid);
+          $("#gluuid").prop("readonly",true);
+          $("#dlg_movesite").modal('show');
+        }
+      } 
+    }
+
+function dlg_addsite(){
+      $("#sharedfile").val("");
+      $("#dlg_addsite").modal('show');  
+  }
+function dlg_vpn(){
+       if (system.os == "Darwin"){
+       var strvpnpref = apppref.getpreference("support.vpn.data");
+       var vpnpref;
+    if ((strvpnpref) && (strvpnpref.length > 0)){
+      vpnpref = JSON.parse(strvpnpref);
+      $("#vpnhost").val(vpnpref.vpnhost);
+      $("#smbuser").val(vpnpref.smbuser);
+      $("#smbpassword").val(vpnpref.smbpassword);
+      $("#vpnkeyfile").val(vpnpref.vpnkeyfile);
+      $("#smbsharedfolder").val(vpnpref.smbsharedfolder);
+    }
+       $("#dlg_vpnconfigmac").modal('show');
+       } else {
+               $("#openvpnname").html("");
+               var strvpnpref = apppref.getpreference("support.openvpn.data");
+               var vpnpref;
+               if ((strvpnpref) && (strvpnpref.length > 0)){
+                        vpnpref = JSON.parse(strvpnpref);
+                       
+               }
+               var data = system.getOpenVPNConfig();
+               for (var i in data){
+                       var sel = "";
+                       if (vpnpref && vpnpref.openvpnname == data[i]){
+                               sel = 'selected="1"';
+                       }
+                       $("#openvpnname").append("<option value=\""+data[i]+"\" "+sel+">"+data[i]+"</option>");
+               }
+               $("#dlg_vpnconfigwin").modal('show');
+       }
+}
+
+
+
+function save_vpnconfig(){
+       if (system.os == "Darwin"){
+       var vpnpref = {vpnhost:"",smbuser:"",smbpassword:"",vpnkeyfile:"",smbsharedfolder:""};
+       var strvpnpref="";
+       vpnpref.vpnhost = $("#vpnhost").val();
+       vpnpref.smbuser = $("#smbuser").val();
+       vpnpref.smbpassword = $("#smbpassword").val();
+       vpnpref.vpnkeyfile = $("#vpnkeyfile").val();
+       vpnpref.smbsharedfolder = $("#smbsharedfolder").val();
+       apppref.setpreference("support.vpn.data",vpnpref);
+       
+       strvpnpref+="LOCALPORT=52187\n";
+       
+       if (vpnpref.vpnhost.indexOf(":") != -1){
+               //var vpnport = vpnpref.vpnhost.substring(vpnpref.vpnhost.indexOf(":"));
+               strvpnpref+="SSHHOST=" + vpnpref.vpnhost.substring(0,vpnpref.vpnhost.indexOf(":")) + "\n";
+               strvpnpref+="SSHPORT=" + vpnpref.vpnhost.substring(vpnpref.vpnhost.indexOf(":")+1) + "\n";
+       }else {
+               strvpnpref+="SSHHOST=" + vpnpref.vpnhost + "\n";
+       }
+       
+       strvpnpref+="SMBUSER=" + vpnpref.smbuser + "\n";
+       strvpnpref+="SMBPWD=" + vpnpref.smbpassword + "\n";
+       strvpnpref+="SMBFOLDER=" + vpnpref.smbsharedfolder + "\n";
+       strvpnpref+="SSHKEYFILE=" + vpnpref.vpnkeyfile + "\n";
+       //dump(strvpnpref +"\n->" + system.profilerootdir() + "/vpncfg.txt\n");
+       system.WriteTextFile(strvpnpref,system.profilerootdir() + "/vpncfg.txt");
+       $("#dlg_vpnconfigmac").modal('hide');
+       } else {
+               var vpnpref = {openvpnname:""};
+               vpnpref.openvpnname = $("#openvpnname").val();
+               apppref.setpreference("support.openvpn.data",vpnpref);
+               var strvpnpref ="OPENVPNNAME="+vpnpref.openvpnname+"\n";
+               system.WriteTextFile(strvpnpref,system.profilerootdir() + system.sep() +"vpncfg.txt");
+               $("#dlg_vpnconfigwin").modal('hide');
+               
+       }
+}
+
+
+
+function remove_vpnconfig(){
+       OS.File.remove(system.profiledir() + system.sep() +"vpncfg.txt");
+       if (system.os == "Darwin"){
+               apppref.setpreference("support.vpn.data",null);
+               $("#dlg_vpnconfigmac").modal('hide');
+       } else {
+               apppref.setpreference("support.openvpn.data",null);
+               $("#dlg_vpnconfigwin").modal('hide');
+       }
+       
+       
+}
+
+
+  function confirm_delete_multisite(dbnum){
+
+        delms = dbnum;
+        $("#confirm_delete_multisite").modal('show');
+        return false;
+      }
+  
+  function delete_multisite(){
+       var deldbsite = JSON.parse(apppref.getpreference("support.database." + delms));
+        apppref.deletepreference("support.database." + delms);
+                               //"delete " + deldbsite.path.local + system.sep() + deldbsite.uuid + ".sqlite\n");
+        if (deldbsite.path.local == system.profiledir()) {
+          OS.File.remove(deldbsite.path.local + system.sep() + deldbsite.uuid + ".sqlite",{ ignoreAbsent:true});
+          OS.File.removeDir(deldbsite.path.local + system.sep() + 'imports' +system.sep() + deldbsite.uuid,{ ignoreAbsent:true});
+          OS.File.removeDir(deldbsite.path.local + system.sep() + 'reports' +system.sep() + deldbsite.uuid,{ ignoreAbsent:true});
+        }
+        delms =null;
+       globelreq.send_request({page:'updatesiteslist',data:null});
+        load_multisite_table();
+        
+        $("#confirm_delete_multisite").modal('hide');
+        
+        return false;
+  }
+  
+   function save_multisite(){
+        var cuuid = "";
+       var rowCount = higestdbnum + 1;
+       var syspath= system.profiledir();
+        var newid=appdb.generate_uuid();
+
+       var dbname = syspath + system.sep() + newid +".sqlite"; 
+       var dbclone = system.appdir() + system.sep() +"defaults"+system.sep()+"profile"+system.sep()+"creorga.sqlite";
+       var sitecfg = {name:"Nouvelle crèche",dbnum:rowCount,uuid:newid,path:{local:system.profiledir(),remote:""},lastsync:""};
+       apppref.setpreference("support.database." + rowCount,sitecfg);
+       globelreq.send_request({page:'updatesiteslist',data:null});
+       OS.File.copy(dbclone, dbname);
+        load_multisite_table();
+      }
+  
+  
+   function save_remotesite() {
+     //if move site partagé
+      var fld = $("#sharedfolder").val();
+      var nuuid = $("#frmeditmultisite #gluuid").val();
+      if ((fld === "") || (nuuid === "")) {
+        errormsg("ERREUR","pas de données!");
+      }else if (($("#oldfolder").val() !== "") && ($("#sharedfolder").val() !== $("#oldfolder").val())) {
+        tools.movecreche($("#oldfolder").val(),$("#sharedfolder").val(),nuuid,$("#dbnum").val());
+        
+      }
+      var strcfgx = apppref.getpreference("support.database."+$("#dbnum").val());
+//      cfgx = JSON.parse(strcfgx);
+//      cfgx.vpncheck=$("#vpnfile").val();
+//      
+//      //dump("new Config: " + JSON.stringify(cfgx) + "\n");
+//      apppref.setpreference("support.database."+$("#dbnum").val(),cfgx);
+      load_multisite_table(); 
+      $("#dlg_movesite").modal('hide');
+   }
+   
+   function add_remotesite() {
+       //if new site partagé
+        var fld = $("#sharedfile").val();
+        if (fld === "") {
+          errormsg("ERREUR","pas de données!");
+          $("#dlg_addsite").modal('hide');
+          return;
+        }
+        if (!system.fileexists(fld)){
+            errormsg("ERREUR","ce fichier n'existe pas!");
+            $("#dlg_addsite").modal('hide');
+            return;  
+        }
+        var rowCount = higestdbnum + 1;
+       var tcurdbnum = curcfg.dbnum; 
+       var nuuid = system.getFileName(fld);
+       nuuid = nuuid.substring(0,nuuid.length-7);
+       var bdpath = system.getDirectory(fld);
+       //dump("new nuuid:" + nuuid + "\n");
+       var sitecfg = {name:"Crèche Partagé",dbnum:rowCount,uuid:nuuid,path:{local:bdpath,remote:""},lastsync:""};
+        apppref.setpreference("support.database." + rowCount,sitecfg);
+          try {
+            curcfg.loadconfig(rowCount);
+            var xsn = appdb.dbquery("select crechename from creche where uuid='"+nuuid+"';");
+            sitecfg.name = xsn.sqldata[0].crechename;
+            apppref.setpreference("support.database." + rowCount,sitecfg);
+          } catch(e){
+            errormsg("ERREUR","Ne peux pas lire la b.d. partagé!");
+          }
+          curcfg.loadconfig(tcurdbnum);
+          globelreq.send_request({page:'updatesiteslist',data:null});
+          load_multisite_table();
+          $("#dlg_addsite").modal('hide');
+          $('#btnvpnconnection').show();
+     }
+   
+     function dbcheck(mydbid){
+       
+       appdb.check_schema(mydbid);
+     } 
+
+   
\ No newline at end of file
diff --git a/modules/settings/support/js/update.js b/modules/settings/support/js/update.js
new file mode 100644 (file)
index 0000000..d43330d
--- /dev/null
@@ -0,0 +1,58 @@
+Components.utils.import("resource://gre/modules/Downloads.jsm");
+
+function initdata(){
+  var lic = apppref.getpreference("support.license");
+  var appdata = system.appinfo(); 
+  var data = {};
+  //alert("Init X");
+  //dump("http://www.dks.lu/creorga/update.cgi?lic=" + lic + "&appid=" +appdata.ID);
+  
+  NetUtil.asyncFetch("http://www.dks.lu/creorga/update.cgi?lic=" + lic + "&appid=" +appdata.ID, function(inputStream, status) {
+    //alert("Test.x");
+    if (!Components.isSuccessCode(status)) {
+      document.getElementById("updmsg").value="Impossible de verifier!";
+    } else {
+      var strdata = NetUtil.readInputStreamToString(inputStream, inputStream.available());
+      //dump("Update data returned!\n: " + JSON.stringify(strdata) + "\n");
+      //jsdump("Data returned:" + strdata + "\n");
+      try {
+        data = JSON.parse(strdata);
+        
+      } catch(e){
+        document.getElementById("updmsg").value="Impossible de verifier!";
+
+        //jsdump(e.message);
+        return data;
+      }
+      //alert(JSON.stringify(data));
+      dldmsg(data);
+      
+
+      
+    }
+  });
+  
+  set_infoheader("Creorga mise Ã  jour");
+  
+}
+
+function dldmsg(data){
+  //dump("Data for message: \n: " + JSON.stringify(data) + "\n");
+  if (!data.update){
+    $("#updmsg").html("<strong>pas de mise-à-jour disponible</strong>");
+  } else {
+    $("#updmsg").html("<strong>Nouvelle Version disponible!</strong><br/><a class=\"btn btn-primary\" onclick=\"dldupdate('"+ data.update+"');\">clicker ici pour installer la mise Ã  jour</a>");
+  }
+  //alert("TEST");
+  
+}
+function dldupdate(dldfile){
+  $("#updmsg").html("<strong>Attendez!!! Téléchargement en cours!</strong>");
+  Downloads.fetch("http://www.dks.lu/creorga/updates/" + dldfile, system.tmpdir() + system.sep() + dldfile)
+         .then(() => afterdld(system.tmpdir() + system.sep() + dldfile), ex => alert("Erreur pendant le chargement"));
+}
+
+function afterdld(res){
+  system.openFile(res);
+  system.closecreorga();
+}
diff --git a/modules/settings/support/multisite.html b/modules/settings/support/multisite.html
new file mode 100644 (file)
index 0000000..55d8ab4
--- /dev/null
@@ -0,0 +1,272 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Creorga - Configuration Site</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css"><!-- Fav and touch icons -->
+</head>
+
+<body>
+
+   <div class="container-fluid">
+<!--   <h2>Configuration Sites</h2>-->
+<br/>
+   <button onclick="save_multisite();" class="btn btn-primary" type="button" id="btnnewsite"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp; nouveau site</button>
+   <button onclick="dlg_addsite();" class="btn btn-primary" type="button" id="btnremotesite"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp; site existant (partagé)</button>
+   <button onclick="dlg_vpn();" class="btn btn-primary" type="button" id="btnvpnconfig" ><span class="glyphicons glyphicons-unlock" aria-hidden="true"></span>&nbsp; Configuration VPN</button>
+<!--    <button onclick="checkdatabases();" class="btn btn-info" type="button" id="btncheckdb" style="display: none;"><span class="glyphicon glyphicon-reload" aria-hidden="true"></span>&nbsp; verification DB</button> -->
+   <button onclick="vpnconnection();" class="btn btn-warning" type="button" id="btnvpnconnection"><span class="glyphicons glyphicons-database-lock" aria-hidden="true"></span>&nbsp; Connecter VPN</button>
+   
+   <table class="display dataTable" width="100%" style="width: 100%;" id="tbl_multisite" role="grid"></table>
+</div>
+   <div class="modal fade" id="dlg_movesite">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Délocaliser Site</h4>
+              </div>
+              <div class="modal-body">
+                <div id="frmeditmultisite">
+                  <input type="hidden" value="0" id="uuid" />
+                  <input type="hidden" value="" id="oldfolder" />
+                  <input type="hidden" value="" id="dbnum" />
+                  <div class="form-group form-inline">
+                    <label for="name">ID Globale</label>
+                    <input type="text" value="" id="gluuid"  nullable="true" style="width: 70%;" class="form-control">
+                  </div>
+                  <div class="form-group" id="sharedfolderdata">
+                    <label for="name">Dossier des données</label>
+                    <div class="form-inline">
+                    <input type="text" class="form-control" id="sharedfolder" style="width: 70%;">
+                    <button class="btn btn-primary" onclick="getremotefolder();">Choisir le dossier...</button>
+                    </div>
+                    <div>
+                      
+                    </div>
+                  </div>
+
+                  
+                </div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_remotesite();" class="btn btn-primary">OK</button>
+              </div>
+              
+            </div>
+          </div>
+        </div>
+        <div class="modal fade" id="dlg_addsite">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Ajouter Site partagé</h4>
+              </div>
+              <div class="modal-body">
+                <div id="frmeditnewsite">
+                  
+                  <div class="form-group" id="sharedfiledata">
+                    <label for="name">Dossier des données</label>
+                    <div class="form-inline">
+                    <input type="text" class="form-control" id="sharedfile" style="width: 70%;" >
+                    <button class="btn btn-primary" onclick="getremotefile();">Choisir la base de donnée</button>
+                    </div>
+                    <div>
+                      
+                    </div>
+                  </div>
+                  
+                  
+                </div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="add_remotesite();" class="btn btn-primary">OK</button>
+              </div>
+              
+            </div>
+          </div>
+        </div>
+        <div class="modal fade" id="confirm_delete_multisite">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Crèche</h4>
+              </div>
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette crèche?<br/>
+              </div>
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_multisite();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+        <!-- VPN Config -->
+        <div class="modal fade" id="dlg_vpnconfigmacos">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Configuration VPN</h4>
+              </div>
+              <div class="modal-body">
+                <div id="frmeditvpn">
+                  
+                  <div class="form-group">
+                    <label for="vpnhost">VPN Connection User@Host:Port</label>
+                    <input type="text" class="form-control" id="vpnhost">
+                  </div>
+                  <div class="form-group">
+                    <label for="vpnkeyfile">VPN Fichier clé privé (*.key)</label>
+                    <div class="form-inline">
+                    <input type="text" class="form-control" id="vpnkeyfile" style="width: 70%;" readonly="true">
+                    <button class="btn btn-primary" onclick="getvpnfile();">Choisir...</button>
+                    </div>
+                  <div>
+                  <div class="form-group">
+                    <label for="smbuser">Utilisateur</label>
+                    <input type="text" class="form-control" id="smbuser">
+                  </div>
+                  <div class="form-group">
+                    <label for="smbpassword">Mot de passe</label>
+                    <input type="password" class="form-control" id="smbpassword">
+                  </div>
+                         <div class="form-group">
+                    <label for="smbsharedfolder">Dossier partagé</label>
+                    <input type="text" class="form-control" id="smbsharedfolder">
+                  </div>    
+                    </div>
+                  </div>
+                </div>
+                </div>
+              <div class="modal-footer">
+               <button onclick="remove_vpnconfig();" class="btn btn-primary">Supprimer Configuration</button>
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> 
+                <button onclick="save_vpnconfig();" class="btn btn-primary">OK</button>
+              </div>
+              
+            </div>
+          </div>
+        </div>
+        <div class="modal fade" id="dlg_vpnconfigwin">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Configuration VPN</h4>
+              </div>
+              <div class="modal-body">
+                <div id="frmeditvpn">
+                  
+                  <div class="form-group">
+                    <label for="openvpnname">VPN</label>
+                    <select id="openvpnname">
+                    </select>
+                    
+                  </div>
+                  
+                  
+                  
+                            
+                    
+                </div>
+                </div>
+              <div class="modal-footer">
+               <button onclick="remove_vpnconfig();" class="btn btn-primary">Supprimer Configuration</button>
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> 
+                <button onclick="save_vpnconfig();" class="btn btn-primary">OK</button>
+              </div>
+              
+            </div>
+          </div>
+        </div>
+        <!-- SYNC Config 
+        <div class="modal fade" id="dlg_syncconfig">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Configuration pour Synchronisation</h4>
+              </div>
+              <div class="modal-body">
+                <div id="frmeditsync">
+                  <div class="form-group ">
+                    <label for="synctype">Protocol://Host:Port</label>
+                    <div class="form-inline">
+                    <select id="synctype"><option value="ftp">FTP</option></select>://
+                    <input type="text" class="form-control" style="width: 60%;" id="synchost">:
+                    <input type="text" class="form-control" style="width: 10%;" id="syncport">
+                       </div>
+                  </div>
+                  <div class="form-group">
+                  <div class="form-inline">
+                    <label for="syncuser">Utilisateur</label>
+                    <input type="text" class="form-control" style="width: 60%;" id="syncuser">
+                    </div>
+                  </div>
+                  <div class="form-group">
+                  <div class="form-inline">
+                    <label for="syncpassword">Mot de passe</label>
+                    <input type="password" class="form-control" style="width: 60%;" id="syncpassword">
+                    </div>
+                  </div>
+                         <div class="form-group">
+                         <div class="form-inline">
+                    <label for="syncfolder">Dossier partagé</label>
+                    <input type="text" class="form-control" style="width: 60%;" id="syncfolder">
+                    </div>
+                  </div>
+                  <div class="form-group">
+                  <div class="form-inline">
+                    <label for="syncinterval">Interval</label>
+                    <input type="text" class="form-control" style="width: 10%;" id="syncinterval">&nbsp;minutes
+                       </div>
+                  </div> 
+                </div>
+              </div>
+              <div class="modal-footer">
+               <button onclick="remove_syncconfig();" class="btn btn-primary">Supprimer Configuration</button>
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> 
+                <button onclick="save_syncconfig();" class="btn btn-primary">OK</button>
+              </div>
+              
+            </div>
+          </div>
+        </div> -->
+      
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/tools.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/multisite.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
\ No newline at end of file
diff --git a/modules/settings/support/support.xul b/modules/settings/support/support.xul
new file mode 100644 (file)
index 0000000..735eaa4
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_support" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+<menupopup id="pophelp">
+  <menuseparator insertafter="mnuabout" id="mnuspoortsep"/>
+  <menuitem label="mise Ã  jour..." insertafter="mnuupdate" oncommand="navigation.load_appview('update','support',null,'mise Ã  jours');"  id="mnuupdate"/>
+  <menuitem label="Configuration Sites" insertafter="mnubackup" oncommand="navigation.load_appview('multisite','support',null,'Configuration Sites');"  id="mnumultisiteconfig"/>
+  
+</menupopup>
+
+</overlay>
\ No newline at end of file
diff --git a/modules/settings/support/update.html b/modules/settings/support/update.html
new file mode 100644 (file)
index 0000000..980dcc9
--- /dev/null
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Creorga - Update</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css"><!-- Fav and touch icons -->
+</head>
+
+<body>
+
+   <div class="container-fluid">
+<!--   <h2>Configuration Sites</h2>-->
+<br/>
+       <div class="row">
+        <div class="col-sm-12">
+          <div class="panel-heading">
+              <h3 class="panel-title"><img src="../../img/creorga16.png" alt="icon">&nbsp;Info mise-à-jour</h3>
+            </div>
+            <div class="panel-body" id="updmsg">
+              Pas de mise-à-jour disponible!
+            </div>
+        </div>
+      </div>
+   
+
+        </div>
+      
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="js/update.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
\ No newline at end of file
diff --git a/modules/staff/coworker.html b/modules/staff/coworker.html
new file mode 100644 (file)
index 0000000..572013d
--- /dev/null
@@ -0,0 +1,610 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+
+  <title>Employé(e)</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/jquery.minicolors.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+
+    <div class="container-fluid">
+        <br/>
+        <!--<span class="pagehead" id="pagehead">Collaborateur</span>&nbsp;-->
+          <input type="hidden" value="" id="staff_uuid">
+                <table style="width: 100%;">
+                  <tbody>
+                    <tr>
+                      <td style="width: 50%">
+                        <form>
+                        <div class="field form-inline">
+                          <label for="staff_surname">Nom / Prénom</label>
+                          <input type="text" value="" id="staff_surname" class="form-control">
+                          <input type="text" value="" id="staff_prename" class="form-control">
+                        </div>
+
+                        <div class="field">
+                          <label for="staff_address">Adresse</label> <input type="text" value="" id="staff_address" class="form-control">
+                        </div>
+
+                        <div class="field form-inline">
+                          <label for="staff_zip">CP / Ville</label>
+                          <input type="text" value="" size="5" id="staff_zip" class="form-control">
+                          <input type="text" value="" id="staff_city" class="form-control">
+                        </div>
+
+                        <div class="field">
+                          <label for="staff_country">Pays</label> <input type="text" value="" id="staff_country" class="form-control">
+                        </div>
+                        <div class="field form-inline">
+                          <label for="staff_phone">Tel / E-Mail</label>
+                          <input type="text" value="" id="staff_phone" class="form-control">
+                          <input type="text" value="" id="staff_email" class="form-control">
+                        </div>
+                        </form>
+                        
+                      </td>
+
+                      <td style="width: 50%;">
+                        <form>
+                        <div class="field form-inline" id="date-container">
+                          <label for="staff_entrydate" style="width: 200px;">Date d'entrée / de sortie</label>
+                          <div id="dt_staff_entrydate" class="input-group date">
+                            <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="staff_entrydate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        
+                          <div id="dt_staff_exitdate" class="input-group date">
+                            <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy" id="staff_exitdate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        </div>
+                  
+                        <div class="field">
+                          <label for="staff_jobtitle">Position / Contrat</label> <input type="text" value="" id="staff_jobtitle" class="form-control">
+                        </div>
+                        <table style="width: 100%;">
+                        <tr><td style="width: 40%;"><div class="field">
+                          <label for="staff_weekhours">heures/semaine</label>
+                          <div class="input-group number">
+                            <input type="number" value="" id="staff_weekhours" style="text-align: right;" class="form-control">
+
+                            <div class="input-group-addon">h</div>
+                          </div>
+                        </div></td><td style="width: 40%;"><div class="field">
+                          <label for="staff_maxdayhours">heures/jour</label>
+                          <div class="input-group number">
+                            <input type="number" value="" id="staff_maxdayhours" style="text-align: right;" class="form-control">
+
+                            <div class="input-group-addon">h</div>
+                          </div>
+                        </div></td><td style="width:20%"><div class="field" >
+                            <label for="staff_color">Couleur</label>
+                            <div class="input-group">
+                            <input type="hidden" id="staff_color" class="form-control " value="">
+                            </div>
+                        </div></td></tr>
+                        </table>
+                        <div class="field">
+                          <label for="staff_iban">Compte Bancaire</label> <input type="text" value="" id="staff_iban" class="form-control">
+                        </div>
+                        <div class="field" id="pwddata">
+                          <label for="staff_password">Mot de Passe</label> 
+                          <div class="input-group">
+                               <input type="password" value="" id="staff_password" class="form-control">
+                               <div class="input-group-addon">(Min: 4 charatères)</div> 
+                          </div>
+                        </div>
+                        
+                        </form>
+                        
+                      </td>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
+              <div class="tabbable">
+            <ul class="nav nav-tabs" id="tabgrouphead">
+              <li><a data-toggle="tab" href="#activity">Organisation interne</a></li>
+              <li><a data-toggle="tab" href="#vacancy">Congé</a></li>
+            </ul>
+
+            <div class="tab-content">
+              
+              <div id="activity" class="tab-pane">
+                <div class="form-group form-inline">
+                      <label for="year_organisation">Année:</label>
+                      <div class="input-group">
+                        <select id="year_organisation" class="selyear">
+                          
+                        </select>
+                    </div>
+                <button onclick="dlg_event({'uuid':''},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp;Activité</button>
+                </div>
+                 <table id="tbl_activity" class="table table-striped">
+                  
+                </table>
+              </div>
+              <div id="vacancy" class="tab-pane">
+                <div class="form-group form-inline">
+                      <label for="year_vacancy">Année:</label>
+                      <div class="input-group">
+                        <select id="year_vacancy" class="selyear">
+                          
+                        </select>
+                    </div>
+                  <button onclick="dlg_vacancy({'uuid':''},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp;Congé</button>
+                      <div class="form-group">
+                        <label for="vacancy_total">congé normale</label>
+                        
+                        <div class="input-group" style="width: 120px;">
+                          <input type="text" id="vacancyyeartotal" class="form-control" value="" onblur="saveyearvacdays();">
+                          <span class="input-group-addon">h</span>
+                        </div>
+                        
+                      </div>
+                      <!--<div class="form-group">
+                        <label for="vacancylastyearrest">congé Ã  récupérer</label>
+                        
+                        <div class="input-group" style="width: 120px;">
+                          <input type="text" id="vacancylastyearrest" class="form-control" value="0" readonly="1">
+                          <span class="input-group-addon">h</span>
+                        </div>
+                        
+                      </div>-->
+                </div>
+              
+                        <table id="tbl_vacancy" class="table table-striped">
+                          
+                        </table>
+                    
+              
+              <div id="vacancystatus" style=" white-space: nowrap; width: 100%; text-align: center;"></div>  
+              
+            </div>
+          </div>
+              </div>
+<!-- EVENT  DLG begin -->
+<div class="modal fade" id="edit_event">
+          <div class="modal-dialog" style="width: 800px; max-width: 800px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer Activité</h4>
+              </div>
+              <div class="modal-body" style=" height: 550px; max-height: 550px ">
+<div id="frmeditevent">
+                  <input type="hidden" value="0" id="uuid" />
+                  <input type="hidden" value="" id="staffuuid" />
+                  <input type="hidden" value="" id="description" />
+                  <input type="hidden" value="" id="color" />
+                  <input type="hidden" value="" id="location" />
+                  <div class="form-inline row">
+                    <label for="staffname" class="col-md-2">Employé(e)</label>
+                    <input value="" id="staffname" readonly class="form-control col-md-8" style="width: 80%;" ></select>
+                  </div> 
+                  <div class="row">
+                    <div class="form-inline">
+                  <div id="date-container">
+                    <label class="col-md-3">Dates début / fin</label>
+                    <div id="dt_datefrom" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="datefrom"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                    <div id="dt_dateto" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="dateto"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  </div>
+                  </div>
+                  <div class="row">
+                  <div class="form-inline ">
+                    <label   class="col-md-3">heures début / fin</label>
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timefrom">
+                    </div>
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timeto">
+                    </div>
+                  </div>
+                  </div>
+                  <div class="row">
+                    
+                  </div>
+                  <div class="row">
+                    <div class="panel panel-default">
+                      <div class="panel-heading">
+                        <h3 class="panel-title">Récurrence
+                        <select id="freq" onchange="setfreq();">
+                          <option value="">pas de récurrence</option>
+                          <option value="daily">quotidienne</option>
+                          <option value="weekly">hebdomaire</option>
+                          <option value="monthly">mensuelle</option>
+                        </select>
+                        </h3>
+                      </div>
+                    <div class="panel-body">
+                        <div class="row">
+                        <div class="form-inline" id="freqinterval">
+                          <label>interval: tous les</label>
+                          <input class="form-control" type="number" id="interval" style="width: 50px;" value="1"/>
+                          <label id="lblfreq"></label>
+                        </div>
+                        </div>
+                        <div class="row" id="freqweekly">
+                           <div class="form-inline">
+                            <label>jours de semaine:</label>
+                            <!--<input class="col-md-2 form-control" style="width: 50px;" type="number" id="xtimes_num" value="1"/>-->
+                            <!--<label class="col-md-2">semaines,le </label>-->
+                            <div class="btn-group form-inline" id="weekly_byday" data-toggle="buttons">
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_mo" value="MO" /> Lundi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_tu" value="TU" /> Mardi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_we" value="WE" /> Mercredi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_th" value="TH" /> Jeudi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="weekly_byday_fr" value="FR" /> Vendredi
+                            </label>
+                            <label class="btn btn-primary">
+                            <input type="checkbox" id="weekly_byday_sa" value="SA" /> Samedi
+                            </label>
+                            <!--<label class="btn btn-primary">-->
+                            <!--  <input type="checkbox" id="weekly_byday_su" value="SU" /> Di-->
+                            <!--</label>-->
+                           </div>
+                           </div>
+                        </div>
+                        <div class="row" id="freqmonthly">
+                          <div class="form-inline">
+                            <div class="btn-group" data-toggle="buttons" id="monthly_by">
+                            <label class="btn btn-primary active">
+                              <input type="radio" id="pnl_monthly_byday" value="monthly_byday" checked="1"/> par jour de semaine
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="radio" id="pnl_monthly_bymonthday" value="monthly_bymonthday"/> par jour du mois
+                            </label>
+                            </div>
+                          </div>
+                          <div class="form-inline" id="freq_monthly_byday">
+                            <!--<label class="col-md-2">tous les</label>-->
+                            <!--<input class="col-md-2 form-control" type="number" id="xtimes_num"  style="width: 50px;" value="1"/>-->
+                            <!--<label class="col-formmd-2">mois, le </label><br/>-->
+                            <div class="btn-group" data-toggle="buttons" id="monthly_bydaypos">
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_1" value="1" /> 1ier
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_2" value="2" /> 2ième
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_3" value="3" /> 3ième
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_4" value="4" /> 4ième
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaypos_5" value="5" /> 5ième
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydayppos_last-1" value="-1" /> dernier
+                            </label>
+                          </div>
+                            <br/>
+                            <div class="btn-group" data-toggle="buttons" id="monthly_bydaywday">
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_mo" value="MO" /> Lundi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_tu" value="TU" /> Mardi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_we" value="WE" /> Merecredi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_th" value="TH" /> Jeudi
+                            </label>
+                            <label class="btn btn-primary">
+                              <input type="checkbox" id="monthly_bydaywday_fr" value="FR" /> Vendredi
+                            </label>
+                            <label class="btn btn-primary">
+                            <input type="checkbox" id="monthly_bydaywday_sa" value="SA" /> Samedi
+                            </label>
+                            <!--<label class="btn btn-primary">-->
+                            <!--  <input type="checkbox" id="monthly_bydaywday_su" value="SU" /> Di-->
+                            <!--</label>-->
+                           </div>
+                            </div>
+                           <div class="form-inline" id="freq_monthly_bymonthday">
+                            <div class="btn-group" data-toggle="buttons" id="monthly_bymonthday">
+                            <label class="btn btn-primary" style="width: 40px; border-radius: 0px;">
+                              <input type="checkbox" id="monthly_bymonthday_1" value="1" />1
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_2" value="2" />2
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_3" value="3" />3
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_4" value="4" />4
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_5" value="5" />5
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_6" value="6" />6
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_7" value="7" />7
+                            </label>                      
+                            <br/>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_8" value="8" />8
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_9" value="9" />9
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_10" value="10" /> 10
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_11" value="11" /> 11
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_12" value="12" /> 12
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_13" value="13" /> 13
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_14" value="14" /> 14
+                            </label>
+                           
+                            <br/>
+                            
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_15" value="15" /> 15
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_16" value="16" /> 16
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_17" value="17" /> 17
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_18" value="18" /> 18
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_19" value="19" /> 19
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_20" value="20" /> 20
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_21" value="21" /> 21
+                            </label>
+                           
+                            <br/>
+                            
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_22" value="22" /> 22
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_23" value="23" /> 23
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_24" value="24" /> 24
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_25" value="25" /> 25
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_26" value="26" /> 26
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_27" value="27" /> 27
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_28" value="28" /> 28
+                            </label>
+                           
+                            <br/>
+                            
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_29" value="29" /> 29
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_31" value="31" /> 30
+                            </label>
+                            <label class="btn btn-primary" style="width: 40px;">
+                              <input type="checkbox" id="monthly_bymonthday_31" value="31" /> 31
+                            </label>
+                            <label class="btn btn-primary" style="width: 157px;" >
+                              <input type="checkbox" id="monthly_bymonthday_-1" value="-1" /> dernier
+                            </label>
+                            
+                            <br/>
+                            <label class="btn btn-primary" style="width: 138px;">
+                              <input type="checkbox" id="monthly_bymonthday_-2" value="-2" /> av.-dernier
+                            </label>
+                            <label class="btn btn-primary" style="width: 138px; border-radius: 0px;">
+                              <input type="checkbox" id="monthly_bymonthday_-3" value="-3" /> av.-av.-dernier
+                            </label>
+                           </div>
+                            
+                          </div>
+                          
+                          
+                          
+                          <br/>
+                          
+                        </div>
+                    </div>
+                    
+                  </div>
+                  </div>
+</div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" id="btndeleteevent" onclick="confirm_delete_event();" class="btn">Supprimer</button>
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_event();" id="btn_save_event" class="btn btn-primary">Accepter</button>
+              </div>
+              </div>
+            </div>
+          </div>
+        <div class="modal fade" id="confirm_delete_event">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Activité</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer cette Activité?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_event();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+<!-- EVENT DLG end -->
+        <div class="modal fade" id="edit_vacancy">
+          <div class="modal-dialog" style="width: 800px; max-width: 800px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer Congé</h4>
+              </div>
+              <div class="modal-body" style="height: 410px; max-height: 410px; ">
+<div id="frmeditvacancy">
+                  <input type="hidden" value="0" id="uuid" />
+                  <input type="hidden" value="" id="staffuuid" />
+                  <!--<div class="form-inline row">-->
+                  <!--  <label for="location" class="col-md-2">Lieu</label>-->
+                  <!--  <input type="text" value="" id="location"  nullable="true" class="form-control col-md-8" style="width: 80%;">-->
+                  <!--</div>-->
+                  
+                  <div class="form-inline row">
+                    <label for="dailyduration" class="col-md-3">Journée</label>
+                    <select value="" id="dailyduration"  class="form-control" onchange="setdailydurationfields();">
+                      <option value="1.0">Journée(s) complet(s)</option>
+                      <option value="0.4">demi(s) Journée(s)</option>
+                      <option value="0.">quelques heures</option>
+                    </select>
+                  </div>
+                  
+                    <div class="row form-inline">
+                    <label class="col-md-3">Date début</label>
+                    <div id="dt_vacdatefrom" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="vacdatefrom"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="row form-inline">
+                    <label class="col-md-3">Date fin</label>
+                    <div id="dt_vacdateto" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="vacdateto"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  
+                  <div id="ftimefrom" class="row form-inline">
+                  
+                    <label   class="col-md-3">heure début</label>
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timefrom">
+                    </div>
+                  </div>
+                  <div class="form-inline row" id="fhours">
+                    <label for="description" class="col-md-3">nbr. d'heures</label>
+                    <input type="text" value="" id="hours"  nullable="true" class="form-control col-md-6" style="width: 20%;">
+                               
+                  </div>
+                  
+                  <div class="form-inline row">
+                    <label for="type" class="col-md-3">Type de congé</label>
+                    <select id="type" value="">
+                      <option value="0">Congé normal</option>
+                      <option value="1">Congé expetionelle</option> 
+                      <option value="-1">Congé de maladie</option>
+                    </select>          
+                  </div>
+                  <div class="form-inline row">
+                    <label for="description" class="col-md-3">Description</label>
+                    <input type="text" value="" id="description"  nullable="true" class="form-control col-md-6" style="width: 70%;">
+    
+                  </div>
+                  <div class="row" style="height: 120px;"></div>
+                </div>
+              </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" onclick="accept_vacancy();" data-dismiss="modal" id="btnacceptvacancy" class="btn">Valider Congé</button>
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button>
+                <button onclick="save_vacancy();" class="btn btn-primary">Accepter</button>
+              </div>
+              </div>
+            </div>
+          </div>
+          <div class="modal fade" id="confirm_delete_vacancy">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Congé</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce congé?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_vacancy();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        
+        
+      </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <script src="../../web/js/jquery.minicolors.min.js" type="text/javascript"></script>
+  <script src="../calendar/js/rrule.js" type="text/javascript"></script>
+  <script src="../calendar/js/nlp.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/encrypt.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/coworker.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/staff/coworker_basic.html b/modules/staff/coworker_basic.html
new file mode 100644 (file)
index 0000000..308e77c
--- /dev/null
@@ -0,0 +1,332 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+
+  <title>Employé(e)</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/jquery.minicolors.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+
+    <div class="container-fluid">
+        <br/>
+        <!--<span class="pagehead" id="pagehead">Collaborateur</span>&nbsp;-->
+          <input type="hidden" value="" id="staff_uuid">
+                <table style="width: 100%;">
+                  <tbody>
+                    <tr>
+                      <td style="width: 50%">
+                        <form>
+                        <div class="field form-inline">
+                          <label for="staff_surname">Nom / Prénom</label>
+                          <input type="text" value="" id="staff_surname" class="form-control">
+                          <input type="text" value="" id="staff_prename" class="form-control">
+                        </div>
+
+                        <div class="field">
+                          <label for="staff_address">Adresse</label> <input type="text" value="" id="staff_address" class="form-control">
+                        </div>
+
+                        <div class="field form-inline">
+                          <label for="staff_zip">CP / Ville</label>
+                          <input type="text" value="" size="5" id="staff_zip" class="form-control">
+                          <input type="text" value="" id="staff_city" class="form-control">
+                        </div>
+
+                        <div class="field">
+                          <label for="staff_country">Pays</label> <input type="text" value="" id="staff_country" class="form-control">
+                        </div>
+                        <div class="field form-inline">
+                          <label for="staff_phone">Tel / E-Mail</label>
+                          <input type="text" value="" id="staff_phone" class="form-control">
+                          <input type="text" value="" id="staff_email" class="form-control">
+                        </div>
+                        </form>
+                        
+                      </td>
+
+                      <td style="width: 50%;">
+                        <form>
+                        <div class="field form-inline" id="date-container">
+                          <label for="staff_entrydate" style="width: 200px;">Date d'entrée / de sortie</label>
+                          <div id="dt_staff_entrydate" class="input-group date">
+                            <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="staff_entrydate" readonly="1"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        
+                          <div id="dt_staff_exitdate" class="input-group date">
+                            <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy" id="staff_exitdate" readonly="1"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                          </div>
+                        </div>
+                  
+                        <div class="field">
+                          <label for="staff_jobtitle">Position / Contrat</label> <input type="text" value="" id="staff_jobtitle"  readonly="1" class="form-control">
+                        </div>
+                        <table style="width: 100%;">
+                        <tr><td style="width: 50%;"><div class="field">
+                          <label for="staff_weekhours">heures/semaine</label>
+                          <div class="input-group number">
+                            <input type="number" value="" id="staff_weekhours" style="text-align: right;" class="form-control"  readonly="1">
+
+                            <div class="input-group-addon">h</div>
+                          </div>
+                        </div></td><td style="width:50%"><div class="field" >
+                            <label for="staff_color">Couleur</label>
+                            <div class="input-group">
+                            <input type="text" id="staff_color" class="form-control" value=""  readonly="1">
+                            </div>
+                        </div></td></tr>
+                        </table>
+                        <div class="field">
+                          <label for="staff_iban">Compte Bancaire</label> <input type="text" value="" id="staff_iban" class="form-control">
+                        </div>
+                        <div class="field" id="pwddata">
+                          <label for="staff_password">Mot de Passe</label> 
+                          <div class="input-group">
+                               <input type="password" value="" id="staff_password" class="form-control">
+                               <div class="input-group-addon">(Min: 4 charatères)</div> 
+                          </div>
+                        </div>
+                        
+                        </form>
+                        
+                      </td>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
+              <div class="tabbable">
+            <ul class="nav nav-tabs" id="tabgrouphead">
+              <li><a data-toggle="tab" href="#activity">Organisation interne</a></li>
+              <li><a data-toggle="tab" href="#vacancy">Congé</a></li>
+            </ul>
+
+            <div class="tab-content">
+              
+              <div id="activity" class="tab-pane">
+                <div class="form-group form-inline">
+                      <label for="year_organisation">Année:</label>
+                      <div class="input-group">
+                        <select id="year_organisation" class="selyear">
+                          
+                        </select>
+                    </div>
+                
+                </div>
+                 <table id="tbl_activity" class="table table-striped">
+                  
+                </table>
+              </div>
+              <div id="vacancy" class="tab-pane">
+                <div class="form-group form-inline">
+                      <label for="year_vacancy">Année:</label>
+                      <div class="input-group">
+                        <select id="year_vacancy" class="selyear">
+                          
+                        </select>
+                    </div>
+                  <button onclick="dlg_vacancy({'uuid':''},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp;demande de Congé</button>
+                      <div class="form-group">
+                        <label for="vacancy_total">congé normale</label>
+                        
+                        <div class="input-group" style="width: 120px;">
+                          <input type="text" id="vacancyyeartotal" class="form-control" value="" readonly="1">
+                          <span class="input-group-addon">h</span>
+                        </div>
+                        
+                      </div>
+                      <div class="form-group">
+                        <label for="vacancylastyearrest">congé Ã  récupérer</label>
+                        
+                        <div class="input-group" style="width: 120px;">
+                          <input type="text" id="vacancylastyearrest" class="form-control" value="0" readonly="1">
+                          <span class="input-group-addon">h</span>
+                        </div>
+                        
+                      </div>
+                      
+                </div>
+              <table>
+                <tr>
+                    <td style="width: 800px; vertical-align: top;">
+                        <table id="tbl_vacancy" class="table table-striped">
+                  
+                        </table>
+                    </td>
+                    <td>
+                        <table style="width: 100%;" class="table table-striped table-bordered">
+                            <thead>
+                                <tr><th colspan="5">Congé <span id="lblyear"></span></th></tr>
+                                <tr><th>&nbsp;</th><th>&nbsp;</th><th colspan="2">planification</th><th>&nbsp;</th></tr>
+                                <tr><th>Type</th><th>ouvert</th><th>demandé</th><th>validé</th><th>pris</th></tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                       <td>normale</td>
+                                       <td class="alignright" id="vacnopen">&nbsp;</td>
+                                       <td class="alignright" id="vacnasked">&nbsp;</td>
+                                       <td class="alignright" id="vacnplanned">&nbsp;</td>
+                                       <td class="alignright" id="vacntaken">&nbsp;</td>
+                                </tr>
+                                <tr>
+                                       <td>exceptionelle</td>
+                                       <td class="alignright" id="vaceopen">&nbsp;</td>
+                                       <td class="alignright" id="vaceasked">&nbsp;</td>
+                                       <td class="alignright" id="vaceplanned">&nbsp;</td>
+                                       <td class="alignright" id="vacetaken">&nbsp;</td>
+                                </tr>
+                                <tr>
+                                       <td>maladie</td>
+                                       <td class="alignright" id="vacmopen">&nbsp;</td>
+                                       <td class="alignright" id="vacmasked">&nbsp;</td>
+                                       <td class="alignright" id="vacmplanned">&nbsp;</td>
+                                       <td class="alignright" id="vacmtaken">&nbsp;</td>
+                                </tr>
+                            </tbody>
+                            <tfoot>
+                                <tr>
+                                       <th>total</th>
+                                       <th class="alignright" id="vactopen">&nbsp;</th>
+                                       <td class="alignright" id="vactasked">&nbsp;</td>
+                                       <th class="alignright"  id="vactplanned">&nbsp;</th>
+                                       <th class="alignright" id="vacttaken">&nbsp;</th>
+                                </tr>
+                            </tfoot>
+                        </table>
+                    </td>
+                </tr>
+              </table>    
+              
+              <div id="vacancystatus" style=" white-space: nowrap; width: 100%; text-align: center;"></div>  
+              
+            </div>
+          </div>
+              </div>
+
+        <div class="modal fade" id="edit_vacancy">
+          <div class="modal-dialog" style="width: 800px; max-width: 800px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer Congé</h4>
+              </div>
+              <div class="modal-body" style="height: 410px; max-height: 410px; ">
+<div id="frmeditvacancy">
+                  <input type="hidden" value="0" id="uuid" />
+                  <input type="hidden" value="" id="staffuuid" />
+
+                  
+                  <div class="form-inline row">
+                    <label for="dailyduration" class="col-md-3">Journée</label>
+                    <select value="" id="dailyduration"  class="form-control" onchange="setdailydurationfields();">
+                      <option value="1.0">Journée(s) complet(s)</option>
+                      <option value="0.4">demi(s) Journée(s)</option>
+                      <option value="0.">quelques heures</option>
+                    </select>
+                  </div>
+                  
+                    <div class="row form-inline">
+                    <label class="col-md-3">Date début</label>
+                    <div id="dt_vacdatefrom" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="vacdatefrom"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="row form-inline">
+                    <label class="col-md-3">Date fin</label>
+                    <div id="dt_vacdateto" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="1" placeholder="dd.mm.yyyy" id="vacdateto"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  
+                  <div id="ftimefrom" class="row form-inline">
+                  
+                    <label   class="col-md-3">heure début</label>
+                    <div class="input-group bootstrap-timepicker time">
+                      <input type="text" class="form-control timepicker" placeholder="" value="" id="timefrom">
+                    </div>
+                  </div>
+                  <div class="form-inline row" id="fhours">
+                    <label for="description" class="col-md-3">nbr. d'heures</label>
+                    <input type="text" value="" id="hours"  nullable="true" class="form-control col-md-6" style="width: 20%;">
+                               
+                  </div>
+                  <div class="form-inline row">
+                    <label for="type" class="col-md-3">Type de congé</label>
+                    <select id="type" value="">
+                      <option value="0">Congé normal</option>
+                      <option value="1">Congé expetionelle</option> 
+                      <option value="-1">Congé de maladie</option>
+                    </select>          
+                  </div>
+                  <div class="form-inline row">
+                    <label for="description" class="col-md-3">Description</label>
+                    <input type="text" value="" id="description"  nullable="true" class="form-control col-md-6" style="width: 70%;">
+    
+                  </div>
+                  <div class="row" style="height: 120px;"></div>
+                </div>
+              </div>
+              <div class="modal-footer">
+                
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button>
+                <button onclick="save_vacancy();" class="btn btn-primary">Envoyer la demande</button>
+              </div>
+              </div>
+            </div>
+          </div>
+          <div class="modal fade" id="confirm_delete_vacancy">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer Congé</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce congé?<br>
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_vacancy();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        
+        
+      </div>
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="../../web/js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="../../web/js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+  <script src="../../web/js/bootstrap-multiselect.js" type="text/javascript"></script>
+  <script src="../calendar/js/rrule.js" type="text/javascript"></script>
+  <script src="../calendar/js/nlp.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/encrypt.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/coworker_basic.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/staff/img/staff.png b/modules/staff/img/staff.png
new file mode 100644 (file)
index 0000000..679ba25
Binary files /dev/null and b/modules/staff/img/staff.png differ
diff --git a/modules/staff/js/coworker.js b/modules/staff/js/coworker.js
new file mode 100644 (file)
index 0000000..9030fe7
--- /dev/null
@@ -0,0 +1,1150 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = null;
+var delplan = null;
+var delvacation = null;
+var wh= window.innerHeight -440;
+var curdatediff = null;
+var redate = /\d\d.\d\d.\d\d\d\d/;
+var curfreq ={};
+var maxdayhours = null;
+var maxhalfdayhours = null;
+//var lictype = apppref.getpreference("support.lictype"); 
+
+function initdata() {
+  load_helpers();
+  var pdata = apppref.getpreference("pageconfig.coworker");
+  if (pdata != '') {
+    pconfig = JSON.parse(pdata);
+  }
+  //"get CoWorker cfg:" +JSON.stringify(pconfig) + "\n");
+  if (!pconfig.year) {
+    pconfig.year=new Date().getFullYear();
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.coworker",pconfig);
+  }
+  var cdatasql = "SELECT jobtitle, prename, surname, address, zip, city, country, strftime('%d.%m.%Y',entrydate) as entrydate, strftime('%d.%m.%Y',exitdate) as exitdate, iban, bic, accountname, phone, email, uuid,color,weekhours,maxdayhours,case when password is not null and length(password) > 3 then 1 else 0 end as passwordset  FROM staff where uuid='" + pconfig.uuid + "';";
+  var cdata = appdb.dbquery(cdatasql);
+  cdata = cdata.sqldata[0];
+  for (var ci in cdata) {
+    if (document.getElementById("staff_" + ci)) {
+      document.getElementById("staff_" + ci).setAttribute('value', cdata[ci]);
+    }
+
+  }
+  
+  var crdata = appdb.dbquery("select stafflist from creche;");
+  if ((crdata) && (crdata.sqldata[0].stafflist == "1")){
+         $("#pwddata").hide();
+  }
+  if (cdata) {
+    set_infoheader(cdata.prename + " " + cdata.surname);
+  }
+  $('#staff_color').minicolors({theme:'bootstrap'});
+  set_selectyears();
+  //load_staff_selection('staffuuid');
+
+  if (pconfig && pconfig.activetab) {
+    $('a[href="#'+pconfig.activetab+'"]').tab('show');
+  }else{
+    $('a[href="#vacancy"]').tab('show');
+    pconfig.activetab = 'vacancy';
+  }
+  
+//  if (pconfig && pconfig.vacancyunit){
+//    //dump("has vacancy unit:" + pconfig.vacancyunit + "\n");
+//    $('#vacancy_unit').val(pconfig.vacancyunit);
+//  }else {
+    pconfig.vacancyunit = "hours";
+//    $('#vacancy_unit').val("days");
+//  }
+    
+  $('#frmeditvacancy #vacdatefrom').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditvacancy #vacdatefrom').val().match(redate)) {
+      $('#btn_save_vacancy').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_vacancy').attr("disabled","1");
+    }
+    if ((ok == true) && ($('#frmeditvacancy #vacdateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditvacancy #vacdatefrom').val(),'date');
+      var nd = new Date(tmpdt1.replace(/'/g,''));
+      var xd = new Date(nd.getFullYear(),nd.getMonth(),nd.getDate() + curdatediff);
+      $('#frmeditvacancy #vacdateto').val(xd.toLocaleFormat("%d.%m.%Y"));
+      var tmpdt2 = encodeparam($('#frmeditvacancy #vacdateto').val(),'date');
+      if (tmpdt1 > tmpdt2) {
+        $('#btn_save_vacancy').attr("disabled","1");
+      } else {
+        $('#btn_save_vacancy').removeAttr("disabled");
+      }
+      
+    }
+  });
+  $('#frmeditvacancy #vacdateto').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditvacancy #vacdateto').val().match(redate)) {
+      $('#btn_save_vacancy').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_vacancy').attr("disabled","1");
+    }
+    curdatediff=daysBetween(new Date(encodeparam($('#frmeditvacancy #vacdatefrom').val(),'date').replace(/'/g,'')),new Date(encodeparam($('#frmeditvacancy #vacdateto').val(),'date').replace(/'/g,''))); 
+    if ((ok == true) && ($('#frmeditvacancy #vacdateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditvacancy #vacdatefrom').val(),'date');
+      var tmpdt2 = encodeparam($('#frmeditvacancy #vacdateto').val(),'date');
+      if (tmpdt1 > tmpdt2) {
+        $('#btn_save_vacancy').attr("disabled","1");
+      } else {
+        $('#btn_save_vacancy').removeAttr("disabled");
+      }
+      
+    }
+  });
+  $('#dailyduration').on('change',function(e){
+    if ($('#dailyduration').val() == "1.0"){
+       $('#frmeditvacancy #hours').val(maxdayhours);
+    }
+    if ($('#dailyduration').val() == "0.4"){
+       $('#frmeditvacancy #hours').val(maxhalfdayhours);
+    }
+  });
+  $('#staff_color').on('change',function(e){
+    saveonfocusout('staff_color');
+  });
+  //$('#frmeditevent #color').minicolors({theme:'bootstrap',position: 'bottom right'});
+  $("#weekly_byday :input").change(function() {
+    if (this.checked) {
+      this.setAttribute("checked",true);
+    }else {
+      this.removeAttribute("checked");
+    }
+
+});
+  $("#monthly_bydaypos :input").change(function() {
+
+    if (this.checked) {
+      this.setAttribute("checked",true);
+    }else {
+      this.removeAttribute("checked");
+    }
+
+});
+  $("#monthly_bydaywday :input").change(function() {
+
+    if (this.checked) {
+      this.setAttribute("checked",true);
+    }else {
+      this.removeAttribute("checked");
+    }
+
+});
+  $("#monthly_bymonthday :input").change(function() {
+
+    if (this.checked) {
+      this.setAttribute("checked",true);
+    }else {
+      this.removeAttribute("checked");
+    }
+
+});
+  $("#monthly_by :input").change(function() {
+    var xd = this.id.split("_");
+    curfreq.freqtype=xd[2];
+
+      this.setAttribute("checked",true);
+
+    $('#freq_monthly_byday').hide();
+    $('#freq_monthly_bymonthday').hide();
+    $('#pnl_monthly_byday').removeAttr("checked");
+    $('#pnl_monthly_bymonthday').removeAttr("checked");
+
+    $('#freq_' + this.value).show();
+
+});
+
+  $('#frmeditevent #datefrom').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditevent #datefrom').val().match(redate)) {
+      $('#btn_save_event').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_event').attr("disabled","1");
+    }
+    if ((ok == true) && ($('#frmeditevent #dateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditevent #datefrom').val(),'date');
+      var tmpdt2 = encodeparam($('#frmeditevent #dateto').val(),'date');
+      if (tmpdt1 >= tmpdt2) {
+        $('#btn_save_event').attr("disabled","1");
+      } else {
+        $('#btn_save_event').removeAttr("disabled");
+      }
+      
+    }
+  });
+  $('#frmeditevent #dateto').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditevent #dateto').val().match(redate)) {
+      $('#btn_save_event').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_event').attr("disabled","1");
+    }
+    if ((ok == true) && ($('#frmeditevent #dateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditevent #datefrom').val(),'date');
+      var tmpdt2 = encodeparam($('#frmeditevent #dateto').val(),'date');
+
+      if (tmpdt1 >= tmpdt2) {
+        $('#btn_save_event').attr("disabled","1");
+      } else {
+        $('#btn_save_event').removeAttr("disabled");
+      }
+      
+    }
+  });
+
+}
+
+$('.selyear').on( "change", function(e){ 
+  e.preventDefault();
+
+  $(".selyear").val($(this).val());
+  pconfig.year = $(this).val();
+  apppref.setpreference("pageconfig.coworker",pconfig);
+  if ($(this).attr('id') == "year_organisation") {
+    load_event_data();
+  }else if ($(this).attr('id') == "year_vacancy") {
+    load_table_vacancy();
+  }
+});
+
+$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+     var tn =  e.target.toString();
+     pconfig.activetab = tn.substring(tn.lastIndexOf("#")+1);
+     //dump(JSON.stringify(pconfig) + "\n");
+     apppref.setpreference("pageconfig.coworker",pconfig);
+     if (pconfig.activetab == 'activity') {
+       load_event_data();
+     }
+     if (pconfig.activetab == 'vacancy') {
+       load_table_vacancy();
+     }
+ });
+
+function load_event_data() {
+  dump("Load event Table!\n");
+  var where = new Array();
+
+    where.push(" st.uuid in ('"+ pconfig.uuid + "')");
+
+  $("div.panel-daybody").html("");
+  var sql = "SELECT cal.uuid, cal.datefrom, cal.dateto, '<div style=\"display:none;\">' || strftime('%Y%m%d',cal.datefrom) ||'</div>' || strftime('%d.%m.%Y',cal.datefrom) AS tbldatefrom ,strftime('%Y%m%d',cal.datefrom) AS strdatefrom, strftime('%Y%m%d',cal.dateto)   AS strdateto,cal.timefrom, cal.timeto, cal.description, cal.location, cal.color, cal.freq, '[\"' || GROUP_CONCAT(sp.staffuuid,'\",\"') || '\"]' as staffuuid, GROUP_CONCAT(coalesce(st.surname,'') || ' ' || coalesce(st.prename,''), '<br/>' ) as staffnames ,'[\"' || GROUP_CONCAT(st.color,'\",\"') || '\"]' as staffcolors from eventcalendar cal " +" join staffplanning sp on (cal.uuid=sp.eventcalendaruuid " + " AND sp.staffuuid in ('"+ pconfig.uuid +"')) left join staff st on (sp.staffuuid=st.uuid) "+
+  " where (cal.datefrom between '" + $('#year_organisation').val() + "-01-01' and '" + $('#year_organisation').val() + "-12-31' and (cal.dateto >= '" + $('#year_organisation').val() + "-01-01' or cal.dateto is null)) or (cal.dateto between '" + $('#year_organisation').val() + "-01-01' and '" + $('#year_organisation').val() + "-12-31' and cal.datefrom < '" + $('#year_organisation').val() + "-01-01') or ((cal.datefrom <= '" + $('#year_organisation').val() + "-01-01') and ((cal.dateto >= '" + $('#year_organisation').val() + "-12-31') or cal.dateto is null)) "+ ((where.length > 0)?" AND (" + where.join(" or ") + ")":"")+"  group by cal.uuid order by cal.datefrom,cal.dateto;";
+  
+  var caldata = appdb.dbquery(sql);
+
+  caldata = caldata.sqldata;
+  
+  var headerdata = getlabels("act,datefrom,hours,recurrance");
+  $("#tbl_activity").html("");
+  
+  var hrow = headerdata;
+  var tdclass= new Array();
+  var tblheader = '<tr>';
+
+  for (var h=0;h<hrow.length;h++){
+    tdclass.push(headerdata[h].class);
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+  }
+  tblheader += '</tr>';
+  
+  $("#tbl_activity").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_activity").append("<tbody>");
+  var tblbody = [];
+  for (var c in caldata) {
+    var tblrow = "<tr>";
+    tblrow += '<td class="noprint"><button type="button" class="btn btn-primary" onclick="dlg_event({uuid:\''+caldata[c].uuid+'\'},\'upd\');" title="editer"><span class="glyphicon glyphicon-pencil"></span></button></td>';
+    //tblrow += "<td><span style=\"display: none;\">"+caldata[c].description+"</span><strong style=\"color:"+ caldata[c].color +"\">" + caldata[c].description + "</strong></td>";
+    //tblrow += "<td>" + caldata[c].staffnames + "</td>";
+    tblrow += "<td>" + caldata[c].tbldatefrom + "</td>";
+    tblrow += "<td>" + caldata[c].timefrom + "- " + caldata[c].timeto + "</td>";
+
+    var freq2 = caldata[c].freq;
+    if (freq2 != '') {
+
+      freq2 += ';DTSTART='+caldata[c].strdatefrom + 'T000000Z';
+      if (caldata[c].dateto != ''){
+        freq2 += ';UNTIL='+caldata[c].strdateto + 'T000000Z';
+      }
+    }
+
+    try {
+
+    var rule2 = RRule.fromString(freq2);
+
+    
+    tblrow += "<td>" + rule2.toText() + "</td>";
+
+    } catch (ex){
+      //"ERROR! loading data!" + ex  + " FREQ:" + freq2 + "\n");
+    }
+    tblrow += "</tr>";
+    tblbody.push(tblrow);
+  }
+  
+  //load table
+  $("#tbl_activity").append(tblbody.join(''));
+  $("#tbl_activity").append("</tbody>");
+
+  tblcal = $("#tbl_activity").dataTable({
+    "language": {
+      "url": "../../web/js/locale/datatable_fr.json"
+    },
+    "paging": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+  
+  //$('#tbl_activity').on( 'search.dt', function () {
+  //  
+  //  pconfig.filter = tblcal.api().search();
+  //
+  //  apppref.setpreference("pageconfig.calactivity",pconfig);
+  //} );
+
+  //$('#tbl_activity').on( 'order.dt', function () {
+  //  pconfig.order= tblcal.fnSettings().aaSorting;
+  //
+  //  apppref.setpreference("pageconfig.calactivity",pconfig);
+  //  
+  //} );
+  
+//    if (pconfig.filter) {
+//      tblcal.fnFilter(pconfig.filter);
+//    }
+    if (pconfig.order) {
+      tblcal.fnSort(pconfig.order);
+    }
+    if (/*(!pconfig.filter) && */ (!pconfig.order)) {
+      tblcal.fnDraw();
+    }
+}
+
+function load_table_vacancy() {
+       //maxdayhours = (parseFloat($("#staff_weekhours").val())/5).toFixed(2);
+  //maxhalfdayhours = (maxdayhours/2).toFixed(2);
+  var yearvacanysql = "select hours from staffvacancydays where staffuuid='"+ pconfig.uuid+"' and vacancyyear='"+ $("#year_vacancy").val() +"';";
+  var yearvac = appdb.dbquery(yearvacanysql);
+  var nvyear = "";
+  //jsdump("XXSQL:" + JSON.stringify(yearvac) + "\n");
+  if (yearvac.sqldata){
+    nvyear = yearvac.sqldata[0].hours;
+  }
+  $("#vacancyyeartotal").val(nvyear);
+  var vacdatasql = "SELECT '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_vacancy({''uuid'':'''|| uuid || '''},''upd'');\"><span class=\"glyphicon glyphicon-pencil\"></span></button>" +
+  "<button type=\"button\" class=\"btn btn-danger\" onclick=\"confirm_delete_vacancy(''' || uuid || ''');\"><span class=\"glyphicon glyphicon-remove\"></span></button>' AS action," + "vacyear," +
+  "strftime('%d.%m.%Y', datefrom) as datefrom,strftime('%d.%m.%Y', dateto) as dateto,printf(\"%.2f\",hours) || 'h' as dayhours,description," +
+  "case when type=0 and accepted != '1' then printf(\"%.2f\",case when hours < maxdayhours  then hours when hours > maxdayhours  then maxdayhours else hours end) || 'h' else '' end as thnormalnv," +
+  "case when type=1 and accepted != '1' then printf(\"%.2f\",case when hours < maxdayhours  then hours when hours > maxdayhours  then maxdayhours else hours end) || 'h' else '' end as thextranv," +
+  "case when type=-1 and accepted != '1' then printf(\"%.2f\",case when hours < maxdayhours  then hours when hours > maxdayhours  then maxdayhours else hours end) || 'h' else '' end as thillnv," +
+  "case when type=0  and accepted = '1'then printf(\"%.2f\",case when hours < maxdayhours  then hours when hours > maxdayhours  then maxdayhours else hours end) || 'h' else '' end as thnormalval," +
+  "case when type=1  and accepted = '1' then printf(\"%.2f\",case when hours < maxdayhours  then hours when hours > maxdayhours  then maxdayhours else hours end) || 'h' else '' end as thextraval," +
+  "case when type=-1  and accepted = '1' then printf(\"%.2f\",case when hours < maxdayhours  then hours when hours > maxdayhours  then maxdayhours else hours end) || 'h' else '' end as thillval," +
+  "case when type=0 then 'normal' when type=1 then 'exceptionnelle' when type=-1 then 'maladie' end as vacancytype,case when accepted='1' and type != -1 then '<span style=\"font-weight: bold; color: green;\">OUI</span>' else '<span style=\"font-weight: bold; color: red\">NON</span>' end as accepted FROM (" +
+  "select vc.uuid,vc.vacyear,vc.datefrom,vc.dateto,vc.type,vc.description,vc.accepted," +
+  "((strftime('%s',vc.dateto) - strftime('%s',vc.datefrom)) /84600) + 1 as days," +
+  "((((strftime('%s',vc.dateto) - strftime('%s',vc.datefrom)) /84600) + 1) / 7) * (7 - (st.weekhours / st.maxdayhours)) as day_to_much," +
+  "(select count(v.vacancydate) from vacancy v where v.vacancydateto is null and strftime('%s',v.vacancydate) not in ('0','6') and v.vacancydate between vc.datefrom and vc.dateto) as vdays,st.weekhours,st.weekhours / maxdayhours as days_per_week,vc.timefrom,vc.timeto,st.maxdayhours, " +
+  "cast(cast(strftime(\"%s\",vc.timeto) as int)- cast(strftime(\"%s\",vc.timefrom) as int) as real)/3600 as hours " +
+  "from vacancycalendar vc join staff st on (vc.staffuuid=st.uuid) where vc.staffuuid='"+ pconfig.uuid+"' and vc.vacyear=" + pconfig.year+");";
+  //   var vacdatasql = "SELECT '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_vacancy({''uuid'':'''|| uuid || '''},''upd'');\"><span class=\"glyphicon glyphicon-pencil\"></span></button> <button type=\"button\" class=\"btn btn-danger\" onclick=\"confirm_delete_vacancy(''' || uuid || ''');\"><span class=\"glyphicon glyphicon-remove\"></span></button>' AS action,vacyear," +
+//    "CASE WHEN datefrom!=dateto THEN 'du:' || strftime('%d.%m.%Y', CASE WHEN datefrom < DATE('"+ pconfig.year +"-01-01') THEN DATE('"+ pconfig.year +"-01-01') ELSE datefrom END) || '<br/>au: ' || strftime('%d.%m.%Y', CASE WHEN dateto > DATE('"+ pconfig.year +"-12-31') THEN DATE('"+ pconfig.year +"-12-31') ELSE dateto END) ELSE strftime('%d.%m.%Y',datefrom) END AS planningdaterange," +
+//   //"case when datefrom!=dateto then strftime('%d.%m.%Y',case when datefrom < date('"+ pconfig.year +"-01-01') then 'de: ' date('"+ pconfig.year +"-01-01') else datefrom end) || '<br/>à: ' || strftime('%d.%m.%Y',case when dateto > date('"+ pconfig.year +"-12-31') then date('"+ pconfig.year +"-12-31') else dateto end) else strftime('%d.%m.%Y',datefrom) end as planningdaterange, " +
+// "case when  timefrom=timeto then '"+ maxdayhours+ "' || 'h' else printf(\"%.2f\",cast(cast(strftime(\"%s\",timeto) as int)- cast(strftime(\"%s\",timefrom) as int) as real)/3600) || 'h' || case when timefrom!='00:00' then '<br/> Ã  partir de ' || timefrom else '' end end as hourrange," +
+//    //"case when  timefrom=timeto then '8h' when  (cast(substr(timeto,1,2) as int) - cast(substr(timefrom,1,2) as int))= 4 then '4h' || case when timefrom!='00:00' then '<br/> Ã  partir de ' || timefrom else '' end else (cast(substr(timeto,1,2) as int) - cast(substr(timefrom,1,2) as int)) || 'h' || case when timefrom!='00:00' then '<br/> Ã  partir de ' || timefrom else '' end end as hourrange, "+ 
+// "description, " +
+// "case when type=0 then 'normal' when type=1 then 'exceptionnelle' when type=-1 then 'maladie' end as vacancytype,case when accepted='1' and type != -1 then '<span style=\"font-weight: bold; color: green;\">OUI</span>' else '<span style=\"font-weight: bold; color: red\">NON</span>' end as accepted FROM vacancycalendar where staffuuid='"+ pconfig.uuid +"' and (strftime('%Y',dateto)='"+ pconfig.year +"' or strftime('%Y',datefrom)='"+ pconfig.year +"');";
+//jsdump("XXSQL:" + vacdatasql + "\n");
+var vacdata = appdb.dbqueryarray(vacdatasql);
+//jsdump("XXSQL:" + JSON.stringify(vacdata) + "\n");
+  
+  $('#tbl_vacancy').html("");
+  //$('#tbl_vacancy').append('<tfoot><tr><th></th><th colspan="4" style="text-align: center;"></th></tr></tfoot>');
+  //getlastyearsrest();
+  //calcvacancy();
+  //vacdata.sqlhead.join(",") + "\n");
+  var headerdata = getlabels(vacdata.sqlhead.join(","));
+  
+  
+  $("#tbl_vacancy").dataTable({
+    "language": {
+      "url": "../../web/js/locale/datatable_fr.json"
+    },
+    "data": vacdata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+  
+}
+
+function dlg_vacancy(uuid, type) {
+       //select weekhours/5 = max daily hours
+       maxdayhours = (parseFloat($("#staff_weekhours").val())/5).toFixed(2);
+       maxhalfdayhours = (maxdayhours/2).toFixed(2);
+    var evdata = {
+      uuid: 0,
+      description: '',
+      vacdatefrom:new Date().toLocaleFormat("%d.%m.%Y"),
+      vacdateto:new Date().toLocaleFormat("%d.%m.%Y"),
+      staffuuid:[pconfig.uuid],
+      timefrom: '00:00',
+      hours: maxdayhours,
+      type:'0',
+      //dailyduration:'1.0',
+      //hourmax: whr
+    };
+    
+    if (type == 'upd') {
+       var evsql = "select uuid,vacdatefrom,vacdateto,timefrom,description,staffuuid,case when hours = '0.00' then '" + maxdayhours +"' else hours end as hours,accepted from (SELECT uuid, strftime(\"%d.%m.%Y\",datefrom) as vacdatefrom, strftime(\"%d.%m.%Y\",dateto) as vacdateto, timefrom, description, '"+pconfig.uuid+"' as staffuuid,type, printf(\"%.2f\",cast((cast(strftime(\"%s\",timeto) as int)- cast(strftime(\"%s\",timefrom) as int))/3600 as real)) as hours,accepted FROM vacancycalendar where uuid='" + uuid.uuid + "');";
+     //var evsql = "SELECT uuid, strftime(\"%d.%m.%Y\",datefrom) as vacdatefrom, strftime(\"%d.%m.%Y\",dateto) as vacdateto, timefrom, description, '"+pconfig.uuid+"' as staffuuid,type, case when timefrom!=timeto then '0.' || (cast(substr(timeto,1,2) as int) - cast(substr(timefrom,1,2) as int)) else 1.0 end as dailyduration,null as hours,accepted FROM vacancycalendar where uuid='" + uuid.uuid + "';";
+      //dump("EVSQL: " + evsql + "\n");
+      evdata = appdb.dbquery(evsql);
+      evdata = evdata.sqldata[0];
+      if (evdata.type == -1){
+        $("#btnacceptvacancy").hide();
+      }else {
+        $("#btnacceptvacancy").show();
+      }
+      if (evdata.hours >= maxdayhours) {
+         evdata.hours=maxdayhours;
+         $('#dailyduration select').val("1.0");
+      } else if (evdata.hours == maxhalfdayhours){
+         $('#dailyduration select').val("0.4");
+      } else {
+         $('#dailyduration select').val("0.");
+      }
+
+    }else {
+       $('#dailyduration select').val("1.0");
+    }
+    for (var w in evdata) {
+      if ((w == 'datefrom') || (w == 'dateto')) {
+        w='vac' + w;
+      }
+      
+      if ($("#frmeditvacancy #" + w)) {
+        //dump(w + "->"+evdata[w]+"\n");
+         if (w == "type"){
+                 $("#frmeditvacancy #" + w + " select").val(evdata[w]);
+         } else {
+                 $("#frmeditvacancy #" + w).val(evdata[w]);  
+         }
+         
+        
+      }
+      
+    }
+    
+    setdailydurationfields();
+    $("#edit_vacancy").modal('show');
+}
+
+function confirm_delete_vacancy(uuid) {
+  delvacation = uuid;
+  $("#confirm_delete_vacancy").modal('show');
+  return false;
+}
+
+function delete_vacancy() {
+  var delsql = "DELETE FROM vacancycalendar where uuid='" + delvacation+"';";
+  appdb.dbexec(delsql);
+  load_table_vacancy();
+  delvacancy=null;
+  $("#confirm_delete_vacancy").modal('hide');
+  
+  return false;
+}
+
+function setdailydurationfields() {
+  var dd = $('#dailyduration :selected').val();
+  if (dd=='1.0') {
+    //$("#ftimefrom").hide();
+    $("#hours").prop("disabled",true);
+  }else if (dd=='0.4') {
+    //$("#ftimefrom").show();
+    $("#hours").prop("disabled",true);
+  }else if (dd=='0.') {
+    //$("#ftimefrom").show();
+    $("#hours").prop("disabled",false);
+  }
+}
+
+function save_vacancy() {
+  var type = 'ins';
+  var cuuid = "";
+  if ($("#frmeditvacancy #uuid").val() != 0) {
+    type = 'upd';
+    cuuid = $("#frmeditvacancy #uuid").val();
+  }
+  var evsvdata = {
+                 uuid:cuuid,
+                 datefrom: $("#frmeditvacancy #vacdatefrom").val(),
+                 dateto: $("#frmeditvacancy #vacdateto").val(),
+                 timefrom: $("#frmeditvacancy #timefrom").val(),
+                 hours: $("#frmeditvacancy #hours").val(),
+                 description: $("#frmeditvacancy #description").val(),
+                 staffuuid: $("#frmeditvacancy #staffuuid").val(),
+      type: $("#frmeditvacancy #type").val()
+  }
+  var savesql = "";
+  if (type == 'ins') {
+         savesql = "INSERT INTO vacancycalendar (uuid, datefrom, dateto, timefrom, timeto, description, staffuuid, type,vacyear) VALUES "
+        +"('" + appdb.generate_uuid() + "', date("+encodeparam(evsvdata.datefrom, 'date')+"), date("+encodeparam(evsvdata.dateto, 'date')+"), "+encodeparam(evsvdata.timefrom, 'text')+", strftime(\"%H:%M\",time("+encodeparam(evsvdata.timefrom, 'text')+",'+"+evsvdata.hours+" hours')), "+encodeparam(evsvdata.description, 'text')+", "+encodeparam(evsvdata.staffuuid, 'text')+","+evsvdata.type+","+encodeparam(evsvdata.datefrom, 'year')+");";
+  } else {
+      savesql = "UPDATE vacancycalendar SET vacyear=" + encodeparam(evsvdata.datefrom, 'year') + ", datefrom = date("+encodeparam(evsvdata.datefrom, 'date')+"), dateto = date("+encodeparam(evsvdata.dateto, 'date')+"), timefrom = "+encodeparam(evsvdata.timefrom, 'text')+", timeto = strftime(\"%H:%M\",time("+encodeparam(evsvdata.timefrom, 'text')+",'+"+evsvdata.hours+" hours')), description = "+encodeparam(evsvdata.description, 'text')+", staffuuid = "+encodeparam(evsvdata.staffuuid, 'text')+", type = "+evsvdata.type+" WHERE uuid = '"+evsvdata.uuid+"';";
+  }
+  //dump("VACSAVESQL:" + savesql + "\n");
+  appdb.dbexec(savesql);
+  load_table_vacancy();
+
+  $("#frmeditvacancy #uuid").val("0");
+  $("#edit_vacancy").modal('hide');
+}
+
+
+function set_selectyears() {
+   
+  var years = appdb.dbquery("select strftime('%Y',coalesce(min(entrydate),date('now','-1 year'))) as minyear, strftime('%Y',date('now', '+1 year')) as maxyear  from staff where uuid='"+pconfig.uuid+"';");
+  var minyear = parseInt(years.sqldata[0].minyear);
+  var maxyear = parseInt(years.sqldata[0].maxyear);
+  for (var y=minyear;y<=maxyear;y++){
+    
+    var sel = "";
+    if (y == pconfig.year) {
+      sel=' selected="1" ';
+      
+    }
+    
+    $(".selyear").append("<option value=\""+y+"\""+sel+">"+y+"</option>");
+  }
+  
+}
+
+// function calcvacancy() {
+//   //"Calc Vacancy Data!\n");
+//   var csel = "select days,hours from staffvacancydays where staffuuid='"+pconfig.uuid+"' and vacancyyear='"+pconfig.year+"';";
+//   //"SQL:"+ csel +"\n");
+//   var cnum = appdb.dbquery(csel);
+  
+//   if (cnum.sqldata.length > 0) {
+//     if (pconfig.vacancyunit == "hours"){
+//       if ((!cnum.sqldata[0].hours) || (cnum.sqldata[0].hours === "")){
+//         cnum.sqldata[0].hours = cnum.sqldata[0].days * 8;
+//       }
+//       $('#vacancyyeartotal').val(cnum.sqldata[0].hours);
+//     }else{
+//       $('#vacancyyeartotal').val(cnum.sqldata[0].days);  
+//     }
+    
+//   }else {
+//     $('#vacancyyeartotal').val("");
+//   }
+//   var vdays = (($('#vacancyyeartotal').val() === "")?"":cnum.sqldata[0].days);
+//   var weekhours = $('#staff_weekhours').val();
+//   if (vdays === '') {
+//     $('#vacancystatus').html('<div class="alert alert-danger" style="padding: 2px;">Pas de jours de congés configuré pour l\'année '+ pconfig.year+'!</div>');
+//     return;
+//   }else if (weekhours === '') {
+//     $('#vacancystatus').html('<div class="alert alert-danger">Pas de heures par semaine configurées!</div>');
+//     return;
+//   }
+
+//   var vcalcsql = "select printf(\"%.2f\",(sum(dayhours) / ("+weekhours+"/5))) as days, printf(\"%.2f\",SUM(dayhours)) as hours,"+
+//   "taken,type,accepted from (" +
+//   "select vd.daydate,case when daydate <= date('now')   then 1 else 0 end as taken,case when vc.timefrom=vc.timeto then cast ("+weekhours+"/5 as real) else cast(cast(strftime(\"%s\",vc.timeto) as int)- cast(strftime(\"%s\",vc.timefrom) as int) as real)/3600 end as dayhours,type,case when type != -1 then accepted else '1' end as accepted "+
+//   "from vacancycalendar vc left join ( "+ 
+//   "select daydate from ( ";
+//   var df = new Date(pconfig.year,0,1);
+//   var dt = new Date(pconfig.year,11,31);
+//   var yd = [];
+//   for (var dx=df;dx<=dt;dx.setDate(dx.getDate()+1)){
+//     yd.push("select date('"+dx.toLocaleFormat('%Y-%m-%d')+"') as daydate");
+//   }
+//   vcalcsql += yd.join(" UNION ") + 
+//   ") yd where strftime('%w',daydate) not in ('0','6') and daydate not in (select vacancydate from vacancy where vacancydate between '"+pconfig.year+"-01-01' and '"+pconfig.year+"-12-31' and vacancydateto is null) " +
+//   ") vd on (vd.daydate between vc.datefrom and vc.dateto) " +
+//   "left join staffvacancydays svd on (vc.staffuuid=svd.staffuuid) " +
+//   "where vc.staffuuid='"+pconfig.uuid+ "' and daydate is not null group by daydate) group by type,taken,accepted;";
+//   //dump("SQL2:" + vcalcsql + "\n");
+//   var vcalc = appdb.dbquery(vcalcsql);
+//   vcalc = vcalc.sqldata;
+//   //dump(JSON.stringify(vcalc)+ "\n");
+//   vhours = vdays * 8;
+//   var vac = {};
+//   $("#lblyear").html(pconfig.year);
+//   vac.normal = {taken:{hours:0,days:0},open:{vhours:parseFloat(vhours), days:parseFloat(vdays)},accepted:{hours:0,days:0},asked:{hours:0,days:0}};
+//   vac.extra = {taken:{hours:0,days:0},open:{hours:0, days:0},accepted:{hours:0,days:0},asked:{hours:0,days:0}};
+//   vac.ill = {taken:{hours:0,days:0},open:{hours:0, days:0},accepted:{hours:0,days:0},asked:{hours:0,days:0}};
+//   vac.total = {taken:{hours:0,days:0},open:{hours:0, days:0},accepted:{hours:0,days:0},asked:{hours:0,days:0}};
+//   //dump(JSON.stringify(vac) + "\n");
+//   if (vcalc) {
+//     for (var c in vcalc){
+//       if (vcalc[c].type == '0' ){ //normal
+//         if (vcalc[c].taken == '1'){
+//             if  (vcalc[c].accepted=='1'){
+//             vac.normal.taken.days = vac.normal.taken.days + parseFloat(vcalc[c].days);
+//                 vac.normal.taken.hours = vac.normal.taken.hours + parseFloat(vcalc[c].hours);
+//             } else {
+//             vac.normal.asked.days = vac.normal.asked.days + parseFloat(vcalc[c].days);
+//                 vac.normal.asked.hours = vac.normal.asked.hours + parseFloat(vcalc[c].hours);
+//             }
+          
+//         } else if (vcalc[c].taken == '0') {
+//           if (vcalc[c].accepted=='1'){
+//               vac.normal.accepted.days = vac.normal.accepted.days + parseFloat(vcalc[c].days);
+//               vac.normal.accepted.hours = vac.normal.accepted.hours + parseFloat(vcalc[c].hours);
+//           } else {
+//               vac.normal.asked.days = vac.normal.asked.days + parseFloat(vcalc[c].days);
+//               vac.normal.asked.hours = vac.normal.asked.hours + parseFloat(vcalc[c].hours);
+//           }
+          
+//         }
+//         vac.normal.open.days = parseFloat(vdays) - vac.normal.taken.days - vac.normal.accepted.days - vac.normal.asked.days;
+//         vac.normal.open.hours = parseFloat(vhours) - vac.normal.taken.hours - vac.normal.accepted.hours - vac.normal.asked.hours;
+//         //total
+        
+//       } else if (vcalc[c].type == '1' ){ //extra
+//         if (vcalc[c].taken == '1'){
+//             if  (vcalc[c].accepted=='1'){
+//             vac.extra.taken.days =  vac.extra.taken.days + parseFloat(vcalc[c].days);
+//             vac.extra.taken.hours = vac.extra.taken.hours + parseFloat(vcalc[c].hours);
+//             } else {
+//             vac.extra.asked.days = vac.extra.asked.days + parseFloat(vcalc[c].days);
+//                 vac.extra.asked.hours = vac.extra.asked.hours + parseFloat(vcalc[c].hours);
+//             }
+//         } else if (vcalc[c].taken == '0'){
+//             if (vcalc[c].accepted=='1'){
+//             vac.extra.accepted.days = vac.extra.accepted.days + parseFloat(vcalc[c].days);
+//             vac.extra.accepted.hours = vac.extra.accepted.hours + parseFloat(vcalc[c].hours);
+//             } else {
+//             vac.extra.asked.days = vac.extra.asked.days + parseFloat(vcalc[c].days);
+//                 vac.extra.asked.hours = vac.extra.asked.hours + parseFloat(vcalc[c].hours);
+//             }
+//         }
+//         vac.extra.open.days = 0;
+//         vac.extra.open.hours = 0;
+//       } else if (vcalc[c].type == '-1' ){ //ill
+//         if (vcalc[c].taken == '1'){
+//           vac.ill.taken.days =  vac.ill.taken.days + parseFloat(vcalc[c].days);
+//           vac.ill.taken.hours = vac.ill.taken.hours + parseFloat(vcalc[c].hours);
+//         } else if (vcalc[c].taken == '0'){
+//             if  (vcalc[c].accepted=='1'){
+//             vac.ill.accepted.days = vac.ill.accepted.days + parseFloat(vcalc[c].days);
+//             vac.ill.accepted.hours = vac.ill.accepted.hours + parseFloat(vcalc[c].hours);
+//             } else {
+//             vac.ill.asked.days = vac.ill.asked.days + parseFloat(vcalc[c].days);
+//                 vac.ill.asked.hours = vac.ill.asked.hours + parseFloat(vcalc[c].hours);
+//             }
+//         }
+//         vac.ill.open.days = 0;
+//         vac.ill.open.hours = 0;
+
+//       }
+//       vac.total.taken.days = vac.normal.taken.days + vac.extra.taken.days + vac.ill.taken.days;
+//       vac.total.taken.hours = vac.normal.taken.hours + vac.extra.taken.hours + vac.ill.taken.hours;
+//       vac.total.open.days = vac.normal.open.days + vac.extra.open.days + vac.ill.open.days;
+//       vac.total.open.hours = vac.normal.open.hours + vac.extra.open.hours + vac.ill.open.hours;
+//       vac.total.accepted.days = vac.normal.accepted.days + vac.extra.accepted.days + vac.ill.accepted.days;
+//       vac.total.accepted.hours = vac.normal.accepted.hours + vac.extra.accepted.hours + vac.ill.accepted.hours;
+//       vac.total.asked.days = vac.normal.asked.days + vac.extra.asked.days + vac.ill.asked.days;
+//       vac.total.asked.hours = vac.normal.asked.hours + vac.extra.asked.hours + vac.ill.asked.hours;
+//     }
+//     //JSON.stringify(vac) + "\n");
+//     if (pconfig.vacancyunit == 'days'){
+//       $("#vacnopen").html(((vac.normal.open.days && vac.normal.open.days != 0)?vac.normal.open.days.toFixed(2)+" j":"&nbsp;"));
+//       $("#vacntaken").html(vac.normal.taken.days.toFixed(2)+" j");
+//       $("#vacnasked").html(vac.normal.asked.days.toFixed(2)+" j");
+//       $("#vacnplanned").html(vac.normal.accepted.days.toFixed(2)+" j");
+    
+//       $("#vaceopen").html("&nbsp;");
+//       $("#vacetaken").html(vac.extra.taken.days.toFixed(2)+" j");
+//       $("#vaceasked").html(vac.extra.asked.days.toFixed(2)+" j");
+//       $("#vaceplanned").html(vac.extra.accepted.days.toFixed(2)+" j");
+    
+//       $("#vacmopen").html("&nbsp;");
+//       $("#vacmtaken").html(vac.ill.taken.days.toFixed(2)+" j");
+//       $("#vacmasked").html(vac.ill.asked.days.toFixed(2)+" j");
+//       $("#vacmplanned").html(vac.ill.accepted.days.toFixed(2)+" j");
+    
+//       $("#vactopen").html(vac.total.open.days.toFixed(2)+" j");
+//       $("#vacttaken").html(vac.total.taken.days.toFixed(2)+" j");
+//       $("#vactasked").html(vac.total.asked.days.toFixed(2)+" j");
+//       $("#vactplanned").html(vac.total.accepted.days.toFixed(2)+" j");
+//     } else {
+//       vac.normal.open.hours=vac.normal.open.hours + parseInt($("#vacancylastyearrest").val());
+//       $("#vacnopen").html(((vac.normal.open.hours && vac.normal.open.hours != 0)?vac.normal.open.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vacntaken").html(((vac.normal.taken.hours && vac.normal.taken.hours > 0)?vac.normal.taken.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vacnasked").html(((vac.normal.asked.hours && vac.normal.asked.hours > 0)?vac.normal.asked.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vacnplanned").html(((vac.normal.accepted.hours && vac.normal.accepted.hours > 0)?vac.normal.accepted.hours.toFixed(2)+" h":"&nbsp;"));
+      
+//       $("#vacetaken").html(((vac.extra.taken.hours && vac.extra.taken.hours > 0)?vac.extra.taken.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vaceasked").html(((vac.extra.asked.hours && vac.extra.asked.hours > 0)?vac.extra.asked.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vaceplanned").html(((vac.extra.accepted.hours && vac.extra.accepted.hours > 0)?vac.extra.accepted.hours.toFixed(2)+" h":"&nbsp;"));
+      
+//       $("#vacmtaken").html(((vac.ill.taken.hours && vac.ill.taken.hours > 0)?vac.ill.taken.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vacmasked").html(((vac.ill.asked.hours && vac.ill.asked.hours > 0)?vac.ill.asked.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vacmplanned").html(((vac.ill.accepted.hours && vac.ill.accepted.hours > 0)?vac.ill.accepted.hours.toFixed(2)+" h":"&nbsp;"));
+      
+//       $("#vactopen").html(((vac.total.open.hours && vac.total.open.hours > 0)?vac.total.open.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vacttaken").html(((vac.total.taken.hours && vac.total.taken.hours > 0)?vac.total.taken.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vactasked").html(((vac.total.asked.hours && vac.total.asked.hours > 0)?vac.total.asked.hours.toFixed(2)+" h":"&nbsp;"));
+//       $("#vactplanned").html(((vac.total.accepted.hours && vac.total.accepted.hours > 0)?vac.total.accepted.hours.toFixed(2)+" h":"&nbsp;"));
+      
+//     }
+    
+//     //dump(JSON.stringify(vac) + " - Set data vacancy status\n");
+//     //  var hdata = "&nbsp;<span style=\"font-weight: normal;\"><span style=\"text-decoration: underline;\">pris:</span> <strong>"+ vac.taken.hours +" h</strong> ("+ vac.taken.days.toFixed(2)+" jour(s)) - ";
+//     //  hdata += "&nbsp;<span style=\"text-decoration: underline;\">planifié:</span> <strong>"+ vac.rest.hours+" h</strong> ("+ vac.rest.days.toFixed(2)+" jour(s)) - ";
+//     //  hdata += "&nbsp;<span style=\"text-decoration: underline;\">ouvert:</span> <strong>"+ vac.open.hours +" h</strong> ("+ vac.open.days.toFixed(2)+" jour(s))";
+//     //  if (vac.ill > 0) {
+//     //    hdata += " - &nbsp;(<span style=\"text-decoration: underline;\">maladie:</span> <strong>"+ vac.ill.hours+" h</strong> ("+ vac.ill.days.toFixed(2)+" jour(s)))</span>";
+//     //  }
+//       //dump("HTML: --" + document.getElementById("vacancystatus").innerHTML +"//\n->" + hdata + "\n");
+//       //$("#vacancystatus").html("");
+//       //if ($("#vacancystatus")){
+//       //dump("vacancystatus exists\n");
+//       //  
+//       //}
+//       $("#vacancystatus").html("");
+//   }
+//   else {
+//     $("#vacancystatus").html("");
+//   }
+// }
+
+function saveyearvacdays() {
+  var csel = "select * from staffvacancydays where staffuuid='"+pconfig.uuid+"' and vacancyyear='"+pconfig.year+"';";  
+  var days = 0;
+  var hours = 0;
+  if ($('#vacancyyeartotal').val() === ""){
+    return;
+  }
+  if (pconfig.vacancyunit == "hours"){
+    days = parseFloat($('#vacancyyeartotal').val().replace(',','.')) / 8;
+    hours = $('#vacancyyeartotal').val();
+  }else {
+    days = parseFloat($('#vacancyyeartotal').val().replace(',','.'));
+    hours = parseFloat($('#vacancyyeartotal').val().replace(',','.')) * 8;
+  }
+  var cnum = appdb.dbquery(csel);
+  var inssql = "INSERT INTO staffvacancydays (staffuuid,vacancyyear,days,hours) VALUES ('"+pconfig.uuid+"','"+pconfig.year+"',"+days+","+hours+");";
+  if (cnum.sqldata.length > 0) {
+    inssql = "UPDATE staffvacancydays SET days="+days+",hours="+hours+" where staffuuid='"+pconfig.uuid+"' and vacancyyear='"+pconfig.year+"';";
+  }
+  appdb.dbexec(inssql);
+  //calcvacancy();
+}
+
+// function setvacancyunit(){
+//   var vacunit = $('#vacancy_unit').val();
+//   if ($('#vacancyyeartotal').val() !== ""){
+//     var vacval = parseFloat($('#vacancyyeartotal').val().replace(',','.'));
+//     if (((!pconfig.vacancyunit) || (pconfig.vacancyunit == 'days')) && (vacunit == 'hours')){
+//       $('#vacancyyeartotal').val(vacval * 8);
+//     }else if (pconfig.vacancyunit != vacunit){
+//       $('#vacancyyeartotal').val(vacval / 8);
+//     }
+//   }
+//   //dump("vacunit: " + vacunit + "\n");
+//   pconfig.vacancyunit = vacunit;
+//   apppref.setpreference("pageconfig.coworker",pconfig);
+// }
+
+function dlg_event(uuid, type) {
+
+  //$('#staffuuid').multiselect('deselectAll', false);
+  //$('#staffuuid').multiselect('updateButtonText');
+  if (type== "ins") {
+    
+    $('#btndeleteevent').hide();
+    
+  }else {
+    $('#btndeleteevent').show();
+  }
+  $('#frmeditevent #freqinterval').hide();
+  $('#frmeditevent #freqmonthly').hide();
+  $('#frmeditevent #freqweekly').hide();
+  $('#frmeditevent #freq_monthly_byday').show();
+  $('#frmeditevent #freq_monthly_bymonthday').hide();
+  $('#frmeditevent #freq').val("");
+  $('#frmeditevent .active').removeClass('active');
+  if ((type == 'upd') || (type == 'ins')) {
+
+    var evdata = {
+      uuid: '0',
+      description: '',
+      activityuuid:'',
+      location: '',
+      color: '',
+      datefrom:new Date().toLocaleFormat("%d.%m.%Y"),
+      dateto:'',
+      staffuuid: pconfig.uuid,
+      timefrom: '00:00',
+      timeto: '00:00',
+      freq: '',
+      staffname: $("#staff_prename").val() + " " + $("#staff_surname").val()
+    };
+    //jsdump(JSON.stringify(pconfig) + "\n");
+    //jsdump(JSON.stringify(evdata) + "\n");
+    if (type == 'upd') {
+     var evsql = "SELECT uuid, strftime(\"%d.%m.%Y\",datefrom) as datefrom, strftime(\"%d.%m.%Y\",dateto) as dateto, timefrom, timeto, description, location, color, freq,  '"+ pconfig.uuid+"' as staffuuid FROM eventcalendar ev left join staffplanning st on (ev.uuid=st.eventcalendaruuid) where ev.uuid='" + uuid.uuid + "' group by ev.uuid;";
+      evdata = appdb.dbquery(evsql);
+      evdata = evdata.sqldata[0];
+      evdata['staffname'] = $("#staff_prename").val() + " " + $("#staff_surname").val();
+      if (evdata.freq != '') {
+        var tmpfreq = evdata.freq.split(';');
+        for (var t in tmpfreq){
+          if (tmpfreq[t] != '') {
+            var spl = tmpfreq[t].split("=");
+            evdata[spl[0].toLowerCase()] = spl[1].toLowerCase();
+          }
+        }
+      }
+    }
+    for (var w in evdata) {
+      if ($("#frmeditevent #" + w)) {
+        // if (w == 'staffuuid') {
+        //   if (evdata[w] == '') {
+        //     $("#frmeditevent #" + w).multiselect('select',[]);
+        //   } else {
+        //     $("#frmeditevent #" + w).multiselect('select',evdata[w].split(','));
+        //   }
+          
+        // }
+        // else if (w == 'color') {
+        //   $("#frmeditevent #color").val(evdata[w]);
+        //   $('#frmeditevent #color').minicolors('value',{color: evdata[w]});
+        // }
+        // else {
+          $("#frmeditevent #" + w).val(evdata[w]);  
+        // }
+      }
+    }
+    if ((evdata.freq == 'weekly') && (evdata.byday)) {
+      var bd = evdata.byday.split(',');
+      for (var i in bd){
+        document.getElementById('weekly_byday_' + bd[i]).setAttribute("checked",true);
+        $('#frmeditevent #weekly_byday_' + bd[i]).parent().addClass("active");
+      }
+    }
+    if (evdata.freq == 'monthly') {
+       $('#freq_monthly_byday').hide();
+       $('#freq_monthly_bymonthday').hide();
+       $('#pnl_monthly_byday').removeAttr("checked");
+       $('#pnl_monthly_bymonthday').removeAttr("checked");
+      if (evdata.byday) {
+        document.getElementById('pnl_monthly_byday').setAttribute("checked",true);
+        $('#frmeditevent #pnl_monthly_byday').parent().addClass("active");
+        $('#freq_monthly_byday').show();
+        var bd = evdata.byday.split(',');
+        var adpos = new Array();
+        var awday = new Array();
+        for (var i in bd){
+          var wday = bd[i].substr(bd[i].length-2);
+          var pos = bd[i].substring(0,bd[i].length-2);
+          awday.push(wday.toLowerCase());
+          adpos.push(pos);
+        }
+
+        for (var i in adpos){
+          document.getElementById('monthly_bydaypos_' + adpos[i]).setAttribute("checked",true);
+          $('#frmeditevent #monthly_bydaypos_' + adpos[i]).parent().addClass("active");
+        }
+        for (var i in awday){
+          document.getElementById('monthly_bydaywday_' + awday[i]).setAttribute("checked",true);
+          $('#frmeditevent #monthly_bydaywday_' + awday[i]).parent().addClass("active");
+        }
+      }else if (evdata.bymonthday) {
+        document.getElementById('pnl_monthly_bymonthday').setAttribute("checked",true);
+        $('#frmeditevent #pnl_monthly_bymonthday').parent().addClass("active");
+        $('#freq_monthly_bymonthday').show();
+        var bd = evdata.bymonthday.split(',');
+        for (var i in bd){
+          document.getElementById('monthly_bymonthday_' + bd[i]).setAttribute("checked",true);
+          $('#frmeditevent #monthly_bymonthday_' + bd[i]).parent().addClass("active");
+        }
+      }
+    }
+    setfreq();
+    $("#edit_event").modal('show');
+  } 
+}
+
+
+function save_event() {
+  var sql1 = new Array();
+  var sql2 = new Array();
+  if ($('#timefrom').val() == $('#timeto').val() || $('#timefrom').val() == "00:00" || $('#timeto').val() == "00:00"){
+    errormsg("Erreur","les heures doivent Ãªtre différent et différent de la valeur 00:00!");
+    return false;
+  }
+  if ($('#timefrom').val() > $('#timeto').val()){
+    errormsg("Erreur","l'heure de début ne peux pas Ãªtre supérieur Ã  l'heure de fin!");
+    return false;
+  }
+  if (!$('#staffuuid').val()){
+    errormsg("Erreur","Vous devez selectionner au moin 1 membre du staff!");
+    return false;
+  }
+  if ($('#dateto').val() != '' && (encodeparam($('#datefrom').val()) > encodeparam($('#dateto').val()))  ) {
+    errormsg("Erreur","La Date début ne peut pas Ãªtre supérieur Ã  la date fin!");
+    return false;
+  }
+  var type = 'ins';
+  var cuuid = "";
+  if ($("#frmeditevent #uuid").val() != 0) {
+    type = 'upd';
+    cuuid = $("#frmeditevent #uuid").val();
+  } else {
+    cuuid = appdb.generate_uuid();
+  }
+  var freqdata = {};
+  var cfreq = $("#frmeditevent #freq").val();
+  $("#frmeditevent :input").each(function() {
+    var input = $(this);
+    
+    if (input.attr("id") && (input.attr("id") != "staffuuid") && (input.attr("id") != "staffname")) {
+      if ((input.attr("type") == "checkbox") && (input.attr("id").indexOf(cfreq) >= 0)){
+        var xd = input.attr("id").split("_");
+        if (input.attr("checked")) {
+          if (!freqdata[xd[1]]) {
+            freqdata[xd[1]] = new Array();
+          }
+          freqdata[xd[1]].push(input.val());
+        }
+      }
+      else if ((input.attr("type") == "radio") && (input.attr("id").indexOf(cfreq) >= 0)) {
+        var xd = input.attr("id").split("_");
+        if (input.attr("checked")) { 
+          freqdata['freqtype'] = xd[2];
+        }
+      }
+      else if ((input.attr("type") != "checkbox") && ((input.attr("type") != "radio"))){
+        if ((input.attr("id") == 'interval') || (input.attr("id") == 'freq')) {
+          freqdata[input.attr("id")] = input.val();
+        } else if ((type == 'ins') && (input.attr("id") != 'staffuuid')) {
+          
+          sql1.push('"' + input.attr("id") + '"');
+          if (input.attr("id") == 'uuid') {
+            if (input.val() == "" || input.val() == "0") {
+              sql2.push("'" + cuuid + "'");
+            } else {
+              sql2.push("'" + input.val() + "'");
+            }
+          } else {
+            var ival = encodeparam(input.val(), input.attr('type'));
+            sql2.push(ival);
+          }
+        } else {
+          if ((input.attr("id") != 'uuid') && (input.attr("id") != 'staffuuid')){
+            var ival = encodeparam(input.val(), input.attr('type'));
+            sql2.push('"' + input.attr("id") + '"=' + ival);
+          }
+        }
+      }
+    }
+
+  });
+  if (!freqdata.freqtype) {
+    freqdata['freqtype'] = curfreq.freqtype;
+  }
+
+  var strfreq ="";
+  if (cfreq != "") {
+    strfreq='FREQ=' + cfreq.toUpperCase()+';INTERVAL=' + freqdata.interval +';';
+    if ((cfreq == 'weekly') && (freqdata.byday)){
+      strfreq += 'BYDAY=' + freqdata.byday.join(","); 
+    }
+    if ((cfreq == 'monthly') && (freqdata.bydaypos) || ((freqdata.bydaywday)) || (freqdata.bymonthday)){
+      strfreq += freqdata.freqtype.toUpperCase() + '=';
+      if (freqdata.freqtype == 'bymonthday') {
+        strfreq += freqdata.bymonthday.join(',') + ";"
+      }else {
+        var abyday = new Array();
+        for (var p in freqdata.bydaypos){
+          for (var w in freqdata.bydaywday){
+            abyday.push(freqdata.bydaypos[p] + freqdata.bydaywday[w]);
+          }
+        }
+        strfreq += abyday.join(",");
+      }
+    }
+    if (strfreq.slice(-1) == ';') {
+      strfreq = strfreq.substring(0,strfreq.length-1);
+    }
+  }
+  var staffuuids = $('#staffuuid').val();
+  var delsql = "";
+  var xsql = [];
+  if (type != 'ins') {
+   xsql.push("DELETE FROM staffplanning where eventcalendaruuid = '"+cuuid+"';");
+  }
+  var staffinssql = "";
+  
+  if (staffuuids && (staffuuids.length != 0)) {
+    
+    staffinssql = "INSERT INTO staffplanning (eventcalendaruuid,staffuuid) VALUES ";
+    var tmps = [];
+    var curcoworkerok = false;
+    for (var s in staffuuids){
+      if (staffuuids[s] == pconfig.uuid){
+        curcoworkerok = true;
+      }
+      tmps.push("('"+cuuid+"','"+staffuuids[s]+"')");
+    }
+    if (!curcoworkerok){
+      tmps.push("('"+cuuid+"','"+pconfig.uuid+"')");
+    } 
+    staffinssql += tmps.join(',') + ";";  
+    xsql.push(staffinssql);
+  }
+  if (staffuuids.length == 0){
+    staffinssql = "INSERT INTO staffplanning (eventcalendaruuid,staffuuid) VALUES ('"+cuuid+"','"+pconfig.uuid+"');";
+    xsql.push(staffinssql);
+  }
+  
+
+  
+  if (type == 'upd') {
+    sql2.push('freq=' + encodeparam(strfreq));
+    xsql.push("UPDATE eventcalendar SET " + sql2.join(',') + " where \"uuid\"='" + cuuid + "';");
+  } else {
+    sql1.push('freq');
+    sql2.push(encodeparam(strfreq));
+    xsql.push("INSERT INTO eventcalendar (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");");
+  }
+  dump(JSON.stringify(xsql));
+  for (var i in xsql){
+         appdb.dbexec(xsql[i]);
+  }
+  
+  load_event_data();
+   
+  $("#frmeditevent #uuid").val("0");
+  $("#edit_event").modal('hide');
+}
+
+function confirm_delete_event() {
+  $("#confirm_delete_event").modal('show');
+  return false;
+}
+
+function delete_event() {
+       appdb.dbexec("DELETE FROM eventcalendar where uuid='" + $('#frmeditevent #uuid').val()+"';");
+       appdb.dbexec("DELETE FROM staffplanning where eventcalendaruuid='" + $('#frmeditevent #uuid').val()+"';");
+  load_event_data();
+  $("#confirm_delete_event").modal('hide');
+  
+  return false;
+}
+
+
+
+function setfreq() {
+
+  curfreq.freq = $('#freq option:selected').val();
+
+  $('#freqinterval').hide();
+  $('#freqmonthly').hide();
+  $('#freqweekly').hide();
+  if (curfreq.freq != "") {
+
+    $('#lblfreq').text(lblfreq[curfreq.freq]);
+    $('#freqinterval').show();
+    if (curfreq.freq !=  'daily') {
+      $('#freq' + curfreq.freq).show();
+    }
+  }
+  
+}
+
+// function load_staff_selection(objid,option){
+//   var stdata = appdb.dbquery("select uuid, coalesce(surname,'') || ' ' || coalesce(prename,'') as name,case when color is null then '#000' else color end as color from staff order by surname,prename");
+
+//   stdata = stdata.sqldata;
+//   for (var s in stdata){
+//     $('#' + objid).append('<option value="'+ stdata[s].uuid+'">&lt;span style="color: '+stdata[s].color+';" &gt;' +stdata[s].name+ '&lt;/span&gt;</option>');
+//   }
+  
+//     var copt = {};
+//     if (option) {
+//       copt = option;
+//     }
+//     copt['enableHTML'] = true;
+//     copt['nonSelectedText']="Sélectionner un(e) employé(e)...";
+//     copt['numberDisplayed']=5;
+//     copt['allSelectedText']='Tous';
+//     copt['nSelectedText']=' selections';
+    
+//     $('#' + objid).multiselect(copt);
+  
+// }
+
+function accept_vacancy(){
+    var cuuid = "";
+    if ($("#frmeditvacancy #uuid").val() != 0) {
+      type = 'upd';
+      cuuid = $("#frmeditvacancy #uuid").val();
+    }
+    var xsql = "UPDATE vacancycalendar SET accepted='1' where \"uuid\"='" + cuuid + "';";
+    appdb.dbexec(xsql);
+    load_table_vacancy();
+
+    $("#frmeditvacancy #uuid").val("0");
+    $("#edit_vacancy").modal('hide');
+}
+
+function getlastyearsrest(){
+    var weekhours = $('#staff_weekhours').val();
+    if (weekhours === '') {
+      $("#vacancylastyearrest").val(0);
+      return;
+    }
+    var df = new Date(pconfig.year-1,0,1);
+    var dt = new Date(pconfig.year-1,11,31);
+    var vcalcrestsql = "select (select hours from staffvacancydays where staffuuid='"+pconfig.uuid+ "' and vacancyyear="+df.getFullYear()+")-SUM(dayhours) AS hours from (" +
+    "select vd.daydate,case when daydate <= date('now')   then 1 else 0 end as taken,case when vc.timefrom=vc.timeto then cast ("+weekhours+"/5 as real) else (cast (substr(vc.timeto,1,2) as int) + (cast(substr(vc.timeto,4,5) as int)/60))  - (cast(substr(vc.timefrom,1,2) as int) + (cast(substr(vc.timeto,4,5) as int)/60)) end as dayhours,type,case when type != -1 then accepted else '1' end as accepted "+
+    "from vacancycalendar vc left join ( "+ 
+    "select daydate from ( ";
+    
+    var yd = [];
+    for (var dx=df;dx<=dt;dx.setDate(dx.getDate()+1)){
+      yd.push("select date('"+dx.toLocaleFormat('%Y-%m-%d')+"') as daydate");
+    }
+    vcalcrestsql += yd.join(" UNION ") + 
+    ") yd where strftime('%w',daydate) not in ('0','6') and daydate not in (select vacancydate from vacancy where vacancydate between '"+df.getFullYear()+"-01-01' and '"+dt.getFullYear()+"-12-31' and vacancydateto is null) " +
+    ") vd on (vd.daydate between vc.datefrom and vc.dateto) " +
+    "left join staffvacancydays svd on (vc.staffuuid=svd.staffuuid) " +
+    "where vc.staffuuid='"+pconfig.uuid+ "' and daydate is not null group by daydate) where type in (0,1) and taken=1 and accepted=1 group by taken,accepted;";
+    //dump("SQLREST:" + vcalcrestsql + "\n");
+    var vcalc = appdb.dbquery(vcalcrestsql);
+    //dump(JSON.stringify(vcalc) + "\n");
+    if (vcalc && vcalc.sqldata[0]){
+       
+       $("#vacancylastyearrest").val(vcalc.sqldata[0].hours);
+    }else {
+       $("#vacancylastyearrest").val(0);
+    }
+    return;
+}
diff --git a/modules/staff/js/coworker_basic.js b/modules/staff/js/coworker_basic.js
new file mode 100644 (file)
index 0000000..fe62ee4
--- /dev/null
@@ -0,0 +1,827 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = null;
+var delplan = null;
+var delvacation = null;
+var wh= window.innerHeight -440;
+var curdatediff = null;
+var redate = /\d\d.\d\d.\d\d\d\d/;
+var curfreq ={};
+//var lictype = apppref.getpreference("support.lictype"); 
+
+function initdata() {
+  load_helpers();
+  var pdata = apppref.getpreference("pageconfig.coworker");
+  if (pdata != '') {
+    pconfig = JSON.parse(pdata);
+  }
+  //"get CoWorker cfg:" +JSON.stringify(pconfig) + "\n");
+  if (!pconfig.year) {
+    pconfig.year=new Date().getFullYear();
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.coworker",pconfig);
+  }
+  var cdatasql = "SELECT jobtitle, prename, surname, address, zip, city, country, strftime('%d.%m.%Y',entrydate) as entrydate, strftime('%d.%m.%Y',exitdate) as exitdate, iban, bic, accountname, phone, email, uuid,color,weekhours,case when password is not null and length(password) > 3 then 1 else 0 end as passwordset  FROM staff where uuid='" + pconfig.uuid + "';";
+  var cdata = appdb.dbquery(cdatasql);
+  cdata = cdata.sqldata[0];
+  for (var ci in cdata) {
+    if (document.getElementById("staff_" + ci)) {
+       
+        $("#staff_" + ci).val(cdata[ci]);
+        if (ci == "color"){
+               $("#staff_color").css("background-color",cdata[ci]);
+               $("#staff_color").val("");
+        }
+      
+    }
+    
+  }
+  var crdata = appdb.dbquery("select stafflist from creche;");
+  if ((crdata) && (crdata.sqldata[0].stafflist == "1")){
+         $("#pwddata").hide();
+  }
+  if (cdata) {
+    set_infoheader(cdata.prename + " " + cdata.surname);
+  }
+  set_selectyears();
+
+  if (pconfig && pconfig.activetab) {
+    $('a[href="#'+pconfig.activetab+'"]').tab('show');
+  }else{
+    $('a[href="#vacancy"]').tab('show');
+    pconfig.activetab = 'vacancy';
+  }
+  
+//if (pconfig && pconfig.vacancyunit){
+////dump("has vacancy unit:" + pconfig.vacancyunit + "\n");
+//$('#vacancy_unit').val(pconfig.vacancyunit);
+//}else {
+pconfig.vacancyunit = "hours";
+//$('#vacancy_unit').val("days");
+//}
+  
+  $('#frmeditvacancy #vacdatefrom').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditvacancy #vacdatefrom').val().match(redate)) {
+      $('#btn_save_vacancy').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_vacancy').attr("disabled","1");
+    }
+    if ((ok == true) && ($('#frmeditvacancy #vacdateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditvacancy #vacdatefrom').val(),'date');
+      var nd = new Date(tmpdt1.replace(/'/g,''));
+      var xd = new Date(nd.getFullYear(),nd.getMonth(),nd.getDate() + curdatediff);
+      $('#frmeditvacancy #vacdateto').val(xd.toLocaleFormat("%d.%m.%Y"));
+      var tmpdt2 = encodeparam($('#frmeditvacancy #vacdateto').val(),'date');
+      if (tmpdt1 > tmpdt2) {
+        $('#btn_save_vacancy').attr("disabled","1");
+      } else {
+        $('#btn_save_vacancy').removeAttr("disabled");
+      }
+      
+    }
+  });
+  $('#frmeditvacancy #vacdateto').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditvacancy #vacdateto').val().match(redate)) {
+      $('#btn_save_vacancy').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_vacancy').attr("disabled","1");
+    }
+    curdatediff=daysBetween(new Date(encodeparam($('#frmeditvacancy #vacdatefrom').val(),'date').replace(/'/g,'')),new Date(encodeparam($('#frmeditvacancy #vacdateto').val(),'date').replace(/'/g,''))); 
+    if ((ok == true) && ($('#frmeditvacancy #vacdateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditvacancy #vacdatefrom').val(),'date');
+      var tmpdt2 = encodeparam($('#frmeditvacancy #vacdateto').val(),'date');
+      if (tmpdt1 > tmpdt2) {
+        $('#btn_save_vacancy').attr("disabled","1");
+      } else {
+        $('#btn_save_vacancy').removeAttr("disabled");
+      }
+      
+    }
+  });
+  
+  
+  $("#weekly_byday :input").change(function() {
+    if (this.checked) {
+      this.setAttribute("checked",true);
+    }else {
+      this.removeAttribute("checked");
+    }
+
+});
+  $("#monthly_bydaypos :input").change(function() {
+
+    if (this.checked) {
+      this.setAttribute("checked",true);
+    }else {
+      this.removeAttribute("checked");
+    }
+
+});
+  $("#monthly_bydaywday :input").change(function() {
+
+    if (this.checked) {
+      this.setAttribute("checked",true);
+    }else {
+      this.removeAttribute("checked");
+    }
+
+});
+  $("#monthly_bymonthday :input").change(function() {
+
+    if (this.checked) {
+      this.setAttribute("checked",true);
+    }else {
+      this.removeAttribute("checked");
+    }
+
+});
+  $("#monthly_by :input").change(function() {
+    var xd = this.id.split("_");
+    curfreq.freqtype=xd[2];
+
+      this.setAttribute("checked",true);
+
+    $('#freq_monthly_byday').hide();
+    $('#freq_monthly_bymonthday').hide();
+    $('#pnl_monthly_byday').removeAttr("checked");
+    $('#pnl_monthly_bymonthday').removeAttr("checked");
+
+    $('#freq_' + this.value).show();
+
+});
+
+  $('#frmeditevent #datefrom').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditevent #datefrom').val().match(redate)) {
+      $('#btn_save_event').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_event').attr("disabled","1");
+    }
+    if ((ok == true) && ($('#frmeditevent #dateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditevent #datefrom').val(),'date');
+      var tmpdt2 = encodeparam($('#frmeditevent #dateto').val(),'date');
+      if (tmpdt1 >= tmpdt2) {
+        $('#btn_save_event').attr("disabled","1");
+      } else {
+        $('#btn_save_event').removeAttr("disabled");
+      }
+      
+    }
+  });
+  $('#frmeditevent #dateto').on("blur",function (e) {
+    var ok = true;
+    if ($('#frmeditevent #dateto').val().match(redate)) {
+      $('#btn_save_event').removeAttr("disabled");
+    }else {
+      ok = false;
+      $('#btn_save_event').attr("disabled","1");
+    }
+    if ((ok == true) && ($('#frmeditevent #dateto').val() != '')) {
+      var tmpdt1 = encodeparam($('#frmeditevent #datefrom').val(),'date');
+      var tmpdt2 = encodeparam($('#frmeditevent #dateto').val(),'date');
+
+      if (tmpdt1 >= tmpdt2) {
+        $('#btn_save_event').attr("disabled","1");
+      } else {
+        $('#btn_save_event').removeAttr("disabled");
+      }
+      
+    }
+  });
+
+}
+
+$('.selyear').on( "change", function(e){ 
+  e.preventDefault();
+
+  $(".selyear").val($(this).val());
+  pconfig.year = $(this).val();
+  apppref.setpreference("pageconfig.coworker",pconfig);
+  if ($(this).attr('id') == "year_organisation") {
+    load_event_data();
+  }else if ($(this).attr('id') == "year_vacancy") {
+    load_table_vacancy();
+  }
+});
+
+$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+     var tn =  e.target.toString();
+     pconfig.activetab = tn.substring(tn.lastIndexOf("#")+1);
+     //dump(JSON.stringify(pconfig) + "\n");
+     apppref.setpreference("pageconfig.coworker",pconfig);
+     if (pconfig.activetab == 'activity') {
+       load_event_data();
+     }
+     if (pconfig.activetab == 'vacancy') {
+       load_table_vacancy();
+     }
+ });
+
+function load_event_data() {
+  var where = new Array();
+
+    where.push(" st.uuid in ('"+ pconfig.uuid + "')");
+
+  $("div.panel-daybody").html("");
+  var sql = "SELECT cal.uuid, cal.datefrom, cal.dateto, '<div style=\"display:none;\">' || strftime('%Y%m%d',cal.datefrom) ||'</div>' || strftime('%d.%m.%Y',cal.datefrom) AS tbldatefrom ,strftime('%Y%m%d',cal.datefrom) AS strdatefrom, strftime('%Y%m%d',cal.dateto)   AS strdateto,cal.timefrom, cal.timeto, cal.description, cal.location, cal.color, cal.freq, '[\"' || GROUP_CONCAT(sp.staffuuid,'\",\"') || '\"]' as staffuuid, GROUP_CONCAT(coalesce(st.surname,'') || ' ' || coalesce(st.prename,''), '<br/>' ) as staffnames ,'[\"' || GROUP_CONCAT(st.color,'\",\"') || '\"]' as staffcolors from eventcalendar cal " +" join staffplanning sp on (cal.uuid=sp.eventcalendaruuid " + " AND sp.staffuuid in ('"+ pconfig.uuid +"')) left join staff st on (sp.staffuuid=st.uuid) "+
+  " where (cal.datefrom between '" + $('#year_organisation').val() + "-01-01' and '" + $('#year_organisation').val() + "-12-31' and (cal.dateto >= '" + $('#year_organisation').val() + "-01-01' or cal.dateto is null)) or (cal.dateto between '" + $('#year_organisation').val() + "-01-01' and '" + $('#year_organisation').val() + "-12-31' and cal.datefrom < '" + $('#year_organisation').val() + "-01-01') or ((cal.datefrom <= '" + $('#year_organisation').val() + "-01-01') and ((cal.dateto >= '" + $('#year_organisation').val() + "-12-31') or cal.dateto is null)) "+ ((where.length > 0)?" AND (" + where.join(" or ") + ")":"")+"  group by cal.uuid order by cal.datefrom,cal.dateto;";
+
+  var caldata = appdb.dbquery(sql);
+
+  caldata = caldata.sqldata;
+  
+  var headerdata = getlabels("act,activity,datefrom,hours,recurrance");
+  $("#tbl_activity").html("");
+  
+  var hrow = headerdata;
+  var tdclass= new Array();
+  var tblheader = '<tr>';
+
+  for (var h=0;h<hrow.length;h++){
+    tdclass.push(headerdata[h].class);
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+  }
+  tblheader += '</tr>';
+  
+  $("#tbl_activity").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_activity").append("<tbody>");
+  var tblbody = [];
+  for (var c in caldata) {
+    var tblrow = "<tr>";
+    tblrow += '<td class="noprint">&nbsp;</td>';
+    tblrow += "<td><span style=\"display: none;\">"+caldata[c].description+"</span><strong style=\"color:"+ caldata[c].color +"\">" + caldata[c].description + "</strong></td>";
+    tblrow += "<td>" + caldata[c].tbldatefrom + "</td>";
+    tblrow += "<td>" + caldata[c].timefrom + "- " + caldata[c].timeto + "</td>";
+
+    var freq2 = caldata[c].freq;
+    if (freq2 != '') {
+
+      freq2 += ';DTSTART='+caldata[c].strdatefrom + 'T000000Z';
+      if (caldata[c].dateto != ''){
+        freq2 += ';UNTIL='+caldata[c].strdateto + 'T000000Z';
+      }
+    }
+
+    try {
+
+    var rule2 = RRule.fromString(freq2);
+
+    
+    tblrow += "<td>" + rule2.toText() + "</td>";
+
+    } catch (ex){
+      //"ERROR! loading data!" + ex  + " FREQ:" + freq2 + "\n");
+    }
+    tblrow += "</tr>";
+    tblbody.push(tblrow);
+  }
+  
+  //load table
+  $("#tbl_activity").append(tblbody.join(''));
+  $("#tbl_activity").append("</tbody>");
+
+  tblcal = $("#tbl_activity").dataTable({
+    "language": {
+      "url": "../../web/js/locale/datatable_fr.json"
+    },
+    "paging": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+  
+  //$('#tbl_activity').on( 'search.dt', function () {
+  //  
+  //  pconfig.filter = tblcal.api().search();
+  //
+  //  apppref.setpreference("pageconfig.calactivity",pconfig);
+  //} );
+
+  //$('#tbl_activity').on( 'order.dt', function () {
+  //  pconfig.order= tblcal.fnSettings().aaSorting;
+  //
+  //  apppref.setpreference("pageconfig.calactivity",pconfig);
+  //  
+  //} );
+  
+//    if (pconfig.filter) {
+//      tblcal.fnFilter(pconfig.filter);
+//    }
+    if (pconfig.order) {
+      tblcal.fnSort(pconfig.order);
+    }
+    if (/*(!pconfig.filter) && */ (!pconfig.order)) {
+      tblcal.fnDraw();
+    }
+}
+
+function load_table_vacancy() {
+    
+    var vacdatasql = "SELECT case when (datefrom > date('now') or accepted!='1') and type != -1 then '<button type=\"button\" class=\"btn btn-primary\" onclick=\"dlg_vacancy({''uuid'':'''|| uuid || '''},''upd'');\"><span class=\"glyphicon glyphicon-pencil\"></span></button> <button type=\"button\" class=\"btn btn-danger\" onclick=\"confirm_delete_vacancy(''' || uuid || ''');\"><span class=\"glyphicon glyphicon-remove\"></span></button>' else '&nbsp;' end AS action," +
+    "CASE WHEN datefrom!=dateto THEN 'du:' || strftime('%d.%m.%Y', CASE WHEN datefrom < DATE('"+ pconfig.year +"-01-01') THEN DATE('"+ pconfig.year +"-01-01') ELSE datefrom END) || '<br/>au: ' || strftime('%d.%m.%Y', CASE WHEN dateto > DATE('"+ pconfig.year +"-12-31') THEN DATE('"+ pconfig.year +"-12-31') ELSE dateto END) ELSE strftime('%d.%m.%Y',datefrom) END AS planningdaterange," +
+   //"case when datefrom!=dateto then strftime('%d.%m.%Y',case when datefrom < date('"+ pconfig.year +"-01-01') then 'de: ' date('"+ pconfig.year +"-01-01') else datefrom end) || '<br/>à: ' || strftime('%d.%m.%Y',case when dateto > date('"+ pconfig.year +"-12-31') then date('"+ pconfig.year +"-12-31') else dateto end) else strftime('%d.%m.%Y',datefrom) end as planningdaterange, " +
+   "case when  timefrom=timeto then '8h' when  (cast(substr(timeto,1,2) as int) - cast(substr(timefrom,1,2) as int))= 4 then '4h' || case when timefrom!='00:00' then '<br/> Ã  partir de ' || timefrom else '' end else (cast(substr(timeto,1,2) as int) - cast(substr(timefrom,1,2) as int)) || 'h' || case when timefrom!='00:00' then '<br/> Ã  partir de ' || timefrom else '' end end as hourrange, "+ 
+ "description, " +
+ "case when type=0 then 'normal' when type=1 then 'exceptionnelle' when type=-1 then 'maladie' end as vacancytype,case when accepted='1' and type != -1 then '<span style=\"font-weight: bold; color: green;\">OUI</span>' else '<span style=\"font-weight: bold; color: red\">NON</span>' end as accepted FROM vacancycalendar where staffuuid='"+ pconfig.uuid +"' and (strftime('%Y',dateto)='"+ pconfig.year +"' or strftime('%Y',datefrom)='"+ pconfig.year +"');";
+ //dump("XXSQL:" + vacdatasql + "\n");
+var vacdata = appdb.dbqueryarray(vacdatasql);
+
+  
+  $('#tbl_vacancy').html("");
+  //$('#tbl_vacancy').append('<tfoot><tr><th></th><th colspan="4" style="text-align: center;"></th></tr></tfoot>');
+  getlastyearsrest();
+  calcvacancy();
+  //vacdata.sqlhead.join(",") + "\n");
+  var headerdata = getlabels(vacdata.sqlhead.join(","));
+
+  $("#tbl_vacancy").dataTable({
+    "language": {
+      "url": "../../web/js/locale/datatable_fr.json"
+    },
+    "data": vacdata.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": false,
+    "destroy": true
+  });
+  
+}
+
+//function add_coworker() {
+//  var newuuid = appdb.generate_uuid();
+//  appdb.dbexec("insert into staff (uuid) VALUES ('" + newuuid + "');");
+//  globelreq.send_request({
+//    page: 'coworker',
+//    data: {
+//      "uuid": newuuid
+//    },
+//    header: 'HEADER TODO'
+//  });
+//}
+
+function dlg_vacancy(uuid, type) {
+    var evdata = {
+      uuid: 0,
+      description: '',
+      vacdatefrom:new Date().toLocaleFormat("%d.%m.%Y"),
+      vacdateto:new Date().toLocaleFormat("%d.%m.%Y"),
+      staffuuid:pconfig.uuid,
+      timefrom: '00:00',
+      hours: '1',
+      type:'0',
+      dailyduration:'1.0'
+    };
+    
+    if (type == 'upd') {
+     var evsql = "SELECT uuid, strftime(\"%d.%m.%Y\",datefrom) as vacdatefrom, strftime(\"%d.%m.%Y\",dateto) as vacdateto, timefrom, description, '"+pconfig.uuid+"' as staffuuid,type, case when timefrom!=timeto then '0.' || (cast(substr(timeto,1,2) as int) - cast(substr(timefrom,1,2) as int)) else 1.0 end as dailyduration,null as hours,accepted FROM vacancycalendar where uuid='" + uuid.uuid + "';";
+      
+      evdata = appdb.dbquery(evsql);
+      evdata = evdata.sqldata[0];
+      if (evdata.type == -1){
+        $("#btnacceptvacancy").hide();
+      }else {
+        $("#btnacceptvacancy").show();
+      }
+      if (evdata.dailyduration == '1') {
+        evdata.dailyduration = '1.0';
+        evdata.hours = '8';
+      }else {
+        evdata.hours = evdata.dailyduration.substring(2,3);
+        if (evdata.dailyduration != '0.4') {
+          evdata.dailyduration = '0.';
+        }
+      }
+
+    }
+
+    for (var w in evdata) {
+      if ((w == 'datefrom') || (w == 'dateto')) {
+        w='vac' + w;
+      }
+      //dump(w + "\n");
+      if ($("#frmeditvacancy #" + w)) {
+        $("#frmeditvacancy #" + w).val(evdata[w]);
+      }
+    }
+    setdailydurationfields();
+    $("#edit_vacancy").modal('show');
+}
+
+function confirm_delete_vacancy(uuid) {
+  delvacation = uuid;
+  $("#confirm_delete_vacancy").modal('show');
+  return false;
+}
+
+function delete_vacancy() {
+  var delsql = "DELETE FROM vacancycalendar where uuid='" + delvacation+"';";
+  appdb.dbexec(delsql);
+  load_table_vacancy();
+  delvacancy=null;
+  $("#confirm_delete_vacancy").modal('hide');
+  
+  return false;
+}
+
+function setdailydurationfields() {
+  var dd = $('#dailyduration :selected').val();
+  if (dd=='1.0') {
+    $("#ftimefrom").hide();
+    $("#fhours").hide();
+  }else if (dd=='0.4') {
+    $("#ftimefrom").show();
+    $("#fhours").hide();
+  }else if (dd=='0.') {
+    $("#ftimefrom").show();
+    $("#fhours").show();
+  }
+}
+
+function save_vacancy() {
+  var sql1 = new Array();
+  var sql2 = new Array();
+  var type = 'ins';
+  var cuuid = "";
+  if ($("#frmeditvacancy #uuid").val() != 0) {
+    type = 'upd';
+    cuuid = $("#frmeditvacancy #uuid").val();
+  }
+  
+  $("#frmeditvacancy :input").each(function() {
+    var input = $(this);
+    
+    if (input.attr("id")) {
+        
+        if (type == 'ins') {
+          
+          
+          if (input.attr("id") == 'uuid') {
+            sql1.push('"' + input.attr("id") + '"');
+            if (input.val() == "" || input.val() == "0") {
+              sql2.push("'" + appdb.generate_uuid() + "'");
+            } else {
+              sql2.push("'" + input.val() + "'");
+            }
+          } else if (input.attr("id") == 'dailyduration') {
+            sql1.push('"timeto"');
+            if (input.val() == '1.0') {
+              sql2.push("'" +$('#timefrom').val() + "'");
+            }else if (input.val() == '0.4') {
+              var xval = parseInt($('#timefrom').val().substring(1,2)) + 4;
+              if (xval < 10) { xval = "0" + xval;}
+              xval += ":00";
+              sql2.push("'" + xval + "'");
+            }else {
+              var xval = parseInt($('#timefrom').val().substring(1,2)) + parseInt($('#hours').val());
+              if (xval < 10) { xval = "0" + xval;}
+              xval += ":00";
+              sql2.push("'" + xval + "'");
+            }
+          } else if ((input.attr("id") != 'dailyduration') && (input.attr("id") != 'hours')) {
+            var xid = input.attr("id")
+            if ((input.attr("id") == 'vacdatefrom') || (input.attr("id") == 'vacdateto')) {
+
+              sql1.push('"' + input.attr("id").substring(3) + '"');
+            }else {
+              sql1.push('"' + input.attr("id") + '"');
+            }
+            
+            var ival = encodeparam(input.val(), input.attr('type'));
+            sql2.push(ival);
+          }
+        } else {
+          if ((input.attr("id") != 'uuid') && (input.attr("id") != 'dailyduration') && (input.attr("id") != 'hours')) {
+            var ival = encodeparam(input.val(), input.attr('type'));
+            var xid =input.attr("id");
+            if ((input.attr("id") == 'vacdatefrom') || (input.attr("id") == 'vacdateto')) {
+              xid =input.attr("id").substring(3);
+            }
+            sql2.push('"' + xid + '"=' + ival);
+          } else if (input.attr("id") == 'dailyduration') {
+            if (input.val() == '1.0') {
+              sql2.push('"timeto"='+ "'" + $('#timefrom').val() + "'");
+            }else if (input.val() == '0.4') {
+              var xval = parseInt($('#timefrom').val().substring(1,2)) + 4;
+              if (xval < 10) { xval = "0" + xval;}
+              xval += ":00";
+              sql2.push('"timeto"=' +"'" + xval + "'");
+            }else {
+              var xval = parseInt($('#timefrom').val().substring(1,2)) + parseInt($('#hours').val());
+              if (xval < 10) { xval = "0" + xval;}
+              xval += ":00";
+              sql2.push('"timeto"=' +"'" + xval + "'");
+            }
+          }
+        }
+
+    }
+
+  });
+  
+  var xsql = "";
+  if (type == 'upd') {
+    xsql = "UPDATE vacancycalendar SET " + sql2.join(',') + " where \"uuid\"='" + cuuid + "';";
+  } else {
+
+    xsql = "INSERT INTO vacancycalendar (" + sql1.join(',') + ") VALUES (" + sql2.join(',') + ");";
+  }
+
+  appdb.dbexec(xsql);
+  load_table_vacancy();
+
+  $("#frmeditvacancy #uuid").val("0");
+  $("#edit_vacancy").modal('hide');
+}
+
+
+function set_selectyears() {
+   
+  var years = appdb.dbquery("select strftime('%Y',coalesce(min(entrydate),date('now','-1 year'))) as minyear, strftime('%Y',date('now', '+1 year')) as maxyear  from staff where uuid='"+pconfig.uuid+"';");
+  var minyear = parseInt(years.sqldata[0].minyear);
+  var maxyear = parseInt(years.sqldata[0].maxyear);
+  for (var y=minyear;y<=maxyear;y++){
+    
+    var sel = "";
+    if (y == pconfig.year) {
+      sel=' selected="1" ';
+      
+    }
+    
+    $(".selyear").append("<option value=\""+y+"\""+sel+">"+y+"</option>");
+  }
+  
+}
+
+function calcvacancy() {
+    //"Calc Vacancy Data!\n");
+    var csel = "select days,hours from staffvacancydays where staffuuid='"+pconfig.uuid+"' and vacancyyear='"+pconfig.year+"';";
+    //"SQL:"+ csel +"\n");
+    var cnum = appdb.dbquery(csel);
+    
+    if (cnum.sqldata.length > 0) {
+      if (pconfig.vacancyunit == "hours"){
+        if ((!cnum.sqldata[0].hours) || (cnum.sqldata[0].hours === "")){
+          cnum.sqldata[0].hours = cnum.sqldata[0].days * 8;
+        }
+        $('#vacancyyeartotal').val(cnum.sqldata[0].hours);
+      }else{
+        $('#vacancyyeartotal').val(cnum.sqldata[0].days);  
+      }
+      
+    }else {
+      $('#vacancyyeartotal').val("");
+    }
+    var vdays = (($('#vacancyyeartotal').val() === "")?"":cnum.sqldata[0].days);
+    var weekhours = $('#staff_weekhours').val();
+    if (vdays === '') {
+      $('#vacancystatus').html('<div class="alert alert-danger" style="padding: 2px;">Pas de jours de congés configuré pour l\'année '+ pconfig.year+'!</div>');
+      return;
+    }else if (weekhours === '') {
+      $('#vacancystatus').html('<div class="alert alert-danger">Pas de heures par semaine configurées!</div>');
+      return;
+    }
+
+    var vcalcsql = "select printf(\"%.2f\",(sum(dayhours) / ("+weekhours+"/5))) as days, SUM(dayhours) as hours,"+
+    "taken,type,accepted from (" +
+    "select vd.daydate,case when daydate <= date('now')   then 1 else 0 end as taken,case when vc.timefrom=vc.timeto then cast ("+weekhours+"/5 as real) else (cast (substr(vc.timeto,1,2) as int) + (cast(substr(vc.timeto,4,5) as int)/60))  - (cast(substr(vc.timefrom,1,2) as int) + (cast(substr(vc.timeto,4,5) as int)/60)) end as dayhours,type,case when type != -1 then accepted else '1' end as accepted "+
+    "from vacancycalendar vc left join ( "+ 
+    "select daydate from ( ";
+    var df = new Date(pconfig.year,0,1);
+    var dt = new Date(pconfig.year,11,31);
+    var yd = [];
+    for (var dx=df;dx<=dt;dx.setDate(dx.getDate()+1)){
+      yd.push("select date('"+dx.toLocaleFormat('%Y-%m-%d')+"') as daydate");
+    }
+    vcalcsql += yd.join(" UNION ") + 
+    ") yd where strftime('%w',daydate) not in ('0','6') and daydate not in (select vacancydate from vacancy where vacancydate between '"+pconfig.year+"-01-01' and '"+pconfig.year+"-12-31' and vacancydateto is null) " +
+    ") vd on (vd.daydate between vc.datefrom and vc.dateto) " +
+    "left join staffvacancydays svd on (vc.staffuuid=svd.staffuuid) " +
+    "where vc.staffuuid='"+pconfig.uuid+ "' and daydate is not null group by daydate) group by type,taken,accepted;";
+    //dump("SQL2:" + vcalcsql + "\n");
+    var vcalc = appdb.dbquery(vcalcsql);
+    vcalc = vcalc.sqldata;
+    //dump(JSON.stringify(vcalc)+ "\n");
+    vhours = vdays * 8;
+    var vac = {};
+    $("#lblyear").html(pconfig.year);
+    vac.normal = {taken:{hours:0,days:0},open:{vhours:parseFloat(vhours), days:parseFloat(vdays)},accepted:{hours:0,days:0},asked:{hours:0,days:0}};
+    vac.extra = {taken:{hours:0,days:0},open:{hours:0, days:0},accepted:{hours:0,days:0},asked:{hours:0,days:0}};
+    vac.ill = {taken:{hours:0,days:0},open:{hours:0, days:0},accepted:{hours:0,days:0},asked:{hours:0,days:0}};
+    vac.total = {taken:{hours:0,days:0},open:{hours:0, days:0},accepted:{hours:0,days:0},asked:{hours:0,days:0}};
+    //dump(JSON.stringify(vac) + "\n");
+    if (vcalc) {
+      for (var c in vcalc){
+        if (vcalc[c].type == '0' ){ //normal
+          if (vcalc[c].taken == '1'){
+              if  (vcalc[c].accepted=='1'){
+               vac.normal.taken.days = vac.normal.taken.days + parseFloat(vcalc[c].days);
+                  vac.normal.taken.hours = vac.normal.taken.hours + parseFloat(vcalc[c].hours);
+              } else {
+               vac.normal.asked.days = vac.normal.asked.days + parseFloat(vcalc[c].days);
+                  vac.normal.asked.hours = vac.normal.asked.hours + parseFloat(vcalc[c].hours);
+              }
+            
+          } else if (vcalc[c].taken == '0') {
+            if (vcalc[c].accepted=='1'){
+                vac.normal.accepted.days = vac.normal.accepted.days + parseFloat(vcalc[c].days);
+                vac.normal.accepted.hours = vac.normal.accepted.hours + parseFloat(vcalc[c].hours);
+            } else {
+                vac.normal.asked.days = vac.normal.asked.days + parseFloat(vcalc[c].days);
+                vac.normal.asked.hours = vac.normal.asked.hours + parseFloat(vcalc[c].hours);
+            }
+            
+          }
+          vac.normal.open.days = parseFloat(vdays) - vac.normal.taken.days - vac.normal.accepted.days - vac.normal.asked.days;
+          vac.normal.open.hours = parseFloat(vhours) - vac.normal.taken.hours - vac.normal.accepted.hours - vac.normal.asked.hours;
+          //total
+          
+        } else if (vcalc[c].type == '1' ){ //extra
+          if (vcalc[c].taken == '1'){
+              if  (vcalc[c].accepted=='1'){
+               vac.extra.taken.days =  vac.extra.taken.days + parseFloat(vcalc[c].days);
+               vac.extra.taken.hours = vac.extra.taken.hours + parseFloat(vcalc[c].hours);
+              } else {
+               vac.extra.asked.days = vac.extra.asked.days + parseFloat(vcalc[c].days);
+                  vac.extra.asked.hours = vac.extra.asked.hours + parseFloat(vcalc[c].hours);
+              }
+          } else if (vcalc[c].taken == '0'){
+              if (vcalc[c].accepted=='1'){
+               vac.extra.accepted.days = vac.extra.accepted.days + parseFloat(vcalc[c].days);
+               vac.extra.accepted.hours = vac.extra.accepted.hours + parseFloat(vcalc[c].hours);
+              } else {
+               vac.extra.asked.days = vac.extra.asked.days + parseFloat(vcalc[c].days);
+                  vac.extra.asked.hours = vac.extra.asked.hours + parseFloat(vcalc[c].hours);
+              }
+          }
+          vac.extra.open.days = 0;
+          vac.extra.open.hours = 0;
+        } else if (vcalc[c].type == '-1' ){ //ill
+          if (vcalc[c].taken == '1'){
+            vac.ill.taken.days =  vac.ill.taken.days + parseFloat(vcalc[c].days);
+            vac.ill.taken.hours = vac.ill.taken.hours + parseFloat(vcalc[c].hours);
+          } else if (vcalc[c].taken == '0'){
+              if  (vcalc[c].accepted=='1'){
+               vac.ill.accepted.days = vac.ill.accepted.days + parseFloat(vcalc[c].days);
+               vac.ill.accepted.hours = vac.ill.accepted.hours + parseFloat(vcalc[c].hours);
+              } else {
+               vac.ill.asked.days = vac.ill.asked.days + parseFloat(vcalc[c].days);
+                  vac.ill.asked.hours = vac.ill.asked.hours + parseFloat(vcalc[c].hours);
+              }
+          }
+          vac.ill.open.days = 0;
+          vac.ill.open.hours = 0;
+
+        }
+        vac.total.taken.days = vac.normal.taken.days + vac.extra.taken.days + vac.ill.taken.days;
+        vac.total.taken.hours = vac.normal.taken.hours + vac.extra.taken.hours + vac.ill.taken.hours;
+        vac.total.open.days = vac.normal.open.days + vac.extra.open.days + vac.ill.open.days;
+        vac.total.open.hours = vac.normal.open.hours + vac.extra.open.hours + vac.ill.open.hours;
+        vac.total.accepted.days = vac.normal.accepted.days + vac.extra.accepted.days + vac.ill.accepted.days;
+        vac.total.accepted.hours = vac.normal.accepted.hours + vac.extra.accepted.hours + vac.ill.accepted.hours;
+        vac.total.asked.days = vac.normal.asked.days + vac.extra.asked.days + vac.ill.asked.days;
+        vac.total.asked.hours = vac.normal.asked.hours + vac.extra.asked.hours + vac.ill.asked.hours;
+      }
+      //JSON.stringify(vac) + "\n");
+      if (pconfig.vacancyunit == 'days'){
+        $("#vacnopen").html(((vac.normal.open.days && vac.normal.open.days != 0)?vac.normal.open.days.toFixed(2)+" j":"&nbsp;"));
+        $("#vacntaken").html(vac.normal.taken.days.toFixed(2)+" j");
+        $("#vacnasked").html(vac.normal.asked.days.toFixed(2)+" j");
+        $("#vacnplanned").html(vac.normal.accepted.days.toFixed(2)+" j");
+      
+        $("#vaceopen").html("&nbsp;");
+        $("#vacetaken").html(vac.extra.taken.days.toFixed(2)+" j");
+        $("#vaceasked").html(vac.extra.asked.days.toFixed(2)+" j");
+        $("#vaceplanned").html(vac.extra.accepted.days.toFixed(2)+" j");
+      
+        $("#vacmopen").html("&nbsp;");
+        $("#vacmtaken").html(vac.ill.taken.days.toFixed(2)+" j");
+        $("#vacmasked").html(vac.ill.asked.days.toFixed(2)+" j");
+        $("#vacmplanned").html(vac.ill.accepted.days.toFixed(2)+" j");
+      
+        $("#vactopen").html(vac.total.open.days.toFixed(2)+" j");
+        $("#vacttaken").html(vac.total.taken.days.toFixed(2)+" j");
+        $("#vactasked").html(vac.total.asked.days.toFixed(2)+" j");
+        $("#vactplanned").html(vac.total.accepted.days.toFixed(2)+" j");
+      } else {
+        vac.normal.open.hours=vac.normal.open.hours + parseInt($("#vacancylastyearrest").val());
+        $("#vacnopen").html(((vac.normal.open.hours && vac.normal.open.hours != 0)?vac.normal.open.hours+" h":"&nbsp;"));
+        $("#vacntaken").html(((vac.normal.taken.hours && vac.normal.taken.hours > 0)?vac.normal.taken.hours+" h":"&nbsp;"));
+        $("#vacnasked").html(((vac.normal.asked.hours && vac.normal.asked.hours > 0)?vac.normal.asked.hours+" h":"&nbsp;"));
+        $("#vacnplanned").html(((vac.normal.accepted.hours && vac.normal.accepted.hours > 0)?vac.normal.accepted.hours+" h":"&nbsp;"));
+        
+        $("#vacetaken").html(((vac.extra.taken.hours && vac.extra.taken.hours > 0)?vac.extra.taken.hours+" h":"&nbsp;"));
+        $("#vaceasked").html(((vac.extra.asked.hours && vac.extra.asked.hours > 0)?vac.extra.asked.hours+" h":"&nbsp;"));
+        $("#vaceplanned").html(((vac.extra.accepted.hours && vac.extra.accepted.hours > 0)?vac.extra.accepted.hours+" h":"&nbsp;"));
+        
+        $("#vacmtaken").html(((vac.ill.taken.hours && vac.ill.taken.hours > 0)?vac.ill.taken.hours+" h":"&nbsp;"));
+        $("#vacmasked").html(((vac.ill.asked.hours && vac.ill.asked.hours > 0)?vac.ill.asked.hours+" h":"&nbsp;"));
+        $("#vacmplanned").html(((vac.ill.accepted.hours && vac.ill.accepted.hours > 0)?vac.ill.accepted.hours+" h":"&nbsp;"));
+        
+        $("#vactopen").html(((vac.total.open.hours && vac.total.open.hours > 0)?vac.total.open.hours+" h":"&nbsp;"));
+        $("#vacttaken").html(((vac.total.taken.hours && vac.total.taken.hours > 0)?vac.total.taken.hours+" h":"&nbsp;"));
+        $("#vactasked").html(((vac.total.asked.hours && vac.total.asked.hours > 0)?vac.total.asked.hours+" h":"&nbsp;"));
+        $("#vactplanned").html(((vac.total.accepted.hours && vac.total.accepted.hours > 0)?vac.total.accepted.hours+" h":"&nbsp;"));
+        
+      }
+      
+      //dump(JSON.stringify(vac) + " - Set data vacancy status\n");
+      //  var hdata = "&nbsp;<span style=\"font-weight: normal;\"><span style=\"text-decoration: underline;\">pris:</span> <strong>"+ vac.taken.hours +" h</strong> ("+ vac.taken.days.toFixed(2)+" jour(s)) - ";
+      //  hdata += "&nbsp;<span style=\"text-decoration: underline;\">planifié:</span> <strong>"+ vac.rest.hours+" h</strong> ("+ vac.rest.days.toFixed(2)+" jour(s)) - ";
+      //  hdata += "&nbsp;<span style=\"text-decoration: underline;\">ouvert:</span> <strong>"+ vac.open.hours +" h</strong> ("+ vac.open.days.toFixed(2)+" jour(s))";
+      //  if (vac.ill > 0) {
+      //    hdata += " - &nbsp;(<span style=\"text-decoration: underline;\">maladie:</span> <strong>"+ vac.ill.hours+" h</strong> ("+ vac.ill.days.toFixed(2)+" jour(s)))</span>";
+      //  }
+        //dump("HTML: --" + document.getElementById("vacancystatus").innerHTML +"//\n->" + hdata + "\n");
+        //$("#vacancystatus").html("");
+        //if ($("#vacancystatus")){
+        //dump("vacancystatus exists\n");
+        //  
+        //}
+        $("#vacancystatus").html("");
+    }
+    else {
+      $("#vacancystatus").html("");
+    }
+  }
+
+
+function setvacancyunit(){
+  var vacunit = $('#vacancy_unit').val();
+  if ($('#vacancyyeartotal').val() !== ""){
+    var vacval = parseFloat($('#vacancyyeartotal').val().replace(',','.'));
+    if (((!pconfig.vacancyunit) || (pconfig.vacancyunit == 'days')) && (vacunit == 'hours')){
+      $('#vacancyyeartotal').val(vacval * 8);
+    }else if (pconfig.vacancyunit != vacunit){
+      $('#vacancyyeartotal').val(vacval / 8);
+    }
+  }
+  //dump("vacunit: " + vacunit + "\n");
+  pconfig.vacancyunit = vacunit;
+  apppref.setpreference("pageconfig.coworker",pconfig);
+}
+
+function setfreq() {
+
+  curfreq.freq = $('#freq option:selected').val();
+
+  $('#freqinterval').hide();
+  $('#freqmonthly').hide();
+  $('#freqweekly').hide();
+  if (curfreq.freq != "") {
+
+    $('#lblfreq').text(lblfreq[curfreq.freq]);
+    $('#freqinterval').show();
+    if (curfreq.freq !=  'daily') {
+      $('#freq' + curfreq.freq).show();
+    }
+  }
+  
+}
+
+function getlastyearsrest(){
+    var weekhours = $('#staff_weekhours').val();
+    if (weekhours === '') {
+      $("#vacancylastyearrest").val(0);
+      return;
+    }
+    var df = new Date(pconfig.year-1,0,1);
+    var dt = new Date(pconfig.year-1,11,31);
+    var vcalcrestsql = "select (select hours from staffvacancydays where staffuuid='"+pconfig.uuid+ "' and vacancyyear="+df.getFullYear()+")-SUM(dayhours) AS hours from (" +
+    "select vd.daydate,case when daydate <= date('now')   then 1 else 0 end as taken,case when vc.timefrom=vc.timeto then cast ("+weekhours+"/5 as real) else (cast (substr(vc.timeto,1,2) as int) + (cast(substr(vc.timeto,4,5) as int)/60))  - (cast(substr(vc.timefrom,1,2) as int) + (cast(substr(vc.timeto,4,5) as int)/60)) end as dayhours,type,case when type != -1 then accepted else '1' end as accepted "+
+    "from vacancycalendar vc left join ( "+ 
+    "select daydate from ( ";
+    
+    var yd = [];
+    for (var dx=df;dx<=dt;dx.setDate(dx.getDate()+1)){
+      yd.push("select date('"+dx.toLocaleFormat('%Y-%m-%d')+"') as daydate");
+    }
+    vcalcrestsql += yd.join(" UNION ") + 
+    ") yd where strftime('%w',daydate) not in ('0','6') and daydate not in (select vacancydate from vacancy where vacancydate between '"+df.getFullYear()+"-01-01' and '"+dt.getFullYear()+"-12-31' and vacancydateto is null) " +
+    ") vd on (vd.daydate between vc.datefrom and vc.dateto) " +
+    "left join staffvacancydays svd on (vc.staffuuid=svd.staffuuid) " +
+    "where vc.staffuuid='"+pconfig.uuid+ "' and daydate is not null group by daydate) where type in (0,1) and taken=1 and accepted=1 group by taken,accepted;";
+    //dump("SQLREST:" + vcalcrestsql + "\n");
+    var vcalc = appdb.dbquery(vcalcrestsql);
+    //dump(JSON.stringify(vcalc) + "\n");
+    if (vcalc && vcalc.sqldata[0]){
+       
+       $("#vacancylastyearrest").val(vcalc.sqldata[0].hours);
+    }else {
+       $("#vacancylastyearrest").val(0);
+    }
+    return;
+}
+
diff --git a/modules/staff/js/staff.js b/modules/staff/js/staff.js
new file mode 100644 (file)
index 0000000..60374b3
--- /dev/null
@@ -0,0 +1,120 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+var delcoworker = null;
+var wh = window.innerHeight - 100;
+var tblstaff = null;
+
+function initdata() {
+
+         loadtable();
+         set_infoheader("");
+         if (!pconfig.printlayout) {
+           pconfig.printlayout = 'list';
+           apppref.setpreference("pageconfig.staff", pconfig);
+         }
+       }
+
+function loadtable() {
+  var sql = "SELECT '<button type=\"button\" class=\"btn btn-primary\" onclick=\"load_coworker(''' || uuid || ''')\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button> <button type=\"button\" class=\"btn btn-danger\" onclick=\"confirm_delete_coworker(''' || uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button> ' as action, coalesce(prename,'') || '<br/>' || coalesce(surname,'') as name,case when color is not null then '<div style=\"width: 50px; height: 30px;background-color: ' || color ||';\"></div>' else null end color, coalesce(address,'')|| '<br/>' || coalesce(zip,'') || ' ' || coalesce(city,'') || '<br/>' || coalesce(country,'') as address, case when phone is not null then '<span class=\"glyphicon glyphicon-earphone\" aria-hidden=\"true\"></span>: ' || phone || '<br/>' else '' end || case when email is not null then '<span class=\"glyphicon glyphicon-envelope\" aria-hidden=\"true\"></span>:' || email else '' end as phonemail, coalesce(jobtitle,'') || '<br/>' || case when entrydate is not null then 'à partir du: ' || strftime('%d.%m.%Y',entrydate) else '' end || case when exitdate is not null then ' jusqu''au: ' || strftime('%d.%m.%Y',exitdate) else '' end as jobtitle FROM staff;";
+  //dump("STAFFSQL:" +sql + "\n");
+  var data = appdb.dbqueryarray(sql);
+
+  var headerdata = getlabels(data.sqlhead.join(","));
+  $("#tbl_staff").html("");
+  tblstaff = $("#tbl_staff").dataTable({
+    "language": {
+      "url": "../../web/js/locale/datatable_fr.json"
+    },
+    "data": data.sqldata,
+    "columns": headerdata,
+    "paging": false,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "ordering": true,
+    "info": false,
+    "filter": true,
+    "destroy": true
+  });
+//  $('#tbl_staff').on('search.dt', function() {
+//    pconfig.filter = tblstaff.api().search();
+//    apppref.setpreference("pageconfig.staff", pconfig);
+//  });
+
+  $('#tbl_staff').on('order.dt', function() {
+    pconfig.order = tblstaff.fnSettings().aaSorting;
+    apppref.setpreference("pageconfig.staff", pconfig);
+
+  });
+//  if (pconfig.filter) {
+//    tblstaff.fnFilter(pconfig.filter);
+//  }
+  if (pconfig.order) {
+    tblstaff.fnSort(pconfig.order);
+  }
+  if (/*(!pconfig.filter) && */ (!pconfig.order)) {
+    tblstaff.fnDraw();
+  }
+}
+
+
+
+function add_coworker() {
+  var newuuid = appdb.generate_uuid();
+  appdb.dbexec("insert into staff (uuid) VALUES ('" + newuuid + "');");
+
+  globelreq.send_request({
+    page: 'coworker',
+    module: 'staff',
+    data: {
+      "uuid": newuuid
+    },
+    header: 'Employé(e)'
+  });
+}
+
+function confirm_delete_coworker(myuuid) {
+  //alert('TEST');
+  delcoworker = myuuid;
+  $("#confirm_delete_coworker").modal('show');
+  return false;
+}
+
+function delete_coworker() {
+  //var frmdata = new Object();
+  //appdb.dbexec("DELETE FROM planningstaff where staffuuid='"+delcoworker +"';");
+  var evdel = appdb.dbquery("select eventcalendaruuid,count(staffuuid) as cnt from staffplanning where staffuuid='" + delcoworker + "';");
+
+  appdb.dbexec("DELETE FROM staffvacancydays where staffuuid='" + delcoworker + "';");
+  appdb.dbexec("DELETE FROM vacancycalendar where staffuuid='" + delcoworker + "';");
+  appdb.dbexec("DELETE FROM staffplanning where staffuuid='" + delcoworker + "';");
+  appdb.dbexec("DELETE FROM staff where uuid='" + delcoworker + "';");
+  for (var e in evdel.sqldata) {
+    if (evdel.sqldata[e].cnt == 1) {
+      appdb.dbexec("DELETE FROM eventcalendar where uuid='" + evdel.sqldata[e].eventcalendaruuid + "';");
+    }
+  }
+  //
+  delcoworker = null;
+  loadtable();
+  //
+  $("#confirm_delete_coworker").modal('hide');
+
+}
+
+function load_coworker(couuid){
+  //"coworker uuid:" + couuid + "\n");
+  var cwdata = apppref.getpreference("pageconfig.coworker"); 
+  var cow = new Object();
+  if (cwdata && cwdata !== ""){
+    cow = JSON.parse(cwdata);
+  }  
+  //dump("Current CoWorker cfg:" +JSON.stringify(cow) + "\n");
+  cow.uuid = couuid;
+  //dump("New CoWorker cfg:" +JSON.stringify(cow) + "\n");
+  apppref.setpreference("pageconfig.coworker",cow);
+  globelreq.send_request({page:'coworker',
+                         module:'staff',
+                         data:null,
+                         header:'Employé(e)'});
+  
+}
\ No newline at end of file
diff --git a/modules/staff/js/staff_basic.js b/modules/staff/js/staff_basic.js
new file mode 100644 (file)
index 0000000..c51de6a
--- /dev/null
@@ -0,0 +1,122 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+var pconfig = {};
+var wh = window.innerHeight - 100;
+
+function initdata() {
+  set_infoheader("");
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.staff", pconfig);
+  }
+  load_staff_selection();
+  var stlist = appdb.dbquery("select * from creche;");
+  //dump(JSON.stringify(stlist) + "\n");
+  if ((stlist.sqldata) && stlist.sqldata[0].stafflist == '1'){
+         $("#stafflist").show();
+         loadtable_staff();
+         $("#stafflogin").hide();
+  }
+}
+
+function loadtable_staff() {
+         var sql = "SELECT '<button type=\"button\" class=\"btn btn-primary\" onclick=\"load_coworker(''' || uuid || ''');\" title=\"editer\"><span class=\"glyphicon glyphicon-pencil\"></span></button> <button type=\"button\" class=\"btn btn-danger\" onclick=\"confirm_delete_coworker(''' || uuid || ''');\" title=\"supprimer\"><span class=\"glyphicon glyphicon-remove\"></span></button> ' as action, coalesce(prename,'') || '<br/>' || coalesce(surname,'') as name,case when color is not null then '<div style=\"width: 50px; height: 30px;background-color: ' || color ||';\"></div>' else null end color, coalesce(address,'')|| '<br/>' || coalesce(zip,'') || ' ' || coalesce(city,'') || '<br/>' || coalesce(country,'') as address, case when phone is not null then '<span class=\"glyphicon glyphicon-earphone\" aria-hidden=\"true\"></span>: ' || phone || '<br/>' else '' end || case when email is not null then '<span class=\"glyphicon glyphicon-envelope\" aria-hidden=\"true\"></span>:' || email else '' end as phonemail, coalesce(jobtitle,'') || '<br/>' || case when entrydate is not null then 'à partir du: ' || strftime('%d.%m.%Y',entrydate) else '' end || case when exitdate is not null then ' jusqu''au: ' || strftime('%d.%m.%Y',exitdate) else '' end as jobtitle FROM staff;";
+         //dump(sql + "\n");
+         var data = appdb.dbqueryarray(sql);
+
+         var headerdata = getlabels(data.sqlhead.join(","));
+         $("#tbl_staff").html("");
+         tblstaff = $("#tbl_staff").dataTable({
+           "language": {
+             "url": "../../web/js/locale/datatable_fr.json"
+           },
+           "data": data.sqldata,
+           "columns": headerdata,
+           "paging": false,
+           "scrollY": wh + "px",
+           "scrollCollapse": true,
+           "ordering": true,
+           "info": false,
+           "filter": true,
+           "destroy": true
+         });
+//       $('#tbl_staff').on('search.dt', function() {
+//         pconfig.filter = tblstaff.api().search();
+//         apppref.setpreference("pageconfig.staff", pconfig);
+//       });
+
+         $('#tbl_staff').on('order.dt', function() {
+           pconfig.order = tblstaff.fnSettings().aaSorting;
+           apppref.setpreference("pageconfig.staff", pconfig);
+
+         });
+//       if (pconfig.filter) {
+//         tblstaff.fnFilter(pconfig.filter);
+//       }
+         if (pconfig.order) {
+           tblstaff.fnSort(pconfig.order);
+         }
+         if (/*(!pconfig.filter) && */ (!pconfig.order)) {
+           tblstaff.fnDraw();
+         }
+       }
+
+function load_coworker_basic(){
+  var couuid= $('#sel_staff :selected').val();
+  var copwd = $('#txtpasswd').val();
+  var encpwd = MD5(copwd);
+  var cwpwd = appdb.dbquery("select password from staff where uuid='"+couuid+"';");
+  //dump(cwpwd + "\n");
+  //dump("SQL: select password from staff where uuid='"+couuid+"';\n");
+  //dump("PWD: " + copwd + " ENC: " + encpwd + " CMP: "+ cwpwd.sqldata[0].password +"\n");
+  if (cwpwd.sqldata[0].password == encpwd){
+         var cwdata = apppref.getpreference("pageconfig.coworker"); 
+         var cow = new Object();
+         if (cwdata && cwdata !== ""){
+           cow = JSON.parse(cwdata);
+         } 
+         cow.uuid = couuid;
+         //dump("New CoWorker cfg:" +JSON.stringify(cow) + "\n");
+         apppref.setpreference("pageconfig.coworker",cow);
+         globelreq.send_request({page:'coworker_basic',
+                                module:'staff',
+                                data:null,
+                                header:'Employé(e)'});
+  
+  }
+  
+    
+}
+
+function load_coworker(couuid){
+         //"coworker uuid:" + couuid + "\n");
+         var cwdata = apppref.getpreference("pageconfig.coworker"); 
+         var cow = new Object();
+         if (cwdata && cwdata !== ""){
+           cow = JSON.parse(cwdata);
+         }  
+         //dump("Current CoWorker cfg:" +JSON.stringify(cow) + "\n");
+         cow.uuid = couuid;
+         //dump("New CoWorker cfg:" +JSON.stringify(cow) + "\n");
+         apppref.setpreference("pageconfig.coworker",cow);
+         globelreq.send_request({page:'coworker_basic',
+                                module:'staff',
+                                data:null,
+                                header:'Employé(e)'});
+         
+       }
+
+function load_staff_selection(){
+  var stdata = appdb.dbquery("select uuid, coalesce(surname,'') || ' ' || coalesce(prename,'') as name,case when color is null then '#000' else color end as color from staff where password is not null order by surname,prename");
+  stdata = stdata.sqldata;
+  //JSON.stringify(stdata));
+  for (var s in stdata){
+    $('#sel_staff').append('<option value="'+ stdata[s].uuid+'">' +stdata[s].name+ '</option>');
+  } 
+}
+
+function onselstaff(objid) {
+
+  //pconfig.filterstaff = $('#' + objid).val();
+  //apppref.setpreference("pageconfig.calactivity",pconfig);
+  //load_calendar_data();
+}
\ No newline at end of file
diff --git a/modules/staff/staff.html b/modules/staff/staff.html
new file mode 100644 (file)
index 0000000..7c05876
--- /dev/null
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+
+  <title>Creorga - Staff</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/style.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css"><!-- Fav and touch icons -->
+  
+  <link rel="shortcut icon" href="img/favicon.png">
+</head>
+
+<body>
+    <div class="container-fluid"  style="padding-top: 5px;">
+    <!--<span class="pagehead" id="pagehead">Personnel</span>&nbsp-->
+    <div class="btn-group" style="z-index: 10;">
+    <button  onclick="add_coworker();" class="btn btn-primary" type="button" >
+  <span class="glyphicon glyphicon-plus"></span>
+</button>
+    </div>
+    <div style="margin-top: -30px;z-index: -10;">
+    <table id="tbl_staff" class="table table-striped">
+    </table>
+    </div>
+    <div class="modal fade" id="confirm_delete_coworker">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer un collaborateur</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce collaborateur et tous ces données?<br>
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_coworker();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+        </div>
+  
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/staff.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/staff/staff.xul b/modules/staff/staff.xul
new file mode 100644 (file)
index 0000000..4bcd895
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_staff" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton class="btn btn-default" id="tbb_staff" insertafter="tbb_presences" label="Personnel" image="modules/staff/img/staff.png" orient="vertical" oncommand="navigation.load_appview('staff','staff',null,'Liste du Personnel');"/>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/staff/staff_basic.html b/modules/staff/staff_basic.html
new file mode 100644 (file)
index 0000000..4688e9b
--- /dev/null
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+
+  <title>Creorga - Staff Basic</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="../../web/css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="../../web/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="../../web/css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/glyphicons.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/style.css" rel="stylesheet" type="text/css">
+  <link href="../../web/css/creorga.css" rel="stylesheet" type="text/css"><!-- Fav and touch icons -->
+  
+  <link rel="shortcut icon" href="img/favicon.png">
+</head>
+
+<body>
+    <div class="container-fluid"  style="padding-top: 5px;">
+       <div style="margin-top: -30px;z-index: -10; display: none" id="stafflist">
+               <table id="tbl_staff" class="table table-striped">
+               </table>
+       </div>
+        <div class="container col-xs-12 col-sm-offset-2 col-sm-8 col-md-offset-3 col-md-6 col-lg-offset-4 col-lg-4" id="stafflogin">
+            <br />
+            <div class="panel panel-default">
+                <div class="panel-heading">
+                    <h1>Login</h1>
+                </div>
+                <div class="panel-body">
+                    <div class="form-group">
+                        <div class="input-group">
+                            <span class="input-group-addon">
+                                <span class="glyphicon glyphicon-user"></span>
+                            </span>
+                            <select id="sel_staff" onchange="onselstaff(this.id);" style="width: 100%">
+                                
+                            </select>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <div class="input-group">
+                            <span class="input-group-addon">
+                                <span class="glyphicon glyphicon-lock"></span>
+                            </span>
+                            <input id="txtpasswd" type="password" class="form-control" />
+                        </div>
+                    </div>
+                    <button id="btnLogin" class="btn btn-primary" style="width: 100%" onclick="load_coworker_basic();">
+                        <span class="glyphicon glyphicon-log-in"></span>&nbsp;Entrez
+                    </button>
+                </div>
+            </div>
+        </div>
+    </div>
+  
+  <script src="../../web/js/jquery.min.js" type="text/javascript"></script>
+  <script src="../../web/js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="../../web/js/datatables.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/encrypt.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="../../web/js/creorga.js" type="text/javascript"></script>
+  <script src="../../web/js/labels.js" type="text/javascript"></script>
+  <script src="js/staff_basic.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/modules/staff/staff_basic.xul b/modules/staff/staff_basic.xul
new file mode 100644 (file)
index 0000000..b8daf7f
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "-//MOZILLA//DTD XUL V1.0//EN"
+"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<overlay id="ov_staffbasic" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml">
+  <toolbar id="co_maintoolbar" style="-moz-appearance: none;">
+    <toolbarbutton class="btn btn-default" id="tbb_staff" insertafter="tbb_presences" label="Personnel" image="modules/staff/img/staff.png" orient="vertical" oncommand="navigation.load_appview('staff_basic','staff',null,'Espace Personnel');"/>
+  </toolbar>
+</overlay>
\ No newline at end of file
diff --git a/modules/waitlist/waitlist.html b/modules/waitlist/waitlist.html
new file mode 100644 (file)
index 0000000..9b8b2a0
--- /dev/null
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+
+<html lang="fr">
+<head>
+  <meta charset="utf-8">
+  <title>Liste d'attente</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+        <meta http-equiv="cache-control" content="max-age=0" />
+  <meta http-equiv="cache-control" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="expires" content="Tue, 01 Jan 1970 1:00:00 GMT" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <link href="css/bootstrap.min.css" rel="stylesheet" type="text/css">
+  <!--<link href="css/bootstrap-theme.min.css" rel="stylesheet" type="text/css">-->
+  <link href="css/datatables.min.css" rel="stylesheet" type="text/css">
+  <link href="css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
+  <link href="css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css">
+  <!-- <link href="css/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css"> -->
+  <link href="css/glyphicons.css" rel="stylesheet" type="text/css">
+       <link href="css/summernote.css" rel="stylesheet" type="text/css">
+  <link href="css/creorga.css" rel="stylesheet" type="text/css"><!-- Fav and touch icons -->
+</head>
+
+<body>
+
+   <div class="container-fluid" style="padding-top: 5px;"><div id="main" class="main">
+   <!--<span class="pagehead" id="pagehead">Liste d'attente</span>&nbsp;-->
+        <div class="btn-group" style="z-index: 10;">
+   <button onclick="dlg_waitlist({'uuid':''},'ins');" class="btn btn-primary" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
+        <!--<button  onclick="print_list();" class="btn btn-primary" type="button" id="btnprintwaitlist"><span class="glyphicon glyphicon-print" aria-hidden="true"></span></button>-->
+   </div>
+        <div style="margin-top: -30px;z-index: -10;">
+               <!--<div id="tbl_waitlist_wrapper" class="dataTables_wrapper" >-->
+      <table class="display compact dataTable" width="100%" style="width: 100%;" id="tbl_waitlist" role="grid"></table>
+               <!--</div>-->
+               </div>
+</div>
+   <div class="modal fade" id="edit_waitlist">
+          <div class="modal-dialog"  style="width: 800px; min-width: 800px;">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title">Editer/Ajouter contact</h4>
+              </div>
+              <div class="modal-body" style=" height: 600px; max-height: 600px ">
+
+                <div id="frmeditwaitlist">
+                  <input type="hidden" value="0" id="uuid" />
+                  
+                  <div class="form-group" id="date-container">
+                    <label for="datestart">date de contacte</label>
+                    <div id="dt_waitdate" class="input-group date">
+                      <input type="date" class="form-control" value="" limits="0" placeholder="dd.mm.yyyy"  id="waitdate"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
+                    </div>
+                  </div>
+                  <div class="form-group">
+                    <label for="name">Nom</label>
+                    <input type="text" value="" id="name"  nullable="true" class="form-control">
+                  </div>
+                                                                       <div class="row col-md-12">
+                  <div class="form-group col-md-4">
+                    <label for="phone">Téléphone</label>
+                    <input type="text" value="" id="phone"  nullable="true" class="form-control">
+                  </div>
+                  <div class="form-group col-md-4">
+                    <label for="email">E-Mail</label>
+                    <input type="text" value="" id="email"  nullable="true" class="form-control">
+                  </div>
+                  <div class="form-group col-md-4">
+                    <label for="age">Âge</label>
+                    <input type="text" value="" id="age"  nullable="true" class="form-control">
+                  </div>
+                                                                       </div>
+                  <div class="form-group">
+                    <label for="note">Remarque</label>
+                    <textarea class="summernote" type="text"  id="note"></textarea>
+                  </div>
+                </div>
+                </div>
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Annuler</button> <button onclick="save_waitlist();" class="btn btn-primary">OK</button>
+              </div>
+              </div>
+
+              
+            </div>
+          </div>
+    
+      
+      <div class="modal fade" id="confirm_delete_waitlist">
+          <div class="modal-dialog">
+            <div class="modal-content">
+              <div class="modal-header">
+                <button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">x</span><span class="sr-only">Close</span></button>
+
+                <h4 class="modal-title">Supprimer</h4>
+              </div><!-- dialog contents -->
+
+              <div class="modal-body">
+                ÃŠtes vous sûre de supprimer ce contact?
+
+                
+              </div><!-- dialog buttons -->
+
+              <div class="modal-footer">
+                <button aria-hidden="true" data-dismiss="modal" class="btn">Non</button> <button onclick="delete_waitlist();" class="btn btn-primary">Oui</button>
+              </div>
+            </div>
+          </div>
+        </div>
+   </div>
+  <script src="js/jquery.min.js" type="text/javascript"></script>
+  <script src="js/bootstrap.min.js" type="text/javascript"></script>
+  <script src="js/datatables.min.js" type="text/javascript"></script>
+  <script src="js/moment-with-locales.js" type="text/javascript"></script>
+  <script src="js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
+  <!-- <script src="js/bootstrap-timepicker.min.js" type="text/javascript"></script> -->
+       <script src="js/summernote.min.js" type="text/javascript"></script>
+  <script src="js/lang/summernote-fr-FR.min.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/navigation.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/system.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/preferences.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/database.js" type="text/javascript"></script>
+  <script src="chrome://creorga/content/js/tools.js" type="text/javascript"></script>
+  <script src="js/labels.js" type="text/javascript"></script>
+  <script src="js/waitlist.js" type="text/javascript"></script>
+  <script src="js/creorga.js" type="text/javascript"></script>
+  
+</body>
+</html>
\ No newline at end of file
diff --git a/modules/waitlist/waitlist.js b/modules/waitlist/waitlist.js
new file mode 100644 (file)
index 0000000..72941a4
--- /dev/null
@@ -0,0 +1,206 @@
+//Source-code licensed under EUPL v1.1 ( Copyright 2016 By DKS s.à r.l. - Kilian Saffran - Luxembourg )
+
+var pconfig = {};
+var wh= window.innerHeight-130;
+var delwl = null;
+var tblwaitlist = null;
+
+function initdata(){
+  load_helpers();
+  var pdata = apppref.getpreference("pageconfig.waitlist");
+  if (pdata != '') {
+    pconfig = JSON.parse(pdata);
+  }
+  if (!pconfig.printlayout) {
+    pconfig.printlayout = 'list';
+    apppref.setpreference("pageconfig.waitlist",pconfig);
+  }
+
+  loadtextareas(200);
+  set_infoheader("");
+  load_waitlist_table();
+  
+}
+
+//$('#tbl_waitlist').on( 'search.dt', function () {
+//  pconfig.filter = tblwaitlist.api().search();
+//  apppref.setpreference("pageconfig.waitlist",pconfig);
+//} );
+
+$('#tbl_waitlist').on( 'order.dt', function () {
+  pconfig.order= tblwaitlist.fnSettings().aaSorting;
+  apppref.setpreference("pageconfig.waitlist",pconfig);
+} );
+
+function load_waitlist_table(){
+  var waitlistsql = "select uuid, '<span style=\"display:none\">' || strftime('%Y-%m-%d',waitdate) || '</span>' || strftime('%d.%m.%Y',waitdate) as waitdate, name,phone, email, age, note FROM waitlist order by waitdate;";
+  var headerdata = [];
+  headerdata = getlabelswithkey("act,waitdate,contactinfo,childinfo");
+
+  var waitlistdata = appdb.dbquery(waitlistsql);
+  $("#tbl_waitlist").html("");
+  var tblheader = '<tr>';
+  for (var h in headerdata){
+    if ((headerdata[h].keyname == 'act') && (headerdata[h].class.indexOf('action1btn') == -1)){
+      headerdata[h].class +=" action1btn";
+    }
+    tblheader += '<th class="' + headerdata[h].class +'">'+ headerdata[h].title+'</th>';
+
+  }
+  tblheader += '</tr>';
+  tblacc = null;
+  $("#tbl_waitlist").append("<thead>" + tblheader + "</thead>");
+  $("#tbl_waitlist").append("<tbody>");
+  for (var i in waitlistdata.sqldata){
+    var row = waitlistdata.sqldata[i];
+        var tr = '<tr><td class="noprint" style="width: 170px;"><button type="button" class="btn btn-primary" onclick="dlg_waitlist({\'uuid\':\'' +row.uuid + '\'},\'upd\');" title="editer"><span class="glyphicon glyphicon-pencil"></span></button>'+
+        '<button type="button" class="btn btn-danger" onclick="dlg_waitlist({\'uuid\':\'' +row. uuid + '\'},\'del\');" title="supprimer"><span class="glyphicon glyphicon-remove"></span></button>'+
+        '<button type="button" class="btn btn-primary" onclick="add_child(\'' + row.uuid + '\');" title="ajouter enfant"><span class="glyphicons glyphicons-child"></span><span class="glyphicons glyphicons-plus"></span></button></td>';
+        tr += '<td style="width: 100px;">' + row.waitdate + '</td>';
+        tr += '<td style="width: 300px;">' + ((row.name !=='')?row.name + '<br/>':'')+((row.phone !== '')?row.phone + '<br/>':'')+row.email + '</td>';
+        tr += '<td>' + ((row.age !== '')?row.age+ '<br/>':'')  + htmlUnescape(row.note) +  '</td></tr>';
+        $("#tbl_waitlist").append(tr);
+
+    }
+    
+  $("#tbl_waitlist").append("</tbody>");
+  tblwaitlist = $("#tbl_waitlist").dataTable({
+    "language": {
+      "url": "js/locale/datatable_fr.json"
+    },
+
+    "paging": false,
+    "ordering": true,
+    "scrollY": wh + "px",
+    "scrollCollapse": true,
+    "info": true,
+    "filter": true,
+    "destroy": true
+  });
+//  if (pconfig.filter) {
+//    tblwaitlist.fnFilter(pconfig.filter);
+//  }
+  if (pconfig.order) {
+    //dump(JSON.stringify(pconfig.order) + "\n");
+    tblwaitlist.fnSort(pconfig.order);
+  } else {
+    pconfig.order = [[1,"asc"]];
+    tblwaitlist.fnSort(pconfig.order);
+  }
+}
+
+function dlg_waitlist(uuid,type){
+      if ((type == 'upd') || (type == 'ins')) {
+
+        var wlsql = "SELECT  '0' as uuid,strftime('%d.%m.%Y',date('now')) as waitdate, '' as name, '' as phone, '' as email, ''as age, '' as note FROM waitlist LIMIT 1;";
+        if (type == 'upd') {
+
+          wlsql = "SELECT uuid, strftime('%d.%m.%Y',date(waitdate)) as waitdate, name, phone, email, age, note FROM waitlist  where uuid='"+uuid.uuid+"';";
+        }
+        var wldata = appdb.dbquery(wlsql);
+        
+        wldata = wldata.sqldata[0];
+        for (var w in wldata){
+          if ($("#frmeditwaitlist #" +w)) { 
+            if ($("#frmeditwaitlist #"+w).prop("tagName") === "TEXTAREA"){
+              $("#frmeditwaitlist #"+w).summernote('code',htmlUnescape(wldata[w]));
+            }
+            else {
+              $("#frmeditwaitlist #"+w).val(wldata[w]);
+            }
+          }
+        }
+        $("#edit_waitlist").modal('show');
+      }else if (type == 'del') {
+        //dump("UUID to delete: " + JSON.stringify(uuid) + "\n");
+        delwl = uuid.uuid;
+        confirm_delete_waitlist();
+      }
+    }
+    
+  function confirm_delete_waitlist(){
+
+        $("#confirm_delete_waitlist").modal('show');
+        return false;
+      }
+  
+  function delete_waitlist(){
+        
+        var delsql = "DELETE FROM waitlist where uuid='"+delwl +"';";
+        //dump(JSON.stringify(delwl) + " - " + delsql + "\n");
+        appdb.dbexec(delsql);
+        delwl =null;
+        load_waitlist_table();
+
+        $("#confirm_delete_waitlist").modal('hide');
+        
+        return false;
+        }
+  
+   function save_waitlist(){
+        var sql1 = new Array();
+        var sql2 = new Array();
+        var type = 'ins';
+        var cuuid = "";
+        if ($("#frmeditwaitlist #uuid").val() != 0) {
+          type = 'upd';
+          cuuid = $("#frmeditwaitlist #uuid").val();
+        }
+        $("#frmeditwaitlist :input").each(function(){
+          var input = $(this);
+          if (input.attr("id")){
+            if (type == 'ins') {
+              sql1.push('"' + input.attr("id") + '"');
+              if (input.attr("id") == 'uuid') {
+                if (input.val() == "" || input.val() == "0") {
+                  sql2.push("'" + appdb.generate_uuid()+"'");
+                }
+                else {
+                  sql2.push("'" + input.val()+"'");
+                }
+              } else {
+                var ival = encodeparam(input.val(),input.attr('type'));
+                sql2.push(ival);
+              }
+            }else {
+              if (input.attr("id") != 'uuid') {
+                var ival = encodeparam(input.val(),input.attr('type'));
+                sql2.push('"' + input.attr("id") +'"='+ ival);
+              }
+            }
+
+           
+          }
+
+        });
+        var xsql = "";
+        if (type == 'upd') {
+          xsql = "UPDATE waitlist SET "+sql2.join(',')+" where \"uuid\"='" + cuuid +"';";
+        }else {
+          xsql = "INSERT INTO waitlist ("+sql1.join(',')+") VALUES ("+sql2.join(',')+");"; 
+        }
+        
+        appdb.dbexec(xsql);
+        load_waitlist_table();
+        $("#frmeditwaitlist #uuid").val("0");
+        $("#edit_waitlist").modal('hide');
+      }
+
+function print_list(){
+  globelreq.send_request({page:'preview2',data:{page: 'waitlist'}});
+}
+
+function add_child(uuid){
+var newuuid = appdb.generate_uuid();
+ var wlsql = "SELECT uuid, name, phone, email, age, note FROM waitlist  where uuid='"+uuid+"';";
+  var wldata = appdb.dbquery(wlsql);
+  appdb.dbexec("insert into childs (uuid,birthday,entrydate,leavedate,remark) VALUES ('" + newuuid + "',date('now','-2 months'),date('now'),date('now'),'"+ appdb.strreplace(wldata.sqldata[0].name + '<br/>' + wldata.sqldata[0].phone + '<br/>' + wldata.sqldata[0].email+  '<br/>' + wldata.sqldata[0].age + '<br/>' +htmlUnescape(wldata.sqldata[0].note)) +"');");
+  appdb.dbexec("DELETE FROM waitlist where waitlist='"+ uuid +"';");
+  globelreq.send_request({
+    page: 'child',
+    data: {
+      "uuid": newuuid
+    },
+    header: 'Enfant'
+  });
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644 (file)
index 0000000..ded50a9
--- /dev/null
@@ -0,0 +1,1261 @@
+{
+  "name": "creorga",
+  "version": "4.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@fortawesome/fontawesome-free": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.7.2.tgz",
+      "integrity": "sha512-Ha4HshKdCVKgu4TVCtG8XyPPYdzTzNW4/fvPnn+LT7AosRABryhlRv4cc4+o84dgpvVJN9reN7jo/c+nYujFug==",
+      "dev": true
+    },
+    "@types/node": {
+      "version": "10.12.26",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.26.tgz",
+      "integrity": "sha512-nMRqS+mL1TOnIJrL6LKJcNZPB8V3eTfRo9FQA2b5gDvrHurC8XbSA86KNe0dShlEL7ReWJv/OU9NL7Z0dnqWTg==",
+      "dev": true
+    },
+    "ajv": {
+      "version": "6.9.1",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz",
+      "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==",
+      "dev": true,
+      "requires": {
+        "fast-deep-equal": "^2.0.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+      "dev": true
+    },
+    "array-find-index": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+      "dev": true
+    },
+    "asn1": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
+    "assert-plus": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+      "dev": true
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "dev": true
+    },
+    "aws-sign2": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+      "dev": true
+    },
+    "aws4": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+      "dev": true
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+      "dev": true,
+      "requires": {
+        "tweetnacl": "^0.14.3"
+      }
+    },
+    "bootstrap": {
+      "version": "4.3.1",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz",
+      "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==",
+      "dev": true
+    },
+    "bootstrap-datepicker": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/bootstrap-datepicker/-/bootstrap-datepicker-1.8.0.tgz",
+      "integrity": "sha512-213St/G8KT3mjs4qu4qwww74KWysMaIeqgq5OhrboZjIjemIpyuxlSo9FNNI5+KzpkkxkRRba+oewiRGV42B1A==",
+      "dev": true,
+      "requires": {
+        "jquery": ">=1.7.1 <4.0.0"
+      }
+    },
+    "bootstrap-table": {
+      "version": "1.13.4",
+      "resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.13.4.tgz",
+      "integrity": "sha512-033fnjYKgFZO98PL6E0JAqmwTJ2isoQxJBFU6BwEbIMmRZETk5iDoPGgV+7wORt4c+yABNWj8EnbFBWAHz5YPw==",
+      "dev": true
+    },
+    "buffer-from": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "dev": true
+    },
+    "camelcase": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+      "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+      "dev": true
+    },
+    "camelcase-keys": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+      "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+      "dev": true,
+      "requires": {
+        "camelcase": "^2.0.0",
+        "map-obj": "^1.0.0"
+      }
+    },
+    "caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+      "dev": true
+    },
+    "code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "dev": true
+    },
+    "combined-stream": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
+      "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+      "dev": true,
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+          "dev": true
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "dev": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
+      }
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "currently-unhandled": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+      "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+      "dev": true,
+      "requires": {
+        "array-find-index": "^1.0.1"
+      }
+    },
+    "dashdash": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "debug": {
+      "version": "3.2.6",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+      "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+      "dev": true,
+      "requires": {
+        "ms": "^2.1.1"
+      }
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+      "dev": true
+    },
+    "deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "dev": true
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "dev": true
+    },
+    "ecc-jsbn": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+      "dev": true,
+      "requires": {
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.1.0"
+      }
+    },
+    "electron": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/electron/-/electron-4.0.5.tgz",
+      "integrity": "sha512-UWFH6SrzNtzfvusGUFYxXDrgsUEbtBXkH/66hpDWxjA2Ckt7ozcYIujZpshbr7LPy8kV3ZRxIvoyCMdaS5DkVQ==",
+      "dev": true,
+      "requires": {
+        "@types/node": "^10.12.18",
+        "electron-download": "^4.1.0",
+        "extract-zip": "^1.0.3"
+      }
+    },
+    "electron-download": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz",
+      "integrity": "sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==",
+      "dev": true,
+      "requires": {
+        "debug": "^3.0.0",
+        "env-paths": "^1.0.0",
+        "fs-extra": "^4.0.1",
+        "minimist": "^1.2.0",
+        "nugget": "^2.0.1",
+        "path-exists": "^3.0.0",
+        "rc": "^1.2.1",
+        "semver": "^5.4.1",
+        "sumchecker": "^2.0.2"
+      }
+    },
+    "env-paths": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz",
+      "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=",
+      "dev": true
+    },
+    "error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+      "dev": true
+    },
+    "extract-zip": {
+      "version": "1.6.7",
+      "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
+      "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=",
+      "dev": true,
+      "requires": {
+        "concat-stream": "1.6.2",
+        "debug": "2.6.9",
+        "mkdirp": "0.5.1",
+        "yauzl": "2.4.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        }
+      }
+    },
+    "extsprintf": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+      "dev": true
+    },
+    "fast-deep-equal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+      "dev": true
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+      "dev": true
+    },
+    "fd-slicer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
+      "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+      "dev": true,
+      "requires": {
+        "pend": "~1.2.0"
+      }
+    },
+    "find-up": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+      "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+      "dev": true,
+      "requires": {
+        "path-exists": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      },
+      "dependencies": {
+        "path-exists": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+          "dev": true,
+          "requires": {
+            "pinkie-promise": "^2.0.0"
+          }
+        }
+      }
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+      "dev": true
+    },
+    "form-data": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "dev": true,
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.6",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "fs-extra": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
+      "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "jsonfile": "^4.0.0",
+        "universalify": "^0.1.0"
+      }
+    },
+    "get-stdin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+      "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+      "dev": true
+    },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.1.15",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
+      "dev": true
+    },
+    "har-schema": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+      "dev": true
+    },
+    "har-validator": {
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.5.5",
+        "har-schema": "^2.0.0"
+      }
+    },
+    "hosted-git-info": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+      "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+      "dev": true
+    },
+    "http-signature": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "jsprim": "^1.2.2",
+        "sshpk": "^1.7.0"
+      }
+    },
+    "indent-string": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+      "dev": true,
+      "requires": {
+        "repeating": "^2.0.0"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+      "dev": true
+    },
+    "ini": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+      "dev": true
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
+    },
+    "is-finite": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-fullwidth-code-point": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+      "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+      "dev": true,
+      "requires": {
+        "number-is-nan": "^1.0.0"
+      }
+    },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+      "dev": true
+    },
+    "is-utf8": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+      "dev": true
+    },
+    "isarray": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+      "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+      "dev": true
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+      "dev": true
+    },
+    "jquery": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
+      "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==",
+      "dev": true
+    },
+    "jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+      "dev": true
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "dev": true
+    },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+      "dev": true
+    },
+    "jsonfile": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+      "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "jsprim": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.2.3",
+        "verror": "1.10.0"
+      }
+    },
+    "load-json-file": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^2.2.0",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0",
+        "strip-bom": "^2.0.0"
+      }
+    },
+    "loud-rejection": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+      "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+      "dev": true,
+      "requires": {
+        "currently-unhandled": "^0.4.1",
+        "signal-exit": "^3.0.0"
+      }
+    },
+    "map-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+      "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+      "dev": true
+    },
+    "meow": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+      "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+      "dev": true,
+      "requires": {
+        "camelcase-keys": "^2.0.0",
+        "decamelize": "^1.1.2",
+        "loud-rejection": "^1.0.0",
+        "map-obj": "^1.0.1",
+        "minimist": "^1.1.3",
+        "normalize-package-data": "^2.3.4",
+        "object-assign": "^4.0.1",
+        "read-pkg-up": "^1.0.1",
+        "redent": "^1.0.0",
+        "trim-newlines": "^1.0.0"
+      }
+    },
+    "mime-db": {
+      "version": "1.38.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
+      "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==",
+      "dev": true
+    },
+    "mime-types": {
+      "version": "2.1.22",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
+      "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
+      "dev": true,
+      "requires": {
+        "mime-db": "~1.38.0"
+      }
+    },
+    "minimist": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+      "dev": true
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "dev": true,
+      "requires": {
+        "minimist": "0.0.8"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+          "dev": true
+        }
+      }
+    },
+    "ms": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+      "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+      "dev": true
+    },
+    "normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "nugget": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz",
+      "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.1.3",
+        "minimist": "^1.1.0",
+        "pretty-bytes": "^1.0.2",
+        "progress-stream": "^1.1.0",
+        "request": "^2.45.0",
+        "single-line-log": "^1.1.2",
+        "throttleit": "0.0.2"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        }
+      }
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "oauth-sign": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+      "dev": true
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-keys": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
+      "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
+      "dev": true
+    },
+    "parse-json": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "dev": true,
+      "requires": {
+        "error-ex": "^1.2.0"
+      }
+    },
+    "path-exists": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "dev": true
+    },
+    "path-type": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+      "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "pend": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+      "dev": true
+    },
+    "performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+      "dev": true
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+      "dev": true
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+      "dev": true
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "dev": true,
+      "requires": {
+        "pinkie": "^2.0.0"
+      }
+    },
+    "popper.js": {
+      "version": "1.14.7",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.7.tgz",
+      "integrity": "sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ==",
+      "dev": true
+    },
+    "pretty-bytes": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
+      "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
+      "dev": true,
+      "requires": {
+        "get-stdin": "^4.0.1",
+        "meow": "^3.1.0"
+      }
+    },
+    "process-nextick-args": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+      "dev": true
+    },
+    "progress-stream": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz",
+      "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=",
+      "dev": true,
+      "requires": {
+        "speedometer": "~0.1.2",
+        "through2": "~0.2.3"
+      }
+    },
+    "psl": {
+      "version": "1.1.31",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
+      "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==",
+      "dev": true
+    },
+    "punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+      "dev": true
+    },
+    "qs": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+      "dev": true
+    },
+    "rc": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "dev": true,
+      "requires": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      }
+    },
+    "read-pkg": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+      "dev": true,
+      "requires": {
+        "load-json-file": "^1.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^1.0.0"
+      }
+    },
+    "read-pkg-up": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+      "dev": true,
+      "requires": {
+        "find-up": "^1.0.0",
+        "read-pkg": "^1.0.0"
+      }
+    },
+    "readable-stream": {
+      "version": "1.1.14",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+      "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+      "dev": true,
+      "requires": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.1",
+        "isarray": "0.0.1",
+        "string_decoder": "~0.10.x"
+      }
+    },
+    "redent": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+      "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+      "dev": true,
+      "requires": {
+        "indent-string": "^2.1.0",
+        "strip-indent": "^1.0.1"
+      }
+    },
+    "repeating": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+      "dev": true,
+      "requires": {
+        "is-finite": "^1.0.0"
+      }
+    },
+    "request": {
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+      "dev": true,
+      "requires": {
+        "aws-sign2": "~0.7.0",
+        "aws4": "^1.8.0",
+        "caseless": "~0.12.0",
+        "combined-stream": "~1.0.6",
+        "extend": "~3.0.2",
+        "forever-agent": "~0.6.1",
+        "form-data": "~2.3.2",
+        "har-validator": "~5.1.0",
+        "http-signature": "~1.2.0",
+        "is-typedarray": "~1.0.0",
+        "isstream": "~0.1.2",
+        "json-stringify-safe": "~5.0.1",
+        "mime-types": "~2.1.19",
+        "oauth-sign": "~0.9.0",
+        "performance-now": "^2.1.0",
+        "qs": "~6.5.2",
+        "safe-buffer": "^5.1.2",
+        "tough-cookie": "~2.4.3",
+        "tunnel-agent": "^0.6.0",
+        "uuid": "^3.3.2"
+      }
+    },
+    "resolve": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
+      "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
+      "dev": true,
+      "requires": {
+        "path-parse": "^1.0.6"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "semver": {
+      "version": "5.6.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
+    "single-line-log": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz",
+      "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=",
+      "dev": true,
+      "requires": {
+        "string-width": "^1.0.1"
+      }
+    },
+    "spdx-correct": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+      "dev": true,
+      "requires": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-exceptions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+      "dev": true
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz",
+      "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==",
+      "dev": true
+    },
+    "speedometer": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz",
+      "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=",
+      "dev": true
+    },
+    "sshpk": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+      "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+      "dev": true,
+      "requires": {
+        "asn1": "~0.2.3",
+        "assert-plus": "^1.0.0",
+        "bcrypt-pbkdf": "^1.0.0",
+        "dashdash": "^1.12.0",
+        "ecc-jsbn": "~0.1.1",
+        "getpass": "^0.1.1",
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.0.2",
+        "tweetnacl": "~0.14.0"
+      }
+    },
+    "store2": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/store2/-/store2-2.7.1.tgz",
+      "integrity": "sha512-zzzP5ZY6QWumnAFV6kBRbS44pUMcpZBNER5DWUe1HETlaKXqLcCQxbNu6IHaKr1pUsjuhUGBdOy8sWKmMkL6pQ==",
+      "dev": true
+    },
+    "string-width": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+      "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+      "dev": true,
+      "requires": {
+        "code-point-at": "^1.0.0",
+        "is-fullwidth-code-point": "^1.0.0",
+        "strip-ansi": "^3.0.0"
+      }
+    },
+    "string_decoder": {
+      "version": "0.10.31",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+      "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+      "dev": true
+    },
+    "strip-ansi": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "strip-bom": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+      "dev": true,
+      "requires": {
+        "is-utf8": "^0.2.0"
+      }
+    },
+    "strip-indent": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+      "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+      "dev": true,
+      "requires": {
+        "get-stdin": "^4.0.1"
+      }
+    },
+    "strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+      "dev": true
+    },
+    "sumchecker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz",
+      "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=",
+      "dev": true,
+      "requires": {
+        "debug": "^2.2.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "dev": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+          "dev": true
+        }
+      }
+    },
+    "throttleit": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz",
+      "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=",
+      "dev": true
+    },
+    "through2": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
+      "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
+      "dev": true,
+      "requires": {
+        "readable-stream": "~1.1.9",
+        "xtend": "~2.1.1"
+      }
+    },
+    "tinymce": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-5.0.0.tgz",
+      "integrity": "sha512-aWBXuV1S+JaZUoteLgOoDv9Ra7wcohpRFoHhldoRWUg9fdA36zC9XPjWfxNgzaANqKdOICxZ3tguLmi3RLtiLA==",
+      "dev": true
+    },
+    "tough-cookie": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+      "dev": true,
+      "requires": {
+        "psl": "^1.1.24",
+        "punycode": "^1.4.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true
+        }
+      }
+    },
+    "trim-newlines": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+      "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+      "dev": true
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "tweetnacl": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+      "dev": true
+    },
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+      "dev": true
+    },
+    "universalify": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+      "dev": true
+    },
+    "uri-js": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+      "dev": true,
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
+    "uuid": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+      "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
+      "dev": true
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "verror": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "core-util-is": "1.0.2",
+        "extsprintf": "^1.2.0"
+      }
+    },
+    "xtend": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
+      "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
+      "dev": true,
+      "requires": {
+        "object-keys": "~0.4.0"
+      }
+    },
+    "yauzl": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
+      "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
+      "dev": true,
+      "requires": {
+        "fd-slicer": "~1.0.1"
+      }
+    }
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644 (file)
index 0000000..aa10d68
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "name": "creorga",
+  "version": "4.0.0",
+  "description": "Crèche Management Software",
+  "main": "main.js",
+  "scripts": {
+    "start": "electron ."
+  },
+  "author": "Kilian Saffran",
+  "license": "MIT",
+  "devDependencies": {
+    "@fortawesome/fontawesome-free": "^5.7.2",
+    "bootstrap": "^4.3.1",
+    "bootstrap-datepicker": "^1.8.0",
+    "bootstrap-table": "^1.13.4",
+    "electron": "^4.0.5",
+    "jquery": "^3.3.1",
+    "popper.js": "^1.14.7",
+    "store2": "^2.7.1",
+    "tinymce": "^5.0.0"
+  }
+}