Merge branch 'releases/release-h2f' into releases/release-h2f-prod
This commit is contained in:
commit
b935617c29
@ -63,6 +63,10 @@ return [
|
||||
['name' => 'settings#setConfig', 'url' => '/v1/config/{key}', 'verb' => 'POST'],
|
||||
// Tools
|
||||
['name' => 'email#sendEmailPublicLink', 'url' => '/v1/public/sendmail', 'verb' => 'POST'],
|
||||
|
||||
//Email box
|
||||
['name' => 'emailBox#loadEmailboxMessage', 'url' => '/load-email-box', 'verb' => 'GET'],
|
||||
['name' => 'emailBox#loadEmailboxAttachement', 'url' => '/load-email-attachement/{messageId}', 'verb' => 'GET'],
|
||||
],
|
||||
'resources' => [
|
||||
'appointmentConfig' => ['url' => '/v1/appointment_configs']
|
||||
|
||||
@ -164570,7 +164570,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"compressed":true,"categories":[{"id"
|
||||
/******/ // This function allow to reference async chunks
|
||||
/******/ __webpack_require__.u = (chunkId) => {
|
||||
/******/ // return url for filenames based on template
|
||||
/******/ return "calendar-" + chunkId + ".js?v=" + {"vendors-node_modules_nextcloud_capabilities_dist_index_js-node_modules_nextcloud_vue-select_d-877981":"7bde6f386631234ba146","vendors-node_modules_vue-material-design-icons_CalendarBlank_vue-node_modules_vue-material-de-e2c1f8":"2e0b0e8bc0e8488c397c","vendors-node_modules_path-browserify_index_js-node_modules_nextcloud_dialogs_dist_chunks_Dial-e0595f":"728c782d2751f8e6150a","node_modules_nextcloud_dialogs_dist_legacy_mjs":"8be838e4c6e9aae56c87","vendors-node_modules_webdav_dist_web_index_js":"454da8f908d41b47c607","vendors-node_modules_nextcloud_dialogs_dist_chunks_FilePicker-8ibBgPg__mjs":"ea54a36450de178d1141"}[chunkId] + "";
|
||||
/******/ return "calendar-" + chunkId + ".js?v=" + {"vendors-node_modules_nextcloud_capabilities_dist_index_js-node_modules_nextcloud_vue-select_d-877981":"741d92f5ec54d0c1ff41","vendors-node_modules_vue-material-design-icons_CalendarBlank_vue-node_modules_vue-material-de-e2c1f8":"0658eb6db50a09dd2afe","vendors-node_modules_path-browserify_index_js-node_modules_nextcloud_dialogs_dist_chunks_Dial-e0595f":"e0f3178442f3c9eb35e1","node_modules_nextcloud_dialogs_dist_legacy_mjs":"8be838e4c6e9aae56c87","vendors-node_modules_webdav_dist_web_index_js":"454da8f908d41b47c607","vendors-node_modules_nextcloud_dialogs_dist_chunks_FilePicker-8ibBgPg__mjs":"ea54a36450de178d1141"}[chunkId] + "";
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
@ -164827,4 +164827,4 @@ const visitorInfo = (0,_nextcloud_initial_state__WEBPACK_IMPORTED_MODULE_1__.loa
|
||||
|
||||
/******/ })()
|
||||
;
|
||||
//# sourceMappingURL=calendar-appointments-booking.js.map?v=b7719d864afe6419c183
|
||||
//# sourceMappingURL=calendar-appointments-booking.js.map?v=312d2cc5b7ca549a9366
|
||||
File diff suppressed because one or more lines are too long
@ -37516,4 +37516,4 @@ const booking = (0,_nextcloud_initial_state__WEBPACK_IMPORTED_MODULE_1__.loadSta
|
||||
|
||||
/******/ })()
|
||||
;
|
||||
//# sourceMappingURL=calendar-appointments-confirmation.js.map?v=e09415d738d19b735882
|
||||
//# sourceMappingURL=calendar-appointments-confirmation.js.map?v=a2ee83495b163cb419ce
|
||||
File diff suppressed because one or more lines are too long
@ -37552,4 +37552,4 @@ const booking = (0,_nextcloud_initial_state__WEBPACK_IMPORTED_MODULE_1__.loadSta
|
||||
|
||||
/******/ })()
|
||||
;
|
||||
//# sourceMappingURL=calendar-appointments-conflict.js.map?v=203b5778e2275f51e478
|
||||
//# sourceMappingURL=calendar-appointments-conflict.js.map?v=b617e2fd0c187cf8a3ef
|
||||
File diff suppressed because one or more lines are too long
@ -160605,4 +160605,4 @@ vue__WEBPACK_IMPORTED_MODULE_5__["default"].prototype.$n = _nextcloud_l10n__WEBP
|
||||
|
||||
/******/ })()
|
||||
;
|
||||
//# sourceMappingURL=calendar-appointments-overview.js.map?v=11949b799a3d070cc45a
|
||||
//# sourceMappingURL=calendar-appointments-overview.js.map?v=f24398268fe4a78a6630
|
||||
File diff suppressed because one or more lines are too long
@ -500,4 +500,4 @@ if(false) {}
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-dashboard-lazy.js.map?v=0dd354a2fd4b9e38ddcf
|
||||
//# sourceMappingURL=calendar-dashboard-lazy.js.map?v=60b7f707e08fff04c7a1
|
||||
File diff suppressed because one or more lines are too long
@ -1322,7 +1322,7 @@ function b(n) {
|
||||
/******/ // This function allow to reference async chunks
|
||||
/******/ __webpack_require__.u = (chunkId) => {
|
||||
/******/ // return url for filenames based on template
|
||||
/******/ return "calendar-" + chunkId + ".js?v=" + {"vendors-node_modules_nextcloud_capabilities_dist_index_js-node_modules_nextcloud_vue-select_d-877981":"7bde6f386631234ba146","vendors-node_modules_vue_dist_vue_runtime_esm_js":"7e3171593bdc0f62040b","vendors-node_modules_nextcloud_cdav-library_dist_dist_js-node_modules_nextcloud_logger_dist_i-36c16b":"c3b3db23da041c717fc1","vendors-node_modules_webdav_dist_web_index_js":"454da8f908d41b47c607","vendors-node_modules_vue-material-design-icons_CalendarBlankOutline_vue-node_modules_nextclou-4adead":"273df538e0dc19672feb","vendors-node_modules_nextcloud_vue-dashboard_dist_vue-dashboard_js-node_modules_css-loader_di-9e6f3d":"86eaa619747854c0da61","src_models_rfcProps_js-src_services_caldavService_js-src_services_talkService_js-src_services-8a2790":"94fac30d128df46a89a6","src_store_index_js":"8e651e1007c1cc1d62d0","src_fullcalendar_eventSources_eventSourceFunction_js-src_utils_moment_js-data_image_svg_xml_3-b73258":"740a2859d1f364b508c1","dashboard-lazy":"0dd354a2fd4b9e38ddcf","vendors-node_modules_vue-material-design-icons_CalendarBlank_vue-node_modules_vue-material-de-e2c1f8":"2e0b0e8bc0e8488c397c","vendors-node_modules_path-browserify_index_js-node_modules_nextcloud_dialogs_dist_chunks_Dial-e0595f":"728c782d2751f8e6150a","node_modules_nextcloud_dialogs_dist_legacy_mjs":"8be838e4c6e9aae56c87","vendors-node_modules_nextcloud_dialogs_dist_chunks_FilePicker-8ibBgPg__mjs":"ea54a36450de178d1141","vendors-node_modules_moment_locale_af_js-node_modules_moment_locale_ar-dz_js-node_modules_mom-582c96":"ce1bed825f57dd1d117a","node_modules_moment_locale_sync_recursive_":"4bc2c39c5e0ff182c2e3"}[chunkId] + "";
|
||||
/******/ return "calendar-" + chunkId + ".js?v=" + {"vendors-node_modules_nextcloud_capabilities_dist_index_js-node_modules_nextcloud_vue-select_d-877981":"741d92f5ec54d0c1ff41","vendors-node_modules_vue_dist_vue_runtime_esm_js":"7e3171593bdc0f62040b","vendors-node_modules_nextcloud_cdav-library_dist_dist_js-node_modules_nextcloud_logger_dist_i-36c16b":"c3b3db23da041c717fc1","vendors-node_modules_webdav_dist_web_index_js":"454da8f908d41b47c607","vendors-node_modules_vue-material-design-icons_CalendarBlankOutline_vue-node_modules_nextclou-4adead":"01a7eb6779cc0e417f44","vendors-node_modules_nextcloud_vue-dashboard_dist_vue-dashboard_js-node_modules_css-loader_di-9e6f3d":"c2bd3081c493a88308a2","src_models_rfcProps_js-src_services_caldavService_js-src_services_talkService_js-src_services-8a2790":"870a881bc445f47fd3e0","src_store_index_js":"748ab31152e1226f9b22","src_fullcalendar_eventSources_eventSourceFunction_js-src_utils_moment_js-data_image_svg_xml_3-b73258":"8bfde7d389740c269cd6","dashboard-lazy":"60b7f707e08fff04c7a1","vendors-node_modules_vue-material-design-icons_CalendarBlank_vue-node_modules_vue-material-de-e2c1f8":"0658eb6db50a09dd2afe","vendors-node_modules_path-browserify_index_js-node_modules_nextcloud_dialogs_dist_chunks_Dial-e0595f":"e0f3178442f3c9eb35e1","node_modules_nextcloud_dialogs_dist_legacy_mjs":"8be838e4c6e9aae56c87","vendors-node_modules_nextcloud_dialogs_dist_chunks_FilePicker-8ibBgPg__mjs":"ea54a36450de178d1141","vendors-node_modules_moment_locale_af_js-node_modules_moment_locale_ar-dz_js-node_modules_mom-582c96":"ce1bed825f57dd1d117a","node_modules_moment_locale_sync_recursive_":"4bc2c39c5e0ff182c2e3"}[chunkId] + "";
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
@ -1580,4 +1580,4 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
/******/ })()
|
||||
;
|
||||
//# sourceMappingURL=calendar-dashboard.js.map?v=561bba8d5d28f5eebd8f
|
||||
//# sourceMappingURL=calendar-dashboard.js.map?v=fd08a5d56f376e2cd30d
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -369,4 +369,4 @@ module.exports = /*#__PURE__*/JSON.parse('[{"country":"Algeria","filename":"Alge
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-public-calendar-subscription-picker.js.map?v=9168fca99a878d4c37e3
|
||||
//# sourceMappingURL=calendar-public-calendar-subscription-picker.js.map?v=0c8b5b050db3beb63d49
|
||||
File diff suppressed because one or more lines are too long
@ -8865,7 +8865,7 @@ window._registerCustomPickerElement = _;
|
||||
/******/ // This function allow to reference async chunks
|
||||
/******/ __webpack_require__.u = (chunkId) => {
|
||||
/******/ // return url for filenames based on template
|
||||
/******/ return "calendar-" + chunkId + ".js?v=" + {"vendors-node_modules_vue_dist_vue_runtime_esm_js":"7e3171593bdc0f62040b","vendors-node_modules_nextcloud_capabilities_dist_index_js-node_modules_nextcloud_vue-select_d-877981":"7bde6f386631234ba146","vendors-node_modules_nextcloud_cdav-library_dist_dist_js-node_modules_nextcloud_logger_dist_i-36c16b":"c3b3db23da041c717fc1","vendors-node_modules_vue-material-design-icons_CalendarBlank_vue-node_modules_vue-material-de-e2c1f8":"2e0b0e8bc0e8488c397c","vendors-node_modules_vue-material-design-icons_CalendarBlankOutline_vue-node_modules_nextclou-4adead":"273df538e0dc19672feb","vendors-node_modules_autosize_dist_autosize_esm_js-node_modules_html-entities_lib_index_js-no-4072c5":"56373f2063898525e8de","src_models_rfcProps_js-src_services_caldavService_js-src_services_talkService_js-src_services-8a2790":"94fac30d128df46a89a6","src_fullcalendar_eventSources_eventSourceFunction_js-src_utils_moment_js-data_image_svg_xml_3-b73258":"740a2859d1f364b508c1","src_views_Calendar_vue-data_image_svg_xml_3csvg_20xmlns_27http_www_w3_org_2000_svg_27_20heigh-4a4254":"c843b5a49512d69e485e","vendors-node_modules_webdav_dist_web_index_js":"454da8f908d41b47c607","src_store_index_js":"8e651e1007c1cc1d62d0","vendors-node_modules_path-browserify_index_js-node_modules_nextcloud_dialogs_dist_chunks_Dial-e0595f":"728c782d2751f8e6150a","node_modules_nextcloud_dialogs_dist_legacy_mjs":"8be838e4c6e9aae56c87","vendors-node_modules_nextcloud_dialogs_dist_chunks_FilePicker-8ibBgPg__mjs":"ea54a36450de178d1141","public-calendar-subscription-picker":"9168fca99a878d4c37e3","vendors-node_modules_moment_locale_af_js-node_modules_moment_locale_ar-dz_js-node_modules_mom-582c96":"ce1bed825f57dd1d117a","node_modules_moment_locale_sync_recursive_":"4bc2c39c5e0ff182c2e3"}[chunkId] + "";
|
||||
/******/ return "calendar-" + chunkId + ".js?v=" + {"vendors-node_modules_vue_dist_vue_runtime_esm_js":"7e3171593bdc0f62040b","vendors-node_modules_nextcloud_capabilities_dist_index_js-node_modules_nextcloud_vue-select_d-877981":"741d92f5ec54d0c1ff41","vendors-node_modules_nextcloud_cdav-library_dist_dist_js-node_modules_nextcloud_logger_dist_i-36c16b":"c3b3db23da041c717fc1","vendors-node_modules_vue-material-design-icons_CalendarBlank_vue-node_modules_vue-material-de-e2c1f8":"0658eb6db50a09dd2afe","vendors-node_modules_vue-material-design-icons_CalendarBlankOutline_vue-node_modules_nextclou-4adead":"01a7eb6779cc0e417f44","vendors-node_modules_autosize_dist_autosize_esm_js-node_modules_html-entities_lib_index_js-no-4072c5":"c3527b981de24f56109b","src_models_rfcProps_js-src_services_caldavService_js-src_services_talkService_js-src_services-8a2790":"870a881bc445f47fd3e0","src_fullcalendar_eventSources_eventSourceFunction_js-src_utils_moment_js-data_image_svg_xml_3-b73258":"8bfde7d389740c269cd6","src_views_Calendar_vue-data_image_svg_xml_3csvg_20xmlns_27http_www_w3_org_2000_svg_27_20heigh-4a4254":"297f1f42ac74bad32e69","vendors-node_modules_webdav_dist_web_index_js":"454da8f908d41b47c607","src_store_index_js":"748ab31152e1226f9b22","vendors-node_modules_path-browserify_index_js-node_modules_nextcloud_dialogs_dist_chunks_Dial-e0595f":"e0f3178442f3c9eb35e1","node_modules_nextcloud_dialogs_dist_legacy_mjs":"8be838e4c6e9aae56c87","vendors-node_modules_nextcloud_dialogs_dist_chunks_FilePicker-8ibBgPg__mjs":"ea54a36450de178d1141","public-calendar-subscription-picker":"0c8b5b050db3beb63d49","vendors-node_modules_moment_locale_af_js-node_modules_moment_locale_ar-dz_js-node_modules_mom-582c96":"ce1bed825f57dd1d117a","node_modules_moment_locale_sync_recursive_":"4bc2c39c5e0ff182c2e3"}[chunkId] + "";
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
@ -9115,4 +9115,4 @@ __webpack_require__.p = (0,_nextcloud_router__WEBPACK_IMPORTED_MODULE_1__.linkTo
|
||||
|
||||
/******/ })()
|
||||
;
|
||||
//# sourceMappingURL=calendar-reference.js.map?v=3d457bacc80e2d3e209d
|
||||
//# sourceMappingURL=calendar-reference.js.map?v=c50a6845f9eb0b6964ef
|
||||
File diff suppressed because one or more lines are too long
@ -53,6 +53,7 @@ __webpack_require__.r(__webpack_exports__);
|
||||
*/
|
||||
function eventSourceFunction(calendarObjects, calendar, start, end, timezone) {
|
||||
const fcEvents = [];
|
||||
const authUser = OC.currentUser;
|
||||
for (const calendarObject of calendarObjects) {
|
||||
let allObjectsInTimeRange;
|
||||
try {
|
||||
@ -123,6 +124,32 @@ function eventSourceFunction(calendarObjects, calendar, start, end, timezone) {
|
||||
title += " (".concat(object.percent, "%)");
|
||||
}
|
||||
}
|
||||
let isPrivateEvent = false;
|
||||
let objectProperties = object._properties.get('ISPRIVATE');
|
||||
if (objectProperties && objectProperties.length > 0) {
|
||||
isPrivateEvent = objectProperties[0]._value == "1" ? true : false;
|
||||
}
|
||||
|
||||
//Get owen object's user
|
||||
let owenUrl = calendarObject.dav._parent.owner;
|
||||
let owenUser = owenUrl.replace('/remote.php/dav/principals/users/', '').split('/')[0];
|
||||
if (!owenUser) {
|
||||
//Get from url shared calendar
|
||||
owenUrl = calendarObject.dav._parent.url;
|
||||
owenUser = owenUrl.replace('/remote.php/dav/calendars/' + authUser + '/personal_shared_by_', '').split('/')[0];
|
||||
}
|
||||
const isOwenOfEvent = owenUser == authUser;
|
||||
if (isPrivateEvent && !isOwenOfEvent) {
|
||||
title = (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', "Absent (".concat(owenUser, ")"));
|
||||
}
|
||||
let absenceTypeIsLeave = false;
|
||||
let absenceTypeProperties = object._properties.get('ABSENCETYPE');
|
||||
if (absenceTypeProperties && absenceTypeProperties.length > 0) {
|
||||
const absenceTypeValue = absenceTypeProperties[0]._value;
|
||||
if (absenceTypeValue == 'LEAVE') {
|
||||
absenceTypeIsLeave = true;
|
||||
}
|
||||
}
|
||||
const fcEvent = {
|
||||
id: [calendarObject.id, object.id].join('###'),
|
||||
title,
|
||||
@ -144,9 +171,18 @@ function eventSourceFunction(calendarObjects, calendar, start, end, timezone) {
|
||||
percent: object.percent || null,
|
||||
davUrl: calendarObject.dav.url,
|
||||
location: object.location,
|
||||
description: object.description
|
||||
description: object.description,
|
||||
isPrivate: isPrivateEvent,
|
||||
calendarObjectOwen: owenUser,
|
||||
calendarObjectIsOwen: isOwenOfEvent,
|
||||
absenceTypeIsLeave: absenceTypeIsLeave
|
||||
}
|
||||
};
|
||||
if (absenceTypeIsLeave) {
|
||||
fcEvent.backgroundColor = calendar.color;
|
||||
fcEvent.borderColor = calendar.color;
|
||||
fcEvent.textColor = (0,_utils_color_js__WEBPACK_IMPORTED_MODULE_1__.generateTextColorForHex)(calendar.color);
|
||||
}
|
||||
if (object.color) {
|
||||
const customColor = (0,_utils_color_js__WEBPACK_IMPORTED_MODULE_1__.getHexForColorName)(object.color);
|
||||
if (customColor) {
|
||||
@ -1032,4 +1068,4 @@ module.exports = "data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/sv
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-src_fullcalendar_eventSources_eventSourceFunction_js-src_utils_moment_js-data_image_svg_xml_3-b73258.js.map?v=740a2859d1f364b508c1
|
||||
//# sourceMappingURL=calendar-src_fullcalendar_eventSources_eventSourceFunction_js-src_utils_moment_js-data_image_svg_xml_3-b73258.js.map?v=8bfde7d389740c269cd6
|
||||
File diff suppressed because one or more lines are too long
@ -292,6 +292,10 @@ const getRFCProperties = () => {
|
||||
placeholder: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Choisir un client'),
|
||||
icon: 'Human'
|
||||
},
|
||||
absenceType: {
|
||||
readableName: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Type d\'absence'),
|
||||
placeholder: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Type d\'absence')
|
||||
},
|
||||
embalmers: {
|
||||
readableName: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Embalmers'),
|
||||
icon: 'Human',
|
||||
@ -316,6 +320,15 @@ const getRFCProperties = () => {
|
||||
placeholder: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Choisir les soins'),
|
||||
tagPlaceholder: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Choisir les soins'),
|
||||
options: []
|
||||
},
|
||||
comment: {
|
||||
readableName: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Comment'),
|
||||
icon: 'TextBoxOutline',
|
||||
info: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Commentaires.'),
|
||||
placeholder: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Commentaires'),
|
||||
tagPlaceholder: (0,_nextcloud_l10n__WEBPACK_IMPORTED_MODULE_0__.translate)('calendar', 'Commentaires'),
|
||||
options: [],
|
||||
defaultNumberOfRows: 4
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -1817,4 +1830,4 @@ function GenColors(steps) {
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-src_models_rfcProps_js-src_services_caldavService_js-src_services_talkService_js-src_services-8a2790.js.map?v=94fac30d128df46a89a6
|
||||
//# sourceMappingURL=calendar-src_models_rfcProps_js-src_services_caldavService_js-src_services_talkService_js-src_services-8a2790.js.map?v=870a881bc445f47fd3e0
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -42554,4 +42554,4 @@ function hasInjectionContext() {
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_autosize_dist_autosize_esm_js-node_modules_html-entities_lib_index_js-no-4072c5.js.map?v=56373f2063898525e8de
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_autosize_dist_autosize_esm_js-node_modules_html-entities_lib_index_js-no-4072c5.js.map?v=c3527b981de24f56109b
|
||||
File diff suppressed because one or more lines are too long
@ -21864,4 +21864,4 @@ const webNamespaces = {
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_nextcloud_capabilities_dist_index_js-node_modules_nextcloud_vue-select_d-877981.js.map?v=7bde6f386631234ba146
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_nextcloud_capabilities_dist_index_js-node_modules_nextcloud_vue-select_d-877981.js.map?v=741d92f5ec54d0c1ff41
|
||||
File diff suppressed because one or more lines are too long
@ -27285,4 +27285,4 @@ window._registerCustomPickerElement = _;
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_nextcloud_vue-dashboard_dist_vue-dashboard_js-node_modules_css-loader_di-9e6f3d.js.map?v=86eaa619747854c0da61
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_nextcloud_vue-dashboard_dist_vue-dashboard_js-node_modules_css-loader_di-9e6f3d.js.map?v=c2bd3081c493a88308a2
|
||||
File diff suppressed because one or more lines are too long
@ -80146,4 +80146,4 @@ module.exports = /*#__PURE__*/JSON.parse('{"compressed":true,"categories":[{"id"
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_path-browserify_index_js-node_modules_nextcloud_dialogs_dist_chunks_Dial-e0595f.js.map?v=728c782d2751f8e6150a
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_path-browserify_index_js-node_modules_nextcloud_dialogs_dist_chunks_Dial-e0595f.js.map?v=e0f3178442f3c9eb35e1
|
||||
File diff suppressed because one or more lines are too long
@ -102420,4 +102420,4 @@ module.exports = /*#__PURE__*/JSON.parse('{"compressed":true,"categories":[{"id"
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_vue-material-design-icons_CalendarBlankOutline_vue-node_modules_nextclou-4adead.js.map?v=273df538e0dc19672feb
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_vue-material-design-icons_CalendarBlankOutline_vue-node_modules_nextclou-4adead.js.map?v=01a7eb6779cc0e417f44
|
||||
File diff suppressed because one or more lines are too long
@ -2030,4 +2030,4 @@ render._withStripped = true
|
||||
/***/ })
|
||||
|
||||
}]);
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_vue-material-design-icons_CalendarBlank_vue-node_modules_vue-material-de-e2c1f8.js.map?v=2e0b0e8bc0e8488c397c
|
||||
//# sourceMappingURL=calendar-vendors-node_modules_vue-material-design-icons_CalendarBlank_vue-node_modules_vue-material-de-e2c1f8.js.map?v=0658eb6db50a09dd2afe
|
||||
File diff suppressed because one or more lines are too long
217
calendar/lib/Controller/EmailBoxController.php
Normal file
217
calendar/lib/Controller/EmailBoxController.php
Normal file
@ -0,0 +1,217 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\Calendar\Controller;
|
||||
|
||||
use OCP\IRequest;
|
||||
use Horde_Imap_Client;
|
||||
use OCA\Calendar\Db\MailRepository;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\Files\IMimeTypeDetector;
|
||||
use OCA\Mail\Contracts\IMailSearch;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCA\Mail\Contracts\IMailManager;
|
||||
use OCA\Mail\IMAP\IMAPClientFactory;
|
||||
use OCA\Mail\Service\AccountService;
|
||||
use OCA\Mail\Service\Sync\SyncService;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCA\Mail\Contracts\IUserPreferences;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
|
||||
class EmailBoxController extends Controller {
|
||||
private ?string $currentUserId;
|
||||
|
||||
private IMailManager $mailManager;
|
||||
|
||||
private IUserPreferences $preferences;
|
||||
|
||||
private IMailSearch $mailSearch;
|
||||
|
||||
private AccountService $accountService;
|
||||
|
||||
private IURLGenerator $urlGenerator;
|
||||
|
||||
private IMimeTypeDetector $mimeTypeDetector;
|
||||
|
||||
private IMAPClientFactory $clientFactory;
|
||||
|
||||
private SyncService $syncService;
|
||||
|
||||
private MailRepository $mailRepository;
|
||||
|
||||
public function __construct(string $appName,
|
||||
IRequest $request,
|
||||
?string $UserId,
|
||||
IMailManager $mailManager,
|
||||
IUserPreferences $preferences,
|
||||
IMailSearch $mailSearch,
|
||||
AccountService $accountService,
|
||||
IURLGenerator $urlGenerator,
|
||||
IMimeTypeDetector $mimeTypeDetector,
|
||||
IMAPClientFactory $clientFactory,
|
||||
SyncService $syncService,
|
||||
MailRepository $mailRepository,
|
||||
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->currentUserId = $UserId;
|
||||
$this->mailManager = $mailManager;
|
||||
$this->preferences = $preferences;
|
||||
$this->mailSearch = $mailSearch;
|
||||
$this->accountService = $accountService;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->mimeTypeDetector = $mimeTypeDetector;
|
||||
$this->clientFactory = $clientFactory;
|
||||
$this->syncService = $syncService;
|
||||
$this->mailRepository = $mailRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function loadEmailboxMessage(): JSONResponse {
|
||||
|
||||
$mailboxId = $this->mailRepository->getCurrentUserMailBoxId($this->currentUserId);
|
||||
if($mailboxId == null){
|
||||
return new JSONResponse([
|
||||
"success" => false,
|
||||
"message" => "MAILBOX_NOT_FOUND",
|
||||
], Http::STATUS_OK);
|
||||
}
|
||||
|
||||
$lastMessageTimestamp = null;
|
||||
$init = true;
|
||||
$sortOrder = 'newest';
|
||||
$query = null;
|
||||
|
||||
try {
|
||||
$mailbox = $this->mailManager->getMailbox($this->currentUserId, $mailboxId);
|
||||
$account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
|
||||
// try {
|
||||
// if (boolval($this->request->getParam('withSync'))) {
|
||||
// $this->syncService->syncMailbox(
|
||||
// $account,
|
||||
// $mailbox,
|
||||
// Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS,
|
||||
// null,
|
||||
// $lastMessageTimestamp,
|
||||
// $init,
|
||||
// $sortOrder,
|
||||
// $query
|
||||
// );
|
||||
// }
|
||||
// } catch (\Throwable $th) {
|
||||
// // on ignioir car il n'est pas est deja synchronise
|
||||
// }
|
||||
} catch (DoesNotExistException $e) {
|
||||
return new JSONResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
|
||||
$order = $this->preferences->getPreference($this->currentUserId, 'sort-order', 'newest') === 'newest' ? 'DESC': 'ASC';
|
||||
return new JSONResponse(
|
||||
$this->mailSearch->findMessages(
|
||||
$account,
|
||||
$mailbox,
|
||||
$order,
|
||||
null,
|
||||
null,
|
||||
400,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function loadEmailboxAttachement(int $messageId = 0): Response {
|
||||
$data = [];
|
||||
try {
|
||||
$message = $this->mailManager->getMessage($this->currentUserId, $messageId);
|
||||
$mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
|
||||
$account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
|
||||
|
||||
// $data["messageObject"] = $message ?? null;
|
||||
} catch (DoesNotExistException $e) {
|
||||
return new JSONResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
|
||||
$client = $this->clientFactory->getClient($account);
|
||||
try {
|
||||
$imapMessage = $this->mailManager->getImapMessage(
|
||||
$client,
|
||||
$account,
|
||||
$mailbox,
|
||||
$message->getUid(), true
|
||||
);
|
||||
$json = $imapMessage->getFullMessage($messageId);
|
||||
} finally {
|
||||
$client->logout();
|
||||
}
|
||||
|
||||
$data['fullMessage'] = $json;
|
||||
$data['attachments'] = array_map(function ($a) use ($messageId) {
|
||||
return $this->enrichDownloadUrl(
|
||||
$messageId,
|
||||
$a
|
||||
);
|
||||
}, $json['attachments']);
|
||||
|
||||
if(isset( $json['attachments'])) {
|
||||
unset($json['attachments']);
|
||||
}
|
||||
return new JSONResponse(($data));
|
||||
}
|
||||
/**
|
||||
* @param int $id
|
||||
* @param array $attachment
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function enrichDownloadUrl(int $id,
|
||||
array $attachment) {
|
||||
$downloadUrl = $this->urlGenerator->linkToRoute('mail.messages.downloadAttachment',
|
||||
[
|
||||
'id' => $id,
|
||||
'attachmentId' => $attachment['id'],
|
||||
]);
|
||||
$downloadUrl = $this->urlGenerator->getAbsoluteURL($downloadUrl);
|
||||
$attachment['downloadUrl'] = $downloadUrl;
|
||||
$attachment['mimeUrl'] = $this->mimeTypeDetector->mimeTypeIcon($attachment['mime']);
|
||||
|
||||
$attachment['isImage'] = $this->attachmentIsImage($attachment);
|
||||
$attachment['isCalendarEvent'] = $this->attachmentIsCalendarEvent($attachment);
|
||||
|
||||
return $attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the content of this attachment is an image
|
||||
*
|
||||
* @param array $attachment
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function attachmentIsImage(array $attachment): bool {
|
||||
return in_array(
|
||||
$attachment['mime'], [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/gif'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $attachment
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function attachmentIsCalendarEvent(array $attachment): bool {
|
||||
return in_array($attachment['mime'], ['text/calendar', 'application/ics'], true);
|
||||
}
|
||||
}
|
||||
@ -26,19 +26,24 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace OCA\Calendar\Controller;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\Defaults;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\IConfig;
|
||||
use OCP\Defaults;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Mail\IEMailTemplate;
|
||||
use OCP\Mail\IMailer;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\Mail\IMessage;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\Mail\IEMailTemplate;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCA\Mail\Contracts\IMailSearch;
|
||||
use OCA\Mail\Contracts\IMailManager;
|
||||
use OCA\Mail\Service\AccountService;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCA\Mail\Contracts\IUserPreferences;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
|
||||
/**
|
||||
* Class EmailController
|
||||
@ -67,6 +72,18 @@ class EmailController extends Controller {
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
|
||||
|
||||
private ?string $currentUserId;
|
||||
|
||||
|
||||
private IMailManager $mailManager;
|
||||
|
||||
private IUserPreferences $preferences;
|
||||
|
||||
private IMailSearch $mailSearch;
|
||||
|
||||
private AccountService $accountService;
|
||||
|
||||
/**
|
||||
* EmailController constructor.
|
||||
*
|
||||
@ -88,7 +105,15 @@ class EmailController extends Controller {
|
||||
IL10N $l10N,
|
||||
Defaults $defaults,
|
||||
IURLGenerator $urlGenerator,
|
||||
IUserManager $userManager) {
|
||||
IUserManager $userManager,
|
||||
?string $UserId,
|
||||
IMailManager $mailManager,
|
||||
IUserPreferences $preferences,
|
||||
IMailSearch $mailSearch,
|
||||
AccountService $accountService,
|
||||
|
||||
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->config = $config;
|
||||
$this->userSession = $userSession;
|
||||
@ -97,6 +122,11 @@ class EmailController extends Controller {
|
||||
$this->defaults = $defaults;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->userManager = $userManager;
|
||||
$this->currentUserId = $UserId;
|
||||
$this->mailManager = $mailManager;
|
||||
$this->preferences = $preferences;
|
||||
$this->mailSearch = $mailSearch;
|
||||
$this->accountService = $accountService;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,4 +256,7 @@ class EmailController extends Controller {
|
||||
'token' => $token,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
52
calendar/lib/Db/MailRepository.php
Normal file
52
calendar/lib/Db/MailRepository.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
namespace OCA\Calendar\Db;
|
||||
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class MailRepository {
|
||||
|
||||
private IDbConnection $pdo;
|
||||
|
||||
public function __construct(IDbConnection $db) {
|
||||
$this->pdo = $db;
|
||||
}
|
||||
|
||||
private function execSQL($sql, $conditions){
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute($conditions);
|
||||
$data = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$stmt->closeCursor();
|
||||
return json_encode($data);
|
||||
}
|
||||
|
||||
private function execSQLNoData($sql, $conditions){
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute($conditions);
|
||||
$stmt->closeCursor();
|
||||
}
|
||||
|
||||
private function execSQLNoJsonReturn($sql, $conditions){
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute($conditions);
|
||||
$data = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$stmt->closeCursor();
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getCurrentUserMailBoxId(string $currentUserId ) {
|
||||
$sql = 'SELECT mail_mailbox.id as mail_box_id
|
||||
FROM oc_mail_accounts as mail_account
|
||||
LEFT JOIN oc_mail_mailboxes as mail_mailbox ON mail_account.id = mail_mailbox.account_id
|
||||
WHERE mail_account.user_id = ?
|
||||
AND mail_mailbox.name = ?';
|
||||
|
||||
$result = $this->execSQLNoJsonReturn($sql, [$currentUserId,"INBOX"]);
|
||||
if(!empty($result)){
|
||||
return $result[0]['mail_box_id'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
17467
calendar/package-lock.json
generated
17467
calendar/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -91,8 +91,8 @@
|
||||
"npm": "^10.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.0",
|
||||
"@babel/preset-env": "^7.24.0",
|
||||
"@babel/core": "^7.26.10",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@nextcloud/babel-config": "^1.0.0",
|
||||
"@nextcloud/browserslist-config": "^3.0.0",
|
||||
"@nextcloud/eslint-config": "^8.3.0",
|
||||
@ -101,6 +101,7 @@
|
||||
"@vue/test-utils": "^1.3.6",
|
||||
"@vue/vue2-jest": "^29.2.6",
|
||||
"babel-jest": "^29.7.0",
|
||||
"babel-loader": "^9.2.1",
|
||||
"babel-loader-exclude-node-modules-except": "^1.2.1",
|
||||
"ical.js": "^1.5.0",
|
||||
"jest": "^29.7.0",
|
||||
@ -108,7 +109,10 @@
|
||||
"jest-serializer-vue": "^3.1.0",
|
||||
"npm-force-resolutions": "^0.0.10",
|
||||
"resolve-url-loader": "^5.0.0",
|
||||
"vue-template-compiler": "^2.7.16"
|
||||
"vue-loader": "^15.11.1",
|
||||
"vue-template-compiler": "^2.7.16",
|
||||
"webpack": "^5.98.0",
|
||||
"webpack-cli": "^5.1.4"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "^2.3.3"
|
||||
|
||||
@ -19,13 +19,13 @@
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<template>
|
||||
<header class="app-navigation-header">
|
||||
<AppNavigationHeaderDatePicker />
|
||||
<AppNavigationHeaderDatePicker :can-access-previous-event="canAccessPreviousEvent" />
|
||||
<div class="new-event-today-view-section">
|
||||
<AppNavigationHeaderNewEvent v-if="!isPublic" />
|
||||
<AppNavigationHeaderTodayButton />
|
||||
<AppNavigationHeaderViewMenu />
|
||||
<AppNavigationHeaderViewMenu :can-access-previous-event="canAccessPreviousEvent" />
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
@ -49,6 +49,10 @@ export default {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
canAccessPreviousEvent: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -20,9 +20,9 @@
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<template>
|
||||
<div class="datepicker-button-section">
|
||||
<NcButton v-if="!isWidget"
|
||||
<NcButton v-if="!isWidget && canAccessPreviousEvent"
|
||||
v-shortkey="previousShortKeyConf"
|
||||
:aria-label="previousLabel"
|
||||
class="datepicker-button-section__previous button"
|
||||
@ -47,6 +47,7 @@
|
||||
:is-all-day="true"
|
||||
:open.sync="isDatepickerOpen"
|
||||
:type="view === 'multiMonthYear' ? 'year' : 'date'"
|
||||
:min="minimumDate"
|
||||
@change="navigateToDate" />
|
||||
<NcButton v-if="!isWidget"
|
||||
v-shortkey="nextShortKeyConf"
|
||||
@ -91,6 +92,10 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
canAccessPreviousEvent: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -101,6 +106,9 @@ export default {
|
||||
...mapState({
|
||||
locale: (state) => state.settings.momentLocale,
|
||||
}),
|
||||
minimumDate(){
|
||||
return this.canAccessPreviousEvent ? new Date(this.$store.state.davRestrictions.minimumDate) : new Date()
|
||||
},
|
||||
selectedDate() {
|
||||
if (this.isWidget) {
|
||||
return getDateFromFirstdayParam(this.$store.getters.widgetDate)
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<template>
|
||||
<Actions v-shortkey="shortKeyConf"
|
||||
menu-align="right"
|
||||
@shortkey.native="selectViewFromShortcut">
|
||||
@ -63,29 +63,43 @@ export default {
|
||||
ViewModule,
|
||||
ViewWeek,
|
||||
},
|
||||
props: {
|
||||
canAccessPreviousEvent: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
views() {
|
||||
return [{
|
||||
id: 'timeGridDay',
|
||||
icon: 'ViewDay',
|
||||
label: this.$t('calendar', 'Day'),
|
||||
}, {
|
||||
id: 'timeGridWeek',
|
||||
icon: 'ViewWeek',
|
||||
label: this.$t('calendar', 'Week'),
|
||||
}, {
|
||||
id: 'dayGridMonth',
|
||||
icon: 'ViewModule',
|
||||
label: this.$t('calendar', 'Month'),
|
||||
}, {
|
||||
id: 'multiMonthYear',
|
||||
icon: 'ViewComfy',
|
||||
label: this.$t('calendar', 'Year'),
|
||||
}, {
|
||||
id: 'listMonth',
|
||||
icon: 'ViewList',
|
||||
label: this.$t('calendar', 'List'),
|
||||
}]
|
||||
let menus = [
|
||||
{
|
||||
id: 'timeGridDay',
|
||||
icon: 'ViewDay',
|
||||
label: this.$t('calendar', 'Day'),
|
||||
}, {
|
||||
id: 'timeGridWeek',
|
||||
icon: 'ViewWeek',
|
||||
label: this.$t('calendar', 'Week'),
|
||||
}
|
||||
];
|
||||
if(this.canAccessPreviousEvent){
|
||||
let additionalMenus =
|
||||
[{
|
||||
id: 'dayGridMonth',
|
||||
icon: 'ViewModule',
|
||||
label: this.$t('calendar', 'Month'),
|
||||
}, {
|
||||
id: 'multiMonthYear',
|
||||
icon: 'ViewComfy',
|
||||
label: this.$t('calendar', 'Year'),
|
||||
}, {
|
||||
id: 'listMonth',
|
||||
icon: 'ViewList',
|
||||
label: this.$t('calendar', 'List'),
|
||||
}];
|
||||
menus = menus.concat(additionalMenus)
|
||||
}
|
||||
return menus;
|
||||
},
|
||||
shortKeyConf() {
|
||||
return {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<header :id="isWidget? 'widget-header' :'embed-header'" role="banner">
|
||||
<div :class="isWidget?'widget-header__date-section' :'embed-header__date-section'">
|
||||
<AppNavigationHeaderDatePicker :is-widget="isWidget" />
|
||||
<AppNavigationHeaderDatePicker :is-widget="isWidget" :can-access-previous-event="canAccessPreviousEvent" />
|
||||
<AppNavigationHeaderTodayButton v-if="!isWidget" />
|
||||
</div>
|
||||
<div :class="isWidget?'widget-header__views-section' :'embed-header__views-section'">
|
||||
@ -79,6 +79,10 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
canAccessPreviousEvent: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
|
||||
@ -84,6 +84,10 @@ export default {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
isAdmin: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -107,10 +111,14 @@ export default {
|
||||
modificationCount: state => state.calendarObjects.modificationCount,
|
||||
}),
|
||||
options() {
|
||||
let defaultView = 'dayGridMonth';
|
||||
if(this.isAdmin === false){
|
||||
defaultView = 'timeGridWeek'
|
||||
}
|
||||
return {
|
||||
// Initialization:
|
||||
initialDate: getYYYYMMDDFromFirstdayParam(this.$route?.params?.firstDay ?? 'now'),
|
||||
initialView: this.$route?.params.view ?? 'dayGridMonth',
|
||||
initialView: this.$route?.params.view ?? defaultView,
|
||||
// Data
|
||||
eventSources: this.eventSources,
|
||||
// Plugins
|
||||
@ -131,7 +139,9 @@ export default {
|
||||
...getFullCalendarLocale(),
|
||||
// Rendering
|
||||
dayHeaderDidMount,
|
||||
eventDidMount,
|
||||
eventDidMount : (info) => {
|
||||
this.addAbsenceTypeEventClass(info);
|
||||
},
|
||||
noEventsDidMount,
|
||||
eventOrder: ['start', '-duration', 'allDay', eventOrder],
|
||||
forceEventDuration: false,
|
||||
@ -179,6 +189,7 @@ export default {
|
||||
]
|
||||
},
|
||||
isEditable() {
|
||||
console.log("this.isAuthenticatedUser" + this.isAuthenticatedUser)
|
||||
// We do not allow drag and drop when the editor is open.
|
||||
return this.isAuthenticatedUser
|
||||
&& this.$route?.name !== 'EditPopoverView'
|
||||
@ -294,6 +305,12 @@ export default {
|
||||
this.$store.dispatch('setInitialView', { initialView })
|
||||
}
|
||||
}, 5000),
|
||||
addAbsenceTypeEventClass(info){
|
||||
if (info.event.extendedProps.absenceTypeIsLeave) {
|
||||
info.el.style.backgroundColor = info.event.backgroundColor;
|
||||
info.el.style.color = info.event.textColor;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -32,6 +32,12 @@
|
||||
</template>
|
||||
{{ t('calendar', 'Upload from device') }}
|
||||
</NcActionButton>
|
||||
<NcActionButton @click="openEmailBoxModal">
|
||||
<template #icon>
|
||||
<Email :size="20" />
|
||||
</template>
|
||||
{{ t('calendar', 'Depuis un email') }}
|
||||
</NcActionButton>
|
||||
</NcActions>
|
||||
</div>
|
||||
<div v-if="attachments.length > 0">
|
||||
@ -58,13 +64,96 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<NcDialog :open.sync="showOpenConfirmation"
|
||||
<NcDialog :open.sync="showOpenConfirmation"
|
||||
:name="t('calendar', 'Confirmation')"
|
||||
:buttons="openConfirmationButtons">
|
||||
<p class="external-link-message">
|
||||
{{ openConfirmationMessage }}
|
||||
</p>
|
||||
</NcDialog>
|
||||
<NcModal v-if="showModal" name="" size='large' @close="resetMailBoxModal">
|
||||
|
||||
<div class="modal__content" v-if="!showAttachmentsSection && !showAttachmentsSection">
|
||||
<NcButton style="text-align: center;" @click="syncEmailBox()" v-if="!loadingDataEmailBox">
|
||||
<template #icon>
|
||||
<Reload :size="20" />
|
||||
</template>
|
||||
Actualiser
|
||||
</NcButton>
|
||||
<template v-if="mailBoxData.length > 0" v-for="mail in mailBoxData">
|
||||
<ul>
|
||||
<NcListItem
|
||||
@click="getAttachments(mail)"
|
||||
:name="getLabelEmailBox(mail.from) + ' : ' + mail.subject"
|
||||
:bold="false"
|
||||
counterType="outlined">
|
||||
<template #subname>
|
||||
{{ getSubstringText(mail.previewText ,50) }}
|
||||
</template>
|
||||
<template v-if="hasAttachements(mail)" #icon>
|
||||
<Paperclip :size="20" />
|
||||
</template>
|
||||
</NcListItem>
|
||||
</ul>
|
||||
</template>
|
||||
</div>
|
||||
<div class="modal__content__attachments" v-if="showAttachmentsSection">
|
||||
<ul class="attachments-list">
|
||||
<NcActionButton @click="displayAttachmentsSection()">
|
||||
<template #icon>
|
||||
<ArrowLeft :size="20" />
|
||||
</template>
|
||||
Revenir dans la listes des emails
|
||||
</NcActionButton>
|
||||
<div v-if="selectedMail" >
|
||||
<div class="mailHeader">
|
||||
{{ getLabelEmailBox(selectedMail.from) + ' : ' + selectedMail.subject }}
|
||||
</div>
|
||||
<div class="mailContent" v-if="selectedMail.body">
|
||||
<div v-html="selectedMail.body "></div>
|
||||
</div>
|
||||
<div class="mailContent" v-else>
|
||||
<div v-html="selectedMail.previewText "></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mailHeader">
|
||||
Pièces jointes :
|
||||
</div>
|
||||
<div class="image-list-attachement " v-if="!loadingDataEmailBox && mailAttachmentData.length > 0" v-for="attachment in mailAttachmentData">
|
||||
<div v-if="attachment.isImage" class="image-item-attachement " @click="selectAttachement(attachment.id)">
|
||||
<img :src="attachment.downloadUrl" :alt="attachment.fileName ">
|
||||
<label>{{ attachment.fileName }} <span v-if="isInSelectedAttachment(attachment.id)"> ✔</span> </label>
|
||||
</div>
|
||||
<div v-else-if="! attachment.isImage && !attachment.isCalendarEvent" class="image-item-attachement " @click="selectAttachement(attachment.id)">
|
||||
<label>{{ attachment.fileName }}
|
||||
<span v-if="isInSelectedAttachment(attachment.id)"> ✔</span>
|
||||
</label>
|
||||
</div>
|
||||
<div v-else-if="attachment.isCalendarEvent" class="image-item-attachement " >
|
||||
<label>{{ attachment.fileName }} ( Non allouée)</label>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!mailAttachmentData.length && !loadingDataEmailBox" >
|
||||
<p> Pas d'attachements</p>
|
||||
</template>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="modal__content" v-if="selectedAttachements.length && !loadingDataEmailBox" >
|
||||
<NcButton style="text-align: center;" @click="pickEmailAttachement()" >
|
||||
Ajouter ({{ selectedAttachements.length }})
|
||||
</NcButton>
|
||||
</div>
|
||||
<div class="modal__content" v-if="loadingDataEmailBox" >
|
||||
<div >
|
||||
<NcLoadingIcon :size="40" appearance="light" :name="loadingText" />
|
||||
</div>
|
||||
<p style="text-align: center;"> {{ loadingText }}</p>
|
||||
</div>
|
||||
</NcModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -74,13 +163,23 @@ import {
|
||||
NcActions,
|
||||
NcActionButton,
|
||||
NcDialog,
|
||||
NcModal,
|
||||
NcButton,
|
||||
NcAvatar,
|
||||
NcLoadingIcon,
|
||||
NcCheckboxRadioSwitch
|
||||
} from '@nextcloud/vue'
|
||||
|
||||
import axios from "@nextcloud/axios";
|
||||
|
||||
import Upload from 'vue-material-design-icons/Upload.vue'
|
||||
import Close from 'vue-material-design-icons/Close.vue'
|
||||
import Folder from 'vue-material-design-icons/Folder.vue'
|
||||
import Paperclip from 'vue-material-design-icons/Paperclip.vue'
|
||||
import Plus from 'vue-material-design-icons/Plus.vue'
|
||||
import Email from 'vue-material-design-icons/Email.vue'
|
||||
import ArrowLeft from 'vue-material-design-icons/ArrowLeft.vue'
|
||||
import Reload from 'vue-material-design-icons/Reload.vue'
|
||||
|
||||
import { generateUrl, getBaseUrl } from '@nextcloud/router'
|
||||
import { getFilePickerBuilder, showError } from '@nextcloud/dialogs'
|
||||
@ -88,8 +187,10 @@ import logger from '../../../utils/logger.js'
|
||||
import {
|
||||
uploadLocalAttachment,
|
||||
getFileInfo,
|
||||
uploadRemoteFile
|
||||
} from '../../../services/attachmentService.js'
|
||||
import { parseXML } from 'webdav'
|
||||
import { size } from 'lodash';
|
||||
|
||||
export default {
|
||||
name: 'AttachmentsList',
|
||||
@ -103,6 +204,14 @@ export default {
|
||||
Paperclip,
|
||||
Plus,
|
||||
NcDialog,
|
||||
NcModal,
|
||||
NcButton,
|
||||
Email,
|
||||
ArrowLeft,
|
||||
Reload,
|
||||
NcAvatar,
|
||||
NcLoadingIcon,
|
||||
NcCheckboxRadioSwitch
|
||||
},
|
||||
props: {
|
||||
calendarObjectInstance: {
|
||||
@ -120,6 +229,14 @@ export default {
|
||||
showOpenConfirmation: false,
|
||||
openConfirmationMessage: '',
|
||||
openConfirmationButtons: [],
|
||||
showModal: false,
|
||||
showAttachmentsSection: false,
|
||||
loadingDataEmailBox: false,
|
||||
mailBoxData: [],
|
||||
mailAttachmentData: [],
|
||||
selectedAttachements: [],
|
||||
loadingText: 'Chargement ...',
|
||||
selectedMail: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -142,6 +259,13 @@ export default {
|
||||
calendarObjectInstance: this.calendarObjectInstance,
|
||||
attachment,
|
||||
})
|
||||
if (this.selectedAttachements.length = 0) {
|
||||
const emailId = null;
|
||||
this.$store.commit('addEmailId', {
|
||||
calendarObjectInstance: this.calendarObjectInstance,
|
||||
emailId,
|
||||
})
|
||||
}
|
||||
},
|
||||
async openFilesModal() {
|
||||
const picker = getFilePickerBuilder(t('calendar', 'Choose a file to add as attachment'))
|
||||
@ -255,6 +379,148 @@ export default {
|
||||
]
|
||||
this.showOpenConfirmation = true
|
||||
},
|
||||
async syncEmailBox(){
|
||||
this.loadingText = 'Synchronisation encours ...'
|
||||
this.loadingDataEmailBox = true
|
||||
this.mailBoxData = [];
|
||||
await this.loadEmailsBox(true)
|
||||
this.loadingDataEmailBox = false
|
||||
},
|
||||
async openEmailBoxModal(){
|
||||
this.loadingText = 'Chargement des emails ...'
|
||||
this.showModal = true
|
||||
this.loadingDataEmailBox = true
|
||||
await this.loadEmailsBox()
|
||||
this.loadingDataEmailBox = false
|
||||
},
|
||||
async getAttachments(mail){
|
||||
this.loadingText = 'Récupération des piecs jointes ...'
|
||||
this.loadingDataEmailBox = true
|
||||
this.showAttachmentsSection = true
|
||||
this.selectedMail = mail
|
||||
this.mailAttachmentData = [] ;
|
||||
await this.loadAttachments(mail)
|
||||
this.loadingDataEmailBox = false
|
||||
},
|
||||
async addEmailToVcalendar(mail){
|
||||
const emailId = mail.databaseId ?? null;
|
||||
this.$store.commit('addEmailId', {
|
||||
calendarObjectInstance: this.calendarObjectInstance,
|
||||
emailId,
|
||||
})
|
||||
},
|
||||
|
||||
selectAttachement(attachementId){
|
||||
if(this.isInSelectedAttachment(attachementId)){
|
||||
console.log("remove")
|
||||
this.selectedAttachements = this.selectedAttachements.filter(id => id !== attachementId)
|
||||
}else{
|
||||
console.log("add")
|
||||
this.selectedAttachements.push(attachementId)
|
||||
}
|
||||
|
||||
},
|
||||
isInSelectedAttachment(attachementId){
|
||||
return this.selectedAttachements.find(id => id === attachementId)
|
||||
},
|
||||
async pickEmailAttachement(){
|
||||
this.loadingText = 'Ajout de l\'attachement encours ...'
|
||||
this.loadingDataEmailBox = true
|
||||
//upload only attachmen if id is in selectedAttachements
|
||||
const selectedAttachements = this.selectedAttachements.map(id => this.mailAttachmentData.find(attachement => attachement.id === id))
|
||||
await this.uploadAttachment(selectedAttachements)
|
||||
this.addEmailToVcalendar(this.selectedMail);
|
||||
|
||||
this.closeMailBoxModal()
|
||||
this.resetMailBoxModal()
|
||||
},
|
||||
async uploadAttachment(attachements = []){
|
||||
await Promise.all(attachements.map(async attachement => {
|
||||
await this.uploadEmailAttachementTodavFile(attachement)
|
||||
}))
|
||||
},
|
||||
resetMailBoxModal() {
|
||||
this.mailBoxData = []
|
||||
this.mailAttachmentData = []
|
||||
this.showModal = false
|
||||
this.showAttachmentsSection = false
|
||||
this.loadingDataEmailBox = false
|
||||
this.loadingText = 'Chargement ...'
|
||||
this.selectedAttachements = []
|
||||
},
|
||||
displayAttachmentsSection() {
|
||||
this.showAttachmentsSection = false
|
||||
this.loadingDataEmailBox = false
|
||||
},
|
||||
closeMailBoxModal() {
|
||||
this.showModal = false
|
||||
this.showAttachmentsSection = false
|
||||
this.loadingDataEmailBox = false
|
||||
this.loadingText = 'Chargement ...'
|
||||
},
|
||||
async loadEmailsBox(withSync = false) {
|
||||
const ajaxUrl = generateUrl('/apps/calendar/load-email-box')
|
||||
await axios.get(ajaxUrl , { params: { withSync } })
|
||||
.then(response => {
|
||||
console.log(response.data.success);
|
||||
if (!response.data.success && response.data.message == "MAILBOX_NOT_FOUND") {
|
||||
this.closeMailBoxModal();
|
||||
showError(t('calendar', 'Veuillez configurer le compte apps email pour pouvoir utiliser cette fonctionnalité.' , {
|
||||
timeout : 7000,
|
||||
}))
|
||||
return;
|
||||
}
|
||||
this.mailBoxData = response.data;
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
async loadAttachments(mail) {
|
||||
// if (!this.hasAttachements(mail)) {
|
||||
// this.mailAttachmentData = [] ;
|
||||
// this.loadingDataEmailBox = false
|
||||
// return;
|
||||
// }
|
||||
const ajaxUrl = generateUrl('/apps/calendar/load-email-attachement/' + mail.databaseId)
|
||||
|
||||
await axios.get(ajaxUrl)
|
||||
.then(response => {
|
||||
this.mailAttachmentData = response.data.attachments
|
||||
this.selectedMail["body"] = response.data.fullMessage.body
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
async uploadEmailAttachementTodavFile(attachement) {
|
||||
const attachmentsFolder = await this.$store.dispatch('createAttachmentsFolder')
|
||||
const attachment = await uploadRemoteFile(attachmentsFolder, attachement.downloadUrl, attachement.fileName ,this.currentUser.dav)
|
||||
// TODO do not share file, move to PHP
|
||||
const data = await getFileInfo(`${attachmentsFolder}/${attachment.path}`, this.currentUser.dav.userId)
|
||||
const davRes = await parseXML(data)
|
||||
const davRespObj = davRes?.multistatus?.response[0]?.propstat?.prop
|
||||
davRespObj.fileName = attachment.path
|
||||
davRespObj.url = generateUrl(`/f/${davRespObj.fileid}`)
|
||||
davRespObj.value = davRespObj.url
|
||||
this.addAttachmentWithProperty(this.calendarObjectInstance, davRespObj)
|
||||
},
|
||||
getLabelEmailBox(from = []) {
|
||||
if (from.length) {
|
||||
return from[0].label ?? from[0].email
|
||||
}
|
||||
return ''
|
||||
},
|
||||
getSubstringText(text = '' , length = 20) {
|
||||
if (text.length < length) {
|
||||
return text;
|
||||
}
|
||||
return text.substring(0, length) + '...'
|
||||
},
|
||||
hasAttachements(mail) {
|
||||
return mail.flags.hasAttachments;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -332,4 +598,57 @@ export default {
|
||||
.external-link-message {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.modal__content {
|
||||
margin: 10px;
|
||||
}
|
||||
.modal__content__attachments {
|
||||
margin: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.attachments-list{
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.image-list-attachement {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.image-item-attachement {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.image-item-attachement img {
|
||||
width: 100px; /* Largeur de l'image */
|
||||
height: auto; /* Hauteur automatique pour garder le ratio */
|
||||
margin-right: 10px; /* Espace entre l'image et la légende */
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 16px; /* Taille de police pour la légende */
|
||||
}
|
||||
|
||||
.mailHeader{
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mailContent{
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 10px;
|
||||
max-height: 400px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div v-if="!isReadOnly" class="property-title-time-picker">
|
||||
<div class="property-title-time-picker__all-day">
|
||||
<NcCheckboxRadioSwitch :checked="isPrivate"
|
||||
@update:checked="toggleIsPrivate">
|
||||
{{ $t('calendar', 'Privé') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ getIsPrivateLabel }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NcCheckboxRadioSwitch } from '@nextcloud/vue'
|
||||
export default {
|
||||
name: "PropertyIsPrivate",
|
||||
components: {
|
||||
NcCheckboxRadioSwitch,
|
||||
},
|
||||
props: {
|
||||
isPrivate: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
getIsPrivateLabel() {
|
||||
return this.isPrivate ? this.$t('calendar', 'Privé') : this.$t('calendar', 'Mettre en privé');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleIsPrivate() {
|
||||
const newState = !this.isPrivate;
|
||||
this.$emit('toggle-is-private',newState)
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.checkbox-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div class="property-select">
|
||||
<div class="property-select__input"
|
||||
:class="{ 'property-select__input--readonly': isReadOnly }">
|
||||
<NcSelect v-if="!isReadOnly"
|
||||
:options="options"
|
||||
:searchable="true"
|
||||
:multiple="false"
|
||||
:taggable="false"
|
||||
:name="readableName"
|
||||
:value="selectedValue"
|
||||
:placeholder="placeholder"
|
||||
:clearable="true"
|
||||
:labelOutside="true"
|
||||
input-id="value"
|
||||
label="label"
|
||||
@input="changeValue" />
|
||||
<div v-else>{{ selectedValue.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NcSelect } from '@nextcloud/vue';
|
||||
import PropertyMixin from '../../../mixins/PropertyMixin.js'
|
||||
export default {
|
||||
name: 'PropertySelectAbsenceType',
|
||||
components: {
|
||||
NcSelect,
|
||||
},
|
||||
props: {
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false, // Par défaut, on permet la modification
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
properties: [
|
||||
{ value: 'LEAVE', label: 'Congé' },
|
||||
{ value: 'REST', label: 'Repos' },
|
||||
{ value: 'DISEASE', label: 'Arrêt maladie' },
|
||||
],
|
||||
};
|
||||
},
|
||||
mixins: [
|
||||
PropertyMixin,
|
||||
],
|
||||
computed: {
|
||||
options() {
|
||||
return this.properties;
|
||||
},
|
||||
selectedValue() {
|
||||
const value = this.value
|
||||
return this.properties.find((option) => option.value == value)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changeValue(selectedOption) {
|
||||
this.$emit('update:value', selectedOption.value ?? null);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.property-select {
|
||||
&__input {
|
||||
width: calc(100% - 34px - 34px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -75,13 +75,13 @@
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-if="!isReadOnly" class="property-title-time-picker__all-day">
|
||||
<!-- <div v-if="!isReadOnly" class="property-title-time-picker__all-day">
|
||||
<NcCheckboxRadioSwitch :checked="isAllDay"
|
||||
:disabled="!canModifyAllDay"
|
||||
@update:checked="toggleAllDay">
|
||||
{{ $t('calendar', 'All day') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@ -41,7 +41,9 @@ import { getAllObjectsInTimeRange } from '../../utils/calendarObject.js'
|
||||
*/
|
||||
export function eventSourceFunction(calendarObjects, calendar, start, end, timezone) {
|
||||
const fcEvents = []
|
||||
const authUser = OC.currentUser;
|
||||
for (const calendarObject of calendarObjects) {
|
||||
|
||||
let allObjectsInTimeRange
|
||||
try {
|
||||
allObjectsInTimeRange = getAllObjectsInTimeRange(calendarObject, start, end)
|
||||
@ -52,7 +54,7 @@ export function eventSourceFunction(calendarObjects, calendar, start, end, timez
|
||||
|
||||
for (const object of allObjectsInTimeRange) {
|
||||
const classNames = []
|
||||
|
||||
|
||||
if (object.status === 'CANCELLED') {
|
||||
classNames.push('fc-event-nc-cancelled')
|
||||
} else if (object.status === 'TENTATIVE') {
|
||||
@ -100,6 +102,8 @@ export function eventSourceFunction(calendarObjects, calendar, start, end, timez
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
let title
|
||||
if (object.name === 'VEVENT') {
|
||||
if (object.title) {
|
||||
@ -119,6 +123,36 @@ export function eventSourceFunction(calendarObjects, calendar, start, end, timez
|
||||
}
|
||||
}
|
||||
|
||||
let isPrivateEvent = false;
|
||||
let objectProperties = object._properties.get('ISPRIVATE');
|
||||
if (objectProperties && objectProperties.length > 0) {
|
||||
isPrivateEvent = objectProperties[0]._value == "1" ? true : false;
|
||||
}
|
||||
|
||||
//Get owen object's user
|
||||
let owenUrl = calendarObject.dav._parent.owner
|
||||
let owenUser = owenUrl.replace('/remote.php/dav/principals/users/','').split('/')[0]
|
||||
if (!owenUser) {
|
||||
//Get from url shared calendar
|
||||
owenUrl = calendarObject.dav._parent.url
|
||||
owenUser = owenUrl.replace('/remote.php/dav/calendars/' + authUser + '/personal_shared_by_' ,'').split('/')[0]
|
||||
}
|
||||
|
||||
const isOwenOfEvent = owenUser == authUser
|
||||
|
||||
if (isPrivateEvent && !isOwenOfEvent ) {
|
||||
title = t('calendar', `Absent (${owenUser})`)
|
||||
}
|
||||
let absenceTypeIsLeave = false;
|
||||
let absenceTypeProperties = object._properties.get('ABSENCETYPE');
|
||||
if (absenceTypeProperties && absenceTypeProperties.length > 0) {
|
||||
const absenceTypeValue = absenceTypeProperties[0]._value
|
||||
if(absenceTypeValue == 'LEAVE'){
|
||||
absenceTypeIsLeave = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const fcEvent = {
|
||||
id: [calendarObject.id, object.id].join('###'),
|
||||
title,
|
||||
@ -143,9 +177,19 @@ export function eventSourceFunction(calendarObjects, calendar, start, end, timez
|
||||
davUrl: calendarObject.dav.url,
|
||||
location: object.location,
|
||||
description: object.description,
|
||||
isPrivate: isPrivateEvent,
|
||||
calendarObjectOwen : owenUser ,
|
||||
calendarObjectIsOwen : isOwenOfEvent,
|
||||
absenceTypeIsLeave : absenceTypeIsLeave
|
||||
},
|
||||
}
|
||||
|
||||
if(absenceTypeIsLeave){
|
||||
fcEvent.backgroundColor = calendar.color
|
||||
fcEvent.borderColor = calendar.color
|
||||
fcEvent.textColor = generateTextColorForHex(calendar.color)
|
||||
}
|
||||
|
||||
if (object.color) {
|
||||
const customColor = getHexForColorName(object.color)
|
||||
if (customColor) {
|
||||
@ -155,6 +199,8 @@ export function eventSourceFunction(calendarObjects, calendar, start, end, timez
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fcEvents.push(fcEvent)
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +69,10 @@ export default function(store, router, route, window, isWidget = false, ref = un
|
||||
* @param {boolean} isWidget Whether the calendar is embedded in a widget
|
||||
*/
|
||||
function handleEventClick(event, store, router, route, window, isWidget = false) {
|
||||
|
||||
if(event.extendedProps.isPrivate && !event.extendedProps.calendarObjectIsOwen ){
|
||||
return;
|
||||
}
|
||||
if (isWidget) {
|
||||
store.commit('setSelectedEvent', { object: event.extendedProps.objectId, recurrenceId: event.extendedProps.recurrenceId })
|
||||
return
|
||||
|
||||
@ -118,6 +118,33 @@ export default {
|
||||
return this.calendarObjectInstance?.embalmer ?? null
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the comment or null if the event is still loading
|
||||
*
|
||||
* @return {string|null}
|
||||
*/
|
||||
comment() {
|
||||
return this.calendarObjectInstance?.comment ?? null
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns the isPrivate property
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
isPrivate() {
|
||||
return this.calendarObjectInstance?.isPrivate ?? false
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the emailId property
|
||||
*
|
||||
* @return {string|null}
|
||||
*/
|
||||
emailId() {
|
||||
return this.calendarObjectInstance?.emailId ?? null
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the description or null if the event is still loading
|
||||
@ -342,7 +369,7 @@ export default {
|
||||
* Returns an object with properties from RFCs including
|
||||
* their displayName, a description, options, etc.
|
||||
*
|
||||
* @return {{geo, color, timeTransparency, description, resources, location, client, categories, accessClass, priority, status, locations, articles, clients,embalmer,embalmers}}
|
||||
* @return {{absenceType, comment, geo, color, timeTransparency, description, resources, location, client, categories, accessClass, priority, status, locations, articles, clients,embalmer,embalmers}}
|
||||
*/
|
||||
rfcProps() {
|
||||
return getRFCProperties()
|
||||
@ -394,6 +421,15 @@ export default {
|
||||
|
||||
return false
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the absence type
|
||||
*
|
||||
* @return {string|null}
|
||||
*/
|
||||
absenceType() {
|
||||
return this.calendarObjectInstance?.absenceType ?? ''
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
@ -614,6 +650,18 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the comments of this event
|
||||
*
|
||||
* @param {string} comment New comments
|
||||
*/
|
||||
updateComment(comment) {
|
||||
this.$store.commit('changeComment', {
|
||||
calendarObjectInstance: this.calendarObjectInstance,
|
||||
comment,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the client of the event
|
||||
*
|
||||
@ -698,6 +746,25 @@ export default {
|
||||
calendarObjectInstance: this.calendarObjectInstance,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the event to private
|
||||
*/
|
||||
toggleIsPrivate(isPrivate) {
|
||||
this.$store.commit('toggleIsPrivate', {
|
||||
calendarObjectInstance: this.calendarObjectInstance,
|
||||
isPrivate
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Toggles the event to private
|
||||
*/
|
||||
addEmailId(emailId) {
|
||||
this.$store.commit('addEmailId', {
|
||||
calendarObjectInstance: this.calendarObjectInstance,
|
||||
emailId
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Resets the internal state after changing the viewed calendar-object
|
||||
*/
|
||||
@ -730,6 +797,19 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the absence type of this event
|
||||
*
|
||||
* @param {string} absenceType New absence type
|
||||
*/
|
||||
updateAbsenceType(absenceType) {
|
||||
this.$store.commit('changeAbsenceType', {
|
||||
calendarObjectInstance: this.calendarObjectInstance,
|
||||
absenceType,
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* This is executed before entering the Editor routes
|
||||
|
||||
@ -60,6 +60,12 @@ const getDefaultEventObject = (props = {}) => Object.assign({}, {
|
||||
client : null,
|
||||
//embalmer(Thanato) of the event
|
||||
embalmer : null,
|
||||
//absenceType
|
||||
absenceType : null,
|
||||
//Private
|
||||
isPrivate: false,
|
||||
//comment of the event
|
||||
comment : null,
|
||||
// description of the event
|
||||
description: null,
|
||||
// Access class of the event (PUBLIC, PRIVATE, CONFIDENTIAL)
|
||||
@ -90,6 +96,8 @@ const getDefaultEventObject = (props = {}) => Object.assign({}, {
|
||||
customColor: null,
|
||||
// Categories
|
||||
categories: [],
|
||||
// The event's UID
|
||||
emailId: null,
|
||||
// Attachments of this event
|
||||
attachments: [],
|
||||
}, props)
|
||||
@ -104,10 +112,14 @@ const mapEventComponentToEventObject = (eventComponent) => {
|
||||
eventComponent,
|
||||
title: eventComponent.title,
|
||||
isAllDay: eventComponent.isAllDay(),
|
||||
isPrivate: false,
|
||||
canModifyAllDay: eventComponent.canModifyAllDay(),
|
||||
location: eventComponent.location,
|
||||
client : "CLIENT",
|
||||
embalmer : "TEST",
|
||||
comment : "",
|
||||
absenceType : "",
|
||||
emailId: null,
|
||||
description: eventComponent.description,
|
||||
accessClass: eventComponent.accessClass,
|
||||
status: eventComponent.status,
|
||||
@ -197,10 +209,26 @@ const mapEventComponentToEventObject = (eventComponent) => {
|
||||
eventObject.client = eventComponent.getFirstPropertyFirstValue('CLIENT');
|
||||
}
|
||||
|
||||
if(eventComponent.hasProperty('ISPRIVATE')){
|
||||
eventObject.isPrivate = eventComponent.getFirstPropertyFirstValue('ISPRIVATE') === '1' ? true : false;
|
||||
}
|
||||
|
||||
if(eventComponent.hasProperty('EMBALMER')){
|
||||
eventObject.embalmer = eventComponent.getFirstPropertyFirstValue('EMBALMER');
|
||||
}
|
||||
|
||||
if(eventComponent.hasProperty('COMMENT')){
|
||||
eventObject.comment = eventComponent.getFirstPropertyFirstValue('COMMENT');
|
||||
}
|
||||
|
||||
if(eventComponent.hasProperty('ABSENCETYPE')){
|
||||
eventObject.absenceType = eventComponent.getFirstPropertyFirstValue('ABSENCETYPE');
|
||||
}
|
||||
|
||||
if(eventComponent.hasProperty('EMAILID')){
|
||||
eventObject.emailId = eventComponent.getFirstPropertyFirstValue('EMAILID');
|
||||
}
|
||||
|
||||
return eventObject;
|
||||
}
|
||||
|
||||
@ -215,6 +243,9 @@ const copyCalendarObjectInstanceIntoEventComponent = (eventObject, eventComponen
|
||||
eventComponent.location = eventObject.location
|
||||
eventComponent.client = eventObject.client
|
||||
eventComponent.embalmer = eventObject.embalmer
|
||||
eventComponent.isPrivate = eventObject.isPrivate
|
||||
eventComponent.comment = eventObject.comment
|
||||
eventComponent.emailId = eventObject.emailId
|
||||
eventComponent.description = eventObject.description
|
||||
eventComponent.accessClass = eventObject.accessClass
|
||||
eventComponent.status = eventObject.status
|
||||
|
||||
@ -141,6 +141,10 @@ const getRFCProperties = () => {
|
||||
placeholder: t('calendar', 'Choisir un client'),
|
||||
icon: 'Human',
|
||||
},
|
||||
absenceType: {
|
||||
readableName: t('calendar', 'Type d\'absence'),
|
||||
placeholder: t('calendar', 'Type d\'absence'),
|
||||
},
|
||||
|
||||
embalmers: {
|
||||
readableName: t('calendar', 'Embalmers'),
|
||||
@ -169,6 +173,15 @@ const getRFCProperties = () => {
|
||||
tagPlaceholder: t('calendar', 'Choisir les soins'),
|
||||
options: [],
|
||||
},
|
||||
comment: {
|
||||
readableName: t('calendar', 'Comment'),
|
||||
icon: 'TextBoxOutline',
|
||||
info: t('calendar', 'Commentaires.'),
|
||||
placeholder: t('calendar', 'Commentaires'),
|
||||
tagPlaceholder: t('calendar', 'Commentaires'),
|
||||
options: [],
|
||||
defaultNumberOfRows: 4
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -167,7 +167,34 @@ const uploadLocalAttachment = async function(folder, files, dav, componentAttach
|
||||
return attachments
|
||||
|
||||
}
|
||||
const uploadRemoteFile = async function(folder , fileUrl, fileName , dav) {
|
||||
try {
|
||||
// Télécharger le fichier distant
|
||||
const response = await axios.get(fileUrl, { responseType: 'blob' });
|
||||
|
||||
// Envoyer le fichier récupéré en PUT vers WebDAV
|
||||
const url = generateRemoteUrl(`dav/files/${dav.userId}/${folder}/${fileName}`)
|
||||
const uploadResponse = await axios.put(url, response.data, {
|
||||
headers: {
|
||||
'Content-Type': response.data.type, // Utilise le type MIME du fichier
|
||||
},
|
||||
});
|
||||
|
||||
if (uploadResponse.status === 204 || uploadResponse.status === 201) {
|
||||
showSuccess(t('calendar', 'Attachment {fileName} added!', { fileName: fileName }));
|
||||
return {
|
||||
fileName: fileName,
|
||||
formatType: response.data.type,
|
||||
uri: url,
|
||||
value: url,
|
||||
path: `/${fileName}`,
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
showError(t('calendar', 'An error occurred during uploading file {fileName}', { fileName: fileName }));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// TODO is shared or not @share-types@
|
||||
const getFileInfo = async function(path, userId) {
|
||||
const url = generateRemoteUrl(`dav/files/${userId}/${path}`)
|
||||
@ -200,4 +227,5 @@ export {
|
||||
shareFileWith,
|
||||
uploadLocalAttachment,
|
||||
createFolder,
|
||||
uploadRemoteFile
|
||||
}
|
||||
|
||||
19
calendar/src/services/roleService.js
Normal file
19
calendar/src/services/roleService.js
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
import axios from "@nextcloud/axios";
|
||||
import {generateUrl} from "@nextcloud/router";
|
||||
export default {
|
||||
async fetchAndCommitRoles(commit) {
|
||||
try {
|
||||
var url = '/apps/gestion/getUserConnectedGroups';
|
||||
const ajaxUrl = generateUrl(url)
|
||||
axios.get(ajaxUrl)
|
||||
.then((response) => {
|
||||
let roles = JSON.parse(response.data)
|
||||
commit("setUserRole", roles);
|
||||
})
|
||||
.catch(error => {
|
||||
});
|
||||
} catch (error) {
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -286,6 +286,31 @@ const mutations = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Is private
|
||||
*
|
||||
* @param {object} state The Vuex state
|
||||
* @param {object} data The destructuring object
|
||||
* @param {object} data.calendarObjectInstance The calendarObjectInstance object
|
||||
*/
|
||||
toggleIsPrivate(state, { calendarObjectInstance, isPrivate }) {
|
||||
calendarObjectInstance.eventComponent.isPrivate = isPrivate
|
||||
calendarObjectInstance.isPrivate = isPrivate
|
||||
},
|
||||
|
||||
/**
|
||||
*Email id
|
||||
*
|
||||
* @param {object} state The Vuex state
|
||||
* @param {object} data The destructuring object
|
||||
* @param {object} data.calendarObjectInstance The calendarObjectInstance object
|
||||
*/
|
||||
addEmailId(state, { calendarObjectInstance, emailId }) {
|
||||
calendarObjectInstance.eventComponent.emailId = emailId
|
||||
calendarObjectInstance.emailId = emailId
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Changes the time of a timed event to the default values
|
||||
*
|
||||
@ -321,6 +346,19 @@ const mutations = {
|
||||
calendarObjectInstance.location = location
|
||||
},
|
||||
|
||||
/**
|
||||
* Change the comment of an event
|
||||
*
|
||||
* @param {object} state The Vuex state
|
||||
* @param {object} data The destructuring object
|
||||
* @param {object} data.calendarObjectInstance The calendarObjectInstance object
|
||||
* @param {string} data.comment New comment to set
|
||||
*/
|
||||
changeComment(state, { calendarObjectInstance, comment }) {
|
||||
calendarObjectInstance.eventComponent.comment = comment
|
||||
calendarObjectInstance.comment = comment
|
||||
},
|
||||
|
||||
/**
|
||||
* Change the client of an event
|
||||
*
|
||||
@ -349,6 +387,44 @@ const mutations = {
|
||||
calendarObjectInstance.embalmer = embalmer
|
||||
},
|
||||
|
||||
/**
|
||||
* Change the absence type of an event
|
||||
*
|
||||
* @param {object} state The Vuex state
|
||||
* @param {object} data The destructuring object
|
||||
* @param {object} data.calendarObjectInstance The calendarObjectInstance object
|
||||
* @param {string} data.embalmer New embalmer to set
|
||||
*/
|
||||
|
||||
changeAbsenceType(state, { calendarObjectInstance, absenceType }) {
|
||||
calendarObjectInstance.eventComponent.absenceType = absenceType ?? null
|
||||
calendarObjectInstance.absenceType = absenceType ?? null
|
||||
if(absenceType){
|
||||
const types = [
|
||||
{ value: 'LEAVE', label: 'Congé' },
|
||||
{ value: 'REST', label: 'Repos' },
|
||||
{ value: 'DISEASE', label: 'Arrêt maladie' },
|
||||
];
|
||||
|
||||
types.forEach((element) => {
|
||||
if(element.value == absenceType){
|
||||
calendarObjectInstance.title = element.label
|
||||
calendarObjectInstance.eventComponent.title = element.label
|
||||
|
||||
if(absenceType == 'LEAVE'){
|
||||
const startDate = calendarObjectInstance.eventComponent.startDate
|
||||
const endDate = calendarObjectInstance.eventComponent.endDate
|
||||
|
||||
startDate.hour = 8 ; endDate.hour = 17
|
||||
|
||||
calendarObjectInstance.startDate = getDateFromDateTimeValue(startDate)
|
||||
calendarObjectInstance.endDate = getDateFromDateTimeValue(endDate)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Change the description of an event
|
||||
*
|
||||
@ -1498,6 +1574,11 @@ const mutations = {
|
||||
}
|
||||
|
||||
},
|
||||
setAbsenceType(state, { calendarObjectInstance, absenceType }) {
|
||||
if (calendarObjectInstance) {
|
||||
calendarObjectInstance.absenceType = absenceType;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const getters = {}
|
||||
@ -1688,7 +1769,11 @@ const actions = {
|
||||
updateAlarms(eventComponent)
|
||||
updateTalkParticipants(eventComponent)
|
||||
let additionalFieldWasUpdated =
|
||||
eventComponent.client != null;
|
||||
eventComponent.client != null ||
|
||||
eventComponent.isPrivate != null ||
|
||||
eventComponent.absenceType ||
|
||||
eventComponent.emailId ||
|
||||
eventComponent.comment != null ;
|
||||
if (eventComponent.isDirty() || additionalFieldWasUpdated) {
|
||||
const isForkedItem = eventComponent.primaryItem !== null
|
||||
let original = null
|
||||
@ -2108,6 +2193,13 @@ const actions = {
|
||||
commit('changeTimeToDefaultForTimedEvents', { calendarObjectInstance })
|
||||
}
|
||||
},
|
||||
// async changeAbsenceType({ commit }, { calendarObjectInstance, absenceType }) {
|
||||
// try {
|
||||
// commit('setAbsenceType', { calendarObjectInstance, absenceType });
|
||||
// } catch (error) {
|
||||
// console.error('Erreur lors de la mise à jour du type d\'absence:', error);
|
||||
// }
|
||||
// },
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -230,8 +230,78 @@ const actions = {
|
||||
if(eventComponent != null){
|
||||
if(eventComponent.client != null){
|
||||
let newClientKeyValue = "CLIENT:"+eventComponent.client;
|
||||
icsValue = icsValue.replace(/CLIENT:\d+/, newClientKeyValue);
|
||||
let regexEmptyClient = /CLIENT:(?!\d)(?=\s*[\r\n])/g;
|
||||
if (regexEmptyClient.test(icsValue)) {
|
||||
icsValue = icsValue.replace(regexEmptyClient, newClientKeyValue);
|
||||
}
|
||||
let regex = /CLIENT:\d+/;
|
||||
if(regex.test(icsValue)){
|
||||
icsValue = icsValue.replace(regex, newClientKeyValue);
|
||||
}
|
||||
else{
|
||||
const customKeyValue = {
|
||||
"CLIENT": eventComponent.client
|
||||
};
|
||||
icsValue = setCustomKeyValuesArrayToIcsAndReturnIcs(icsValue,customKeyValue);
|
||||
}
|
||||
}
|
||||
if(eventComponent.comment != null){
|
||||
let newCommentKeyValue = "COMMENT:"+eventComponent.comment;
|
||||
let regex = /^COMMENT:.*$/m;
|
||||
if(regex.test(icsValue)){
|
||||
icsValue = icsValue.replace(regex, newCommentKeyValue);
|
||||
}
|
||||
else{
|
||||
const customKeyValue = {
|
||||
"COMMENT": eventComponent.comment
|
||||
};
|
||||
icsValue = setCustomKeyValuesArrayToIcsAndReturnIcs(icsValue,customKeyValue);
|
||||
}
|
||||
}
|
||||
|
||||
if(eventComponent.isPrivate != null){
|
||||
let isPrivateValue = eventComponent.isPrivate ? "1" : "0";
|
||||
let newIsPrivateKeyValue = "ISPRIVATE:"+isPrivateValue;
|
||||
let regex = /ISPRIVATE:\d+/;
|
||||
if(regex.test(icsValue)){
|
||||
icsValue = icsValue.replace(regex, newIsPrivateKeyValue);
|
||||
}
|
||||
else{
|
||||
const customKeyValue = {
|
||||
"ISPRIVATE": isPrivateValue
|
||||
};
|
||||
icsValue = setCustomKeyValuesArrayToIcsAndReturnIcs(icsValue,customKeyValue);
|
||||
}
|
||||
}
|
||||
if(eventComponent.emailId != null){
|
||||
let emailIdValue = eventComponent.emailId ;
|
||||
let emailIdValueValue = "EMAILID:"+emailIdValue;
|
||||
let regex = /EMAILID:\d+/;
|
||||
if(regex.test(icsValue)){
|
||||
icsValue = icsValue.replace(regex, emailIdValueValue);
|
||||
}
|
||||
else{
|
||||
const customKeyValue = {
|
||||
"EMAILID": emailIdValue
|
||||
};
|
||||
icsValue = setCustomKeyValuesArrayToIcsAndReturnIcs(icsValue,customKeyValue);
|
||||
}
|
||||
}
|
||||
if(eventComponent.absenceType != null && eventComponent.absenceType != ''){
|
||||
let absenceTypeValue = eventComponent.absenceType;
|
||||
let key = "ABSENCETYPE:"+absenceTypeValue;
|
||||
let regex = /^ABSENCETYPE:.*$/m;
|
||||
if(regex.test(icsValue)){
|
||||
icsValue = icsValue.replace(regex, key);
|
||||
}
|
||||
else{
|
||||
const customKeyValue = {
|
||||
"ABSENCETYPE": absenceTypeValue
|
||||
};
|
||||
icsValue = setCustomKeyValuesArrayToIcsAndReturnIcs(icsValue,customKeyValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
calendarObject.dav.data = icsValue;
|
||||
await calendarObject.dav.update()
|
||||
@ -247,7 +317,15 @@ const actions = {
|
||||
const calendar = context.getters.getCalendarById(calendarObject.calendarId)
|
||||
let icsValue = calendarObject.calendarComponent.toICS();
|
||||
if(eventComponent != null){
|
||||
const customKeyValue = {"CLIENT": eventComponent.client, "EMBALMER": eventComponent.embalmer};
|
||||
const customKeyValue = {
|
||||
"CLIENT": eventComponent.client,
|
||||
"EMBALMER": eventComponent.embalmer ,
|
||||
"ISPRIVATE": eventComponent.isPrivate ? "1" : "0",
|
||||
"COMMENT": eventComponent.comment,
|
||||
"EMAILID": eventComponent.emailId,
|
||||
"ABSENCETYPE": eventComponent.absenceType ?? ''
|
||||
|
||||
};
|
||||
icsValue = setCustomKeyValuesArrayToIcsAndReturnIcs(icsValue,customKeyValue);
|
||||
}
|
||||
calendarObject.dav = await calendar.dav.createVObject(icsValue);
|
||||
|
||||
@ -36,7 +36,7 @@ import importFiles from './importFiles.js'
|
||||
import importState from './importState.js'
|
||||
import principals from './principals.js'
|
||||
import settings from './settings.js'
|
||||
|
||||
import userRole from './userRole.js'
|
||||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
@ -51,6 +51,7 @@ export default new Vuex.Store({
|
||||
importState,
|
||||
principals,
|
||||
settings,
|
||||
userRole
|
||||
},
|
||||
// // Throw errors when the state is edited outside of mutations
|
||||
// strict: true
|
||||
|
||||
34
calendar/src/store/userRole.js
Normal file
34
calendar/src/store/userRole.js
Normal file
@ -0,0 +1,34 @@
|
||||
import roleService from "../services/roleService";
|
||||
const state = {
|
||||
roles: [], // Store the roles here
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
setUserRole(state, roles) {
|
||||
state.roles = roles;
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
async fetchUserRoles({ commit }) {
|
||||
try {
|
||||
// Pass commit to the service
|
||||
await roleService.fetchAndCommitRoles(commit);
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const getters = {
|
||||
isAdmin: (state) => state.roles.includes("admin"),
|
||||
canAccessPreviousEvent: (state) => (state.roles.includes("Ligne") == false) && (state.roles.includes("ligne") == false),
|
||||
};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
getters,
|
||||
};
|
||||
@ -22,12 +22,11 @@
|
||||
|
||||
<template>
|
||||
<div v-if="isWidget" class="calendar-Widget calendar-Widget-Custom">
|
||||
<EmbedTopNavigation v-if="!showEmptyCalendarScreen" :is-widget="true" />
|
||||
<EmbedTopNavigation v-if="!showEmptyCalendarScreen" :is-widget="true"
|
||||
:can-access-previous-event="canAccessPreviousEvent" />
|
||||
|
||||
<CalendarGrid v-if="!showEmptyCalendarScreen"
|
||||
ref="calendarGridWidget"
|
||||
:is-widget="isWidget"
|
||||
:is-authenticated-user="isAuthenticatedUser" />
|
||||
<CalendarGrid v-if="!showEmptyCalendarScreen" ref="calendarGridWidget" :is-widget="isWidget"
|
||||
:can-access-previous-event="canAccessPreviousEvent" :is-authenticated-user="isAuthenticatedUser" />
|
||||
<EmptyCalendar v-else />
|
||||
|
||||
<EditSimple v-if="showWidgetEventDetails" :is-widget="true" :locations="locations" />
|
||||
@ -36,17 +35,16 @@
|
||||
</div>
|
||||
|
||||
<NcContent v-else app-name="calendar calendar-custom" :class="classNames">
|
||||
<AppNavigation v-if="!isWidget &&!isEmbedded && !showEmptyCalendarScreen">
|
||||
<AppNavigation v-if="!isWidget && !isEmbedded && !showEmptyCalendarScreen">
|
||||
<!-- Date Picker, View Buttons, Today Button -->
|
||||
<AppNavigationHeader :is-public="!isAuthenticatedUser" />
|
||||
<AppNavigationHeader :is-public="!isAuthenticatedUser"
|
||||
:can-access-previous-event="canAccessPreviousEvent" />
|
||||
<template #list>
|
||||
<AppNavigationSpacer />
|
||||
|
||||
<!-- Calendar / Subscription List -->
|
||||
<CalendarList :is-public="!isAuthenticatedUser"
|
||||
:loading-calendars="loadingCalendars" />
|
||||
<CalendarListNew v-if="!loadingCalendars && isAuthenticatedUser"
|
||||
:disabled="loadingCalendars" />
|
||||
<CalendarList :is-public="!isAuthenticatedUser" :loading-calendars="loadingCalendars" />
|
||||
<CalendarListNew v-if="!loadingCalendars && isAuthenticatedUser" :disabled="loadingCalendars" />
|
||||
<EditCalendarModal />
|
||||
|
||||
<!-- Appointment Configuration List -->
|
||||
@ -60,13 +58,12 @@
|
||||
</template>
|
||||
<!-- Settings and import -->
|
||||
<template #footer>
|
||||
<Settings v-if="isAuthenticatedUser"
|
||||
:loading-calendars="loadingCalendars" />
|
||||
<Settings v-if="isAuthenticatedUser" :loading-calendars="loadingCalendars" />
|
||||
</template>
|
||||
</AppNavigation>
|
||||
<EmbedTopNavigation v-if="isEmbedded" />
|
||||
<EmbedTopNavigation v-if="isEmbedded" :is-admin="false" />
|
||||
<AppContent>
|
||||
<CalendarGrid v-if="!showEmptyCalendarScreen"
|
||||
<CalendarGrid v-if="!showEmptyCalendarScreen" :can-access-previous-event="canAccessPreviousEvent"
|
||||
:is-authenticated-user="isAuthenticatedUser" />
|
||||
<EmptyCalendar v-else />
|
||||
</AppContent>
|
||||
@ -92,7 +89,6 @@ import EmptyCalendar from '../components/EmptyCalendar.vue'
|
||||
import CalendarGrid from '../components/CalendarGrid.vue'
|
||||
import EditCalendarModal from '../components/AppNavigation/EditCalendarModal.vue'
|
||||
import EditSimple from './EditSimple.vue'
|
||||
import axios from "@nextcloud/axios";
|
||||
|
||||
// Import CalDAV related methods
|
||||
import {
|
||||
@ -122,8 +118,8 @@ import {
|
||||
import '@nextcloud/dialogs/dist/index.css'
|
||||
import Trashbin from '../components/AppNavigation/CalendarList/Trashbin.vue'
|
||||
import AppointmentConfigList from '../components/AppNavigation/AppointmentConfigList.vue'
|
||||
import axios from "@nextcloud/axios";
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
|
||||
export default {
|
||||
name: 'Calendar',
|
||||
components: {
|
||||
@ -165,8 +161,8 @@ export default {
|
||||
timezoneId: 'getResolvedTimezone',
|
||||
hasTrashBin: 'hasTrashBin',
|
||||
currentUserPrincipal: 'getCurrentUserPrincipal',
|
||||
},
|
||||
),
|
||||
canAccessPreviousEvent: 'userRole/canAccessPreviousEvent'
|
||||
}),
|
||||
...mapState({
|
||||
eventLimit: state => state.settings.eventLimit,
|
||||
skipPopover: state => state.settings.skipPopover,
|
||||
@ -179,6 +175,7 @@ export default {
|
||||
modificationCount: state => state.calendarObjects.modificationCount,
|
||||
disableAppointments: state => state.settings.disableAppointments,
|
||||
attachmentsFolder: state => state.settings.attachmentsFolder,
|
||||
roles: state => state.userRole.roles
|
||||
}),
|
||||
defaultDate() {
|
||||
return getYYYYMMDDFromFirstdayParam(this.$route?.params?.firstDay ?? 'now')
|
||||
@ -326,7 +323,7 @@ export default {
|
||||
|
||||
toastElement.classList.add('toast-calendar-multiline')
|
||||
}
|
||||
|
||||
await this.$store.dispatch("userRole/fetchUserRoles");
|
||||
await this.loadMomentLocale()
|
||||
},
|
||||
methods: {
|
||||
@ -345,7 +342,7 @@ export default {
|
||||
const calendarOwner = calendar.owner;
|
||||
const userPrincipalId = calendarOwner.split('/').filter(Boolean).pop();
|
||||
const userType = await this.fetchUserTypeForCalendar(userPrincipalId);
|
||||
if(userType !=""){
|
||||
if (userType != "") {
|
||||
calendar.displayName = `${calendar.displayName} (${userType})`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,6 +103,27 @@
|
||||
@update-end-timezone="updateEndTimezone"
|
||||
@toggle-all-day="toggleAllDay" />
|
||||
|
||||
|
||||
|
||||
<div style='display:flex ;margin-left: 8px;'>
|
||||
<div style='width:70%'>
|
||||
<PropertySelectAbsenceType
|
||||
:value="absenceType"
|
||||
:is-read-only="isReadOnly"
|
||||
:prop-model="rfcProps.absenceType"
|
||||
:noWrap='true'
|
||||
@update:value="updateAbsenceType" />
|
||||
</div>
|
||||
<div style='width:30% ;margin-top: -11px;'>
|
||||
<PropertyIsPrivate
|
||||
:is-read-only="isReadOnly"
|
||||
:is-private="isPrivate"
|
||||
@toggle-is-private="toggleIsPrivate"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<PropertySelectClient class="property-location"
|
||||
url="/apps/gestion/ajaxGetClientsName"
|
||||
:is-read-only="isReadOnly"
|
||||
@ -129,6 +150,13 @@
|
||||
@add-single-value="addArticle"
|
||||
@remove-single-value="removeArticle" />
|
||||
|
||||
<PropertyText
|
||||
:is-read-only="isReadOnly"
|
||||
:prop-model="rfcProps.comment"
|
||||
:value="comment"
|
||||
:linkify-links="false"
|
||||
@update:value="updateComment" />
|
||||
|
||||
<InvitationResponseButtons v-if="isViewedByAttendee"
|
||||
:attendee="userAsAttendee"
|
||||
:calendar-id="calendarId"
|
||||
@ -188,7 +216,7 @@
|
||||
:calendar-object-instance="calendarObjectInstance"
|
||||
:is-read-only="isReadOnly" />
|
||||
|
||||
<NcModal v-if="showModal && !isPrivate()"
|
||||
<NcModal v-if="showModal && !checkIsPrivate()"
|
||||
:name="t('calendar', 'Managing shared access')"
|
||||
@close="closeAttachmentsModal">
|
||||
<div class="modal-content">
|
||||
@ -219,7 +247,7 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="modal-footer-checkbox">
|
||||
<NcCheckboxRadioSwitch v-if="!isPrivate()" :checked.sync="doNotShare">
|
||||
<NcCheckboxRadioSwitch v-if="!checkIsPrivate()" :checked.sync="doNotShare">
|
||||
{{ t('calendar', 'Deny access') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
</div>
|
||||
@ -347,6 +375,9 @@ import PropertySelectAjaxMultiple from "../components/Editor/Properties/Property
|
||||
import PropertySelectLieu from "../components/Editor/Properties/PropertySelectLieu.vue";
|
||||
import PropertySelectClient from "../components/Editor/Properties/PropertySelectClient.vue";
|
||||
import PropertySelectArticle from "../components/Editor/Properties/PropertySelectArticle.vue";
|
||||
import PropertyIsPrivate from "../components/Editor/Properties/PropertyIsPrivate.vue";
|
||||
import PropertySelectAbsenceType from "../components/Editor/Properties/PropertySelectAbsenceType.vue";
|
||||
|
||||
|
||||
export default {
|
||||
name: 'EditSidebar',
|
||||
@ -356,6 +387,7 @@ export default {
|
||||
PropertySelectLieu,
|
||||
PropertySelectClient,
|
||||
PropertySelectArticle,
|
||||
PropertyIsPrivate,
|
||||
ResourceList,
|
||||
PropertyColor,
|
||||
PropertySelectMultiple,
|
||||
@ -386,6 +418,7 @@ export default {
|
||||
AttachmentsList,
|
||||
CalendarPickerHeader,
|
||||
PropertyTitle,
|
||||
PropertySelectAbsenceType
|
||||
},
|
||||
mixins: [
|
||||
EditorMixin,
|
||||
@ -536,7 +569,7 @@ export default {
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
isPrivate() {
|
||||
checkIsPrivate() {
|
||||
return this.calendarObjectInstance.attendees.filter((attendee) => {
|
||||
if (this.currentUser.emailAddress.toLowerCase() !== (
|
||||
attendee.uri.split('mailto:').length === 2
|
||||
@ -560,7 +593,7 @@ export default {
|
||||
if (!this.doNotShare) {
|
||||
const total = this.showModalNewAttachments.length
|
||||
this.showPreloader = true
|
||||
if (!this.isPrivate()) {
|
||||
if (!this.checkIsPrivate()) {
|
||||
this.showModalNewAttachments.map(async (attachment, i) => {
|
||||
// console.log('Add share', attachment)
|
||||
this.sharedProgress = Math.ceil(100 * (i + 1) / total)
|
||||
@ -622,10 +655,10 @@ export default {
|
||||
const newAttachments = this.calendarObjectInstance.attachments.filter(attachment => {
|
||||
// get only new attachments
|
||||
// TODO get NOT only new attachments =) Maybe we should filter all attachments without share-type, 'cause event can be private and AFTER save owner could add new participant
|
||||
return !this.isPrivate() ? attachment.isNew && attachment.shareTypes === null : attachment.isNew && attachment.shareTypes !== null
|
||||
return !this.checkIsPrivate() ? attachment.isNew && attachment.shareTypes === null : attachment.isNew && attachment.shareTypes !== null
|
||||
})
|
||||
// if there are new attachment and event not saved
|
||||
if (newAttachments.length > 0 && !this.isPrivate()) {
|
||||
if (newAttachments.length > 0 && !this.checkIsPrivate()) {
|
||||
// and is event NOT private,
|
||||
// then add share to each attachment
|
||||
// only if attachment['share-types'] is null or empty
|
||||
|
||||
@ -106,7 +106,7 @@
|
||||
<PropertyTitle :value="titleOrPlaceholder"
|
||||
:is-read-only="isReadOnlyOrViewing"
|
||||
@update:value="updateTitle" />
|
||||
|
||||
|
||||
<PropertyTitleTimePicker :start-date="startDate"
|
||||
:start-timezone="startTimezone"
|
||||
:end-date="endDate"
|
||||
@ -121,6 +121,28 @@
|
||||
@update-end-timezone="updateEndTimezone"
|
||||
@toggle-all-day="toggleAllDay" />
|
||||
|
||||
|
||||
<div style='display:flex ;margin-left: 7%;'>
|
||||
<div style='width:70%'>
|
||||
<PropertySelectAbsenceType
|
||||
:value="absenceType"
|
||||
:is-read-only="isReadOnly"
|
||||
:prop-model="rfcProps.absenceType"
|
||||
:noWrap='true'
|
||||
@update:value="updateAbsenceType" />
|
||||
</div>
|
||||
<div style='width:30% ;margin-top: -11px;'>
|
||||
<PropertyIsPrivate
|
||||
:is-read-only="isReadOnly"
|
||||
:is-private="isPrivate"
|
||||
@toggle-is-private="toggleIsPrivate"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<PropertySelectClient class="property-location"
|
||||
url="/apps/gestion/ajaxGetClientsName"
|
||||
:is-read-only="isReadOnly"
|
||||
@ -146,6 +168,14 @@
|
||||
@add-single-value="addArticle"
|
||||
@remove-single-value="removeArticle" />
|
||||
|
||||
<PropertyText
|
||||
:is-read-only="isReadOnly"
|
||||
:prop-model="rfcProps.comment"
|
||||
:value="comment"
|
||||
:linkify-links="false"
|
||||
@update:value="updateComment"
|
||||
/>
|
||||
|
||||
<InviteesList class="event-popover__invitees"
|
||||
:hide-if-empty="true"
|
||||
:hide-buttons="true"
|
||||
@ -218,13 +248,14 @@ import Download from 'vue-material-design-icons/Download.vue'
|
||||
import ContentDuplicate from 'vue-material-design-icons/ContentDuplicate.vue'
|
||||
import EditIcon from 'vue-material-design-icons/Pencil.vue'
|
||||
import { mapState } from 'vuex'
|
||||
import {showError} from "@nextcloud/dialogs";
|
||||
import PropertySelect from "../components/Editor/Properties/PropertySelect.vue";
|
||||
import PropertySelectAjax from "../components/Editor/Properties/PropertySelectAjax.vue";
|
||||
import PropertySelectAjaxMultiple from "../components/Editor/Properties/PropertySelectAjaxMultiple.vue";
|
||||
import PropertySelectLieu from "../components/Editor/Properties/PropertySelectLieu.vue";
|
||||
import PropertySelectClient from "../components/Editor/Properties/PropertySelectClient.vue";
|
||||
import PropertySelectArticle from "../components/Editor/Properties/PropertySelectArticle.vue";
|
||||
import PropertySelectAbsenceType from "../components/Editor/Properties/PropertySelectAbsenceType.vue";
|
||||
import PropertyIsPrivate from "../components/Editor/Properties/PropertyIsPrivate.vue";
|
||||
|
||||
export default {
|
||||
name: 'EditSimple',
|
||||
@ -234,12 +265,14 @@ export default {
|
||||
PropertySelectLieu,
|
||||
PropertySelectClient,
|
||||
PropertySelectArticle,
|
||||
PropertyIsPrivate,
|
||||
PropertySelect,
|
||||
PopoverLoadingIndicator,
|
||||
SaveButtons,
|
||||
PropertyText,
|
||||
PropertyTitleTimePicker,
|
||||
PropertyTitle,
|
||||
PropertySelectAbsenceType,
|
||||
Popover,
|
||||
Actions,
|
||||
ActionButton,
|
||||
|
||||
@ -200,5 +200,14 @@ return [
|
||||
['name' => 'vehicle#createDefaultVehicle','url' => '/vehicle/createDefaultVehicle', 'verb' => 'POST'],
|
||||
//thanatoType
|
||||
['name' => 'page#getUserTypeByUserUuid', 'url' => '/getUserTypeByUserUuid/{userUuid}', 'verb' => 'GET'],
|
||||
|
||||
//user groups getUserConnectedGroups
|
||||
['name' => 'page#getUserConnectedGroups', 'url' => '/getUserConnectedGroups', 'verb' => 'GET'],
|
||||
|
||||
|
||||
['name' => 'provider#moveAttachmentFile', 'url' => '/test-move', 'verb' => 'GET'],
|
||||
['name' => 'provider#sendEmailAttachment', 'url' => '/test-send-mail-attach', 'verb' => 'GET'],
|
||||
|
||||
|
||||
]
|
||||
];
|
||||
10
gestion/lib/Constants/AbsenceTypeConstant.php
Normal file
10
gestion/lib/Constants/AbsenceTypeConstant.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\Gestion\Constants;
|
||||
abstract class AbsenceTypeConstant
|
||||
{
|
||||
const LEAVE = "LEAVE";
|
||||
const DISEASE = "DISEASE";
|
||||
const REST = "REST";
|
||||
}
|
||||
10
gestion/lib/Constants/UserGroupConstant.php
Normal file
10
gestion/lib/Constants/UserGroupConstant.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\Gestion\Constants;
|
||||
abstract class UserGroupConstant
|
||||
{
|
||||
const THANATOS_GROUP_NAME = "Thanatos";
|
||||
const LIGNE_GROUP_NAME = "Ligne";
|
||||
const ADMIN_GROUP_NAME = "admin";
|
||||
}
|
||||
21
gestion/lib/Constants/VCalendarPropertyConstant.php
Normal file
21
gestion/lib/Constants/VCalendarPropertyConstant.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\Gestion\Constants;
|
||||
abstract class VCalendarPropertyConstant
|
||||
{
|
||||
const PROPERTY_IS_LEAVE = "ISPRIVATE";
|
||||
const ABSENCE_TYPE = "ABSENCETYPE";
|
||||
|
||||
const ABSENCE_TYPES = [
|
||||
AbsenceTypeConstant::LEAVE,
|
||||
AbsenceTypeConstant::REST,
|
||||
AbsenceTypeConstant::DISEASE
|
||||
];
|
||||
|
||||
const ABSENCE_TYPES_KEYS_VALUES = [
|
||||
AbsenceTypeConstant::LEAVE => "CONGE",
|
||||
AbsenceTypeConstant::REST => "REPOS",
|
||||
AbsenceTypeConstant::DISEASE => "MALADIE"
|
||||
];
|
||||
}
|
||||
@ -22,6 +22,7 @@ use \Datetime;
|
||||
use \DatetimeImmutable;
|
||||
use \IntlDateFormatter;
|
||||
use \FPDF;
|
||||
use OCA\Gestion\Constants\UserGroupConstant;
|
||||
use OCA\Gestion\Service\Certificate\CertificateService;
|
||||
use OCA\Gestion\Service\Devis\Pdf\DevisPdfService;
|
||||
use OCA\Gestion\Service\ExportClientStatisticService;
|
||||
@ -1981,7 +1982,10 @@ class PageController extends Controller {
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getStats(){
|
||||
$result = $this->menuStatisticService->getStats($this->idNextcloud);
|
||||
$isThanato = in_array(UserGroupConstant::THANATOS_GROUP_NAME,$this->groups);
|
||||
$isAdmin = in_array(UserGroupConstant::ADMIN_GROUP_NAME,$this->groups);
|
||||
$isUserThanatoOnly = $isThanato && !$isAdmin;
|
||||
$result = $this->menuStatisticService->getStats($this->idNextcloud,$isUserThanatoOnly);
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
@ -2028,7 +2032,10 @@ class PageController extends Controller {
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getDefunts() {
|
||||
return $this->myDb->getDefunts($this->idNextcloud);
|
||||
$isThanato = in_array(UserGroupConstant::THANATOS_GROUP_NAME,$this->groups);
|
||||
$isAdmin = in_array(UserGroupConstant::ADMIN_GROUP_NAME,$this->groups);
|
||||
$isUserThanatoOnly = $isThanato && !$isAdmin;
|
||||
return $this->myDb->getDefunts($this->idNextcloud,$isUserThanatoOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2592,36 +2599,14 @@ class PageController extends Controller {
|
||||
*
|
||||
*/
|
||||
|
||||
public function exportThanatoStatistic($thanatoIdsToExport){
|
||||
public function exportThanatoStatistic($thanatoIdsToExport,$month,$year){
|
||||
if(empty($thanatoIdsToExport)){
|
||||
return "";
|
||||
}
|
||||
$month = $month ?? date('m');
|
||||
$year = $year ?? date('Y');
|
||||
$exportData = $this->myDb->getExportThanatoStatisticData($thanatoIdsToExport,$month,$year);
|
||||
try{
|
||||
$current_config = json_decode($this->myDb->getConfiguration($this->idNextcloud));
|
||||
$clean_folder = html_entity_decode($current_config[0]->path).'/';
|
||||
$thanatoList = $this->myDb->getThanatoByIds($thanatoIdsToExport);
|
||||
$thanatoFolders = $this->exportThanatoStatisticService->getThanatoStatisticFolders($thanatoList,$year);
|
||||
$fileHeader = $this->exportThanatoStatisticService->getExportThanatoFileHeader();
|
||||
$fileContent = $this->exportThanatoStatisticService->populateExportDataIntoFileContent($exportData,$fileHeader);
|
||||
$filename = $this->exportThanatoStatisticService->getFilename($thanatoList,$month,$year);
|
||||
$filenames = [];
|
||||
foreach($thanatoFolders as $thanatoFolder){
|
||||
$fullPath = $clean_folder.$thanatoFolder;
|
||||
try {
|
||||
$this->storage->newFolder($fullPath);
|
||||
}
|
||||
catch(\OCP\Files\NotPermittedException $e) {
|
||||
|
||||
}
|
||||
$fileNamePath = $fullPath."STAT-THANATOS-" . $filename . '.csv';
|
||||
$this->storage->newFile($fileNamePath);
|
||||
$file = $this->storage->get($fileNamePath);
|
||||
$file->putContent($fileContent);
|
||||
$filenames[] = $fileNamePath;
|
||||
}
|
||||
$filenames = $this->exportThanatoStatisticService->exportThanatosListStatistic($thanatoIdsToExport,$month,$year,$this->idNextcloud);
|
||||
return $filenames;
|
||||
}
|
||||
catch(\OCP\Files\NotFoundException $e) { }
|
||||
@ -2897,7 +2882,7 @@ class PageController extends Controller {
|
||||
return $this->myDb->getClientGroupFacturations();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
@ -2906,6 +2891,11 @@ class PageController extends Controller {
|
||||
return $this->myDb->createDefaultGroupFacturation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function getUserTypeByUserUuid($userUuid){
|
||||
try{
|
||||
return json_encode(value: $this->myDb->getUserTypeByUserUuid($userUuid));
|
||||
@ -2917,4 +2907,17 @@ class PageController extends Controller {
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @param int $defuntId
|
||||
*/
|
||||
|
||||
public function getUserConnectedGroups(){
|
||||
try{
|
||||
return json_encode($this->groups);
|
||||
}
|
||||
catch(\OCP\Files\NotFoundException $e) { }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,29 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\Gestion\Controller;
|
||||
|
||||
use Exception;
|
||||
use OCA\Gestion\Service\ConfigurationService;
|
||||
use OCA\Gestion\Service\NavigationService;
|
||||
use OCA\Gestion\Service\Provider\ProviderService;
|
||||
use OCA\Gestion\Service\Provider\Statistic\ProviderStatisticService;
|
||||
use Psr\Log\LoggerInterface;
|
||||
defined("TAB1") or define("TAB1", "\t");
|
||||
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IConfig;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Mail\IMailer;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCA\Gestion\Db\Bdd;
|
||||
use OCP\IGroupManager;
|
||||
|
||||
defined("TAB1") or define("TAB1", "\t");
|
||||
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IConfig;
|
||||
use OCA\Gestion\Db\Bdd;
|
||||
use OC\Files\Filesystem;
|
||||
use OCP\Files\IRootFolder;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCA\Gestion\Service\GestionService;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCA\Gestion\Service\NavigationService;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCA\Gestion\Service\ConfigurationService;
|
||||
use OCA\Gestion\Service\Provider\ProviderService;
|
||||
use OCA\Gestion\Service\Provider\Statistic\ProviderStatisticService;
|
||||
|
||||
date_default_timezone_set('Europe/Paris');
|
||||
|
||||
class ProviderController extends Controller {
|
||||
class ProviderController extends Controller
|
||||
{
|
||||
private $idNextcloud;
|
||||
private $urlGenerator;
|
||||
private $mailer;
|
||||
@ -38,31 +43,36 @@ class ProviderController extends Controller {
|
||||
/** @var \OCA\Gestion\Service\NavigationService */
|
||||
private $navigationService;
|
||||
|
||||
private $providerService;
|
||||
private $providerService;
|
||||
|
||||
private $providerStatisticService;
|
||||
|
||||
private $logger;
|
||||
//Gestion service
|
||||
private $gestionService;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($AppName,
|
||||
IRequest $request,
|
||||
$UserId,
|
||||
Bdd $myDb,
|
||||
IRootFolder $rootFolder,
|
||||
IURLGenerator $urlGenerator,
|
||||
IMailer $mailer,
|
||||
Iconfig $config,
|
||||
IUserSession $userSession,
|
||||
IGroupManager $groupManager,
|
||||
NavigationService $navigationService,
|
||||
ConfigurationService $configurationService,
|
||||
LoggerInterface $logger,
|
||||
ProviderService $providerService,
|
||||
ProviderStatisticService $providerStatisticService
|
||||
){
|
||||
public function __construct(
|
||||
$AppName,
|
||||
IRequest $request,
|
||||
$UserId,
|
||||
Bdd $myDb,
|
||||
IRootFolder $rootFolder,
|
||||
IURLGenerator $urlGenerator,
|
||||
IMailer $mailer,
|
||||
Iconfig $config,
|
||||
IUserSession $userSession,
|
||||
IGroupManager $groupManager,
|
||||
NavigationService $navigationService,
|
||||
ConfigurationService $configurationService,
|
||||
LoggerInterface $logger,
|
||||
ProviderService $providerService,
|
||||
ProviderStatisticService $providerStatisticService,
|
||||
GestionService $gestionService
|
||||
) {
|
||||
|
||||
parent::__construct($AppName, $request);
|
||||
|
||||
@ -74,55 +84,89 @@ class ProviderController extends Controller {
|
||||
$this->navigationService = $navigationService;
|
||||
$this->configurationService = $configurationService;
|
||||
$this->logger = $logger;
|
||||
$this->providerService = $providerService;
|
||||
$this->providerService = $providerService;
|
||||
$this->providerStatisticService = $providerStatisticService;
|
||||
$this->gestionService = $gestionService;
|
||||
|
||||
if ($userSession->isLoggedIn()) {
|
||||
$this->user = $userSession->getUser();
|
||||
}
|
||||
if ($userSession->isLoggedIn()) {
|
||||
$this->user = $userSession->getUser();
|
||||
}
|
||||
|
||||
if ($this->user != null) {
|
||||
$groups = $groupManager->getUserGroups($this->user);
|
||||
$this->groups = [];
|
||||
foreach ($groups as $group) {
|
||||
$this->groups[] = $group->getGID();
|
||||
}
|
||||
}
|
||||
if ($this->user != null) {
|
||||
$groups = $groupManager->getUserGroups($this->user);
|
||||
$this->groups = [];
|
||||
foreach ($groups as $group) {
|
||||
$this->groups[] = $group->getGID();
|
||||
}
|
||||
}
|
||||
|
||||
try{
|
||||
try {
|
||||
$this->storage = $rootFolder->getUserFolder($this->idNextcloud);
|
||||
}catch(\OC\User\NoUserException $e){
|
||||
|
||||
} catch (\OC\User\NoUserException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function provider() {
|
||||
*/
|
||||
public function provider()
|
||||
{
|
||||
return new TemplateResponse('gestion', 'provider', array('groups' => $this->groups, 'user' => $this->user, 'path' => $this->idNextcloud, 'url' => $this->navigationService->getNavigationLink()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getProviders() {
|
||||
*/
|
||||
public function getProviders()
|
||||
{
|
||||
$providers = $this->providerService->getProvidersAsArray();
|
||||
return json_encode($providers);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getProvidersTest() {
|
||||
|
||||
$client = \OC::$server->getHTTPClientService()->newClient();
|
||||
$token = file_get_contents('http://127.0.0.1/ocs/v2.php/core/getcsrftoken', false, stream_context_create([
|
||||
'http' => [
|
||||
'header' => "OCS-APIRequest: true\r\n"
|
||||
]
|
||||
]));
|
||||
$response = $client->post('http://127.0.0.1/ocs/v2.php/apps/files_sharing/api/v1/shares', [
|
||||
'body' => [
|
||||
"path" => "//Talk/narindra-dev.png",
|
||||
"referenceId" => "dkzcesdsdhae",
|
||||
"shareWith" => "dkzcehae",
|
||||
"shareType" => 10,
|
||||
'talkMetaData' => "{\"messageType\":\"\"}"
|
||||
],
|
||||
'headers' => [
|
||||
'Cookie' =>"_ga=GA1.1.259457270.1732194936; _ga_699NE13B0K=GS1.1.1732203040.2.0.1732203040.0.0.0; nc_sameSiteCookielax=true; nc_sameSiteCookiestrict=true; nc_username=Tiavina; oc_sessionPassphrase=v7ncJ0h%2BYxrmzJViNygGkErBa9cSDs1m3mpgW4M6wZ%2BqphceZK2S7PMELp%2BlHgxQxcZuGPrpzZSwzp2SQCXADxDehB7OkwdBEr3DtG8ZzlnXZWzB%2Fbfl7xsuQYTnvmLU; oczp8j7d6k88=1b54a2ea877ffca7154bea254f70886c; nc_token=OEez5vu%2FWTz7FsafIbVDbAXA7lSdkG9U; nc_session_id=1b54a2ea877ffca7154bea254f70886c",
|
||||
'OCS-APIRequest' => 'true',
|
||||
'requesttoken' => $token
|
||||
]
|
||||
]);
|
||||
|
||||
var_dump($response);die;
|
||||
return json_encode($providers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function createDefaultProvider() {
|
||||
try{
|
||||
*/
|
||||
public function createDefaultProvider()
|
||||
{
|
||||
try {
|
||||
$this->providerService->createDefaultProvider($this->idNextcloud);
|
||||
return true;
|
||||
}
|
||||
catch(Exception $e){
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -130,14 +174,18 @@ class ProviderController extends Controller {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function exportProvidersStatistic(array $providerIds,$year){
|
||||
try{
|
||||
$filenames = $this->providerStatisticService->exportProvidersStatisticByYear($providerIds,$year,$this->idNextcloud);
|
||||
*/
|
||||
public function exportProvidersStatistic(array $providerIds, $year)
|
||||
{
|
||||
try {
|
||||
$filenames = $this->providerStatisticService->exportProvidersStatisticByYear($providerIds, $year, $this->idNextcloud);
|
||||
return $filenames;
|
||||
}
|
||||
catch(Exception $e){
|
||||
} catch (Exception $e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ use OCA\Gestion\Helpers\VCalendarHelpers;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IL10N;
|
||||
use \Datetime;
|
||||
use OCA\Gestion\Constants\VCalendarPropertyConstant;
|
||||
use OCA\Gestion\Helpers\FileExportHelpers;
|
||||
|
||||
class Bdd {
|
||||
@ -510,7 +511,33 @@ class Bdd {
|
||||
return $this->execSQL($sql, array());
|
||||
}
|
||||
|
||||
public function getDefunts($idNextcloud) {
|
||||
private function getDevisMadeByAThanato($thanatoId){
|
||||
$sql = "SELECT
|
||||
devis.id,
|
||||
devis.id_thanato,
|
||||
devis.id_defunt
|
||||
FROM ".$this->tableprefix."devis as devis
|
||||
WHERE devis.id_thanato = ? ;";
|
||||
|
||||
$devisList = $this->execSQLNoJsonReturn($sql, array($thanatoId));
|
||||
return $devisList;
|
||||
}
|
||||
|
||||
private function getDefuntIdsFromDevisList($devisList){
|
||||
$defuntIds = [];
|
||||
foreach($devisList as $devis){
|
||||
$defuntIds[] = $devis["id_defunt"];
|
||||
}
|
||||
return $defuntIds;
|
||||
}
|
||||
|
||||
private function getDefuntIdsRelatedToThanato($thanatoId){
|
||||
$devis = $this->getDevisMadeByAThanato($thanatoId);
|
||||
$defuntIds = $this->getDefuntIdsFromDevisList($devis);
|
||||
return $defuntIds;
|
||||
}
|
||||
|
||||
public function getDefunts($idNextcloud,$isUserThanatoOnly = false) {
|
||||
$sql = "SELECT ".$this->tableprefix."defunt.id, ".$this->tableprefix."defunt.nom, ".$this->tableprefix."defunt.date_naissance, ".$this->tableprefix."defunt.ref_pacemaker, ".$this->tableprefix."defunt.sexe, "
|
||||
.$this->tableprefix."client.nom as nom_client, ".$this->tableprefix."client.id as id_client, ".$this->tableprefix."devis.user_id as user_id, "
|
||||
.$this->tableprefix."devis.num as numero_devis, ".$this->tableprefix."devis.id as id_devis, "
|
||||
@ -518,9 +545,26 @@ class Bdd {
|
||||
FROM ".$this->tableprefix."defunt
|
||||
LEFT JOIN ".$this->tableprefix."devis ON ".$this->tableprefix."devis.id_defunt = ".$this->tableprefix."defunt.id
|
||||
LEFT JOIN ".$this->tableprefix."client ON ".$this->tableprefix."devis.id_client = ".$this->tableprefix."client.id
|
||||
LEFT JOIN ".$this->tableprefix."lieu ON ".$this->tableprefix."devis.id_lieu = ".$this->tableprefix."lieu.id
|
||||
ORDER BY ".$this->tableprefix."defunt.id DESC;";
|
||||
return $this->execSQL($sql, array());
|
||||
LEFT JOIN ".$this->tableprefix."lieu ON ".$this->tableprefix."devis.id_lieu = ".$this->tableprefix."lieu.id";
|
||||
|
||||
$conditions = [];
|
||||
if($isUserThanatoOnly){
|
||||
$thanato = $this->getThanatoByUserUuid($idNextcloud);
|
||||
if($thanato == null){
|
||||
return json_encode([]);
|
||||
}
|
||||
$thanatoId = $thanato["id"];
|
||||
$defuntsIdRelatedToThanato = $this->getDefuntIdsRelatedToThanato($thanatoId);
|
||||
if(empty($defuntsIdRelatedToThanato)){
|
||||
return json_encode([]);
|
||||
}
|
||||
$defuntListConditionPlaceholder = implode(',', array_fill(0, count($defuntsIdRelatedToThanato), '?'));
|
||||
$conditions = $defuntsIdRelatedToThanato;
|
||||
$sql .= " WHERE ".$this->tableprefix."defunt.id IN ($defuntListConditionPlaceholder)";
|
||||
}
|
||||
$sql .= " ORDER BY ".$this->tableprefix."defunt.id DESC;";
|
||||
$defuntsList = $this->execSQL($sql,$conditions);
|
||||
return $defuntsList;
|
||||
}
|
||||
|
||||
public function getUnusedDefunts($idNextcloud) {
|
||||
@ -1532,9 +1576,24 @@ class Bdd {
|
||||
/**
|
||||
* Number defunt
|
||||
*/
|
||||
public function numberDefunt($idNextcloud){
|
||||
$sql = "SELECT count(*) as c from ".$this->tableprefix."defunt;";
|
||||
return $this->execSQL($sql, array());
|
||||
public function numberDefunt($idNextcloud,$isUserThanatoOnly = false){
|
||||
$defuntCount = 0;
|
||||
if($isUserThanatoOnly == false){
|
||||
$sql = "SELECT count(*) as c from ".$this->tableprefix."defunt;";
|
||||
$defuntCountBythanato = $this->execSQLNoJsonReturn($sql, array());
|
||||
if(!empty($defuntCountBythanato)){
|
||||
$defuntCount = $defuntCountBythanato[0]['c'];
|
||||
}
|
||||
}
|
||||
else{
|
||||
$thanato = $this->getThanatoByUserUuid($idNextcloud);
|
||||
if($thanato != null){
|
||||
$thanatoId = $thanato["id"];
|
||||
$defuntsIdRelatedToThanato = $this->getDefuntIdsRelatedToThanato($thanatoId);
|
||||
$defuntCount = count($defuntsIdRelatedToThanato);
|
||||
}
|
||||
}
|
||||
return $defuntCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1930,7 +1989,7 @@ class Bdd {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function insertDevisFromVCalendarAndReturnId($thanatoId,$clientId,$locationId,$defuntId,$calendarUuid = self::DEFAULT_CALENDAR_UUID_FOR_DEVIS,$date = null,$idNextcloud = "admin"){
|
||||
public function insertDevisFromVCalendarAndReturnId($thanatoId,$clientId,$locationId,$defuntId,$devisComment,$calendarUuid = self::DEFAULT_CALENDAR_UUID_FOR_DEVIS,$date = null,$idNextcloud = "admin"){
|
||||
|
||||
if($date == null){
|
||||
$dateTime = new Datetime();
|
||||
@ -1974,7 +2033,7 @@ class Bdd {
|
||||
$this->l->t('New'),
|
||||
$locationId,
|
||||
$this->l->t('Mention'),
|
||||
$this->l->t('Comment'),
|
||||
$devisComment,
|
||||
$last,
|
||||
$devisNumber,
|
||||
$devisFullNumber
|
||||
@ -2035,10 +2094,9 @@ class Bdd {
|
||||
$this->calculer_distance_trajet($ligne_trajet->id_trajet, $idNextcloud);
|
||||
}
|
||||
|
||||
public function getExportThanatoStatisticData(array $thanatoIds,$month,$year){
|
||||
$devisList = $this->getDevisListByThanatoIds($thanatoIds,$month,$year);
|
||||
$devisListGroupedByDateAndThenByThanato = $this->getDevisListGroupedByDateAndThenByThanato($devisList);
|
||||
return $devisListGroupedByDateAndThenByThanato;
|
||||
public function getExportThanatoStatisticData($thanatoId,$month,$year){
|
||||
$devisList = $this->getThanatoDevisPerDateInAMonthYear($thanatoId,$month,$year);
|
||||
return $devisList;
|
||||
}
|
||||
|
||||
private function getDevisListByThanatoIds(array $thanatoIds,$month,$year){
|
||||
@ -2161,6 +2219,8 @@ class Bdd {
|
||||
$devisTimeValue = VCalendarHelpers::GetStartAndEndTimeFromVCalendarString($calendarData);
|
||||
$devis["startTime"] = $devisTimeValue["startTime"];
|
||||
$devis["endTime"] = $devisTimeValue["endTime"];
|
||||
$devis["totalHours"] = $devisTimeValue["totalHours"];
|
||||
$devis["totalWorkedHours"] = $devisTimeValue["totalWorkedHours"];
|
||||
return $devis;
|
||||
}
|
||||
|
||||
@ -2888,6 +2948,7 @@ class Bdd {
|
||||
}
|
||||
$sql = "SELECT
|
||||
devis.id,
|
||||
devis.date,
|
||||
devis.id_thanato,
|
||||
devis.id_defunt as defunt_id,
|
||||
devis.num,
|
||||
@ -2986,6 +3047,23 @@ class Bdd {
|
||||
}
|
||||
}
|
||||
|
||||
public function updateDevisComment($devisId,$requestedComment,$currentComment = null){
|
||||
$commentIsUpdated = $currentComment != $requestedComment;
|
||||
if($commentIsUpdated){
|
||||
$sql= "UPDATE ".$this->tableprefix."devis as devis
|
||||
SET devis.comment = ?
|
||||
WHERE devis.id = ?";
|
||||
$this->execSQLNoData($sql,[$requestedComment,$devisId]);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateDevisDate($devisId,$requestedDate){
|
||||
$sql= "UPDATE ".$this->tableprefix."devis as devis
|
||||
SET devis.date = ?
|
||||
WHERE devis.id = ?";
|
||||
$this->execSQLNoData($sql,[$requestedDate,$devisId]);
|
||||
}
|
||||
|
||||
public function deleteDevisProduit($devisProductId){
|
||||
$sql = "DELETE FROM ".$this->tableprefix."produit_devis WHERE id = ?;";
|
||||
$this->execSQLNoData($sql, array($devisProductId));
|
||||
@ -3208,7 +3286,7 @@ class Bdd {
|
||||
}
|
||||
|
||||
private function getDevisTalkRoomClientContent($clientPrenom){
|
||||
$message = ". Pour PF: ";
|
||||
$message = "Pour PF: ";
|
||||
$clientNameContent = "aucun";
|
||||
$clientPrenomIsSet = $clientPrenom != null && $clientPrenom != "" && $clientPrenom != "-";
|
||||
if($clientPrenomIsSet){
|
||||
@ -3230,8 +3308,16 @@ class Bdd {
|
||||
}
|
||||
$calendarData = $this->getCalendarDataByCalendarObjectUuid($devis->num);
|
||||
$devisTimeValue = VCalendarHelpers::GetStartAndEndTimeFromVCalendarString($calendarData);
|
||||
$devis->startTime = $devisTimeValue["startTime"];
|
||||
$devis->endTime = $devisTimeValue["endTime"];
|
||||
$startTimeValueWithMinutes = "";
|
||||
$endTimeValueWithMinutes = "";
|
||||
if($devisTimeValue["datetimeStart"]){
|
||||
$startTimeValueWithMinutes = $devisTimeValue["datetimeStart"]->format('H\hi');
|
||||
}
|
||||
if($devisTimeValue["datetimeEnd"]){
|
||||
$endTimeValueWithMinutes = $devisTimeValue["datetimeEnd"]->format('H\hi');
|
||||
}
|
||||
$devis->startTime = $startTimeValueWithMinutes;
|
||||
$devis->endTime = $endTimeValueWithMinutes;
|
||||
$devisProducts = $this->getDevisProduits($devisId);
|
||||
$devisProducts = json_encode($devisProducts);
|
||||
$devisProducts = json_decode($devisProducts);
|
||||
@ -3243,7 +3329,7 @@ class Bdd {
|
||||
if(empty($devisProducts)){
|
||||
return "";
|
||||
}
|
||||
$productMessage = ". ACTE A FAIRE : ";
|
||||
$productMessage = "ACTE A FAIRE : ";
|
||||
foreach($devisProducts as $product){
|
||||
$productMessage.= html_entity_decode($product->produit_reference).", ";
|
||||
}
|
||||
@ -3261,19 +3347,24 @@ class Bdd {
|
||||
$devisDate = $devisDate->format('d/m/Y');
|
||||
$message = "NOUVELLE INTERVENTION: ";
|
||||
$message .= html_entity_decode($devis->nom_defunt) . ' ';
|
||||
$message .= 'le '.$devisDate. ' ';
|
||||
$message .= 'à '.$devis->startTime. ' ';
|
||||
$message .= 'à '.html_entity_decode($devis->lieu). ' '. html_entity_decode($devis->adresse_soin);
|
||||
$message .= '
|
||||
le '.$devisDate;
|
||||
$message .= ' à '.$devis->startTime. ' ';
|
||||
$message .= '
|
||||
à '.html_entity_decode($devis->lieu). ' '. html_entity_decode($devis->adresse_soin);
|
||||
|
||||
$clientMessageContent = $this->getDevisTalkRoomClientContent($devis->prenom);
|
||||
$message .= $clientMessageContent;
|
||||
$message .= '
|
||||
'.$clientMessageContent;
|
||||
$productMessage = $this->getDevisTalkRoomProductSectionMessage($devis->products);
|
||||
$message .= $productMessage;
|
||||
$message .= '
|
||||
'.$productMessage;
|
||||
$comment = "aucun";
|
||||
if(strtolower($devis->comment) != "commentaire" && $devis->comment != ""){
|
||||
$comment = html_entity_decode($devis->comment);
|
||||
}
|
||||
$message .= ". COMMENTAIRES: ".$comment.". ";
|
||||
$message .= "
|
||||
COMMENTAIRES: ".$comment;
|
||||
$locationCodes = [
|
||||
"Code portail" => $devis->portal_code,
|
||||
"Code alarme" => $devis->alarm_code,
|
||||
@ -3288,8 +3379,209 @@ class Bdd {
|
||||
$locationCodeMessageContent .= $label. ": ".$value.". ";
|
||||
}
|
||||
$locationCodeMessageContent = trim($locationCodeMessageContent);
|
||||
$message .= $locationCodeMessageContent;
|
||||
$message .= '
|
||||
'.$locationCodeMessageContent;
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function getThanatoById($thanatoId){
|
||||
$sql = "SELECT id, nom, prenom,fk_user_uuid FROM ".$this->tableprefix."thanato WHERE id = ? LIMIT 1;";
|
||||
$thanato = $this->execSQLNoJsonReturn($sql,[$thanatoId]);
|
||||
if(!empty($thanato)){
|
||||
return $thanato[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getCalendarByThanatoIdNextcloud($idNextCloud){
|
||||
$searchString = "%principals/users/$idNextCloud%";
|
||||
$sql = "SELECT * FROM ".self::DEFAULT_TABLE_PREFIX."calendars as calendar WHERE calendar.principaluri LIKE ? LIMIT 1;";
|
||||
$calendar = $this->execSQLNoJsonReturn($sql,[$searchString]);
|
||||
if(!empty($calendar)){
|
||||
return $calendar[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getThanatoDevisListByDate($thanatoId,$date){
|
||||
$dateFormatted = $date->format('Y-m-d');
|
||||
$sql = "SELECT
|
||||
devis.id,
|
||||
devis.date,
|
||||
devis.mentions,
|
||||
devis.num as calendar_uuid,
|
||||
devis.id_defunt as id_defunt,
|
||||
devis.id_lieu as id_lieu,
|
||||
devis.id_client as id_client,
|
||||
devis.id_thanato as id_thanato,
|
||||
thanato.nom as nom_thanato,
|
||||
thanato.prenom as prenom_thanato,
|
||||
defunt.nom as nom_defunt,
|
||||
lieu.nom as nom_lieu,
|
||||
lieu.latitude as lieu_latitude,
|
||||
lieu.longitude as lieu_longitude,
|
||||
client.nom as nom_client,
|
||||
client.entreprise as client_entreprise,
|
||||
client.adresse as client_adresse,
|
||||
facture.num as facture_num
|
||||
FROM ".$this->tableprefix."devis as devis
|
||||
LEFT JOIN ".$this->tableprefix."thanato as thanato on devis.id_thanato = thanato.id
|
||||
LEFT JOIN ".$this->tableprefix."lieu as lieu on devis.id_lieu = lieu.id
|
||||
LEFT JOIN ".$this->tableprefix."defunt as defunt on devis.id_defunt = defunt.id
|
||||
LEFT JOIN ".$this->tableprefix."client as client on devis.id_client = client.id
|
||||
LEFT JOIN ".$this->tableprefix."facture as facture on devis.id = facture.id_devis
|
||||
WHERE devis.date = ? AND
|
||||
devis.id_thanato = ? AND
|
||||
(devis.mentions = ? OR devis.mentions = ?)
|
||||
ORDER BY devis.date ASC;";
|
||||
$devisList = $this->execSQLNoJsonReturn(
|
||||
$sql,
|
||||
[$dateFormatted,$thanatoId,DevisMentionConstant::FACTURED,DevisMentionConstant::FACTURED_FORMATTED]);
|
||||
return $devisList;
|
||||
}
|
||||
|
||||
private function getThanatoLeaveByCalendarAndDate($calendarId,$date){
|
||||
$isLeaveConditionAsString = "ABSENCETYPE:";
|
||||
$datetimeFormatted = $date->format('Ymd');
|
||||
$dateCondition = "%DTSTART%".$datetimeFormatted."%";
|
||||
$conditions = [];
|
||||
$params = [ $calendarId, $dateCondition ]; // First parameters for placeholders
|
||||
|
||||
$absenceTypes = VCalendarPropertyConstant::ABSENCE_TYPES;
|
||||
foreach ($absenceTypes as $type) {
|
||||
$conditions[] = "calendarobject.calendardata LIKE ?";
|
||||
$params[] = "%$isLeaveConditionAsString$type%"; // Add corresponding values
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM ".self::DEFAULT_TABLE_PREFIX."calendarobjects as calendarobject WHERE
|
||||
calendarobject.calendarid = ? AND
|
||||
calendarobject.calendardata LIKE ? AND
|
||||
calendarobject.deleted_at IS NULL AND
|
||||
(" . implode(" OR ", $conditions) . ");";
|
||||
$leaves = $this->execSQLNoJsonReturn($sql,$params);
|
||||
return $leaves;
|
||||
}
|
||||
|
||||
private function setDevisIsPublicHolidayOrNotText($devis){
|
||||
$isPublicHoliday = DateHelpers::isPublicHoliday($devis['date']);
|
||||
$devis["dayType"] = DateHelpers::getPublicHolidayText($isPublicHoliday);
|
||||
return $devis;
|
||||
}
|
||||
|
||||
public function getThanatoDevisPerDateInAMonthYear($thanatoId,$month,$year){
|
||||
$dateOfMonths = DateHelpers::getDatesOfMonth($year,$month);
|
||||
$devisListPerThanatoPerDate = [];
|
||||
$thanato = $this->getThanatoById($thanatoId);
|
||||
$thanatoName = $thanato["nom"];
|
||||
$thanatoCalendar = $this->getCalendarByThanatoIdNextcloud($thanato["fk_user_uuid"] ?? $thanato["nom"]);
|
||||
if($thanatoCalendar == null){
|
||||
return [];
|
||||
}
|
||||
$thanatoCalendarId = $thanatoCalendar["id"];
|
||||
foreach($dateOfMonths as $currentDate){
|
||||
$currentDateFormatted = $currentDate->format('Y-m-d');
|
||||
$isPublicHoliday = DateHelpers::isPublicHoliday($currentDateFormatted);
|
||||
$devisList = $this->getThanatoDevisListByDate($thanatoId,$currentDate);
|
||||
$thereIsNoDevisForCurrentDate = empty($devisList);
|
||||
if($thereIsNoDevisForCurrentDate){
|
||||
$devisListPerThanatoPerDate[$currentDateFormatted]["hasDevis"] = false;
|
||||
$thanatoLeavesThisDay = $this->getThanatoLeaveByCalendarAndDate($thanatoCalendarId,$currentDate);
|
||||
if(empty($thanatoLeavesThisDay)){
|
||||
$devisListPerThanatoPerDate[$currentDateFormatted]["leaves"][] = [
|
||||
"onLeave" => false,
|
||||
"startTime" => null,
|
||||
"endTime" => null,
|
||||
"thanatoName"=>$thanatoName,
|
||||
"date" => $currentDateFormatted,
|
||||
"totalHours" => 0,
|
||||
"totalWorkedHours" => 8,
|
||||
"isPublicHoliday" => $isPublicHoliday
|
||||
];
|
||||
}
|
||||
else{
|
||||
foreach($thanatoLeavesThisDay as $currentLeave){
|
||||
$leaveTime = VCalendarHelpers::GetStartAndEndTimeFromVCalendarString($currentLeave['calendardata']);
|
||||
$absenceType = VCalendarHelpers::GetValueFromKeyInVCalendarString(VCalendarPropertyConstant::ABSENCE_TYPE,$currentLeave['calendardata']);
|
||||
$absenceTypeKey = null;
|
||||
$absenceTypeLabel = null;
|
||||
if($absenceType){
|
||||
$absenceTypeKey = $absenceType;
|
||||
$absenceTypeLabel = FileExportHelpers::GetAbsenceTypeLabelFromKey($absenceType);
|
||||
}
|
||||
$devisListPerThanatoPerDate[$currentDateFormatted]["leaves"][] = [
|
||||
"onLeave" => true,
|
||||
"startTime" => $leaveTime["startTime"],
|
||||
"endTime" => $leaveTime["endTime"],
|
||||
"thanatoName"=>$thanatoName,
|
||||
"date" => $currentDateFormatted,
|
||||
"totalHours" => $leaveTime["totalHours"],
|
||||
"totalWorkedHours" => $leaveTime["totalWorkedHours"],
|
||||
"isPublicHoliday" => $isPublicHoliday,
|
||||
"absenceTypeKey" => $absenceTypeKey,
|
||||
"absenceTypeLabel" => $absenceTypeLabel
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
foreach($devisList as $devis){
|
||||
$devis = $this->setDevisStartAndEndTime($devis);
|
||||
$devis = $this->setDevisIsPublicHolidayOrNotText($devis);
|
||||
$devis = $this->setDevisProduitsList($devis);
|
||||
if (!isset($devisListPerThanatoPerDate[$currentDateFormatted])) {
|
||||
$devisListPerThanatoPerDate[$currentDateFormatted] = [
|
||||
'total_distance' => 0,
|
||||
"devis" => [],
|
||||
"devisId" => [],
|
||||
"hasDevis" => true,
|
||||
"leaves" => []
|
||||
];
|
||||
}
|
||||
$devisListPerThanatoPerDate[$currentDateFormatted]["devis"][] = $devis;
|
||||
$devisListPerThanatoPerDate[$currentDateFormatted]["devisId"][] = $devis['id'];
|
||||
}
|
||||
$devisListPerThanatoPerDate[$currentDateFormatted]["leaves"] = [];
|
||||
$thanatoLeavesThisDay = $this->getThanatoLeaveByCalendarAndDate($thanatoCalendarId,$currentDate);
|
||||
foreach($thanatoLeavesThisDay as $currentLeave){
|
||||
$leaveTime = VCalendarHelpers::GetStartAndEndTimeFromVCalendarString($currentLeave['calendardata']);
|
||||
$absenceType = VCalendarHelpers::GetValueFromKeyInVCalendarString(VCalendarPropertyConstant::ABSENCE_TYPE,$currentLeave['calendardata']);
|
||||
$absenceTypeKey = null;
|
||||
$absenceTypeLabel = null;
|
||||
if($absenceType){
|
||||
$absenceTypeKey = $absenceType;
|
||||
$absenceTypeLabel = FileExportHelpers::GetAbsenceTypeLabelFromKey($absenceType);
|
||||
}
|
||||
$devisListPerThanatoPerDate[$currentDateFormatted]["leaves"][] = [
|
||||
"onLeave" => true,
|
||||
"startTime" => $leaveTime["startTime"],
|
||||
"endTime" => $leaveTime["endTime"],
|
||||
"thanatoName"=>$thanatoName,
|
||||
"date" => $currentDateFormatted,
|
||||
"totalHours" => $leaveTime["totalHours"],
|
||||
"totalWorkedHours" => $leaveTime["totalWorkedHours"],
|
||||
"isPublicHoliday" => $isPublicHoliday,
|
||||
"absenceTypeKey" => $absenceTypeKey,
|
||||
"absenceTypeLabel" => $absenceTypeLabel
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $devisListPerThanatoPerDate;
|
||||
}
|
||||
|
||||
public function getRouteLinesByDevisIdList(array $devisIdList){
|
||||
if(empty($devisIdList)){
|
||||
return [];
|
||||
}
|
||||
$sqlConditionsPlaceholder = implode(',', array_fill(0, count($devisIdList), '?'));
|
||||
$sql = "SELECT ligne_trajet.id, ligne_trajet.rang, ligne_trajet.id_nextcloud, ligne_trajet.date,
|
||||
ligne_trajet.user_id, ligne_trajet.commentaire, ligne_trajet.source,
|
||||
lieu.id as lieu_id, lieu.nom as lieu, lieu.latitude as latitude, lieu.longitude as longitude
|
||||
FROM (".$this->tableprefix."ligne_trajet as ligne_trajet
|
||||
LEFT JOIN ".$this->tableprefix."lieu as lieu on ligne_trajet.id_lieu = lieu.id)
|
||||
WHERE ligne_trajet.id_devis IN ($sqlConditionsPlaceholder)
|
||||
ORDER BY ligne_trajet.date ASC, ligne_trajet.rang ASC;";
|
||||
return $this->execSQLNoJsonReturn($sql, $devisIdList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ class TalkDb {
|
||||
|
||||
$rooms = $this->execSQLNoJsonReturn(
|
||||
$sql,
|
||||
[$names['createdByUser'],$names['createdByAdmin']]);
|
||||
[$names['target'],$names['sender']]);
|
||||
|
||||
if(!empty($rooms)){
|
||||
return $rooms[0];
|
||||
@ -161,13 +161,13 @@ class TalkDb {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function createDevisTalkRoomAndReturnDevisTalkRoom($idNextCloud,$token){
|
||||
$roomName = '["'.$idNextCloud.'","'.BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD.'"]';
|
||||
public function createDevisTalkRoomAndReturnDevisTalkRoom($targetUser,$senderUser,$token){
|
||||
$roomName = '["'.$targetUser.'","'.$senderUser.'"]';
|
||||
$this->createDevisTalkRoom($roomName,$token);
|
||||
$room = $this->getDevisTalkRoomByName($roomName);
|
||||
$attendees = [
|
||||
$idNextCloud,
|
||||
BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD
|
||||
$targetUser,
|
||||
$senderUser
|
||||
];
|
||||
$this->createDevisTalkRoomAttendeesByActors($attendees,$room['id']);
|
||||
return $room;
|
||||
@ -195,9 +195,9 @@ class TalkDb {
|
||||
[$messageId,$roomId,$idNextCloud]);
|
||||
}
|
||||
|
||||
public function createDevisTalkRoomMessageAndReturnMessage($roomId,$message){
|
||||
public function createDevisTalkRoomMessageAndReturnMessage($roomId,$message,$senderUser){
|
||||
$this->createDevisTalkRoomMessage(
|
||||
BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD,
|
||||
$senderUser,
|
||||
$message,
|
||||
self::DEVIS_TALK_ROOM_VERB_COMMENT,
|
||||
$roomId,
|
||||
|
||||
@ -64,4 +64,71 @@ class DateHelpers
|
||||
return $lastDay;
|
||||
}
|
||||
|
||||
public static function getDaysCountInAMonthAndYear($month,$year){
|
||||
return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31);
|
||||
}
|
||||
|
||||
public static function getDatesOfMonth($year, $month) {
|
||||
$dates = [];
|
||||
$daysInMonth = self::getDaysCountInAMonthAndYear($month, $year);
|
||||
|
||||
for ($day = 1; $day <= $daysInMonth; $day++) {
|
||||
$dateString = sprintf("%04d-%02d-%02d", $year, $month, $day);
|
||||
$dates[] = new DateTime($dateString);
|
||||
}
|
||||
|
||||
return $dates;
|
||||
}
|
||||
|
||||
public static function isPublicHoliday(string $dateString): bool
|
||||
{
|
||||
try {
|
||||
$date = new DateTime($dateString);
|
||||
$dayOfWeek = $date->format('N');
|
||||
return $dayOfWeek == 7;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getPublicHolidayText($isPublicHoliday){
|
||||
return $isPublicHoliday ? "Ferie" : "J";
|
||||
}
|
||||
|
||||
public static function getHoursBetweenTwoDatetime($datetimeEnd,$datetimeStart){
|
||||
if($datetimeEnd == null || $datetimeStart == null){
|
||||
return 0;
|
||||
}
|
||||
$interval = $datetimeStart->diff($datetimeEnd);
|
||||
$hours = $interval->h + ($interval->days * 24) + ($interval->i / 60);
|
||||
return $hours;
|
||||
}
|
||||
|
||||
public static function GetWorkingHoursBetweenDatetimeEndAndDatetimeStart(Datetime|null $datetimeEnd,Datetime|null $datetimeStart){
|
||||
if($datetimeEnd == null || $datetimeStart == null){
|
||||
return 0;
|
||||
}
|
||||
$workingStartAM = new DateTime($datetimeStart->format('Y-m-d') . ' 08:00',$datetimeStart->getTimezone());
|
||||
$workingEndAM = new DateTime($datetimeStart->format('Y-m-d') . ' 12:00',$datetimeStart->getTimezone());
|
||||
$workingStartPM = new DateTime($datetimeStart->format('Y-m-d') . ' 13:00',$datetimeStart->getTimezone());
|
||||
$workingEndPM = new DateTime($datetimeStart->format('Y-m-d') . ' 17:00',$datetimeStart->getTimezone());
|
||||
$totalHours = 0;
|
||||
if ($datetimeStart->format('N') < 7) {
|
||||
$dayStartAM = max($datetimeStart, $workingStartAM);
|
||||
$dayEndAM = min($datetimeEnd, $workingEndAM);
|
||||
if ($dayStartAM < $dayEndAM) {
|
||||
$totalHours += ($dayEndAM->getTimestamp() - $dayStartAM->getTimestamp()) / 3600;
|
||||
}
|
||||
$dayStartPM = max($datetimeStart, $workingStartPM);
|
||||
$dayEndPM = min($datetimeEnd, $workingEndPM);
|
||||
if ($dayStartPM < $dayEndPM) {
|
||||
$totalHours += ($dayEndPM->getTimestamp() - $dayStartPM->getTimestamp()) / 3600;
|
||||
}
|
||||
}
|
||||
else{
|
||||
$totalHours = ($datetimeEnd->getTimestamp() - $datetimeStart->getTimestamp()) / 3600;
|
||||
}
|
||||
return $totalHours;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
namespace OCA\Gestion\Helpers;
|
||||
|
||||
use OCA\Gestion\Constants\VCalendarPropertyConstant;
|
||||
|
||||
class FileExportHelpers
|
||||
{
|
||||
|
||||
@ -37,4 +39,16 @@ class FileExportHelpers
|
||||
return $stringWithoutSpace;
|
||||
}
|
||||
|
||||
public static function GetAbsenceTypeLabelFromKey(string $key){
|
||||
$label = null;
|
||||
$absenceTypes = VCalendarPropertyConstant::ABSENCE_TYPES_KEYS_VALUES;
|
||||
foreach($absenceTypes as $absenceTypeKey => $absenceTypeLabel){
|
||||
if($absenceTypeKey == $key){
|
||||
$label = $absenceTypeLabel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $label;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
12
gestion/lib/Helpers/FolderHelpers.php
Normal file
12
gestion/lib/Helpers/FolderHelpers.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\Gestion\Helpers;
|
||||
|
||||
class FolderHelpers
|
||||
{
|
||||
public static function GetDefuntFolder(string $clientEntreprise,string $defuntNom){
|
||||
$clientRacineFolder = 'CLIENTS/'.strtoupper($clientEntreprise).'/';
|
||||
$defuntFolder = $clientRacineFolder.'DEFUNTS/'.strtoupper($defuntNom).'/';
|
||||
return $defuntFolder;
|
||||
}
|
||||
}
|
||||
17
gestion/lib/Helpers/GeoHelpers.php
Normal file
17
gestion/lib/Helpers/GeoHelpers.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace OCA\Gestion\Helpers;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use Exception;
|
||||
use IntlDateFormatter;
|
||||
|
||||
class GeoHelpers
|
||||
{
|
||||
public static function getPointsTextFromLatitudeAndLongitude($latitude,$longitude): string
|
||||
{
|
||||
return (string)$latitude.','.(string)$longitude;
|
||||
}
|
||||
|
||||
}
|
||||
@ -8,30 +8,29 @@ use Exception;
|
||||
|
||||
class VCalendarHelpers
|
||||
{
|
||||
|
||||
public static function GetValueFromKeyInVCalendarString(string $key, string $vCalendarString): string
|
||||
|
||||
public static function GetValueFromKeyInVCalendarString(string $key, string $vCalendarString , ): string
|
||||
{
|
||||
$value = "";
|
||||
preg_match("/$key:(.*)\r\n/", $vCalendarString, $matches);
|
||||
if (isset($matches[1])) {
|
||||
$value = trim($matches[1]);
|
||||
}
|
||||
return $value;
|
||||
if (isset($matches[1])) {
|
||||
$value = trim($matches[1]);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function GetDateStartOrDateEndFromVCalendarString(string $key, string $vCalendarString)
|
||||
{
|
||||
preg_match("/$key;TZID=([^:]+):(\d+T\d+)/", $vCalendarString, $matches);
|
||||
if(!$matches){
|
||||
if (!$matches) {
|
||||
return null;
|
||||
}
|
||||
try{
|
||||
try {
|
||||
$dateTz = $matches[1];
|
||||
$datetimeString = $matches[2];
|
||||
$datetimeValue = new DateTime($datetimeString, new DateTimeZone($dateTz));
|
||||
return $datetimeValue;
|
||||
}
|
||||
catch(Exception $e){
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -39,6 +38,10 @@ class VCalendarHelpers
|
||||
public static function GetStartAndEndTimeFromVCalendarString(string $vCalendarString){
|
||||
$startTimeValue = "";
|
||||
$endTimeValue = "";
|
||||
$totalHours = 0;
|
||||
$totalWorkedHours = 0;
|
||||
$dateStart = null;
|
||||
$dateEnd = null;
|
||||
if($vCalendarString != ""){
|
||||
$dateStart = self::GetDateStartOrDateEndFromVCalendarString("DTSTART", $vCalendarString);
|
||||
if($dateStart != null){
|
||||
@ -48,17 +51,57 @@ class VCalendarHelpers
|
||||
if($dateEnd != null){
|
||||
$endTimeValue = $dateEnd->format("H") . "h";
|
||||
}
|
||||
$totalHours = DateHelpers::getHoursBetweenTwoDatetime($dateEnd,$dateStart);
|
||||
$totalWorkedHours = DateHelpers::GetWorkingHoursBetweenDatetimeEndAndDatetimeStart($dateEnd,$dateStart);
|
||||
}
|
||||
return [
|
||||
"datetimeStart" => $dateStart,
|
||||
"datetimeEnd" => $dateEnd,
|
||||
"startTime" => $startTimeValue,
|
||||
"endTime" => $endTimeValue
|
||||
"endTime" => $endTimeValue,
|
||||
"totalHours" => $totalHours,
|
||||
"totalWorkedHours" => $totalWorkedHours
|
||||
];
|
||||
}
|
||||
|
||||
public static function ReadVCalendarDataBlob($vCalendarData){
|
||||
|
||||
public static function ReadVCalendarDataBlob($vCalendarData)
|
||||
{
|
||||
if (is_resource($vCalendarData)) {
|
||||
return stream_get_contents($vCalendarData);
|
||||
}
|
||||
return $vCalendarData;
|
||||
return stream_get_contents($vCalendarData);
|
||||
}
|
||||
return $vCalendarData;
|
||||
}
|
||||
|
||||
public static function hasAttachment(string $vCalendarString): bool
|
||||
{
|
||||
return str_contains($vCalendarString, 'ATTACH;FMTTYPE');
|
||||
}
|
||||
|
||||
public static function hasEmailIdInVCalendar(string $vCalendarString): bool
|
||||
{
|
||||
return self::getEmailIdInVCalendar("EMAILID", $vCalendarString) ? true : false;
|
||||
}
|
||||
|
||||
public static function getEmailIdInVCalendar(string $vCalendarString): string|int|null
|
||||
{
|
||||
return self::GetValueFromKeyInVCalendarString("EMAILID", $vCalendarString) ?? null;
|
||||
}
|
||||
|
||||
public static function extractAttachments(string $vCalendarString): array
|
||||
{
|
||||
$attachments = [];
|
||||
$vCalendarString = preg_replace("/\r\n|\n|\r/", "\n", $vCalendarString);
|
||||
$vCalendarString = preg_replace("/\n[ \t]/", "", $vCalendarString);
|
||||
preg_match_all('/ATTACH;FMTTYPE=([^;]+);FILENAME=([^;]+);X-NC-FILE-ID=(\d+)/', $vCalendarString, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
$attachments[] = [
|
||||
'type' => explode("/", $match[1])[0],
|
||||
'mime_type' => $match[1],
|
||||
'name' => trim($match[2], '/'),
|
||||
'file_id' => (int) $match[3],
|
||||
];
|
||||
}
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ use OCA\DAV\Events\CalendarObjectCreatedEvent;
|
||||
use OCA\Gestion\Service\GestionService;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\IRequest;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class CalendarObjectCreatedListener implements IEventListener {
|
||||
@ -39,9 +40,14 @@ class CalendarObjectCreatedListener implements IEventListener {
|
||||
/** @var GestionService */
|
||||
private $gestionService;
|
||||
|
||||
/** @var IRequest */
|
||||
private $request;
|
||||
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
LoggerInterface $logger,GestionService $gestionService) {
|
||||
$this->logger = $logger;
|
||||
$this->request = $request;
|
||||
$this->gestionService = $gestionService;
|
||||
}
|
||||
|
||||
@ -49,9 +55,12 @@ class CalendarObjectCreatedListener implements IEventListener {
|
||||
if (!($event instanceof CalendarObjectCreatedEvent)) {
|
||||
return;
|
||||
}
|
||||
$cookie = $this->request->getHeader("Cookie");
|
||||
|
||||
|
||||
$calendarData = $event->getObjectData();
|
||||
$vCalendarString = $calendarData["calendardata"];
|
||||
$this->gestionService->HandleCreatedCalendarObject($vCalendarString);
|
||||
$this->gestionService->HandleCreatedCalendarObject($vCalendarString , $cookie);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ use OCA\DAV\Events\CalendarObjectUpdatedEvent;
|
||||
use OCA\Gestion\Service\GestionService;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\IRequest;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class CalendarObjectUpdatedListener implements IEventListener {
|
||||
@ -40,19 +41,25 @@ class CalendarObjectUpdatedListener implements IEventListener {
|
||||
/** @var GestionService */
|
||||
private $gestionService;
|
||||
|
||||
/** @var IRequest */
|
||||
private $request;
|
||||
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
LoggerInterface $logger,GestionService $gestionService) {
|
||||
$this->logger = $logger;
|
||||
$this->gestionService = $gestionService;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function handle(Event $event): void {
|
||||
if (!($event instanceof CalendarObjectUpdatedEvent)) {
|
||||
return;
|
||||
}
|
||||
$cookie = $this->request->getHeader("Cookie");
|
||||
$calendarData = $event->getObjectData();
|
||||
$vCalendarString = $calendarData["calendardata"];
|
||||
$this->gestionService->HandleUpdatedCalendarObject($vCalendarString);
|
||||
$this->gestionService->HandleUpdatedCalendarObject($vCalendarString,$cookie);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -26,11 +26,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Gestion\Service;
|
||||
|
||||
use OCA\Gestion\Constants\OrderTypeConstant;
|
||||
use OCA\Gestion\Constants\ThanatoTypeConstant;
|
||||
use OCA\Gestion\Constants\AbsenceTypeConstant;
|
||||
use OCA\Gestion\Constants\BddConstant;
|
||||
use OCA\Gestion\Db\Bdd;
|
||||
use OCA\Gestion\Helpers\DateHelpers;
|
||||
use OCA\Gestion\Helpers\FileExportHelpers;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use OCP\Files\IRootFolder;
|
||||
|
||||
class ExportThanatoStatisticService {
|
||||
/** @var Bdd */
|
||||
@ -39,35 +41,70 @@ class ExportThanatoStatisticService {
|
||||
/** @var LoggerInterface */
|
||||
private $logger;
|
||||
|
||||
/** @var IRootFolder */
|
||||
private $rootFolder;
|
||||
|
||||
private $geoService;
|
||||
|
||||
public function __construct(
|
||||
Bdd $gestionBdd,
|
||||
LoggerInterface $logger) {
|
||||
LoggerInterface $logger,
|
||||
IRootFolder $rootFolder,
|
||||
GeoService $geoService) {
|
||||
$this->geoService = $geoService;
|
||||
$this->rootFolder = $rootFolder;
|
||||
$this->logger = $logger;
|
||||
$this->gestionBdd = $gestionBdd;
|
||||
}
|
||||
|
||||
public function getThanatoStatisticFolders($thanatoList,$year){
|
||||
$thanatoStatFolders = ['STATISTIQUES/THANATOS/'];
|
||||
foreach($thanatoList as $thanato){
|
||||
if($thanato['fk_thanato_type_key'] == ThanatoTypeConstant::THANATO_TYPE_SUBCONTRACTOR){
|
||||
$thanatoStatFolders[] = 'STATISTIQUES/FOURNISSEURS/'.$year.'/';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $thanatoStatFolders;
|
||||
}
|
||||
|
||||
public function getFilename(array $thanatoList,$month,$year){
|
||||
private function getFilename($thanatoName,$thanatoLastName,$month,$year){
|
||||
$filename = "$year-$month-";
|
||||
foreach($thanatoList as $thanato){
|
||||
$filename .= $thanato['thanato_nom'] . '-' . $thanato['thanato_prenom'] . '--';
|
||||
}
|
||||
$filename = rtrim($filename, '-');
|
||||
$filename .= $thanatoName . '-' . $thanatoLastName;
|
||||
$filename = str_replace(' ','-', $filename);
|
||||
$filename = str_replace(' ','-', $filename);
|
||||
return $filename;
|
||||
}
|
||||
|
||||
private function exportThanatoStatistic($thanatoId,$month,$year,$idNextcloud){
|
||||
$thanato = $this->gestionBdd->getThanatoById($thanatoId);
|
||||
if($thanato == null){
|
||||
return null;
|
||||
}
|
||||
$exportData = $this->gestionBdd->getExportThanatoStatisticData($thanatoId,$month,$year);
|
||||
if(empty($exportData)){
|
||||
return null;
|
||||
}
|
||||
$defaultConfig = json_decode($this->gestionBdd->getConfiguration(BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD));
|
||||
$racineFolder = html_entity_decode($defaultConfig[0]->path).'/';
|
||||
$thanatoFolder = $racineFolder.'STATISTIQUES/THANATOS/';
|
||||
$fileHeader = $this->getExportThanatoFileHeader();
|
||||
$fileContent = $this->populateExportDataIntoFileContent($exportData,$fileHeader);
|
||||
$storage = $this->rootFolder->getUserFolder($idNextcloud);
|
||||
try{
|
||||
$storage->newFolder($thanatoFolder);
|
||||
}
|
||||
catch(\OCP\Files\NotPermittedException $e) {
|
||||
|
||||
}
|
||||
$filename = $this->getFilename($thanato["nom"],$thanato["prenom"],$month,$year);
|
||||
$fileNamePath = $thanatoFolder."STAT-THANATO-" . $filename . '.csv';
|
||||
$storage->newFile($fileNamePath);
|
||||
$file = $storage->get($fileNamePath);
|
||||
$file->putContent($fileContent);
|
||||
return $fileNamePath;
|
||||
}
|
||||
|
||||
public function exportThanatosListStatistic(array $thanatoIds,$month,$year,$idNextcloud){
|
||||
$filenames = [];
|
||||
foreach($thanatoIds as $thanatoId){
|
||||
$filename = $this->exportThanatoStatistic($thanatoId,$month,$year,$idNextcloud);
|
||||
if($filename != null){
|
||||
$filenames[] = $filename;
|
||||
}
|
||||
}
|
||||
return $filenames;
|
||||
}
|
||||
|
||||
public function getExportThanatoFileHeader(): string{
|
||||
$fileHeader =
|
||||
'FACTURE'.';'.
|
||||
@ -77,34 +114,144 @@ class ExportThanatoStatisticService {
|
||||
'HEURE DE FIN'.';'.
|
||||
'SOINS'.';'.
|
||||
'JOUR/FERIE'.';'.
|
||||
'CONGE'.';'.
|
||||
'REPOS'.';'.
|
||||
'MALADIE'.';'.
|
||||
'NOM ET PRENOM'.';'.
|
||||
'LIEU'.';'.
|
||||
'POMPES FUNEBRES'.';'.
|
||||
'ADRESSE'.';'.
|
||||
'BON DE COMMANDE'.';'.
|
||||
'TOTAL ACHAT'.';'.
|
||||
'DISTANCE TOTALE KM'.';'.
|
||||
'HEURES TOTAL DE SOIN'.';'.
|
||||
'HEURES TOTAL DE CONGE'.';'.
|
||||
'HEURES TOTAL DE REPOS'.';'.
|
||||
'HEURES TOTAL DE MALADIE'.';'.
|
||||
'HEURES TOTAL DE TRAVAIL'.';'.
|
||||
'HEURES TOTAL DE PARCOURS ENTRE DEVIS'.';'.
|
||||
"\n";
|
||||
return $fileHeader;
|
||||
}
|
||||
|
||||
private function populateNoDevisDataInADay(string $fileContent,$leave){
|
||||
$startTimeValue = "";
|
||||
$endTimeValue = "";
|
||||
$leaveValue = "Non";
|
||||
$diseaseValue = "Non";
|
||||
$restValue = "Non";
|
||||
if($leave["onLeave"]){
|
||||
$startTimeValue = $leave["startTime"];
|
||||
$endTimeValue = $leave["endTime"];
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::LEAVE){
|
||||
$leaveValue = "Oui";
|
||||
}
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::DISEASE){
|
||||
$diseaseValue = "Oui";
|
||||
}
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::REST){
|
||||
$restValue = "Oui";
|
||||
}
|
||||
}
|
||||
$fileContent = $fileContent.
|
||||
''.';'.
|
||||
FileExportHelpers::FormatTextForExport($leave['thanatoName']).';'.
|
||||
$leave['date'].';'.
|
||||
$startTimeValue.';'.
|
||||
$endTimeValue.';'.
|
||||
''.';'.
|
||||
DateHelpers::getPublicHolidayText($leave['isPublicHoliday']).';'.
|
||||
$leaveValue.';'.
|
||||
$restValue.';'.
|
||||
$diseaseValue.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'."\n";
|
||||
return $fileContent;
|
||||
}
|
||||
|
||||
public function populateExportDataIntoFileContent(array $exportData,string $fileContent): string{
|
||||
foreach($exportData as $thanatoId => $devisPerThanato){
|
||||
foreach($devisPerThanato as $devisDate => $devisData){
|
||||
$distanceTotal = $this->gestionBdd->getDistanceTotalByDevisIdList($devisData["devisId"]);
|
||||
foreach($exportData as $devisDate => $devisData){
|
||||
$totalDevisHours = 0;
|
||||
$totalWorkedHours = 8;
|
||||
$totalLeaveHours = 0;
|
||||
$totalDiseaseHours = 0;
|
||||
$totalRestHours = 0;
|
||||
$totalDistance = 0;
|
||||
$totalTravelingHoursBetweenDevisLocation = 0;
|
||||
$hasDevisInTheCurrentDate = $devisData['hasDevis'];
|
||||
if($hasDevisInTheCurrentDate === false){
|
||||
$leaves = $devisData["leaves"];
|
||||
foreach($leaves as $leave){
|
||||
$fileContent = $this->populateNoDevisDataInADay($fileContent,$leave);
|
||||
if($leave["onLeave"]){
|
||||
$totalLeaveHoursInsideWorkingHours = $leave["totalWorkedHours"];
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::LEAVE){
|
||||
$totalLeaveHours += $totalLeaveHoursInsideWorkingHours;
|
||||
}
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::REST){
|
||||
$totalRestHours += $totalLeaveHoursInsideWorkingHours;
|
||||
}
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::DISEASE){
|
||||
$totalDiseaseHours += $totalLeaveHoursInsideWorkingHours;
|
||||
}
|
||||
}
|
||||
}
|
||||
$totalAbsenceHours = $totalLeaveHours + $totalRestHours + $totalDiseaseHours;
|
||||
$totalWorkedHours -= $totalAbsenceHours;
|
||||
}
|
||||
else{
|
||||
$routeLines = $this->gestionBdd->getRouteLinesByDevisIdList($devisData["devisId"]);
|
||||
$totalDistanceAndTotalTravelingHoursBetweenDevis = $this->geoService->getTotalDistanceAndTotalTravelingHoursBetweenDevisLocationByRouteLines($routeLines);
|
||||
$totalDistance = $totalDistanceAndTotalTravelingHoursBetweenDevis["totalDistance"];
|
||||
$totalTravelingHoursBetweenDevisLocation = $totalDistanceAndTotalTravelingHoursBetweenDevis["totalTravelingHours"];
|
||||
$devisList = $devisData["devis"];
|
||||
$leaves = $devisData["leaves"];
|
||||
if(!empty($devisList)){
|
||||
foreach($devisList as $devis){
|
||||
$fileContent = $this->populateDevisDataIntoThanatoExportFileContent($fileContent,$devis);
|
||||
$totalDevisHours += $devis["totalHours"];
|
||||
}
|
||||
$fileContent = $this->populateDistanceTotalIntoThanatoExportFileContent($fileContent,$distanceTotal);
|
||||
}
|
||||
foreach($leaves as $leave){
|
||||
$fileContent = $this->populateNoDevisDataInADay($fileContent,$leave);
|
||||
if($leave["onLeave"]){
|
||||
$totalLeaveHoursInsideWorkingHours = $leave["totalWorkedHours"];
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::LEAVE){
|
||||
$totalLeaveHours += $totalLeaveHoursInsideWorkingHours;
|
||||
}
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::REST){
|
||||
$totalRestHours += $totalLeaveHoursInsideWorkingHours;
|
||||
}
|
||||
if($leave["absenceTypeKey"] == AbsenceTypeConstant::DISEASE){
|
||||
$totalDiseaseHours += $totalLeaveHoursInsideWorkingHours;
|
||||
}
|
||||
}
|
||||
}
|
||||
$totalAbsenceHours = $totalLeaveHours + $totalRestHours + $totalDiseaseHours;
|
||||
$totalWorkedHours -= $totalAbsenceHours;
|
||||
}
|
||||
$fileContent = $this->populateLastRecapForTheLine(
|
||||
$fileContent,
|
||||
$totalDistance,
|
||||
$totalDevisHours,
|
||||
$totalWorkedHours,
|
||||
$totalLeaveHours,
|
||||
$totalTravelingHoursBetweenDevisLocation,
|
||||
$totalDiseaseHours,
|
||||
$totalRestHours
|
||||
);
|
||||
}
|
||||
return $fileContent;
|
||||
}
|
||||
|
||||
private function populateDistanceTotalIntoThanatoExportFileContent(string $fileContent,$distance){
|
||||
private function populateLastRecapForTheLine(string $fileContent,$distance,$totalDevisHours,$totalWorkedHours,$totalLeaveHours,$totalTravelingHours,$totalDiseaseHours = 0,$totalRestHours = 0){
|
||||
$fileContent = $fileContent.
|
||||
''.';'.
|
||||
''.';'.
|
||||
@ -119,7 +266,14 @@ class ExportThanatoStatisticService {
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
utf8_decode(html_entity_decode("$distance"))."\n";
|
||||
''.';'.
|
||||
"$distance"."KM".';'.
|
||||
"$totalDevisHours"."H".';'.
|
||||
"$totalLeaveHours"."H".';'.
|
||||
"$totalRestHours"."H".';'.
|
||||
"$totalDiseaseHours"."H".';'.
|
||||
"$totalWorkedHours"."H".';'.
|
||||
"$totalTravelingHours"."H"."\n";
|
||||
return $fileContent;
|
||||
}
|
||||
|
||||
@ -135,15 +289,6 @@ class ExportThanatoStatisticService {
|
||||
|
||||
private function populateDevisDataIntoThanatoExportFileContent(string $fileContent,array $devis){
|
||||
$produitAsString = $this->getFormatDevisProduitsAsString($devis["produits"]);
|
||||
$orderFullNumber = "";
|
||||
$totalOrderPrice = "";
|
||||
$isDevisDoneBySubContractor = $devis['fk_order_type_key'] == OrderTypeConstant::ORDER_TYPE_DEVIS &&
|
||||
$devis['order_id'] != null && $devis["fk_thanato_type_key"] == ThanatoTypeConstant::THANATO_TYPE_SUBCONTRACTOR;
|
||||
|
||||
if($isDevisDoneBySubContractor){
|
||||
$orderFullNumber = $devis["order_full_number"];
|
||||
$totalOrderPrice = $devis["total_price"];
|
||||
}
|
||||
$fileContent = $fileContent.
|
||||
FileExportHelpers::FormatTextForExport($devis["facture_num"]).';'.
|
||||
FileExportHelpers::FormatTextForExport($devis['nom_thanato'] . ' ' . $devis['prenom_thanatho']).';'.
|
||||
@ -152,12 +297,19 @@ class ExportThanatoStatisticService {
|
||||
FileExportHelpers::FormatTextForExport($devis["endTime"]).';'.
|
||||
FileExportHelpers::FormatTextForExport($produitAsString).';'.
|
||||
FileExportHelpers::FormatTextForExport($devis["dayType"]).';'.
|
||||
FileExportHelpers::FormatTextForExport('Non').';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
FileExportHelpers::FormatTextForExport($devis["nom_defunt"]).';'.
|
||||
FileExportHelpers::FormatTextForExport($devis["nom_lieu"] ?? "").';'.
|
||||
FileExportHelpers::FormatTextForExport($devis["nom_client"] ?? "").';'.
|
||||
FileExportHelpers::FormatTextForExport($devis["client_adresse"] ?? "").';'.
|
||||
FileExportHelpers::FormatTextForExport($orderFullNumber).';'.
|
||||
"$totalOrderPrice".';'.
|
||||
FileExportHelpers::FormatTextForExport($devis["client_adresse"] ?? "").
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'.
|
||||
''.';'."\n";
|
||||
|
||||
return $fileContent;
|
||||
|
||||
128
gestion/lib/Service/GeoService.php
Normal file
128
gestion/lib/Service/GeoService.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* Calendar App
|
||||
*
|
||||
* @copyright 2021 Anna Larch <anna.larch@gmx.net>
|
||||
*
|
||||
* @author Anna Larch <anna.larch@gmx.net>
|
||||
* @author Richard Steinmetz <richard@steinmetz.cloud>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Gestion\Service;
|
||||
|
||||
use Exception;
|
||||
use OCA\Gestion\Constants\GeoConstant;
|
||||
use OCA\Gestion\Helpers\GeoHelpers;
|
||||
|
||||
class GeoService {
|
||||
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcul la distance entre les deux points à vol d'oiseau
|
||||
*/
|
||||
private function getDistanceInKmBetweenTwoPoints($lat1, $lon1, $lat2, $lon2) {
|
||||
$R = 6371; // Rayon moyen de la Terre en kilomètres
|
||||
$dLat = deg2rad($lat2 - $lat1);
|
||||
$dLon = deg2rad($lon2 - $lon1);
|
||||
$a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon/2) * sin($dLon/2);
|
||||
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
|
||||
$d = $R * $c;
|
||||
return round($d, 2);
|
||||
}
|
||||
|
||||
private function getTravelingHourBetweenTwoPoints(array $origin,array $destination,$mode = "driving"){
|
||||
$baseUrl = "https://api.geoapify.com/v1/routing";
|
||||
$originPoints = GeoHelpers::getPointsTextFromLatitudeAndLongitude($origin["latitude"],$origin["longitude"]);
|
||||
$destinationPoints = GeoHelpers::getPointsTextFromLatitudeAndLongitude($destination["latitude"],$destination["longitude"]);
|
||||
|
||||
$fullUrl = $baseUrl."?waypoints=$originPoints|$destinationPoints&mode=$mode&apiKey=9e23d93e7f454c988344f9171bf867aa";
|
||||
$curl = curl_init();
|
||||
try {
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => $fullUrl,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => '',
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 0,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => 'GET',
|
||||
));
|
||||
|
||||
$response = curl_exec($curl);
|
||||
|
||||
curl_close($curl);
|
||||
|
||||
if ($response === false) {
|
||||
return 0;
|
||||
} else {
|
||||
$timeInSecondes = json_decode($response)->features[0]->properties->time;
|
||||
$travelTimeHours = $timeInSecondes / 3600;
|
||||
$travelTimeHours = round($travelTimeHours, 2);
|
||||
return $travelTimeHours;
|
||||
}
|
||||
}
|
||||
catch(Exception $e){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function getTotalDistanceAndTotalTravelingHoursBetweenDevisLocationByRouteLines(array $routeLines){
|
||||
$distanceCumul = 0;
|
||||
$totalTravelingHoursBetweenTwoDevisLocation = 0;
|
||||
$lastPoint = NULL;
|
||||
for ($i=0; $i < sizeof($routeLines); $i++) {
|
||||
$currentDistance = 0;
|
||||
if($routeLines[$i]['lieu_id'] != NULL){
|
||||
$lastPoint = $routeLines[$i];
|
||||
}
|
||||
if($lastPoint['lieu_id'] != NULL && $routeLines[$i+1]['lieu_id'] != NULL){
|
||||
$currentDistance = $this->getDistanceInKmBetweenTwoPoints(
|
||||
floatval(value: $lastPoint['latitude']),
|
||||
floatval($lastPoint['longitude']),
|
||||
floatval($routeLines[$i+1]['latitude']),
|
||||
floatval($routeLines[$i+1]['longitude'])
|
||||
);
|
||||
$targetIsBetweenTwoDevisLocation = $lastPoint['source'] != "siege" && $routeLines[$i+1]["source"] != "siege";
|
||||
if($targetIsBetweenTwoDevisLocation){
|
||||
$originPoints = [
|
||||
"latitude" => $lastPoint["latitude"],
|
||||
"longitude" => $lastPoint["longitude"]
|
||||
];
|
||||
$destinationPoints = [
|
||||
"latitude" => $routeLines[$i+1]["latitude"],
|
||||
"longitude" => $routeLines[$i+1]["longitude"]
|
||||
];
|
||||
$totalTravelingHoursBetweenTwoDevisLocation+= $this->getTravelingHourBetweenTwoPoints(
|
||||
$originPoints,
|
||||
$destinationPoints,
|
||||
GeoConstant::DRIVING_MODE
|
||||
);
|
||||
}
|
||||
}
|
||||
$distanceCumul += $currentDistance;
|
||||
}
|
||||
return [
|
||||
"totalDistance" => $distanceCumul,
|
||||
"totalTravelingHours" => $totalTravelingHoursBetweenTwoDevisLocation
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -26,17 +26,30 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Gestion\Service;
|
||||
|
||||
use OCP\IConfig;
|
||||
use OCP\DB\Exception;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Mail\IMailer;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use OCA\Gestion\Db\Bdd;
|
||||
use OC\Files\Filesystem;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCA\Gestion\Db\OrderBdd;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use OCA\Mail\Contracts\IMailManager;
|
||||
use OCA\Mail\IMAP\IMAPClientFactory;
|
||||
use OCA\Mail\Service\AccountService;
|
||||
use OCA\Gestion\Constants\BddConstant;
|
||||
use OCA\Gestion\Constants\DevisMentionConstant;
|
||||
use OCA\Gestion\Helpers\FolderHelpers;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use OCA\Gestion\Helpers\VCalendarHelpers;
|
||||
use OCA\Gestion\Constants\OrderStatusConstant;
|
||||
use OCA\Gestion\Constants\ThanatoTypeConstant;
|
||||
use OCA\Gestion\Db\Bdd;
|
||||
use OCA\Gestion\Db\OrderBdd;
|
||||
use OCA\Gestion\Service\Devis\Pdf\DevisPdfService;
|
||||
use OCA\Gestion\Service\Order\OrderPdfService;
|
||||
use OCP\DB\Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use OCA\Gestion\Helpers\VCalendarHelpers;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCA\Gestion\Constants\DevisMentionConstant;
|
||||
use OCA\Gestion\Service\Devis\Pdf\DevisPdfService;
|
||||
use OCA\Gestion\Constants\VCalendarPropertyConstant;
|
||||
|
||||
class GestionService {
|
||||
/** @var Bdd */
|
||||
@ -53,19 +66,57 @@ class GestionService {
|
||||
private $orderPdfService;
|
||||
private $devisPdfService;
|
||||
|
||||
private string $userConnectedUuid;
|
||||
|
||||
private $userConnectedStorage;
|
||||
|
||||
private $mailer;
|
||||
|
||||
protected $config;
|
||||
|
||||
private IMailManager $mailManager;
|
||||
|
||||
private $accountService;
|
||||
|
||||
private IMAPClientFactory $clientFactory;
|
||||
|
||||
private ?string $currentUserId;
|
||||
|
||||
|
||||
public function __construct(
|
||||
?string $UserId,
|
||||
Bdd $gestionBdd,
|
||||
OrderBdd $orderBdd,
|
||||
LoggerInterface $logger,
|
||||
OrderPdfService $orderPdfService,
|
||||
DevisPdfService $devisPdfService,
|
||||
TalkService $talkService) {
|
||||
TalkService $talkService,
|
||||
IUserSession $userSession,
|
||||
IRootFolder $rootFolder,
|
||||
IMailer $mailer,
|
||||
IConfig $config,
|
||||
IMailManager $mailManager,
|
||||
AccountService $accountService,
|
||||
IMAPClientFactory $clientFactory,
|
||||
|
||||
|
||||
) {
|
||||
$this->currentUserId = $UserId;
|
||||
$this->orderBdd = $orderBdd;
|
||||
$this->logger = $logger;
|
||||
$this->gestionBdd = $gestionBdd;
|
||||
$this->orderPdfService = $orderPdfService;
|
||||
$this->devisPdfService = $devisPdfService;
|
||||
$this->talkService = $talkService;
|
||||
$this->userConnectedUuid = $userSession->getUser()?->getUID() ?? BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD;
|
||||
$this->userConnectedStorage = $rootFolder->getUserFolder($this->userConnectedUuid);
|
||||
$this->mailer = $mailer;
|
||||
$this->config = $config;
|
||||
$this->mailManager = $mailManager;
|
||||
$this->accountService = $accountService;
|
||||
$this->clientFactory = $clientFactory;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private function GetCalendarSummaryFromVCalendarString(string $vCalendarString): string
|
||||
@ -160,8 +211,29 @@ class GestionService {
|
||||
return $calendarStartDate;
|
||||
}
|
||||
|
||||
public function HandleCreatedCalendarObject(string $vCalendarString){
|
||||
private function GetIsPivateFromVCalendarString(string $vCalendarString): bool{
|
||||
$isPrivateValue = VCalendarHelpers::GetValueFromKeyInVCalendarString(VCalendarPropertyConstant::PROPERTY_IS_LEAVE, $vCalendarString);
|
||||
return $isPrivateValue === "1" ? true : false;
|
||||
}
|
||||
private function GetDevisCommentFromVCalendarString(string $vCalendarString){
|
||||
$commentValue = VCalendarHelpers::GetValueFromKeyInVCalendarString("COMMENT", $vCalendarString);
|
||||
if($commentValue == ""){
|
||||
$commentValue = "Commentaire";
|
||||
}
|
||||
return $commentValue;
|
||||
}
|
||||
|
||||
public function HandleCreatedCalendarObject(string $vCalendarString ,$cookie){
|
||||
try{
|
||||
|
||||
|
||||
$isPrivate = $this->GetIsPivateFromVCalendarString($vCalendarString);
|
||||
$absenceType = VCalendarHelpers::GetValueFromKeyInVCalendarString('ABSENCETYPE',$vCalendarString);
|
||||
if($isPrivate || $absenceType){
|
||||
//Nothing to do manage fo a private calendar
|
||||
return;
|
||||
}
|
||||
|
||||
$thanato = $this->GetThanatoFromVCalendarString($vCalendarString);
|
||||
if($thanato != null){
|
||||
$thanatoId = $thanato["id"];
|
||||
@ -175,13 +247,16 @@ class GestionService {
|
||||
$calendarUuid = $this->GetCalendarUuidFromVCalendarString($vCalendarString);
|
||||
$userName = $this->GetThanatoNameFromVCalendarString($vCalendarString);
|
||||
$devisAlreadyCreated = $this->IsDevisAlreadyCreated($clientId,$locationId,$thanatoId,$calendarSummary,$calendarUuid);
|
||||
|
||||
|
||||
if($devisAlreadyCreated){
|
||||
return;
|
||||
}
|
||||
$defuntId = $this->gestionBdd->insertDefuntByNameAndReturnId($calendarSummary);
|
||||
$calendarStartDate = $this->GetCalendarDateFromVCalendarString($vCalendarString);
|
||||
$devisDate = $calendarStartDate->format('Y-m-d');
|
||||
$devisId = $this->gestionBdd->insertDevisFromVCalendarAndReturnId($thanatoId,$clientId,$locationId,$defuntId,$calendarUuid,$devisDate,$userName);
|
||||
$devisComment = $this->GetDevisCommentFromVCalendarString($vCalendarString);
|
||||
$devisDate = $calendarStartDate->format(format: 'Y-m-d');
|
||||
$devisId = $this->gestionBdd->insertDevisFromVCalendarAndReturnId($thanatoId,$clientId,$locationId,$defuntId,$devisComment,$calendarUuid,$devisDate,$userName);
|
||||
$articlesValue = $this->GetArticlesNameFromVCalendarString($vCalendarString);
|
||||
if(!empty($articlesValue)){
|
||||
$articleIds = $this->gestionBdd->getArticleIdsByArticleReferences($articlesValue);
|
||||
@ -194,15 +269,45 @@ class GestionService {
|
||||
$order = $this->orderBdd->getOrderByDevisId($devisId);
|
||||
$this->logger->debug(json_encode($order));
|
||||
if($order != null){
|
||||
$this->orderPdfService->generateOrderPdfByOrderId($order['id'],BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD);
|
||||
$this->orderPdfService->generateOrderPdfByOrderId($order['id'],BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD);
|
||||
$this->orderPdfService->generateOrderPdfByOrderId($order['id'],$this->userConnectedUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
$devisTalkMessage = $this->gestionBdd->getDevisTalkRoomMessage($devisId,$userName);
|
||||
$this->talkService->sendDevisTalkNotifications($devisTalkMessage,$userName);
|
||||
$this->devisPdfService->generateDevisPdfByDevisId($devisId,BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD);
|
||||
$this->devisPdfService->generateDevisPdfByDevisId($devisId,BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD);
|
||||
$this->talkService->sendDevisTalkNotifications($devisTalkMessage,$userName,$this->userConnectedUuid);
|
||||
$this->devisPdfService->generateDevisPdfByDevisId($devisId,$this->userConnectedUuid);
|
||||
//Move calendar attachment file to defunt folder
|
||||
if (VCalendarHelpers::hasAttachment($vCalendarString)) {
|
||||
$devis = $this->gestionBdd->getDevisByDevisId($devisId);
|
||||
if($devis != null && $devis["client_entreprise"] != null){
|
||||
$destinationFolderAttachment = FolderHelpers::GetDefuntFolder($devis["client_entreprise"],$devis["defunt_nom"]);
|
||||
$attachments = VCalendarHelpers::extractAttachments($vCalendarString);
|
||||
|
||||
|
||||
|
||||
$this->moveCalendarAttachmentFile($attachments,$destinationFolderAttachment);
|
||||
if ($thanatoIsSubcontractor) {
|
||||
$thanatoHasEmail = $thanato["thanato_email"] != null;
|
||||
if($thanatoHasEmail){
|
||||
$emailBody = $this->extractBodyOfEmailAttachment(VCalendarHelpers::getEmailIdInVCalendar($vCalendarString));
|
||||
$this->sendEmailAndAttachment($thanato["thanato_email"] , $devis["defunt_nom"],$emailBody ,$attachments);
|
||||
}
|
||||
}else {
|
||||
$roomToken = $this->talkService->getRoomTokenBeetwenTwoUser($this->userConnectedUuid, $userName);
|
||||
if($roomToken != null){
|
||||
foreach ( $attachments as $attachment) {
|
||||
$this->userConnectedStorage->getFullPath("/");
|
||||
$path = Filesystem::getPath($attachment['file_id']);
|
||||
$destination = 'Talk/';
|
||||
Filesystem::copy($path, $destination . $attachment['name']);
|
||||
$this->sendFileAttachmentToTalk($roomToken,$cookie , $attachment['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$this->gestionBdd->createDevisTrajetFromVCalendar($devisId,$userName);
|
||||
}
|
||||
catch(Exception $e){
|
||||
@ -210,6 +315,14 @@ class GestionService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function moveCalendarAttachmentFile(array $attachments ,string $destinationFolder ){
|
||||
$this->userConnectedStorage->getFullPath("/");
|
||||
foreach ($attachments as $attachment) {
|
||||
$path = Filesystem::getPath($attachment['file_id']);
|
||||
Filesystem::copy($path, $destinationFolder . $attachment['name']);
|
||||
}
|
||||
}
|
||||
private function GetThanatoNameFromVCalendarString($vCalendarString){
|
||||
$thanatoName = null;
|
||||
$thanatoNames = $this->GetAttendeesNameFromVCalendarString($vCalendarString);
|
||||
@ -274,7 +387,10 @@ class GestionService {
|
||||
$requestedClientId = $this->GetClientIdFromVCalendarString($vCalendarString);
|
||||
$requestLocationId = $this->GetLocationIdFromVCalendarString($vCalendarString);
|
||||
$requestedArticleReferences = $this->GetArticlesNameFromVCalendarString($vCalendarString);
|
||||
$requestedDevisComment = $this->GetDevisCommentFromVCalendarString($vCalendarString);
|
||||
$requestedArticleIds = $this->gestionBdd->getArticleIdsByArticleReferences($requestedArticleReferences);
|
||||
$requestedDevisDate = $this->GetCalendarDateFromVCalendarString($vCalendarString);
|
||||
$requestedDevisDate = $requestedDevisDate->format('Y-m-d');
|
||||
$articleDevis = $this->gestionBdd->getProduitDevisByDevisId($devis['id']);
|
||||
$articleDevisIds = [];
|
||||
foreach($articleDevis as $currentArticleDevis){
|
||||
@ -287,6 +403,8 @@ class GestionService {
|
||||
$devis['defunt_nom'] == $requestedDefuntName &&
|
||||
$devis['client_id'] == $requestedClientId &&
|
||||
$devis['lieu_id'] == $requestLocationId &&
|
||||
$devis['comment'] == $requestedDevisComment &&
|
||||
$devis['date'] == $requestedDevisDate &&
|
||||
$requestedArticleIds == $articleDevisIds;
|
||||
}
|
||||
|
||||
@ -301,6 +419,13 @@ class GestionService {
|
||||
$requestLocationId = $this->GetLocationIdFromVCalendarString($vCalendarString);
|
||||
$this->gestionBdd->updateDevisLieu($devis['id'],$requestLocationId,$devis['lieu_id']);
|
||||
|
||||
$requestedDevisComment = $this->GetDevisCommentFromVCalendarString($vCalendarString);
|
||||
$this->gestionBdd->updateDevisComment($devis['id'],$requestedDevisComment,$devis['comment']);
|
||||
|
||||
$requestedDevisDate = $this->GetCalendarDateFromVCalendarString($vCalendarString);
|
||||
$requestedDevisDate = $requestedDevisDate->format('Y-m-d');
|
||||
$this->gestionBdd->updateDevisDate($devis['id'],$requestedDevisDate);
|
||||
|
||||
$articlesValue = $this->GetArticlesNameFromVCalendarString($vCalendarString);
|
||||
if(!empty($articlesValue)){
|
||||
$articleIds = $this->gestionBdd->getArticleIdsByArticleReferences($articlesValue);
|
||||
@ -308,27 +433,156 @@ class GestionService {
|
||||
}
|
||||
}
|
||||
|
||||
public function HandleUpdatedCalendarObject(string $vCalendarString){
|
||||
public function HandleUpdatedCalendarObject(string $vCalendarString , $cookie){
|
||||
try{
|
||||
$isPrivate = $this->GetIsPivateFromVCalendarString($vCalendarString);
|
||||
$absenceType = VCalendarHelpers::GetValueFromKeyInVCalendarString('ABSENCETYPE',$vCalendarString);
|
||||
if($isPrivate || $absenceType){
|
||||
//Nothing to do manage fo a private calendar
|
||||
return;
|
||||
}
|
||||
|
||||
$calendarUuid = $this->GetCalendarUuidFromVCalendarString($vCalendarString);
|
||||
$devis = $this->gestionBdd->getDevisByCalendarUuid($calendarUuid);
|
||||
if($devis != null){
|
||||
$this->gestionBdd->updateDevisMention($devis['id'],DevisMentionConstant::NEW);
|
||||
$isDevisAlreadyUpdated = $this->CheckIfDevisIsAlreadyUpdated($devis,$vCalendarString);
|
||||
if($isDevisAlreadyUpdated){
|
||||
return true;
|
||||
}
|
||||
$devisIsAlreadyFactured = $devis['mentions'] == DevisMentionConstant::FACTURED || $devis['mentions'] == DevisMentionConstant::FACTURED_FORMATTED;
|
||||
$this->UpdateDevisDataByVCalendarString($devis,$vCalendarString);
|
||||
$userName = $this->GetThanatoNameFromVCalendarString($vCalendarString);
|
||||
$devisTalkMessage = $this->gestionBdd->getDevisTalkRoomMessage($devis['id'],$userName);
|
||||
$this->talkService->sendDevisTalkNotifications($devisTalkMessage,$userName);
|
||||
if($devisIsAlreadyFactured == false){
|
||||
$devisTalkMessage = $this->gestionBdd->getDevisTalkRoomMessage($devis['id'],$userName);
|
||||
$this->talkService->sendDevisTalkNotifications($devisTalkMessage,$userName,$this->userConnectedUuid);
|
||||
$this->devisPdfService->generateDevisPdfByDevisId($devis['id'],$this->userConnectedUuid);
|
||||
}
|
||||
|
||||
if (VCalendarHelpers::hasAttachment($vCalendarString) || VCalendarHelpers::hasEmailIdInVCalendar($vCalendarString)) {
|
||||
|
||||
$thanato = $this->gestionBdd->getThanatoByThanatoId($devis['id_thanato']);
|
||||
$thanatoIsSubcontractor = $thanato["fk_thanato_type_key"] === ThanatoTypeConstant::THANATO_TYPE_SUBCONTRACTOR;
|
||||
|
||||
$devis = $this->gestionBdd->getDevisByDevisId($devis['id']);
|
||||
if($devis != null && $devis["client_entreprise"] != null){
|
||||
$destinationFolderAttachment = FolderHelpers::GetDefuntFolder($devis["client_entreprise"],$devis["defunt_nom"]);
|
||||
$attachments = VCalendarHelpers::extractAttachments($vCalendarString);
|
||||
$this->moveCalendarAttachmentFile($attachments , $destinationFolderAttachment);
|
||||
if ($thanatoIsSubcontractor ) {
|
||||
$thanatoHasEmail = $thanato["thanato_email"] != null;
|
||||
if($thanatoHasEmail){
|
||||
$emailBody = $this->extractBodyOfEmailAttachment(VCalendarHelpers::getEmailIdInVCalendar($vCalendarString));
|
||||
$this->sendEmailAndAttachment($thanato["thanato_email"] , $devis["defunt_nom"],$emailBody,$attachments);
|
||||
}
|
||||
|
||||
}else{
|
||||
$roomToken = $this->talkService->getRoomTokenBeetwenTwoUser($this->userConnectedUuid, $userName);
|
||||
if($roomToken != null){
|
||||
foreach ( $attachments as $attachment) {
|
||||
$this->userConnectedStorage->getFullPath("/");
|
||||
$path = Filesystem::getPath($attachment['file_id']);
|
||||
$destination = 'Talk/';
|
||||
Filesystem::copy($path, $destination . $attachment['name']);
|
||||
//sendFileAttachmentToTalk
|
||||
$this->sendFileAttachmentToTalk($roomToken,$cookie , $attachment['name']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
$this->HandleCreatedCalendarObject($vCalendarString,$cookie);
|
||||
}
|
||||
$this->devisPdfService->generateDevisPdfByDevisId($devis['id'],BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD);
|
||||
$this->devisPdfService->generateDevisPdfByDevisId($devis['id'],BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD);
|
||||
return true;
|
||||
}
|
||||
catch(Exception $e){
|
||||
$this->logger->debug("error creating devis");
|
||||
}
|
||||
}
|
||||
|
||||
private function extractBodyOfEmailAttachment($emailId){
|
||||
$messageId = (int) $emailId;
|
||||
try {
|
||||
$message = $this->mailManager->getMessage($this->currentUserId, $messageId);
|
||||
$mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
|
||||
$account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
|
||||
|
||||
} catch (DoesNotExistException $e) {
|
||||
|
||||
}
|
||||
|
||||
$client = $this->clientFactory->getClient($account);
|
||||
try {
|
||||
$imapMessage = $this->mailManager->getImapMessage(
|
||||
$client,
|
||||
$account,
|
||||
$mailbox,
|
||||
$message->getUid(), true
|
||||
);
|
||||
$fullMessage = $imapMessage->getFullMessage($messageId);
|
||||
} finally {
|
||||
$client->logout();
|
||||
}
|
||||
|
||||
return $fullMessage["body"] ?? '';
|
||||
}
|
||||
|
||||
public function sendEmailAndAttachment($to , $defunt_nom ,$emailBody = '' ,$attachments = []){
|
||||
$this->userConnectedStorage->getFullPath("/");
|
||||
$subject = "Piece jointe";
|
||||
$body = "
|
||||
<p>Bonjour.</p>
|
||||
<p>Vous trouverez ci-dessous l'email et le(s) pièce(s) jointe(s) de « $defunt_nom ».</p>
|
||||
<p>Vous en souhaitant bonne réception</p>
|
||||
|
||||
<div>$emailBody</div>";
|
||||
|
||||
$message = $this->mailer->createMessage();
|
||||
$message->setSubject($subject);
|
||||
$message->setTo(recipients: [$to]);
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
$path = Filesystem::getPath($attachment['file_id']);
|
||||
$content = $this->mailer->createAttachment( Filesystem::file_get_contents($path),$attachment['name'],$attachment['mime_type']);
|
||||
$message->attach($content);
|
||||
}
|
||||
|
||||
$message->setHtmlBody($body);
|
||||
|
||||
$this->mailer->send($message);
|
||||
}
|
||||
|
||||
public function sendFileAttachmentToTalk($roomToken, $cookie , $fileName ) {
|
||||
try{
|
||||
$host = 'http://127.0.0.1';
|
||||
$client = \OC::$server->getHTTPClientService()->newClient();
|
||||
$token = file_get_contents("$host/ocs/v2.php/core/getcsrftoken", false, stream_context_create([
|
||||
'http' => [
|
||||
'header' => "OCS-APIRequest: true\r\n"
|
||||
]
|
||||
]));
|
||||
$client->post("$host/ocs/v2.php/apps/files_sharing/api/v1/shares", [
|
||||
'body' => [
|
||||
"path" => "//Talk/$fileName",
|
||||
"referenceId" => Uuid::uuid4()->toString(),
|
||||
"shareWith" => $roomToken,
|
||||
"shareType" => 10,
|
||||
'talkMetaData' => "{\"messageType\":\"\"}"
|
||||
],
|
||||
'headers' => [
|
||||
'Cookie' =>$cookie,
|
||||
'OCS-APIRequest' => 'true',
|
||||
'requesttoken' => $token
|
||||
]
|
||||
]);
|
||||
}
|
||||
catch(GuzzleException $e){
|
||||
$this->logger->debug("error sending file to talk");
|
||||
}
|
||||
catch(Exception $e){
|
||||
$this->logger->debug("error sending file to talk");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,10 +58,10 @@ class MenuStatisticService {
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getStats($idNextCloud){
|
||||
public function getStats($idNextCloud,$isUserThanatoOnly = false){
|
||||
$res = array();
|
||||
$res['client'] = json_decode($this->gestionBdd->numberClient($idNextCloud))[0]->c;
|
||||
$res['defunt'] = json_decode($this->gestionBdd->numberDefunt($idNextCloud))[0]->c;
|
||||
$res['defunt'] = $this->gestionBdd->numberDefunt($idNextCloud,$isUserThanatoOnly);
|
||||
$res['thanato'] = json_decode($this->gestionBdd->numberThanato($idNextCloud))[0]->c;
|
||||
$res['devis'] = json_decode($this->gestionBdd->numberDevis($idNextCloud))[0]->c;
|
||||
$res['lieu'] = json_decode($this->gestionBdd->numberLieu($idNextCloud))[0]->c;
|
||||
|
||||
@ -48,12 +48,12 @@ class TalkService {
|
||||
$this->talkDb = $talkDb;
|
||||
}
|
||||
|
||||
private function getUserDevisTalkRoomNames($idNextCloud){
|
||||
$roomNamesCreatedByUser = '["'.$idNextCloud.'","'.BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD.'"]';
|
||||
$roomNamesCreatedByAdmin = '["'.BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD.'","'.$idNextCloud.'"]';
|
||||
private function getUserDevisTalkRoomNames($target ,$senderUser){
|
||||
$roomNamesCreatedBytargetUser = '["'.$target.'","'.$senderUser.'"]';
|
||||
$roomNamesCreatedBySenderUser = '["'.$senderUser.'","'.$target.'"]';
|
||||
return [
|
||||
"createdByUser" => $roomNamesCreatedByUser,
|
||||
"createdByAdmin" => $roomNamesCreatedByAdmin
|
||||
"target" => $roomNamesCreatedBytargetUser,
|
||||
"sender" => $roomNamesCreatedBySenderUser
|
||||
];
|
||||
}
|
||||
|
||||
@ -68,36 +68,59 @@ class TalkService {
|
||||
return $randomToken;
|
||||
}
|
||||
|
||||
private function getNotificationsSubjectsParameters(){
|
||||
return '{"userType":"users","userId":"'.BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD.'"}';
|
||||
private function getNotificationsSubjectsParameters(string $senderUser){
|
||||
return '{"userType":"users","userId":"'.$senderUser.'"}';
|
||||
}
|
||||
|
||||
private function getNotificationsMessageParameters($commentId){
|
||||
return '{"commentId":"'.$commentId.'"}';
|
||||
}
|
||||
|
||||
public function sendDevisTalkNotifications(string $message,string $idNextcloud){
|
||||
if($idNextcloud === BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD || $idNextcloud === BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD){
|
||||
return true;
|
||||
|
||||
|
||||
public function sendDevisTalkNotifications(string $message,string $targetUser ,string $senderUser){
|
||||
$senderAndTargetIsTheSameUser = $targetUser == $senderUser;
|
||||
$senderUser = $senderAndTargetIsTheSameUser ? BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD : $senderUser;
|
||||
if( $targetUser === BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD && $senderUser === BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD){
|
||||
return;
|
||||
}
|
||||
$roomNames = $this->getUserDevisTalkRoomNames($idNextcloud);
|
||||
$roomNames = $this->getUserDevisTalkRoomNames($targetUser , $senderUser);
|
||||
$room = $this->talkDb->getDevisTalkRoomByNames($roomNames);
|
||||
if($room == null){
|
||||
$roomToken = $this->generateTalkRandomToken();
|
||||
$room = $this->talkDb->createDevisTalkRoomAndReturnDevisTalkRoom($idNextcloud,$roomToken);
|
||||
$initialMessage = $this->talkDb->setDevisTalkRoomInitialMessageAndReturnMessage($room['id'],$idNextcloud);
|
||||
$room = $this->talkDb->createDevisTalkRoomAndReturnDevisTalkRoom($targetUser,$senderUser, $roomToken);
|
||||
$this->talkDb->setDevisTalkRoomInitialMessageAndReturnMessage($room['id'],$targetUser);
|
||||
}
|
||||
else{
|
||||
$roomToken = $room['token'];
|
||||
}
|
||||
$devisMessage = $this->talkDb->createDevisTalkRoomMessageAndReturnMessage($room['id'],$message);
|
||||
$devisMessage = $this->talkDb->createDevisTalkRoomMessageAndReturnMessage($room['id'],$message,$senderUser);
|
||||
$this->talkDb->updateRoomLastMessage($room['id'],$devisMessage['id']);
|
||||
$this->talkDb->setAttendeeLastReadMessage($room['id'],$devisMessage['id'],BddConstant::DEFAULT_ADMIN_APP_ID_NEXTCLOUD);
|
||||
$this->talkDb->setAttendeeLastReadMessage($room['id'],$devisMessage['id'],$senderUser);
|
||||
//send notifications
|
||||
$notificationsSubjectsParameters = $this->getNotificationsSubjectsParameters();
|
||||
$notificationsSubjectsParameters = $this->getNotificationsSubjectsParameters($senderUser);
|
||||
$notificationsMessageParameters = $this->getNotificationsMessageParameters($devisMessage['id']);
|
||||
$this->talkDb->sendAttendeeNotifications($idNextcloud,$roomToken,$notificationsSubjectsParameters,$notificationsMessageParameters);
|
||||
return true;
|
||||
$this->talkDb->sendAttendeeNotifications($targetUser,$roomToken,$notificationsSubjectsParameters,$notificationsMessageParameters);
|
||||
}
|
||||
|
||||
public function getRoomTokenBeetwenTwoUser( $senderUser , $targetUser){
|
||||
$senderAndTargetIsTheSameUser = $targetUser == $senderUser;
|
||||
$senderUser = $senderAndTargetIsTheSameUser ? BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD : $senderUser;
|
||||
if( $targetUser === BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD && $senderUser === BddConstant::DEFAULT_ADMIN_ID_NEXTCLOUD){
|
||||
return null;
|
||||
}
|
||||
$roomNames = $this->getUserDevisTalkRoomNames($targetUser , $senderUser);
|
||||
$room = $this->talkDb->getDevisTalkRoomByNames($roomNames);
|
||||
if($room == null){
|
||||
$roomToken = $this->generateTalkRandomToken();
|
||||
$room = $this->talkDb->createDevisTalkRoomAndReturnDevisTalkRoom($targetUser,$senderUser, $roomToken);
|
||||
$this->talkDb->setDevisTalkRoomInitialMessageAndReturnMessage($room['id'],$targetUser);
|
||||
}
|
||||
else{
|
||||
$roomToken = $room['token'];
|
||||
}
|
||||
|
||||
return $roomToken;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
$currentUserIsAdmin = (isset($_['groups']) && in_array('admin', $_['groups']));
|
||||
|
||||
$currentUserIsAdmin = (isset($_['groups']) && in_array(OCA\Gestion\Constants\UserGroupConstant::ADMIN_GROUP_NAME, $_['groups']));
|
||||
?>
|
||||
<ul class="app-navigation">
|
||||
<li class="app-navigation-entry"><span class="navmarg"></span><b><?php p($l->t('Manage')); ?></b></li>
|
||||
@ -98,23 +99,21 @@ $currentUserIsAdmin = (isset($_['groups']) && in_array('admin', $_['groups']));
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
<li class="app-navigation-entry-submenu">
|
||||
<span class="navmarg icon-template-add"></span>
|
||||
<a class="a-entry-submenu" href="<?php echo ($_['url']['devis']); ?>">
|
||||
<?php p($l->t('Quotes')); ?>
|
||||
</a>
|
||||
<div class="app-navigation-entry-utils-submenu">
|
||||
<ul>
|
||||
<li class="app-navigation-entry-utils-counter">
|
||||
<span id="statsdevis">
|
||||
<div class="loader"></div>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<?php if ($currentUserIsAdmin): ?>
|
||||
<li class="app-navigation-entry-submenu">
|
||||
<span class="navmarg icon-template-add"></span>
|
||||
<a class="a-entry-submenu" href="<?php echo ($_['url']['devis']); ?>">
|
||||
<?php p($l->t('Quotes')); ?>
|
||||
</a>
|
||||
<div class="app-navigation-entry-utils-submenu">
|
||||
<ul>
|
||||
<li class="app-navigation-entry-utils-counter">
|
||||
<span id="statsdevis">
|
||||
<div class="loader"></div>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="app-navigation-entry-submenu">
|
||||
<span class="navmarg icon-toggle-pictures"></span>
|
||||
<a class="a-entry-submenu" href="<?php echo ($_['url']['facture']); ?>">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user