diff --git a/Layout/default/Calendar/Form.php b/Layout/default/Calendar/Form.php
new file mode 100644
index 000000000..c0e73b15f
--- /dev/null
+++ b/Layout/default/Calendar/Form.php
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1) : ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/Api/v1/CalendarApicontroller.php b/application/Api/v1/CalendarApicontroller.php
new file mode 100644
index 000000000..1125abdcb
--- /dev/null
+++ b/application/Api/v1/CalendarApicontroller.php
@@ -0,0 +1,213 @@
+addRoute("/calendar/calendarStream", "calendarStream", "GET");
+ $this->addRoute("/calendar/calendarNotify", "calendarNotify", "POST");
+ $this->addRoute("/calendar/calendarUserSubscriptions", "getcalendarUserSubscriptions", "GET");
+ $this->addRoute("/calendar/calendarUserSubscriptions", "updatecalendarUserSubscriptions", "POST");
+ $this->addRoute("/calendar/calendarUsers", "getcalendarUsers", "GET");
+ }
+
+
+ protected function calendarNotify()
+ {
+
+ $myfile = fopen(__DIR__ . "/../../../var/log/microsoft_notify_log.txt", "a") or die("Unable to open file!");
+ $get = json_encode($_GET);
+ fwrite($myfile, "\nGET: " . $get);
+ $post = serialize($_POST);
+ fwrite($myfile, "\nPOST: " . $post);
+ if ($_GET['validationToken']) {
+ echo $_GET['validationToken'];
+ die();
+ }
+ $input = file_get_contents('php://input');
+
+ fwrite($myfile, "\nINPUT: " . $input);
+ $result = 'ok';
+ CalendarModel::insertMicrosoftCalendarEvent($input);
+ die();
+ }
+
+ protected function getcalendarUsers()
+ {
+ $users = UserModel::search(['employee' => 'true']);
+ $json['data'] = $users;
+ $json['status'] = "success";
+ $result = json_encode($json);
+ echo $result;
+ die();
+ }
+
+ protected function getcalendarUserSubscriptions()
+ {
+ if ($_GET['onlymsuser']) {
+ $userSubscriptions = CalendarModel::search(array("checkSubscriptions" => 1));
+ } else {
+ $userSubscriptions = CalendarModel::getAll();
+ }
+ $json['data'] = $userSubscriptions;
+ $json['status'] = "success";
+ $result = json_encode($json);
+ echo $result;
+ die();
+ }
+
+ protected function updatecalendarUserSubscriptions()
+ {
+ $id = $this->post['id'];
+ $user_id = $this->post['user_id'];
+ $go_calendar_id = $this->post['go_calendar_id'];
+ $microsoft_id = $this->post['microsoft_id'];
+ $subscription_id = $this->post['subscription_id'];
+ $expirationDateTime = $this->post['expirationDateTime'];
+ $Calendar = new Calendar($id);
+
+ if (!($Calendar->id) || $Calendar->id != $id) {
+ $mode = "add";
+ } else {
+ $mode = "update";
+ }
+ $data = [];
+ if ($user_id) {
+ $data['user_id'] = $user_id;
+ }
+ if ($go_calendar_id) {
+ $data['go_calendar_id'] = $go_calendar_id;
+ }
+ if ($microsoft_id) {
+ $data['microsoft_id'] = $microsoft_id;
+ }
+ if ($subscription_id) {
+ $data['subscription_id'] = $subscription_id;
+ }
+ if ($expirationDateTime) {
+ $data['expirationDateTime'] = $expirationDateTime;
+ }
+ if ($mode == "add") {
+ $data['create_by'] = '154';
+ }
+ $data['edit_by'] = '154';
+ $Calendar->update($data);
+ $Calendar->save();
+ $json['status'] = "success";
+ $result = json_encode($json);
+ echo $result;
+ die();
+ }
+
+ protected function decryptString($cipherText, $password, $salt)
+ {
+ // Definiere den Algorithmus und die Länge des Initialisierungsvektors
+ $cipher = "aes-256-cbc";
+ $ivlen = openssl_cipher_iv_length($cipher);
+
+ // Dekodiere den verschlüsselten Text von base64
+ $cipherText = base64_decode($cipherText);
+
+ // Extrahiere den Initialisierungsvektor und den verschlüsselten Text
+ $iv = substr($cipherText, 0, $ivlen);
+ $cipherText = substr($cipherText, $ivlen);
+
+ // Erzeuge einen Schlüssel aus dem Passwort und dem Salt
+ $key = hash_pbkdf2("sha256", $password, $salt, 1000, 32, true);
+
+ // Entschlüssele den Text
+ $plainText = openssl_decrypt($cipherText, $cipher, $key, 0, $iv);
+
+ return $plainText;
+ }
+
+ protected function calendarStream()
+ {
+ $decstring = $this->decryptString($_GET['user'], "testpw", "testsalt");
+ date_default_timezone_set('Europe/Berlin');
+ header('Content-Type: text/event-stream');
+ header('Cache-Control: no-cache');
+ header('Connection: keep-alive');
+ $timestamp = time();
+
+ $Calendar = CalendarModel::search(array("user_id" => $decstring));
+ $rights = json_decode($Calendar[0]->rights, true);
+ if (!$Calendar[0]->rights) {
+ $allowedCalendar[] = $Calendar[0]->calendar_id;
+ } else {
+ foreach (json_decode($Calendar[0]->rights, true) as $key => $value) {
+ $allowedCalendar[] = $key;
+ }
+ }
+ if ($Calendar[0]->colors) {
+ $calendarColors = json_decode($Calendar[0]->colors, true);
+ }
+ $redis = new Redis();
+//Connecting to Redis
+ $redis->connect('172.16.5.5', '6379');
+//$redis->auth('password');
+
+ $oldoutput = "";
+ $now = floor(microtime(true) * 1000);
+ $timenow = time();
+ while (true) {
+ $colors = $redis->get('thetool_calendar_usercolors_' . $decstring);
+ if ($colors) {
+ $calendarColors = json_decode($colors, true);
+ }
+ $output = $redis->get('thetool_calendar_event_tigger');
+ $json = json_decode($output, true);
+ $message[0] = $json;
+
+
+ if ($json['time'] > $now && $output !== $oldoutput) {
+ $timenow = time();
+ // $Calendar=CalendarModel::getCalendarEvents($decstring, $json['cal_events_id']);
+ $Calendarevent = json_decode(CalendarModel::getCalendarEvents($decstring, $json['cal_events_id']), true);
+ if ($json['all_day_event'] == 1) {
+ $message[0]['start_time'] = date('Y-m-d', $json['start_time']);
+ $message[0]['end_time'] = date('Y-m-d', $json['end_time']);
+ } else {
+ $message[0]['start_time'] = date('Y-m-d H:i', $json['start_time']);
+ $message[0]['end_time'] = date('Y-m-d H:i', $json['end_time']);
+ }
+ $message[0]['event_type'] = $Calendarevent['data'][0]['event_type']['event_type'];
+ $message[0]['attachment'] = $Calendarevent['data'][0]['attachment']['attachment'];
+ $message[0]['attachments'] = $Calendarevent['data'][0]['attachments']['attachments'];
+ $message[0]['calendar_name'] = $Calendarevent['data'][0]['calendar_name']['calendar_name'];
+ $message[0]['mtime'] = $Calendarevent['data'][0]['mtime']['mtime'];
+ $message[0]['mname'] = $Calendarevent['data'][0]['mname']['mname'];
+ $message[0]['ctime'] = $Calendarevent['data'][0]['ctime']['ctime'];
+ $message[0]['cname'] = $Calendarevent['data'][0]['cname']['cname'];
+ $message[0]['busy'] = $Calendarevent['data'][0]['busy']['busy'];
+ $message[0]['calendar_id_check'] = array('calendar_id' => $json['calendar_id'], 'order' => $json['calendar_id']);;
+ $message[0]['userr'] = $Calendar[0]->calendar_id;
+ $message[0]['bgColor'] = $calendarColors[$json['calendar_id']]['bgcolor'];
+ $message[0]['txtColor'] = $calendarColors[$json['calendar_id']]['txtcolor'];
+ $message[0]['rights'] = $rights[$json['calendar_id']];
+
+ $result = json_encode($message);
+ if (in_array($message[0]['calendar_id'], $allowedCalendar)) {
+ echo "data: " . ($result) . "\n\n";
+ }
+ unset($Array);
+ $now = floor(microtime(true) * 1000);;
+ }
+ if (ob_get_level() > 0) {
+ ob_flush();
+ }
+ if ($timenow + 300 < time()) {
+ die();
+ }
+
+ flush();
+ if (connection_aborted()) die();
+ usleep(100000);
+ $oldoutput = $output;;
+ }
+ die();
+ }
+
+
+}
\ No newline at end of file
diff --git a/application/Calendar/Calendar.php b/application/Calendar/Calendar.php
new file mode 100644
index 000000000..27d8dcfb7
--- /dev/null
+++ b/application/Calendar/Calendar.php
@@ -0,0 +1,60 @@
+$name == null) {
+
+ if (!$this->id) {
+ return null;
+ }
+
+ if ($name == "creator") {
+ $this->creator = mfValuecache::singleton()->get("Worker-id-" . $this->create_by);
+ if ($this->creator === null) {
+ $this->creator = new User($this->create_by);
+ if ($this->creator->id) {
+ mfValuecache::singleton()->set("Worker-id-" . $this->create_by, $this->creator);
+ }
+ }
+ return $this->creator;
+ }
+
+ if ($name == "editor") {
+ $this->editor = mfValuecache::singleton()->get("Worker-id-" . $this->edit_by);
+ if ($this->editor === null) {
+ $this->editor = new User($this->edit_by);
+ if ($this->editor->id) {
+ mfValuecache::singleton()->set("Worker-id-" . $this->edit_by, $this->editor);
+ }
+ }
+ return $this->editor;
+ }
+
+ $classname = ucfirst($name);
+ $idfield = $name . "_id";
+ $this->$name = mfValuecache::singleton()->get("mfObjectmodel-$name-" . $this->$idfield);
+ if (!$this->$name) {
+ $this->$name = new $classname($this->$idfield);
+ }
+
+ if ($this->$name->id) {
+ mfValuecache::singleton()->set("mfObjectmodel-$name-" . $this->$name->id, $this->$name);
+ return $this->$name;
+ } else {
+ return null;
+ }
+
+ }
+
+ return $this->$name;
+ }
+
+}
\ No newline at end of file
diff --git a/application/Calendar/CalendarController.php b/application/Calendar/CalendarController.php
new file mode 100644
index 000000000..be733ad51
--- /dev/null
+++ b/application/Calendar/CalendarController.php
@@ -0,0 +1,435 @@
+needlogin = true;
+ $me = new User();
+ $me->loadMe();
+ $this->me = $me;
+ $this->layout()->set("me", $me);
+
+ if (!$me->is(["Admin"])) {
+ $this->redirect("Dashboard");
+ }
+ }
+
+ protected function detailAction()
+ {
+ $this->layout()->setTemplate("Calendar/Detail");
+ }
+
+ protected function apiAction()
+ {
+ if (!$this->me->is(["Admin"])) {
+ $return = false;
+ }
+ $do = $this->request->do;
+
+ switch ($do) {
+ case "getCalendarEvents":
+ $r = $this->request;
+ $calendarEvents = CalendarModel::getCalendarEvents($this->me->id, 0, $r);
+ return $calendarEvents;
+ die();
+ case "getCalendarEvent":
+ $r = $this->request;
+ $id = ($r->id);
+ $calendarEvents = CalendarModel::getCalendarEvent($id);
+ return $calendarEvents;
+ die();
+ case "searchCalendarEvents" :
+ $r = $this->request;
+ $calendarEvents = CalendarModel::searchCalendarEvents($r);
+ return $calendarEvents;
+ die();
+ case "getCalendarEventAttachment" :
+ $r = $this->request;
+ $id = ($r->id);
+ $this->getCalendarAttachment($id);
+ die();
+ case "getCalendarEventAttachmentTmp" :
+ $r = $this->request;
+ $id = ($r->id);
+ $name = ($r->name);
+ $this->getCalendarAttachmentTmp($id, $name);
+ die();
+ case "updateCalendarEvent":
+ $r = $this->request;
+ $calendarEvents = CalendarModel::updateCalendarEvent($r, $this->me);
+ if ($r->customer_info_check) {
+ if ($r->customer_info_type == 1) {
+ $body = $r->customer_info_text;
+ $email = new Emailnotification();
+ $email->setSubject('Inbetriebnahme');
+ $email->setBody($body);
+ $email->setFrom('termin@xinon.at', 'Terminbestätigung');
+ $email->setTo($r->customer_info_type_text);
+ $email->send();
+ } else if ($r->customer_info_type == 2) {
+ $sms = new SmsNotification();
+ $body = "Xinon Terminbestätigung:" . PHP_EOL . $r->customer_info_text;
+ $sms->setBody($body);
+ $sms->setRecipient($r->customer_info_type_text);
+ $sms->send();
+ }
+ }
+ die();
+ case "getAddress":
+ $r = $this->request;
+ $this->getAddress($r);
+
+ die();
+ case "insertCalendarEvent":
+ $r = $this->request;
+ $calendarEvents = CalendarModel::insertCalendarEvent($r, $this->me);
+ if ($r->customer_info_check) {
+ if ($r->customer_info_type == 1) {
+ $body = $r->customer_info_text;
+ $email = new Emailnotification();
+ $email->setSubject('Inbetriebnahme');
+ $email->setBody($body);
+ $email->setFrom('termin@xinon.at', 'Terminbestätigung');
+ $email->setTo($r->customer_info_type_text);
+ $email->send();
+ } else if ($r->customer_info_type == 2) {
+ $sms = new SmsNotification();
+ $body = "Xinon Terminbestätigung:" . PHP_EOL . $r->customer_info_text;
+ $sms->setBody($body);
+ $sms->setRecipient($r->customer_info_type_text);
+ $sms->send();
+ }
+ }
+ die();
+ case "deleteCalendarEvent":
+ $r = $this->request;
+ $id = ($r->id);
+ CalendarModel::deleteCalendarEvent($r);
+ die();
+ case "updateCalendarColor":
+ $r = $this->request;
+ $calendar_id = ($r->calendar_id);
+ $bgcolors = ($r->bgcolors);
+ $txtcolors = ($r->txtcolors);
+ $id = ($r->id);
+ $this->updateCalendarColor($id, $calendar_id, $bgcolors, $txtcolors);
+ die();
+ case "uploadCalendarEventAttachment":
+ $r = $this->request;
+ $filename = $_FILES['upload_file']['name'];
+ $filesize = $_FILES['upload_file']['size'];
+ $file_content = file_get_contents($_FILES['upload_file']['tmp_name']);
+ $filetype = $_FILES['upload_file']['type'];
+ $file_content = base64_encode($file_content);
+ $newkey = $r->newkey;
+ $id = CalendarModel::insertCalendarEventAttachmentTemp($filename, $filetype, $file_content, $filesize, $newkey);
+ if ($id) {
+ $json['success'] = true;
+ $json['id'] = $id;
+ }
+ $json = json_encode($json);
+ echo $json;
+
+ die();
+ case "deleteCalendarEventAttachmentTmp":
+ $r = $this->request;
+ $newkey = ($r->newkey);
+ $name = ($r->name);
+ CalendarModel::deleteCalendarEventAttachmentTemp($newkey, $name);
+ die();
+ default:
+ $return = false;
+ }
+
+ }
+
+ protected function encryptString($plainText, $password, $salt)
+ {
+ // Definiere den Algorithmus und die Länge des Initialisierungsvektors
+ $cipher = "aes-256-cbc";
+ $ivlen = openssl_cipher_iv_length($cipher);
+
+ // Generiere einen Initialisierungsvektor
+ $iv = openssl_random_pseudo_bytes($ivlen);
+
+ // Erzeuge einen Schlüssel aus dem Passwort und dem Salt
+ $key = hash_pbkdf2("sha256", $password, $salt, 1000, 32, true);
+
+ // Verschlüssele den String
+ $cipherText = openssl_encrypt($plainText, $cipher, $key, 0, $iv);
+
+ // Füge den IV an den verschlüsselten Text an, da dieser für die Entschlüsselung benötigt wird
+ $cipherText = base64_encode($iv . $cipherText);
+
+ return $cipherText;
+ }
+
+ protected function updateCalendarColor($id, $calendar_id, $bgcolors, $txtcolors)
+ {
+ $r = $this->request;
+ $groups = $r->groups;
+
+
+ $redis = new Redis();
+//Connecting to Redis
+ $redis->connect('172.16.5.5', '6379');
+//$redis->auth('password');
+
+ $Calendar = new Calendar($id);
+
+ foreach ($bgcolors as $key => $value) {
+ $colordata[$calendar_id[$key]]['bgcolor'] = $value;
+ $colordata[$calendar_id[$key]]['txtcolor'] = $txtcolors[$key];
+ }
+
+
+ $Calendar->colors = json_encode($colordata);
+ if ($groups) {
+ $Calendar->groups = $groups;
+ }
+ $redis->set('thetool_calendar_usercolors_' . $this->me->id, json_encode($colordata));
+ $Calendar->save();
+ die();
+ }
+
+ protected function viewAction()
+ {
+ $Calendar = CalendarModel::search(array("user_id" => $this->me->id));
+ $CalendarAll = CalendarModel::getAll();
+ $encryptedUser = $this->encryptString($this->me->id, "testpw", "testsalt");
+ $this->layout()->set("Calendar", $Calendar);
+ $this->layout()->set("CalendarAll", $CalendarAll);
+ $this->layout()->set("encryptedUser", $encryptedUser);
+ $timerecordingholidays = TimerecordingHolidayModel::getAll();
+ $this->layout()->set("timerecordingholidays", $timerecordingholidays);
+ $timerecordingemployees = TimerecordingEmployeeModel::getAll();
+ $standardCalendarColors = CalendarModel::$standardCalendarColors;
+ $specialCalendarColors = CalendarModel::$specialCalendarColors;
+ $this->layout()->set("timerecordingemployees", $timerecordingemployees);
+ $this->layout()->set("standardCalendarColors", $standardCalendarColors);
+ $this->layout()->set("specialCalendarColors", $specialCalendarColors);
+ $this->layout()->setTemplate("Calendar/View");
+
+ }
+
+ private function getCalendarAttachment($id)
+ {
+ $content = CalendarModel::getCalendarEventAttachment($id);
+//
+
+// header('Content-Type: application/octet-stream');
+ header('Content-Type: ' . $content['contentType']);
+ header('Content-disposition: attachment; filename="' . $content['name'] . '"');
+ echo base64_decode($content['content']);
+ exit;
+ }
+
+ private function getCalendarAttachmentTmp($id, $name)
+ {
+ $content = CalendarModel::getCalendarEventAttachmentTmp($id, $name);
+//
+
+// header('Content-Type: application/octet-stream');
+ header('Content-Type: ' . $content['contentType']);
+ header('Content-disposition: attachment; filename="' . $content['name'] . '"');
+ echo base64_decode($content['content']);
+ exit;
+ }
+
+ private function getAddress($r)
+ {
+ $address = AddressModel::search(array("Controller!" => 'Calendar', "search_term!" => $r->term), array('count' => '20'));
+ $mobiles = CalendarModel::$austrian_mobile_prefixes;
+ $prefixes = array('0043', '43 ', '43', '0');
+ foreach ($address as $key => $value) {
+ unset($mobilenumber);
+ $id = $value->id;
+ if ($value->company) {
+ $text = "(F) " . $value->company;
+ } else {
+ $text = "(P) " . $value->firstname . " " . $value->lastname;
+ }
+
+ if ($value->mobile) {
+ foreach ($mobiles as $mobile) {
+ foreach ($prefixes as $prefix) {
+ if (strpos($value->mobile, $prefix . $mobile) !== false) {
+ $mobilenumber = str_replace($prefix . $mobile, '+43' . $mobile, $value->mobile);
+ $found = 1;
+ break;
+ }
+ }
+ if ($found) {
+ break;
+ }
+ }
+ }
+ if ($value->phone) {
+ foreach ($mobiles as $mobile) {
+ foreach ($prefixes as $prefix) {
+ if (strpos($value->phone, $prefix . $mobile) !== false) {
+ $mobilenumber = str_replace($prefix . $mobile, '+43' . $mobile, $value->phone);
+ $found = 1;
+ break;
+ }
+ }
+ if ($found) {
+ break;
+ }
+ }
+ }
+ if ($mobilenumber) {
+ if (strlen($mobilenumber) > 0 && strlen($mobilenumber) < 22) {
+ $mobilenumber = str_replace(" ", "", $mobilenumber);
+ $mobilenumber = str_replace("(", "", $mobilenumber);
+ $mobilenumber = str_replace(")", "", $mobilenumber);
+ $mobilenumber = str_replace("-", "", $mobilenumber);
+ $mobilenumber = str_replace("/", "", $mobilenumber);
+ $mobilenumber = str_replace(".", "", $mobilenumber);
+ $mobilenumber = str_replace(",", "", $mobilenumber);
+ $mobilenumber = str_replace(";", "", $mobilenumber);
+ $mobilenumber = str_replace(":", "", $mobilenumber);
+ }
+ } else if ($value->mobile) {
+ $mobilenumber = $value->mobile;
+ } else if ($value->phone) {
+ $mobilenumber = $value->phone;
+ } else {
+ $mobilenumber = "";
+ }
+ $rows[] = array(
+ 'id' => $id,
+ 'text' => $value->customer_number . " " . $text . " - " . $value->street . ", " . $value->zip . " " . $value->city,
+ 'mail' => $value->email,
+ 'mobilenumber' => $mobilenumber,
+ 'location' => $value->street . ", " . $value->zip . " " . $value->city,
+ 'name' => $value->customer_number . " " . $text
+ );
+ }
+
+ $json['incomplete_results'] = false;
+ $json['total_count'] = count($rows);
+ $json['items'] = $rows;
+ $json = json_encode($json);
+ echo trim($json);
+ die();
+ }
+
+ protected function indexAction()
+ {
+
+ $this->layout()->setTemplate("Calendar/Index");
+ $calendars = CalendarModel::getAll();
+ $this->layout()->set("calendars", $calendars);
+
+ }
+
+ protected function addAction()
+ {
+ $users = UserModel::getAll();
+ $this->layout()->set("users", $users);
+ $this->layout()->setTemplate("Calendar/Form");
+
+ }
+
+ protected function editAction()
+ {
+ $id = $this->request->id;
+
+ if (!is_numeric($id) || !$id) {
+ $this->layout()->setFlash("Kalender Verwaltung nicht gefunden", "error");
+ $this->redirect("Calendar");
+ }
+
+ $calendars = new Calendar($id);
+ if ($calendars->id != $id) {
+ $this->layout()->setFlash("Kalender Verwaltung nicht gefunden", "error");
+ $this->redirect("Calendar");
+ }
+ $this->layout()->set("calendars", $calendars);
+ return $this->addAction();
+ }
+
+ protected function saveAction()
+ {
+ $r = $this->request;
+ $id = $r->id;
+ //var_dump($r->get());exit;
+ if (is_numeric($id) && $id > 0) {
+ $mode = "edit";
+ $calendars = new Calendar($id);
+ if (!$calendars->id) {
+ $this->layout()->setFlash("Kalender Verwaltung nicht gefunden", "error");
+ $this->redirect("Calendar");
+ }
+ } else {
+ $mode = "add";
+ }
+
+ $data = [];
+ if ($mode == "add") {
+ $data['user_id'] = trim($r->user_id);
+ if (!$data['user_id']) {
+ $this->layout()->setFlash("Name darf nicht leer sein", "error");
+ $this->redirect("Calendar");
+ }
+ }
+ $data['go_calendar_id'] = trim($r->go_calendar_id);
+ $data['microsoft_id'] = trim($r->microsoft_id);
+// $data['rights'] = trim($r->rights);
+// $data['colors'] = trim($r->colors);
+// $data['subscription_id'] = trim($r->subscription_id);
+// $data['expirationDateTime'] = trim($r->expirationDateTime);
+ $data['active'] = trim($r->active);
+
+
+ if (!$data['go_calendar_id']) {
+ $data['go_calendar_id'] = NULL;
+ }
+ if (!$data['microsoft_id']) {
+ $data['microsoft_id'] = NULL;
+ }
+ if (!$data['active']) {
+ $data['active'] = '0';
+ }
+
+
+ if ($mode == "edit") {
+ $calendars->update($data);
+
+ } else {
+ $calendars = CalendarModel::create($data);
+ }
+
+ $id = $calendars->save();
+
+ if (!$id) {
+ $this->layout()->setFlash("Kalender Verwaltung konnte nicht angelegt werden", "error");
+ $this->redirect("Calendar");
+ }
+
+ if ($mode == "edit") {
+ $this->layout()->setFlash("Kalender Verwaltung erfolgreich geändert", "success");
+ } else if ($mode = "add") {
+ $this->layout()->setFlash("Kalender Verwaltung erfolgreich angelegt", "success");
+ }
+ $this->redirect("Calendar");
+ }
+
+
+ protected function deleteAction()
+ {
+ $id = $this->request->id;
+ $calendars = new Calendar($id);
+ if (!$calendars->id || $calendars->id != $id) {
+ $this->layout()->setFlash("Kalender Verwaltung nicht gefunden.", "error");
+ $this->redirect("Calendar");
+ }
+
+ $calendars->delete();
+ $this->redirect("Calendar");
+ }
+
+}
\ No newline at end of file
diff --git a/application/Calendar/CalendarModel.php b/application/Calendar/CalendarModel.php
new file mode 100644
index 000000000..ccf1946ef
--- /dev/null
+++ b/application/Calendar/CalendarModel.php
@@ -0,0 +1,792 @@
+ '#bd0000', 998 => '#8000A3', 999 => '#08769b');
+
+ public static function dbKalender()
+ {
+ if (!TT_CALENDAR_ENABLE) {
+ $json['errormessage'] = "Calendar is is disabled.";
+ $json['success'] = false;
+ $json = json_encode($json);
+ echo trim($json);
+ die();
+ }
+
+ $db = FronkDB::singleton(TT_CALENDAR_HOSTNAME, TT_CALENDAR_USERNAME, TT_CALENDAR_PASSWORD, TT_CALENDAR_DATABASE);
+
+ return $db;
+ }
+
+ public static function searchCalendarEvents($r)
+ {
+ $dbcal = self::dbKalender();
+ $termstring = trim($r->term);
+
+ $termExplode = explode(" ", $termstring);
+ $where = "";
+ foreach ($termExplode as $term) {
+ $where .= " AND (name LIKE '%" . $term . "%' OR location LIKE '%" . $term . "%') ";
+ }
+ $res = $dbcal->select("cal_events", "id, uuid, calendar_id, user_id, start_time, end_time, timezone, all_day_event, name, description, location, repeat_end_time, reminder, ctime, mtime, muser_id, busy, status, resource_event_id, private, rrule, background, files_folder_id, read_only, category_id, exception_for_event_id, recurrence_id, is_organizer,event_type", "1=1 $where ORDER BY name");
+
+
+ while ($data = $dbcal->fetch_array($res)) {
+ if ($data['location']) {
+ $searchName = $data['name'] . " @" . $data['location'];
+ } else {
+ $searchName = $data['name'];
+ }
+ $id = $data['id'] . ";" . date("Y-m-d", $data['start_time']);
+ $rows[] = array(
+ 'id' => $id,
+ 'text' => $searchName . " (" . date("Y-m-d", $data['start_time']) . ")"
+ );
+ }
+ $json['incomplete_results'] = false;
+ $json['total_count'] = count($rows);
+ $json['items'] = $rows;
+
+ $json = json_encode($json);
+ echo trim($json);
+ die();
+ }
+
+ public static function getCalendarEvents($me, $id = 0, $r = 0)
+ {
+ $calendar = self::search(array("user_id" => $me));
+ $standardCalendarColors = CalendarModel::$standardCalendarColors;
+ $calendarColors = json_decode($calendar[0]->colors, true);
+ $calenderRights = json_decode($calendar[0]->rights, true);
+ $colorCounter = 0;
+ foreach ($calenderRights as $key => $value) {
+ if (!$calendarColors[$key]['bgcolor']) {
+ $calendarColors[$key]['bgcolor'] = $standardCalendarColors[$colorCounter];;
+ $calendarColors[$key]['txtcolor'] = '#000';
+ $colorCounter++;
+ }
+ }
+ $dbcal = self::dbKalender();
+ $req = $dbcal->select("cal_events_attachments", "id,cal_events_id,name,size,contentType", "");
+ $oldcalevent = "";
+ while ($data = $dbcal->fetch_array($req)) {
+ if ($oldcalevent != $data['cal_events_id']) {
+ $counter = 0;
+ }
+ $attachments[$data['cal_events_id']]['attachments'][$counter]['name'] = $data['name'];
+ $attachments[$data['cal_events_id']]['attachments'][$counter]['id'] = $data['id'];
+ $attachments[$data['cal_events_id']]['attachments'][$counter]['size'] = $data['size'];
+ $attachments[$data['cal_events_id']]['attachments'][$counter]['contentType'] = $data['contentType'];
+
+
+ $oldcalevent = $data['cal_events_id'];
+ $counter++;
+ }
+ if ($id != 0) {
+ $where = " AND `cal_events`.id='" . $id . "'";
+ } else {
+ $where = "";
+ }
+ $visibleCalendars = $r->visibleCalendars;
+ if ($visibleCalendars) {
+ $where .= " AND calendar_id IN (" . implode(",", $visibleCalendars) . ")";
+ }
+ $sql = "SELECT `cal_events`.id, uuid, calendar_id, `cal_events`.user_id, start_time, end_time, timezone, all_day_event, `cal_events`.name,`cal_calendars`.name calendar_name, description, location, repeat_end_time, reminder, ctime,cname, mtime,mname, muser_id, busy, status, resource_event_id, private, rrule, `cal_events`.background, `cal_events`.files_folder_id, read_only, category_id, exception_for_event_id, recurrence_id, is_organizer,event_type,busy FROM cal_events INNER JOIN `cal_calendars` ON (`cal_calendars`.`id`=`cal_events`.`calendar_id`) WHERE 1=1 $where ";
+
+ $res = $dbcal->query($sql);
+ if ($dbcal->num_rows($res)) {
+
+ while ($data = $dbcal->fetch_array($res)) {
+ if ($attachments[$data['uuid']]) {
+ $attachment = 1;
+ $attachmentLinks = json_encode($attachments[$data['uuid']]['attachments']);
+ } else {
+ $attachment = 0;
+ $attachmentLinks = "";
+ }
+ if ($data['all_day_event'] == 1) {
+ if (strpos($data['name'], "Bereitschaft") === false && strpos($data['name'], "Blocker") === false) {
+ continue;
+ }
+ $starttime = date("Y-m-d", $data['start_time']);
+ $endtime = date("Y-m-d", $data['end_time']);
+ } else {
+ $starttime = date("Y-m-d H:i", $data['start_time']);
+ $endtime = date("Y-m-d H:i", $data['end_time']);
+ }
+ if (!empty($fetch['location'])) {
+ $name = $data['name'] . " @ " . $data['location'];
+ } else {
+ $name = $data['name'];
+ }
+
+ if ($calendarColors[$data['calendar_id']]['bgcolor']) {
+ $bgcolor = $calendarColors[$data['calendar_id']]['bgcolor'];
+ $txtcolor = $calendarColors[$data['calendar_id']]['txtcolor'];
+ } else {
+ $bgcolor = $standardCalendarColors[$colorCounter];
+ $txtcolor = "#000";
+ $colorCounter++;
+ }
+ if ($calenderRights[$data['calendar_id']]) {
+ $rights = $calenderRights[$data['calendar_id']];
+
+ $rows[] = array(
+ 'id' => array('id' => $data['id']),
+ 'cstart' => array('cstart' => $starttime),
+ 'cend' => array('cend' => $endtime),
+ 'ccategory' => array('ccategory' => $name),
+ 'category' => array('category' => $name),
+ 'calendar_id' => array('calendar_id' => $data['calendar_id']),
+ 'bgColor' => array('bgColor' => $bgcolor),
+ 'txtColor' => array('txtColor' => $txtcolor),
+ 'rights' => array('rights' => $rights, 'order' => $rights),
+ 'location' => array('location' => $data['location']),
+ 'busy' => array('busy' => $data['busy']),
+ 'event_type' => array('event_type' => $data['event_type']),
+ 'description' => array('description' => ($data['description'])),
+ 'attachment' => array('attachment' => $attachment),
+ 'attachments' => array('attachments' => $attachmentLinks),
+ 'calendar_name' => array('calendar_name' => $data['calendar_name']),
+ 'ctime' => array('ctime' => date("d.m.Y H:i", $data['ctime'])),
+ 'cname' => array('cname' => $data['cname']),
+ 'mtime' => array('mtime' => date("d.m.Y H:i", $data['mtime'])),
+ 'mname' => array('mname' => $data['mname']),
+ 'busy' => array('busy' => $data['busy']),
+ );
+ }
+ }
+ $json['success'] = true;
+ $json['data'] = $rows;
+ } else {
+ $json['success'] = true;
+ $json['errormessage'] = "No data found.";
+ }
+
+
+ $json = json_encode($json);
+ if ($id == 0) {
+ echo trim($json);
+ die();
+ } else {
+ return $json;
+ }
+ }
+
+
+ public static function getCalendarEventAttachment($id)
+ {
+ $return = array();
+ $dbcal = self::dbKalender();
+ $req = $dbcal->select("cal_events_attachments", "id, cal_events_id,name,contentType,content,size", "1=1 AND id='" . $id . "' ORDER BY id");
+ if ($dbcal->num_rows($req)) {
+ $data = $dbcal->fetch_array($req);
+ $return = $data;
+ }
+ return $return;
+ }
+
+ public static function getCalendarEventAttachmenttmp($id, $name)
+ {
+ $return = array();
+ $dbcal = self::dbKalender();
+ $req = $dbcal->select("tmp_cal_events_attachments", "id,name,contentType,content,size", "1=1 AND newkey='" . $id . "' AND name='" . $name . "' ORDER BY id");
+ if ($dbcal->num_rows($req)) {
+ $data = $dbcal->fetch_array($req);
+ $return = $data;
+ }
+ return $return;
+ }
+
+ public static function getCalendarEvent($id)
+ {
+ $calendar = self::search(array("user_id" => $me));
+
+ $dbcal = self::dbKalender();
+
+
+ $res = $dbcal->select("cal_events", "id, uuid, calendar_id, user_id, start_time, end_time, timezone, all_day_event, name, description, location, repeat_end_time, reminder, ctime, mtime, muser_id, busy, status, resource_event_id, private, rrule, background, files_folder_id, read_only, category_id, exception_for_event_id, recurrence_id, is_organizer,event_type,customer,customer_info,customer_info_send,customer_info_reminder,busy,attendees,is_organizer", "1=1 AND id='" . $id . "' ORDER BY id");
+ if ($dbcal->num_rows($res)) {
+ $data = $dbcal->fetch_array($res);
+
+
+ $attachment = 0;
+
+ if ($data['all_day_event'] == 1) {
+ $starttime = date("Y-m-d", $data['start_time']);
+ $endtime = date("Y-m-d", $data['end_time']);
+ } else {
+ $starttime = date("Y-m-d H:i", $data['start_time']);
+ $endtime = date("Y-m-d H:i", $data['end_time']);
+ }
+ if (!empty($fetch['location'])) {
+ $name = $data['name'] . " @ " . $data['location'];
+ } else {
+ $name = $data['name'];
+ }
+ $req = $dbcal->select("cal_events_attachments", "id, cal_events_id,name,contentType,size", "1=1 AND cal_events_id='" . $data['uuid'] . "' ORDER BY id");
+ $counter = 0;
+ $contentType['application/pdf'] = 'fa-file-pdf';
+ $contentType['application/vnd.openxmlformats-officedocument.wordprocessingml.document'] = 'fa-file-doc';
+ $contentType['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] = 'fa-file-xls';
+ $contentType['application/octet-stream'] = 'fa-file-csv';
+ $contentType['text/csv'] = 'fa-file-csv';
+ $contentType['application/vnd.openxmlformats-officedocument.presentationml.presentation'] = 'fa-file-ppt';
+ $contentType['application/zip'] = 'fa-file-zip';
+ $contentType['application/x-zip-compressed'] = 'fa-file-zip';
+ $contentType['application/x-rar-compressed'] = 'fa-file-archive';
+ $contentType['application/x-7z-compressed'] = 'fa-file-archive';
+ $contentType['application/x-tar'] = 'fa-file-archive';
+ $contentType['application/x-gzip'] = 'fa-file-archive';
+ $contentType['application/x-bzip2'] = 'fa-file-archive';
+ $contentType['text/xml'] = 'fa-file-xml';
+ $contentType['application/xml'] = 'fa-file-xml';
+ $contentType['audio/mpeg'] = 'fa-file-mp3';
+ $contentType['application/x-7z-compressed'] = 'fa-file-archive';
+ $contentType['image/png'] = 'fa-file-png';
+ $contentType['image/jpeg'] = 'fa-file-jpg';
+ while ($dataAttachments = $dbcal->fetch_array($req)) {
+ $attachment = 1;
+ $attachments[$counter]['name'] = $dataAttachments['name'];
+ $attachments[$counter]['contentType'] = $dataAttachments['contentType'];
+ $attachments[$counter]['size'] = $dataAttachments['size'];
+ $attachments[$counter]['id'] = $dataAttachments['id'];
+ if ($contentType[$dataAttachments['contentType']]) {
+ $attachments[$counter]['icon'] = $contentType[$dataAttachments['contentType']];
+ } else {
+ $attachments[$counter]['icon'] = 'fa-file';
+ }
+ $counter++;
+ }
+ $rows = array(
+ 'id' => array('id' => $data['id'], 'order' => $data['id']),
+ 'cstart' => array('cstart' => $starttime, 'order' => $data['ctime']),
+ 'cend' => array('cend' => $endtime, 'order' => $data['mtime']),
+ 'ccategory' => array('ccategory' => $name, 'order' => $data['name']),
+ 'category' => array('category' => $name, 'order' => $data['name']),
+ 'calendar_id' => array('calendar_id' => $data['calendar_id'], 'order' => $data['calendar_id']),
+ 'location' => array('location' => $data['location'], 'order' => $data['location']),
+ 'description' => array('description' => $data['description'], 'order' => $data['description']),
+ 'reminder' => array('reminder' => $data['reminder'], 'order' => $data['reminder']),
+ 'busy' => array('busy' => $data['busy'], 'order' => $data['busy']),
+ 'type' => array('type' => $data['event_type'], 'order' => $data['event_type']),
+ 'customer' => array('customer' => $data['customer']),
+ 'customer_info' => array('customer_info' => $data['customer_info']),
+ 'customer_info_send' => array('customer_info_send' => $data['customer_info_send']),
+ 'customer_info_reminder' => array('customer_info_reminder' => $data['customer_info_reminder']),
+ 'isorganizer' => array('isorganizer' => $data['is_organizer']),
+ 'attendees' => array('attendees' => $data['attendees']),
+ 'attachment' => array('attachment' => $attachment, 'order' => $attachment),
+ 'attachments' => array('attachments' => $attachments, 'order' => $attachments)
+ );
+ $json['success'] = true;
+ $json['data'] = $rows;
+ } else {
+ $json['success'] = false;
+ $json['errormessage'] = "No data found.";
+ }
+
+
+ $json = json_encode($json);
+ echo trim($json);
+ die();
+ }
+
+ public static function insertMicrosoftCalendarEvent($request)
+ {
+
+ $db = self::dbKalender();
+ $json_data = json_decode($request, true);
+ $data = [];
+ $data['ms_event_id'] = $json_data['value'][0]['resourceData']['id'];
+ $msUserIdExplode = explode("/", $json_data['value'][0]['resource']);
+ $data['ms_user_id'] = trim($msUserIdExplode[1]);
+ $Calendar = self::search(array("microsoft_id" => $data['ms_user_id']));
+ $data['go_calendar_id'] = $Calendar[0]->go_calendar_id;
+ $data['data'] = $request;
+ $data['source'] = 'ms';
+ if ($json_data['value'][0]['changeType'] == 'created')
+ $data['type'] = 'c';
+ else if ($json_data['value'][0]['changeType'] == 'updated')
+ $data['type'] = 'u';
+ else if ($json_data['value'][0]['changeType'] == 'deleted')
+ $data['type'] = 'd';
+ $data['status'] = 'p';
+ $data['edit'] = time();
+ $data['create'] = time();
+ $data['edit_by'] = 89;
+ $data['create_by'] = 89;
+
+ $db->insert("TheTool_CalendarQueue", $data);
+ return "";
+ die();
+ }
+
+ public static function updateCalendarEvent($r, $me)
+ {
+
+
+ $description = ($r->description);
+ $attachments = ($r->attachments);
+ $location = ($r->location);
+ $title = ($r->title);
+ $start = ((($r->start - 7200000) / 1000));
+ $end = ((($r->end - 7200000) / 1000));
+ if ($title) {
+ $start = strtotime($r->start);
+ $end = strtotime($r->end);
+ }
+ $allday = ($r->allday);
+ $reminder = ($r->reminder);
+ $newkey = ($r->newkey);
+ $id = ($r->id);
+ $type = ($r->type);
+ $busy = ($r->busy);
+ $users = ($r->users);
+ foreach ($users as $key => $value) {
+ $user_id = $value;
+ }
+
+ date_default_timezone_set('Europe/Berlin');
+ header('Content-Type: application/json');
+ $db = self::dbKalender();
+
+ $sql = "SELECT `cal_events`.id,microsoft_id,uuid,ms_user_id FROM `cal_events` INNER JOIN `cal_calendars` ON (`cal_calendars`.`id`=`cal_events`.`calendar_id`) WHERE `cal_events`.id = '" . $id . "' LIMIT 1";
+ $res = $db->query($sql);
+ if ($db->num_rows($res)) {
+ $result = $db->fetch_object($res);
+ $microsoft_id = $result->microsoft_id;
+ $cal_events_id = $result->uuid;
+ $microsoft_user_id = $result->ms_user_id;
+ }
+
+ $updateArray['start_time'] = $start;
+ $updateArray['end_time'] = $end;
+ $updateArray['mtime'] = time();
+ $updateArray['mname'] = $me->name;
+ if ($title) {
+ $updateArray['name'] = $title;
+ }
+ if ($description)
+ $updateArray['description'] = $description;
+
+
+ if ($location)
+ $updateArray['location'] = $location;
+
+ if (isset($allday))
+ $updateArray['all_day_event'] = $allday;
+
+ if (isset($reminder)) {
+ if ($reminder == 'NULL')
+ $updateArray['reminder'] = NULL;
+ else
+ $updateArray['reminder'] = $reminder;
+ }
+ if ($type)
+ $updateArray['event_type'] = $type;
+ if (isset($busy))
+ $updateArray['busy'] = $busy;
+
+
+ if ($type == 2) {
+ if ($r->customer)
+ $updateArray['customer'] = $r->customer;
+ else
+ $updateArray['customer'] = NULL;
+
+ if (($r->customer_info_type)) {
+ $customer_info_type = $r->customer_info_type;
+ }
+ if (($r->customer_info_text)) {
+ $customer_info_text = $r->customer_info_text;
+ }
+ if (($r->customer_info_type_text)) {
+ $customer_info_type_text = $r->customer_info_type_text;
+ }
+ if ($r->customer_info_reminder_check) {
+ $updateArray['customer_info_reminder'] = $r->customer_info_reminder_check;
+ }
+ $customerJson = array('customer_info_type' => $customer_info_type, 'customer_info_text' => $customer_info_text, 'customer_info_type_text' => $customer_info_type_text);
+ $updateArray['customer_info'] = json_encode($customerJson);
+ if ($r->customer_info_check) {
+ $customerJson['sendby'] = $me->name;
+ $customerJson['sendtime'] = time();
+ $updateArray['customer_info_send'] = json_encode($customerJson);
+ }
+ }
+ if ($type == 1) {
+ $updateArray['customer'] = NULL;
+ $updateArray['customer_info'] = NULL;
+ }
+
+
+ $db->update("cal_events", $updateArray, "id = '" . $id . "'");
+ if ($newkey) {
+ $res = $db->select("cal_events_attachments", "id,cal_events_id", "1=1 AND cal_events_id = '" . $cal_events_id . "'");
+ if ($db->num_rows($res)) {
+ while ($dataAttachment = $db->fetch_array($res)) {
+ $toolattachments[$dataAttachment['id']] = 1;
+ }
+ }
+ foreach ($attachments as $key => $value) {
+ unset($toolattachments[$value]);
+ }
+ if (!empty($toolattachments)) {
+ foreach ($toolattachments as $key => $value) {
+ $db->delete("cal_events_attachments", "id = '" . $key . "'");
+ }
+ }
+
+ $res = $db->select("tmp_cal_events_attachments", "id,name,contentType,content,size,create_timestamp,edit_timestamp", "1=1 AND newkey='" . $newkey . "' ORDER BY id");
+ if ($db->num_rows($res)) {
+ while ($data = $db->fetch_array($res)) {
+ $tmpid = $data['id'];
+ unset($data['id']);
+ $data['cal_events_id'] = $cal_events_id;
+ $db->insert("cal_events_attachments", $data);
+ $db->delete("tmp_cal_events_attachments", "id = '" . $tmpid . "'");
+ }
+ }
+
+
+ $updateArray['attachments'] = $attachments;
+ }
+ $json_data = json_encode($updateArray);
+ $data = [];
+ $data['ms_user_id'] = $microsoft_user_id;
+ $data['ms_event_id'] = $microsoft_id;
+ $data['data'] = $json_data;
+ $data['type'] = 'u';
+ $data['status'] = 'p';
+ $data['edit'] = time();
+ $data['create'] = time();
+ $data['edit_by'] = 89;
+ $data['create_by'] = 89;
+
+ $db->insert("TheTool_CalendarQueue", $data);
+
+ }
+
+ public static function insertCalendarEvent($r, $me)
+ {
+ $description = ($r->description);
+ $attachments = ($r->attachments);
+ $location = ($r->location);
+ $title = ($r->title);
+ $start = strtotime($r->start);
+ $end = strtotime($r->end);
+ $allday = ($r->allday);
+ $reminder = ($r->reminder);
+ $newkey = ($r->newkey);
+ $type = ($r->type);
+ $busy = ($r->busy);
+ $users = ($r->users);
+ $customer_info_reminder_check = 0;
+ date_default_timezone_set('Europe/Berlin');
+ header('Content-Type: application/json');
+ foreach ($users as $key => $value) {
+ $user_id = $value;
+ }
+
+ $db = self::dbKalender();
+ $res = $db->select("cal_calendars", "id,ms_user_id", "id = '" . $user_id . "' LIMIT 1");
+ if ($db->num_rows($res)) {
+ $result = $db->fetch_object($res);
+ $microsoft_user_id = $result->ms_user_id;
+
+ }
+
+ if ($reminder == 'NULL') {
+ $reminder = NULL;
+ }
+ if ($type == 2) {
+ $customer = $r->customer;
+ $customer_info_type = $r->customer_info_type;
+ $customer_info_text = $r->customer_info_text;
+ $customer_info_type_text = $r->customer_info_type_text;
+ $customerJson = array('customer_info_type' => $customer_info_type, 'customer_info_text' => $customer_info_text, 'customer_info_type_text' => $customer_info_type_text);
+ $customer_info = json_encode($customerJson);
+ if ($r->customer_info_reminder_check) {
+ $customer_info_reminder_check = $r->customer_info_reminder_check;
+ }
+ if ($r->customer_info_check) {
+ $customerJson['sendby'] = $me->name;
+ $customerJson['sendtime'] = time();
+ $customer_info_send = json_encode($customerJson);
+ }
+ } else {
+ $customer = NULL;
+ $customer_info = NULL;
+ $customer_info_send = NULL;
+ }
+
+ $data = array("start_time" => $start, 'end_time' => $end, 'name' => $title, 'description' => $description, 'location' => $location, 'calendar_id' => $user_id, 'uuid' => "a5eb79b3-fca7-5378-a09e-" . rand(100000000000, 999999999999), 'user_id' => 1, 'timezone' => 'Europe/Amsterdam', 'all_day_event' => 0, 'repeat_end_time' => 0, 'reminder' => $reminder, 'ctime' => time(), 'cname' => $me->name, 'mtime' => time(), 'mname' => $me->name, 'user_id' => 1, 'busy' => $busy, 'status' => 'CONFIRMED', 'resource_event_id' => 0, 'private' => 0, 'rrule' => '', 'background' => 'EBF1E2', 'files_folder_id' => 0, 'read_only' => 0, 'exception_for_event_id' => 0, 'recurrence_id' => 0, 'is_organizer' => 1, 'event_type' => $type, 'customer' => $customer, 'customer_info' => $customer_info, 'customer_info_send' => $customer_info_send, 'customer_info_reminder' => $customer_info_reminder_check);
+
+ $db->insert("cal_events", $data);
+ $event_id = $data['uuid'];
+ if ($newkey) {
+ $res = $db->select("tmp_cal_events_attachments", "id,name,contentType,content,size,create_timestamp,edit_timestamp", "1=1 AND newkey='" . $newkey . "' ORDER BY id");
+ if ($db->num_rows($res)) {
+ while ($data = $db->fetch_array($res)) {
+ $tmpid = $data['id'];
+ unset($data['id']);
+ $data['cal_events_id'] = $event_id;
+ $db->insert("cal_events_attachments", $data);
+ $db->delete("tmp_cal_events_attachments", "id = '" . $tmpid . "'");
+ }
+ }
+
+
+ }
+ $data['attachments'] = $attachments;
+ $json_data = json_encode($data);
+
+ $data = [];
+ $data['ms_user_id'] = $microsoft_user_id;
+ $data['event_id'] = $event_id;
+ $data['data'] = $json_data;
+ $data['type'] = 'c';
+ $data['status'] = 'p';
+ $data['edit'] = time();
+ $data['create'] = time();
+ $data['edit_by'] = 89;
+ $data['create_by'] = 89;
+
+ $db->insert("TheTool_CalendarQueue", $data);
+ }
+
+ public static function insertCalendarEventAttachmentTemp($name, $contantType, $content, $size, $newkey)
+ {
+ $db = self::dbKalender();
+ $data = [];
+ $data['name'] = $name;
+ $data['contentType'] = $contantType;
+ $data['content'] = $content;
+ $data['size'] = $size;
+ $data['newkey'] = $newkey;
+ $data['create_timestamp'] = time();
+ $data['edit_timestamp'] = time();
+ $db->insert("tmp_cal_events_attachments", $data);
+ echo "insert_id: " . $db->insert_id;
+ return $db->insert_id;
+ }
+
+ public static function deleteCalendarEventAttachmentTemp($newkey, $name)
+ {
+ $db = self::dbKalender();
+ $db->delete("tmp_cal_events_attachments", "newkey = '" . $newkey . "' AND name = '" . $name . "'");
+ }
+
+
+ public static function deleteCalendarEvent($r)
+ {
+ $id = $r->id;
+ $users = $r->users;
+ foreach ($users as $key => $value) {
+ $user_id = $value;
+ }
+ date_default_timezone_set('Europe/Berlin');
+ header('Content-Type: application/json');
+ $db = self::dbKalender();
+ $res = $db->select("cal_calendars", "id,ms_user_id", "id = '" . $user_id . "' LIMIT 1");
+ if ($db->num_rows($res)) {
+ $result = $db->fetch_object($res);
+ $microsoft_user_id = $result->ms_user_id;
+
+ }
+ $res = $db->select("cal_events", 'id,microsoft_id', "id = '" . $id . "' LIMIT 1");
+ if ($db->num_rows($res)) {
+ $result = $db->fetch_object($res);
+
+ $data = [];
+ $data['ms_user_id'] = $microsoft_user_id;
+ $data['ms_event_id'] = $result->microsoft_id;
+ $data['type'] = 'd';
+ $data['status'] = 'p';
+ $data['edit'] = time();
+ $data['create'] = time();
+ $data['edit_by'] = 89;
+ $data['create_by'] = 89;
+ $db->insert("TheTool_CalendarQueue", $data);
+ }
+ $db->delete("cal_events", "id = '" . $id . "'");
+ die();
+ }
+
+ public static function create(array $data)
+ {
+ $model = new Calendar();
+
+ foreach ($data as $field => $value) {
+ if (property_exists(get_called_class(), $field)) {
+ if (substr($field, 0, 5) == "vlan_" && !$value) {
+ $model->$field = null;
+ continue;
+ }
+ $model->$field = $value;
+ }
+ }
+
+ $me = mfValuecache::singleton()->get("me");
+ if (!$me) {
+ $me = new User();
+ $me->loadMe();
+ mfValuecache::singleton()->set("me", $me);
+ }
+
+ if ($model->create_by === null) {
+ $model->create_by = $me->id;
+ }
+ if ($model->edit_by === null) {
+ $model->edit_by = $me->id;
+ }
+
+ return $model;
+ }
+
+ public static function getOne($id)
+ {
+ if (!is_numeric($id) || !$id) {
+ throw new Exception("Invalid number", 400);
+ }
+ $item = [];
+ $db = FronkDB::singleton();
+
+ $res = $db->select("Calendar", "*", "id=$id LIMIT 1");
+ if ($db->num_rows($res)) {
+ $data = $db->fetch_object($res);
+ $item = new Calendar($data);
+ }
+ return $item;
+ }
+
+ public static function getAll()
+ {
+ $items = [];
+
+ $db = FronkDB::singleton();
+
+ $res = $db->select("Calendar", "*", "1=1");
+ if ($db->num_rows($res)) {
+ while ($data = $db->fetch_object($res)) {
+ $items[$data->go_calendar_id] = new Calendar($data);
+ }
+ }
+ return $items;
+
+ }
+
+ public static function getAllIndex()
+ {
+ $items = [];
+
+ $db = FronkDB::singleton();
+
+ $res = $db->select("Calendar", "*", "1=1");
+ if ($db->num_rows($res)) {
+ while ($data = $db->fetch_object($res)) {
+ $items[] = new Calendar($data);
+ }
+ }
+ return $items;
+
+ }
+
+ public static function getFirst()
+ {
+ $db = FronkDB::singleton();
+
+ $where = self::getSqlFilter($filter);
+ $res = $db->select("Calendar", "*", "$where ");
+ if ($db->num_rows($res)) {
+ $data = $db->fetch_object($res);
+ $item = new Calendar($data);
+ if ($item->id) {
+ return $item;
+ } else {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public static function search($filter)
+ {
+ $items = [];
+ $db = FronkDB::singleton();
+
+ $where = self::getSqlFilter($filter);
+ $res = $db->select("Calendar", "*", "$where");
+ if ($db->num_rows($res)) {
+ while ($data = $db->fetch_object($res)) {
+ $items[] = new Calendar($data);
+ }
+ }
+ return $items;
+ }
+
+ private static function getSqlFilter($filter)
+ {
+ $where = "1=1 ";
+
+ //var_dump($filter);exit;
+ if (array_key_exists("user_id", $filter)) {
+ $user_id = $filter['user_id'];
+ if (is_numeric($user_id)) {
+ $where .= " AND user_id=$user_id";
+ }
+ }
+ if (array_key_exists("microsoft_id", $filter)) {
+ $microsoft_id = $filter['microsoft_id'];
+ $where .= " AND microsoft_id='$microsoft_id'";
+ }
+ if (array_key_exists("checkSubscriptions", $filter)) {
+ $where .= " AND microsoft_id!='' AND microsoft_id IS NOT NULL AND active=1";
+ }
+
+ //var_dump($filter, $where);exit;
+ return $where;
+ }
+
+}
diff --git a/public/css/pages/Calendar/View.css b/public/css/pages/Calendar/View.css
new file mode 100644
index 000000000..0656b61d6
--- /dev/null
+++ b/public/css/pages/Calendar/View.css
@@ -0,0 +1,557 @@
+.fc-event {
+ border-radius: 2px;
+ border: none;
+ cursor: move;
+ font-size: 13px;
+ margin: 3px 7px;
+ padding: 3px 5px;
+ text-align: center;
+}
+
+.fc-toolbar {
+ @media (max-width: 767px) {
+ flex-direction: column;
+ .fc-toolbar-chunk {
+ margin-bottom: 12px;
+ }
+ }
+}
+
+.fc .fc-button-primary:focus {
+ box-shadow: none;
+}
+
+.fc .fc-button:focus {
+ box-shadow: none;
+ outline: 0px;
+}
+
+.fc .fc-button-primary:not(:disabled).fc-button-active:focus, .fc .fc-button-primary:not(:disabled):active:focus {
+ box-shadow: none;
+}
+
+.popper, .tooltip {
+ position: absolute;
+ z-index: 9999;
+ /* background: #FFC107; */
+ color: #0f5be9;
+ width: auto;
+ /* border-radius: 3px; */
+ /* box-shadow: 0 0 1px rgba(0, 0, 0, 0.5); */
+ padding: 10px;
+ text-align: center;
+ opacity: 0.9;
+}
+
+.tooltip-inner {
+ max-width: 500px;
+ padding: 0.4rem 0.8rem;
+ color: #fff;
+ text-align: center;
+ background-color: #2c3e50;
+ border-radius: 0.2rem;
+}
+
+.style5 .tooltip {
+ background: #1E252B;
+ color: #FFFFFF;
+ max-width: 200px;
+ width: auto;
+ font-size: .8rem;
+ padding: .5em 1em;
+}
+
+.popper .popper__arrow,
+.tooltip .tooltip-arrow {
+ width: 0;
+ height: 0;
+ border-style: solid;
+ position: absolute;
+ margin: 5px;
+}
+
+.tooltip .tooltip-arrow,
+.popper .popper__arrow {
+ border-color: #FFC107;
+}
+
+.style5 .tooltip .tooltip-arrow {
+ border-color: #1E252B;
+}
+
+.popper[x-placement^="top"],
+.tooltip[x-placement^="top"] {
+ margin-bottom: 5px;
+}
+
+.popper[x-placement^="top"] .popper__arrow,
+.tooltip[x-placement^="top"] .tooltip-arrow {
+ border-width: 5px 5px 0 5px;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ border-bottom-color: transparent;
+ bottom: -5px;
+ left: calc(50% - 5px);
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+.popper[x-placement^="bottom"],
+.tooltip[x-placement^="bottom"] {
+ margin-top: 5px;
+}
+
+.tooltip[x-placement^="bottom"] .tooltip-arrow,
+.popper[x-placement^="bottom"] .popper__arrow {
+ border-width: 0 5px 5px 5px;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ border-top-color: transparent;
+ top: -5px;
+ left: calc(50% - 5px);
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+.tooltip[x-placement^="right"],
+.popper[x-placement^="right"] {
+ margin-left: 5px;
+}
+
+.popper[x-placement^="right"] .popper__arrow,
+.tooltip[x-placement^="right"] .tooltip-arrow {
+ border-width: 5px 5px 5px 0;
+ border-left-color: transparent;
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+ left: -5px;
+ top: calc(50% - 5px);
+ margin-left: 0;
+ margin-right: 0;
+}
+
+.popper[x-placement^="left"],
+.tooltip[x-placement^="left"] {
+ margin-right: 5px;
+}
+
+.popper[x-placement^="left"] .popper__arrow,
+.tooltip[x-placement^="left"] .tooltip-arrow {
+ border-width: 5px 0 5px 5px;
+ border-top-color: transparent;
+ border-right-color: transparent;
+ border-bottom-color: transparent;
+ right: -5px;
+ top: calc(50% - 5px);
+ margin-left: 0;
+ margin-right: 0;
+}
+
+thead .fc-day-today .fc-scrollgrid-sync-inner {
+ background-color: #2c3e50;
+
+}
+
+thead .fc-day-today .fc-scrollgrid-sync-inner .fc-col-header-cell-cushion {
+ color: #fff;
+}
+
+.fc .fc-col-header-cell-cushion {
+ color: #2c3e50;
+}
+
+.fc .fc-daygrid-day-number {
+ color: #2c3e50;
+}
+
+.fc .fc-daygrid-day.fc-day-today {
+ background-color: rgb(44 62 80 / 12%);
+}
+
+.fc-event-title {
+ font-weight: 500;
+}
+
+.fc-day-today .fc-daygrid-day-top {
+ background-color: #2c3e50;
+}
+
+.fc-day-today .fc-daygrid-day-number {
+ color: #fff;
+}
+
+.card-fullscreen {
+ display: block;
+ z-index: 1040;
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ right: 0;
+ left: 0;
+ bottom: 0;
+ overflow: auto;
+}
+
+.fa-window-maximize, .fa-window-restore {
+ font-size: 20px;
+ cursor: pointer;
+ color: #323a36;
+
+}
+
+.color-input {
+ height: 20px;
+ width: 30px;
+ padding: 0;
+ margin: 0;
+ block-size: 20px;
+ border-image: none;
+ inline-size: 30px;
+ border-radius: 5px;
+ border-color: #ccc;
+ padding-block: 0;
+ padding-inline: 0;
+ background-color: #fff;
+}
+
+.color-input::-webkit-color-swatch {
+ border-radius: 3px;
+ border: none;
+}
+
+.color-input::-moz-color-swatch {
+ border-radius: 3px;
+ border: none;
+}
+
+.color-text-input {
+ height: 20px;
+ width: 30px;
+ padding: 0;
+ margin: 0;
+ block-size: 20px;
+ border-image: none;
+ inline-size: 20px;
+ border-radius: 5px;
+ border-color: #ccc;
+ padding-block: 0;
+ padding-inline: 0;
+ background-color: #fff;
+}
+
+.color-text-input::-webkit-color-swatch {
+ border-radius: 3px;
+ border: 1px #ccc;
+}
+
+.color-text-input::-moz-color-swatch {
+ border-radius: 3px;
+ border: 1px #ccc;
+}
+
+.calendar-side-borders-sub {
+ border: 1px solid #ccc;
+ border-radius: 5px;
+ position: relative;
+}
+
+.calendar-side-borders-main {
+ border: 1px solid #ccc;
+ padding: 0px 5px 15px 5px;
+ border-radius: 5px;
+}
+
+.calendar-side-label {
+ font-size: 13px;
+}
+
+.fc-daygrid-day-events .fc-event {
+ margin-bottom: 10px;
+ padding-left: 8px;
+ padding-right: 8px;
+ border-radius: 2px;
+ border: 0;
+ border-left: 3px solid #6571ff;
+ color: #000;
+ font-weight: 500;
+ text-align: left;
+}
+
+.fc-daygrid-dot-event .fc-event-title {
+ font-weight: 500;
+}
+
+.fc-daygrid-day-events .fc-event {
+ text-align: center;
+ border: 1px solid #3788d840;
+}
+
+.tooltip-description {
+ font-size: 13px;
+ font-weight: 300;
+}
+
+.tooltip-location {
+ font-size: 13px;
+ font-weight: 300;
+}
+
+.fc-timegrid-event-harness-inset .fc-timegrid-event, .fc-timegrid-event.fc-event-mirror, .fc-timegrid-more-link {
+ box-shadow: 0px 0px 1px 1px #535353;
+}
+
+.fc-event-attachment {
+ position: absolute;
+ right: 1px;
+ top: 0;
+}
+
+.fc-event-type {
+ position: absolute;
+ top: 0;
+ left: 1px;
+}
+
+.fa-duotone {
+ font-size: 20px;
+ cursor: pointer;
+}
+
+.doc-icon-div {
+ width: 25px;
+}
+
+.fa-file-pdf:after {
+ content: "\f1c1\f1c1";
+ color: #f00;
+ opacity: 0.5;
+}
+
+.fa-file-xls:after {
+ content: "\f1c1\f1c1";
+ color: #279800;
+ opacity: 0.5;
+}
+
+.fa-file-csv:after {
+ content: "\f1c1\f1c1";
+ color: #279800;
+ opacity: 0.5;
+}
+
+.fa-file-zip:after {
+ content: "\f1c1\f1c1";
+ color: #d9c800;
+ opacity: 0.8;
+}
+
+.fa-file-doc:after {
+ content: "\f1c1\f1c1";
+ color: #003498;
+ opacity: 0.5;
+}
+
+.fa-file-ppt:after {
+ content: "\f1c1\f1c1";
+ color: #ff6400;
+ opacity: 0.5;
+}
+
+.fa-file-xml:after {
+ content: "\f1c1\f1c1";
+ color: #009091;
+ opacity: 0.6;
+}
+
+.fa-file-mp3:after {
+ content: "\f1c1\f1c1";
+ color: #d104ad;
+ opacity: 0.6;
+}
+
+.fa-file-png:after, .fa-file-jpg:after {
+ content: "\f1c1\f1c1";
+ color: #001dff;
+ opacity: 0.5;
+}
+
+.fa-calendar-symbol:after {
+ color: #0600ff;
+ opacity: 0.7;
+}
+
+.fa-calendar-lines-pen:before {
+ color: #ff0000;
+}
+
+.fa-calendar-circle-plus:before {
+ color: #0d9f00;
+}
+
+.fa-del-attachment {
+ color: #ff0000;
+ cursor: pointer;
+
+}
+
+.fa-circle-info {
+ font-size: 21px;
+ vertical-align: bottom;
+ margin-left: 5px;
+ cursor: pointer;
+}
+
+.fa-circle-info:before, .fa-info-circle:before {
+ content: "\f05a";
+ color: #e70404;
+}
+
+.doc-main-div {
+ border-bottom: 1px dotted #ccc;
+ margin-top: 4px;
+}
+
+.doc-content-div {
+ cursor: pointer;
+ max-width: 70%;
+ vertical-align: middle;
+}
+
+.doc-content-div a {
+ color: #000;
+}
+
+.doc-content-tooltip-div a {
+ color: #fff;
+}
+
+.modal-title {
+ color: #1b1d1c;
+}
+
+.checkbox-label {
+ margin-top: 2px;;
+}
+
+#documents {
+ margin-left: -30px;
+ margin-right: -30px;
+}
+
+.custom-file-input:lang(en) ~ .custom-file-label::after {
+ content: "Durchsuchen";
+}
+
+.required {
+ background-color: #fba5a5;
+
+}
+
+.event-search-result {
+ box-shadow: 0px 0px 3px 3px #48ff00 !important;
+}
+
+.search-div .select2 {
+ text-align: left;
+}
+
+.text-template {
+ cursor: pointer;
+}
+
+.font-12 {
+ font-size: 12px !important;
+}
+
+.form-check-input {
+ position: absolute;
+ margin-top: 5px;
+ margin-left: -1.25rem;
+}
+
+.add-cal-group-div {
+ position: absolute;
+ right: 24px;
+ top: 11px;
+ font-size: 22px;
+ color: #2a8504;
+}
+
+.fa-rectangle-history-circle-plus:after {
+ color: #0600ff;
+ opacity: 0.7;
+}
+
+#calendar-side-div {
+ max-height: 850px;
+ overflow: scroll;
+}
+
+/* width */
+::-webkit-scrollbar {
+ width: 7px;
+}
+
+/* Track */
+::-webkit-scrollbar-track {
+ background: #f1f1f1;
+}
+
+/* Handle */
+::-webkit-scrollbar-thumb {
+ background: #d7d3f9;
+ border-radius: 10px;
+}
+
+/* Handle on hover */
+::-webkit-scrollbar-thumb:hover {
+ background: #8577f9;
+}
+
+.dropdown-group-div {
+ position: absolute;
+ right: 10px;
+ top: 6px;
+ font-size: 20px;
+ color: #000000;
+}
+
+.move-group-div {
+ position: absolute;
+ left: 7px;
+ top: 10px;
+ font-size: 15px;
+ color: #676767;
+ cursor: grab;
+}
+
+.fa-square-arrow-down:after {
+ color: #0eb202;
+ opacity: 0.3;
+}
+
+.fa-square-arrow-up:after {
+ color: #ff3434;
+ opacity: 0.3;
+}
+
+.group-checkbox-div {
+ position: absolute;
+ top: 7px;
+ left: 58px;
+}
+
+.event-free {
+ border-left: 5px solid #0043d3;
+
+}
+
+.event-busy {
+ border-left: 5px solid #24ab00;
+}
+
+.event-tentative {
+
+ border-left: 5px solid #df0000;
+}
\ No newline at end of file
diff --git a/public/js/pages/Calendar/View.js b/public/js/pages/Calendar/View.js
new file mode 100644
index 000000000..cc5c3717f
--- /dev/null
+++ b/public/js/pages/Calendar/View.js
@@ -0,0 +1,1591 @@
+var hidesearch = [2, 3, 4, 8];
+var columnfilter = [7];
+var columnoptions = '
';
+
+const fileTypeClasses = {
+ 'image/png': 'fa-file-png',
+ 'image/jpeg': 'fa-file-jpg',
+ 'application/pdf': 'fa-file-pdf',
+ 'application/zip': 'fa-file-zip',
+ 'application/x-zip-compressed': 'fa-file-zip',
+ 'application/octet-stream': 'fa-file-csv',
+ 'text/csv': 'fa-file-csv',
+ 'text/xml': 'fa-file-xml',
+ 'application/xml': 'fa-file-xml',
+ 'audio/mpeg': 'fa-file-mp3',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'fa-file-doc',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'fa-file-xls',
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'fa-file-ppt',
+ 'application/x-rar-compressed': 'fa-file-archive',
+ 'application/msword': 'fa-file-doc',
+ 'application/vnd.ms-excel': 'fa-file-xls',
+ 'application/vnd.ms-powerpoint': 'fa-file-ppt',
+ 'application/vnd.ms-outlook': 'fa-file-outlook',
+ 'application/vnd.ms-access': 'fa-file-access',
+ 'application/vnd.ms-project': 'fa-file-project',
+ 'application/vnd.ms-visio': 'fa-file-visio',
+ 'application/vnd.ms-publisher': 'fa-file-publisher',
+
+ // Weitere Typen und Klassen hinzufügen...
+};
+var calendar;
+var calendarEl = document.getElementById('calendar');
+calendarRights = JSON.parse(calendarRights);
+
+function formatFileSize(bytes) {
+ // Wenn die Dateigröße größer als 1 MB ist
+ if (bytes >= 1024 * 1024) {
+ const megabytes = bytes / (1024 * 1024);
+ return megabytes.toFixed(2) + ' MB';
+ }
+ // Wenn die Dateigröße größer als 1 KB ist
+ else if (bytes >= 1024) {
+ const kilobytes = bytes / 1024;
+ return kilobytes.toFixed(2) + ' KB';
+ }
+ // Wenn die Dateigröße kleiner als 1 KB ist (also in Bytes)
+ else {
+ return Math.round(bytes) + ' Bytes'; // Keine Nachkommastellen
+ }
+}
+
+function getOffset(unixTimestamp) {
+ const date = new Date(unixTimestamp); // Convert to milliseconds
+ const isDST = date.getTimezoneOffset() < Math.max(
+ new Date(date.getFullYear(), 0, 1).getTimezoneOffset(),
+ new Date(date.getFullYear(), 6, 1).getTimezoneOffset()
+ );
+
+ return isDST ? 7200 : 3600;
+}
+
+
+document.addEventListener('DOMContentLoaded', function () {
+ let checkbox = $(".form-check-input");
+ let visibleCalendars = [];
+ visibleCalendars.push(0);
+ checkbox.each(function () {
+ if ($(this).prop('checked')) {
+ visibleCalendars.push($(this).data('calendar_id'));
+ }
+ });
+
+
+ $.post(requestUrl, {visibleCalendars: visibleCalendars}, function (data) {
+
+ }, 'json').done(function (json) {
+ if (json.success == true) {
+ var userevents = [];
+ var otherevents = [];
+ var resources = [];
+ var category = "";
+ var rights = false;
+ var resourceCounter = 0;
+ $.each($('.calendar-check'), function (index, value) {
+ if ($(this).prop('checked')) {
+ rights = true;
+
+ resources.push({
+ id: $(this).data('calendar_id'),
+ title: $.trim($(this).closest('div').find('label').text()),
+ order: resourceCounter
+ });
+
+ resourceCounter++;
+ }
+ });
+
+
+ $.each(json.data, function (index, value) {
+ category = value.ccategory.ccategory;
+
+ if (value.calendar_id.calendar_id in calendarRights) {
+ if (calendarRights[value.calendar_id.calendar_id] == 'all') {
+ rights = true;
+ } else {
+ rights = false;
+ }
+ userevents.push({
+ id: value.id.id,
+ start: value.cstart.cstart,
+ end: value.cend.cend,
+ title: category,
+ description: value.description.description,
+ location: value.location.location,
+ attachment: value.attachment.attachment,
+ attachments: value.attachments.attachments,
+ calendar_id: value.calendar_id,
+ event_type: value.event_type.event_type,
+ classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id],
+ textColor: value.txtColor.txtColor,
+ backgroundColor: value.bgColor.bgColor,
+ editable: rights,
+ resourceId: value.calendar_id.calendar_id,
+ calendar_name: value.calendar_name.calendar_name,
+ mtime: value.mtime.mtime,
+ mname: value.mname.mname,
+ ctime: value.ctime.ctime,
+ cname: value.cname.cname,
+ busy: value.busy.busy
+ });
+ } else {
+ otherevents.push({
+ id: value.id.id,
+ start: value.cstart.cstart,
+ end: value.cend.cend,
+ title: category,
+ description: category,
+ color: 'red',
+ editable: false,
+ calendar_id: value.calendar_id,
+ event_type: value.event_type.event_type,
+ classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id],
+ attachment: value.attachment.attachment,
+ attachments: value.attachments.attachments,
+ resourceId: value.calendar_id.calendar_id,
+ calendar_name: value.calendar_name.calendar_name,
+ mtime: value.mtime.mtime,
+ mname: value.mname.mname,
+ ctime: value.ctime.ctime,
+ cname: value.cname.cname,
+ busy: value.busy.busy
+ });
+
+ }
+ });
+
+ function sleep(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+ }
+
+ calendar = new FullCalendar.Calendar(calendarEl, {
+ schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
+ timeZone: 'UTC',
+ locale: 'de',
+
+
+ themeSystem: 'bootstrap4',
+ snapDuration: '00:15:00',
+ selectable: true,
+ headerToolbar: {
+ left: "prev,today,next",
+ center: 'title',
+ right: 'dayGridMonth,timeGridWeek,timeGridDay,resourceTimelineDay,listMonth'
+ },
+ buttonText: {
+ resourceTimelineDay: 'Planung'
+ },
+ select: function (info) {
+ let cestDate = new Date(info.startStr);
+ let cestOffset = 0; // 2 Stunden in Minuten
+ let utcTime = cestDate.getTime() - cestOffset * 60 * 1000;
+
+ let utcDate = new Date(utcTime);
+ let year = utcDate.getUTCFullYear();
+ let month = String(utcDate.getUTCMonth() + 1).padStart(2, '0');
+ let day = String(utcDate.getUTCDate()).padStart(2, '0');
+ let hours = String(utcDate.getUTCHours()).padStart(2, '0');
+ let minutes = String(utcDate.getUTCMinutes()).padStart(2, '0');
+ let seconds = String(utcDate.getUTCSeconds()).padStart(2, '0');
+
+ let StartformattedDate = year + "-" + month + "-" + day;
+ let StarteformattedTime = hours + ":" + minutes;
+
+ cestDate = new Date(info.endStr);
+ cestOffset = 0; // 2 Stunden in Minuten
+ utcTime = cestDate.getTime() - cestOffset * 60 * 1000;
+
+ utcDate = new Date(utcTime);
+ year = utcDate.getUTCFullYear();
+ month = String(utcDate.getUTCMonth() + 1).padStart(2, '0');
+ day = String(utcDate.getUTCDate()).padStart(2, '0');
+ hours = String(utcDate.getUTCHours()).padStart(2, '0');
+ minutes = String(utcDate.getUTCMinutes()).padStart(2, '0');
+ seconds = String(utcDate.getUTCSeconds()).padStart(2, '0');
+
+ let EndformattedDate = year + "-" + month + "-" + day;
+ let EndformattedTime = hours + ":" + minutes;
+
+
+ $('#EventModal').modal('show');
+ $('#start-date').val(StartformattedDate);
+ $('#start-time').val(StarteformattedTime);
+ $('#end-date').val(EndformattedDate);
+ $('#end-time').val(EndformattedTime);
+
+ }, eventClick: function (info, element) {
+ let isOrganizer;
+
+ $.getJSON(requestEventUrl, {
+ id: info.event.id
+ }, function (data) {
+
+ }).done(function (data) {
+ if (data.data.attachment.attachment) {
+ let docs = "";
+ $.each(data.data.attachments.attachments, function (index, value) {
+ docs += `
` + formatFileSize(value.size) + ``;
+ });
+ $('.attachment-div').append(docs);
+ }
+ if (data.data.reminder.reminder) {
+ $('#reminder').val(data.data.reminder.reminder);
+ } else {
+ $('#reminder').val('NULL');
+ }
+ $('#type').val(data.data.type.type);
+ $('#busy').val(data.data.busy.busy);
+ isOrganizer = data.data.isorganizer.isorganizer;
+ if (data.data.type.type == "1") {
+ $('.customer-div').hide();
+ } else if (data.data.type.type == "2") {
+ $('.customer-div').show();
+ if (data.data.customer.customer) {
+ $('#customer').html('
');
+ } else {
+ $('#customer').html('
');
+ }
+ if (data.data.customer_info_reminder.customer_info_reminder) {
+ $('#customer-info-reminder-check').prop('checked', true);
+ }
+ $('#customer').select2({
+ placeholder: "Kunden Suche",
+ minimumInputLength: 3,
+ dropdownParent: $('#EventModal'),
+ language: "de",
+ ajax: {
+ url: requestAddressUrl,
+ dataType: 'json',
+ delay: 250,
+ processResults: function (data) {
+ // Transforms the top-level key of the response object from 'items' to 'results'
+ return {
+ results: data.items
+ };
+ }
+ }
+ });
+ if (data.data.customer_info.customer_info) {
+ const obj = JSON.parse(data.data.customer_info.customer_info);
+ $('#customer-info-text').val(obj.customer_info_text);
+ $('#customer-info-type').val(obj.customer_info_type);
+ $('#customer-info-type-text').val(obj.customer_info_type_text);
+ }
+ if (data.data.customer_info_send.customer_info_send) {
+ const obj = JSON.parse(data.data.customer_info_send.customer_info_send);
+ $('#customer-info-check-info').html('
');
+ const unixTime = obj.sendtime;
+ const date = new Date(unixTime * 1000);
+ const germanDateTime = date.toLocaleString('de-DE', {
+ day: '2-digit',
+ month: '2-digit',
+ year: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ second: '2-digit',
+ });
+ var typeText;
+ if (obj.customer_info_type == 1) {
+ typeText = 'E-Mail';
+ } else if (obj.customer_info_type == 2) {
+ typeText = 'SMS';
+ }
+ var title = `
Letzte gesendete Info (` + typeText + `):
+
` + obj.customer_info_text.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1
$2') + `
+
gesendet an: ` + obj.customer_info_type_text + `
+
gesendet von: ` + obj.sendby + `
+
gesendet am: ` + germanDateTime + `
+
+`;
+ var tooltip = new Tooltip($('.fa-circle-info'), {
+ title: title,
+ placement: 'right',
+ trigger: 'hover',
+ container: 'body',
+ html: true
+ });
+ }
+ }
+ if (isOrganizer == "1") {
+ $('.show-update').show();
+ } else {
+ $('.show-update').hide();
+ }
+
+ });
+ if (info.event.startEditable) {
+ let cestDate = new Date(info.event.startStr);
+ let cestOffset = 0; // 2 Stunden in Minuten
+ let utcTime = cestDate.getTime() - cestOffset * 60 * 1000;
+
+ let utcDate = new Date(utcTime);
+ let year = utcDate.getUTCFullYear();
+ let month = String(utcDate.getUTCMonth() + 1).padStart(2, '0');
+ let day = String(utcDate.getUTCDate()).padStart(2, '0');
+ let hours = String(utcDate.getUTCHours()).padStart(2, '0');
+ let minutes = String(utcDate.getUTCMinutes()).padStart(2, '0');
+ let seconds = String(utcDate.getUTCSeconds()).padStart(2, '0');
+
+ let StartformattedDate = year + "-" + month + "-" + day;
+ let StarteformattedTime = hours + ":" + minutes;
+
+ cestDate = new Date(info.event.endStr);
+ cestOffset = 0; // 2 Stunden in Minuten
+ utcTime = cestDate.getTime() - cestOffset * 60 * 1000;
+
+ utcDate = new Date(utcTime);
+ year = utcDate.getUTCFullYear();
+ month = String(utcDate.getUTCMonth() + 1).padStart(2, '0');
+ day = String(utcDate.getUTCDate()).padStart(2, '0');
+ hours = String(utcDate.getUTCHours()).padStart(2, '0');
+ minutes = String(utcDate.getUTCMinutes()).padStart(2, '0');
+ seconds = String(utcDate.getUTCSeconds()).padStart(2, '0');
+
+ let EndformattedDate = year + "-" + month + "-" + day;
+ let EndformattedTime = hours + ":" + minutes;
+
+
+ $('#EventModal').modal('show');
+ $('#start-date').val(StartformattedDate);
+ $('#start-time').val(StarteformattedTime);
+ $('#end-date').val(EndformattedDate);
+ $('#end-time').val(EndformattedTime);
+
+ $('#EventModal').modal('show');
+ if (info.event.allDay) {
+ $('#allday').prop('checked', true)
+ $('#allday').change();
+
+ $('#end-time').val('');
+ $('#end-date').val(StartformattedDate);
+ $('#start-time').val('');
+ } else {
+ $('#end-date').val(EndformattedDate);
+ $('#allday').prop('checked', false);
+ $('#end-time').val(EndformattedTime);
+ $('#start-time').val(StarteformattedTime);
+ }
+
+ $('#calendar-users').val(info.event.extendedProps.calendar_id.calendar_id).trigger('change');
+ $('#calendar-users').prop("disabled", true);
+ $('#name').val(info.event.title);
+ $('#location').val(info.event.extendedProps.location);
+ $('#description').val(info.event.extendedProps.description);
+ $('#delete-event').data('id', info.event.id);
+ $('#update-event').data('id', info.event.id);
+ $('#EventModalLabel').data('id', info.event.id);
+ $('#EventModalLabel span').text('Termin bearbeiten');
+ $('#EventModalLabel .fa-calendar-symbol').removeClass('fa-calendar-circle-plus');
+ $('#EventModalLabel .fa-calendar-symbol').addClass('fa-calendar-lines-pen');
+ $('#add-event').hide();
+ }
+ },
+ eventDidMount: function (info) {
+ var eventstart = new Date(info.event.start);
+
+ var eventend = new Date(info.event.end);
+
+
+ var title;
+ if (!info.event.allDay) {
+ eventstart = eventstart.toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'});
+ eventend = eventend.toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'});
+ title = '
von ' + eventstart + ' bis ' + eventend + '
';
+ } else {
+ eventstart = eventstart.toLocaleDateString();
+ eventend = eventend.toLocaleDateString();
+ title = '
Ganztägig von ' + eventstart + ' bis ' + eventend + '
';
+ }
+
+
+ title += info.event.title;
+ if (info.event.extendedProps['description']) {
+ title += '
' + info.event.extendedProps['description'] + '
';
+ }
+ if (info.event.extendedProps['location']) {
+ title += '
@ ' + info.event.extendedProps['location'] + '
';
+ }
+ if (info.event.extendedProps['attachment'] == 1) {
+ const obj = JSON.parse(info.event.extendedProps['attachments']);
+ let docs = "";
+ $.each(obj, function (index, value) {
+ var filename;
+ if (fileTypeClasses[value.contentType]) {
+ filename = fileTypeClasses[value.contentType];
+ } else {
+ filename = 'fa-file';
+ }
+ docs += `
` + formatFileSize(value.size) + ``;
+ });
+ title += '
' + docs + '
';
+ }
+ if (info.event.extendedProps['ctime']) {
+ title += '
Kalender: ' + info.event.extendedProps['calendar_name'] + '
';
+ title += '
erstellt am ' + info.event.extendedProps['ctime'] + '
';
+ title += '
erstellt von ' + info.event.extendedProps['cname'] + '
';
+ title += '
geändert am ' + info.event.extendedProps['mtime'] + '
';
+ title += '
geändert von ' + info.event.extendedProps['mname'] + '
';
+ }
+ // console.log(info);
+ if ($('.fc-button-active').hasClass('fc-timeGridWeek-button') || $('.fc-button-active').hasClass('fc-timeGridDay-button')) {
+ if (info.event.extendedProps['attachment']) {
+ info.el.querySelector(".fc-event-title").insertAdjacentHTML("afterend", "
");
+ }
+ if (info.event.extendedProps['event_type'] == '2') {
+
+ info.el.querySelector(".fc-event-title").insertAdjacentHTML("afterend", "
");
+ }
+ }
+
+ var tooltip = new Tooltip(info.el, {
+ title: title,
+ placement: 'right',
+ delay: {hide: 50},
+ trigger: 'hover',
+ container: 'body',
+ html: true,
+ });
+
+ var tooltips = info.event.extendedProps['tooltips'] || [];
+ tooltips.push(tooltip);
+ info.event.setExtendedProp('tooltips', tooltips);
+ },
+
+ eventWillUnmount: function (info) {
+ for (var tooltip of info.event.extendedProps['tooltips']) {
+ tooltip.dispose();
+ }
+ },
+ eventResize: function (info) {
+
+ var start = info.event.start.getTime();
+ const offsetstart = getOffset(start);
+ start = (start / 1000 + offsetstart) * 1000;
+ var end = info.event.end.getTime();
+ const offsetend = getOffset(end);
+ end = (end / 1000 + offsetend) * 1000;
+ var id = info.event.id;
+ $.post(requestUpdateUrl, {
+ start: start,
+ end: end,
+ id: id
+ }, function (data) {
+
+ }).done(function (data) {
+ var tooltip = new Tooltip(info.el, {
+ title: info.event.extendedProps.description,
+ placement: 'right',
+ trigger: 'hover',
+ container: 'body'
+ });
+
+ var tooltips = info.event.extendedProps['tooltips'] || [];
+ tooltips.push(tooltip);
+ info.event.setExtendedProp('tooltips', tooltips);
+ });
+
+ },
+ eventDrop: function (info) {
+ // sleep(2000).then(() => {
+ var start = info.event.start.getTime();
+ const offsetstart = getOffset(start);
+ start = (start / 1000 + offsetstart) * 1000;
+ var end = info.event.end.getTime();
+ const offsetend = getOffset(end);
+ end = (end / 1000 + offsetend) * 1000;
+ var id = info.event.id;
+ $.post(requestUpdateUrl, {
+ start: start,
+ end: end,
+ id: id
+ }, function (data) {
+
+ }).done(function (data) {
+ });
+ // });
+ },
+ eventClassNames: function (info) {
+
+ let result = '';
+
+ if (typeof info.event.extendedProps.calendar_id === 'undefined') {
+ return '';
+ }
+ let checkbox = $(".form-check-input");
+ checkbox.each(function () {
+ if ($(this).prop('checked')) {
+ if (Number(info.event.extendedProps.calendar_id.calendar_id) === $(this).data('calendar_id')) {
+
+ }
+ } else {
+ if (Number(info.event.extendedProps.calendar_id.calendar_id) === $(this).data('calendar_id')) {
+ result = "";
+ }
+ }
+ });
+ if (info.event.extendedProps.busy == '0') {
+ result += ' event-free';
+ } else if (info.event.extendedProps.busy == '1') {
+ result += ' event-busy';
+ } else if (info.event.extendedProps.busy == '2') {
+ result += ' event-tentative';
+ }
+
+
+ return result;
+ },
+ datesSet: function (dateInfo) {
+ $('.event-search-result').removeClass('event-search-result');
+ $('#jumpevent').val(null).trigger('change');
+ ;
+ // $('#jumpevent').change();
+ },
+ editable: true,
+ droppable: true, // this allows things to be dropped onto the calendar
+ fixedWeekCount: true,
+ // height: 300,
+ initialView: 'timeGridWeek',
+ timeZone: 'UTC',
+ hiddenDays: [],
+ navLinks: 'true',
+ events: [],
+ height: 800,
+ eventSources: [userevents, otherevents, holiDays, birthdays],
+ resourceOrder: 'order',
+ resources: resources,
+ });
+ calendar.render();
+
+ } else {
+ $('#calendar').closest('.row').html('
' + json.errormessage + '
');
+ }
+ });
+});
+
+
+if (typeof (EventSource) !== 'undefined') {
+ console.info('Starting connection...');
+
+ var source = new EventSourcePolyfill(requestUpdateEventsUrl, {
+ // Specifying custom request headers
+ headers: {
+ 'X-API-KEY': 'wcdqEHXcXl5f1sZTEHKPTutqpFBbRf55'
+ },
+ heartbeatTimeout: 6000000
+ });
+ source.addEventListener('open', function (e) {
+ console.info('Connection was opened.');
+ }, false);
+ let jsondata;
+ source.addEventListener('error', function (e) {
+ var txt;
+ switch (Event.target.readyState) {
+ // if reconnecting
+ case EventSource.CONNECTING:
+ txt = 'Reconnecting...';
+ break;
+ // if error was fatal
+ case EventSource.CLOSED:
+ txt = 'Connection failed. Will not retry.';
+ break;
+ }
+ console.error('Connection error: ' + txt);
+ }, false);
+
+ source.addEventListener('message', function (e) {
+ // document.getElementById('result').innerHTML += e.data + '
';
+
+ jsondata = JSON.parse(e.data);
+ jsondata.forEach(function (event) {
+ var cevent = calendar.getEventById(event.cal_events_id);
+ var rights = false;
+ if (event.calendar_id in calendarRights) {
+ if (calendarRights[event.calendar_id] == 'all') {
+ rights = true;
+ } else {
+ rights = false;
+ }
+ }
+ if (event.change_type == '2' && cevent) {
+ if (cevent) {
+ if (event.calendar_id == event.calendar_id) {
+ cevent.remove();
+ calendar.addEvent({
+ id: event.cal_events_id,
+ title: event.name,
+ start: event.start_time,
+ end: event.end_time,
+ description: event.description,
+ calendar_id: event.calendar_id_check,
+ textColor: event.txtColor,
+ backgroundColor: event.bgColor,
+ location: event.location,
+ event_type: event.event_type,
+ classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id],
+ attachment: event.attachment,
+ attachments: event.attachments,
+ editable: rights,
+ resourceId: event.calendar_id,
+ calendar_name: event.calendar_name,
+ mtime: event.mtime,
+ mname: event.mname,
+ ctime: event.ctime,
+ cname: event.cname,
+ busy: event.busy
+ });
+ } else {
+ cevent.remove();
+ calendar.addEvent({
+ id: event.cal_events_id,
+ title: event.name,
+ start: event.start_time,
+ end: event.end_time,
+ description: event.description,
+ calendar_id: event.calendar_id_check,
+ color: '#ab0000',
+ editable: false,
+ location: event.location,
+ event_type: event.event_type,
+ classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id],
+ attachment: event.attachment,
+ attachments: event.attachments,
+ calendar_id: event.calendar_id_check,
+ resourceId: event.calendar_id,
+ calendar_name: event.calendar_name,
+ mtime: event.mtime,
+ mname: event.mname,
+ ctime: event.ctime,
+ cname: event.cname,
+ busy: event.busy
+ });
+ }
+ calendar.render();
+ }
+
+ } else if (event.change_type == '1' || !cevent) {
+ if (event.calendar_id == event.calendar_id) {
+ var info = calendar.addEvent({
+ id: event.cal_events_id,
+ title: event.name,
+ start: event.start_time,
+ end: event.end_time,
+ description: event.description,
+ calendar_id: event.calendar_id_check,
+ textColor: event.txtColor,
+ backgroundColor: event.bgColor,
+ location: event.location,
+ event_type: event.event_type,
+ classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id],
+ attachment: event.attachment,
+ attachments: event.attachments,
+ editable: rights,
+ resourceId: event.calendar_id,
+ calendar_name: event.calendar_name,
+ mtime: event.mtime,
+ mname: event.mname,
+ ctime: event.ctime,
+ cname: event.cname,
+ busy: event.busy
+ });
+
+ } else {
+ var info = calendar.addEvent({
+ id: event.cal_events_id,
+ title: event.name,
+ start: event.start_time,
+ end: event.end_time,
+ description: event.description,
+ calendar_id: event.calendar_id_check,
+ color: '#ab0000',
+ editable: false,
+ location: event.location,
+ event_type: event.event_type,
+ classNames: ['cal-class-group-' + event.calendar_id, 'cal-class-id-' + event.cal_events_id],
+ attachment: event.attachment,
+ attachments: event.attachments,
+ calendar_id: event.calendar_id_check,
+ resourceId: event.calendar_id,
+ calendar_name: event.calendar_name,
+ mtime: event.mtime,
+ mname: event.mname,
+ ctime: event.ctime,
+ cname: event.cname,
+ busy: event.busy
+ });
+ }
+ calendar.render();
+ } else if (event.change_type == '3') {
+ var cevent = calendar.getEventById(event.cal_events_id);
+ cevent.remove();
+ }
+
+ });
+ }, false);
+} else {
+ alert('Your browser does not support Server-sent events! Please upgrade it!');
+ console.error('Connection aborted');
+}
+$(document).ready(function () {
+
+ $('body').on('click', '.fa-window-maximize', function () {
+ $('.card').addClass('card-fullscreen');
+ $('#card-size').removeClass('fa-window-maximize').addClass('fa-window-restore');
+ calendar.render();
+ });
+
+ $('body').on('click', '.fa-window-restore', function () {
+ $('.card').removeClass('card-fullscreen');
+ $('#card-size').removeClass('fa-window-restore').addClass('fa-window-maximize');
+ calendar.render();
+ });
+
+ $(document).keyup(function (e) {
+ if (e.key === "Escape") { // escape key maps to keycode `27`
+ if ($('.card').hasClass('card-fullscreen')) {
+ $('.card').removeClass('card-fullscreen');
+ $('#card-size').removeClass('fa-window-restore').addClass('fa-window-maximize');
+ }
+ $('.cal-group-name-input').each(function (index, value) {
+ $(this).closest('div').find('.dropdown-group-div').show();
+ $(this).closest('div').find('.move-group-div').show();
+ $(this).closest('div').find('.group-checkbox-div').show();
+ $(this).closest('.cal-group-name').text($(this).data('oldname'));
+
+ });
+
+ }
+ });
+
+ $('#EventModal').on('show.bs.modal', function (event) {
+ $('.attachment-div').empty();
+ $('#reminder').val('NULL');
+ $('#type').val('1');
+ $('#customer-info-check-info').empty();
+ $('#customer-info-type').val('1');
+ $('#customer').val('');
+ $('.customer-div').hide();
+ $('#EventModalLabel span').text('Termin erstellen');
+ $('#EventModalLabel .fa-calendar-symbol').addClass('fa-calendar-circle-plus');
+ $('#EventModalLabel .fa-calendar-symbol').removeClass('fa-calendar-lines-pen');
+ $('#EventModalLabel').data('id', '');
+ $('.eventmodal-input').val('');
+ $('.eventmodal-input').prop('disabled', false);
+ $('.eventmodal-checkbox').prop('checked', false);
+ $('#EventModal .is-require').each(function (index, value) {
+ $(this).removeClass('required');
+ });
+ $('#calendar-users').prop("disabled", false);
+ $("#calendar-users option").each(function () {
+ if ($(this).data('mainuser') == "1") {
+ $(this).prop('selected', true).trigger('change');
+ }
+ });
+ $('#type').val('1');
+ $('#busy').val('1');
+ $('#files-input').val('');
+ $('#start-time').addClass('is-require');
+ $('#end-time').addClass('is-require');
+ $('.show-update').hide();
+ $('#add-event').show();
+ $('#attachments').data('newkey', Math.floor(Math.random() * 10000));
+ });
+
+ $('body').on('click', '#add-event', function () {
+ var valid = true;
+
+ $('#EventModal .is-require').each(function (index, value) {
+ if ($(this).val() == "") {
+ valid = false;
+ $(this).addClass('required');
+ } else {
+ $(this).removeClass('required');
+ }
+ });
+
+ if (!valid) {
+ return;
+ }
+ var attachments = [];
+ $('.doc-main-div').each(function (index, value) {
+ if ($(this).data('docid')) {
+ attachments.push($(this).data('docid'));
+ }
+ });
+
+ var start = $('#start-date').val() + ' ' + $('#start-time').val();
+ var end = $('#end-date').val() + ' ' + $('#end-time').val();
+ var title = $('#name').val();
+ var location = $('#location').val();
+ var description = $('#description').val();
+ var newkey = $('#attachments').data('newkey');
+ var allday = 0;
+ var reminder = $('#reminder').val();
+ var type = $('#type').val();
+ var busy = $('#busy').val();
+ var customer;
+ var customer_info_check = 0;
+ var customer_info_text;
+ var customer_info_type;
+ var customer_info_type_text;
+ var customer_info_reminder_check = 0;
+ var users = [];
+
+ if ($('#allday').is(':checked')) {
+ allday = 1;
+ }
+ if ($('#customer-info-check').is(':checked')) {
+ customer_info_check = 1;
+ }
+ if (type == '2') {
+ customer_info_text = $('#customer-info-text').val();
+ customer_info_type = $('#customer-info-type').val();
+ customer_info_type_text = $('#customer-info-type-text').val();
+ customer = $('#customer option:selected').text();
+ if ($('#customer-info-reminder-check').is(':checked')) {
+ customer_info_reminder_check = 1;
+ }
+ }
+ $('#calendar-users > option:selected').each(function () {
+ users.push($(this).val());
+ });
+
+
+ $.post(requestInsertUrl, {
+ start: start,
+ end: end,
+ allday: allday,
+ title: title,
+ location: location,
+ reminder: reminder,
+ type: type,
+ busy: busy,
+ description: description,
+ attachments: attachments,
+ users: users,
+ customer: customer,
+ customer_info_check: customer_info_check,
+ customer_info_text: customer_info_text,
+ customer_info_type: customer_info_type,
+ customer_info_type_text: customer_info_type_text,
+ customer_info_reminder_check: customer_info_reminder_check,
+ newkey: newkey
+ }, function (data) {
+
+ }).done(function (data) {
+ });
+ $('#EventModal').modal('hide');
+ });
+
+ $('body').on('click', '#update-event', function () {
+
+ var valid = true;
+
+ $('#EventModal .is-require').each(function (index, value) {
+ if ($(this).val() == "") {
+ valid = false;
+ $(this).addClass('required');
+ } else {
+ $(this).removeClass('required');
+ }
+ });
+
+ if (!valid) {
+ return;
+ }
+ var attachments = [];
+ $('.doc-main-div').each(function (index, value) {
+ if ($(this).data('docid')) {
+ attachments.push($(this).data('docid'));
+ }
+ });
+
+ var start = $('#start-date').val() + ' ' + $('#start-time').val();
+ var end = $('#end-date').val() + ' ' + $('#end-time').val();
+ var title = $('#name').val();
+ var location = $('#location').val();
+ var description = $('#description').val();
+ var newkey = $('#attachments').data('newkey');
+ var allday = 0;
+ var reminder = $('#reminder').val();
+ var type = $('#type').val();
+ var busy = $('#busy').val();
+ var customer;
+ var customer_info_check = 0;
+ var customer_info_text;
+ var customer_info_type;
+ var customer_info_type_text;
+ var customer_info_reminder_check = 0;
+ var users = [];
+
+ if ($('#allday').is(':checked')) {
+ allday = 1;
+ }
+
+ if ($('#customer-info-check').is(':checked')) {
+ customer_info_check = 1;
+ }
+ if (type == '2') {
+ customer_info_text = $('#customer-info-text').val();
+ customer_info_type = $('#customer-info-type').val();
+ customer_info_type_text = $('#customer-info-type-text').val();
+ customer = $('#customer option:selected').text();
+ if ($('#customer-info-reminder-check').is(':checked')) {
+ customer_info_reminder_check = 1;
+ }
+
+
+ }
+ var id = $(this).data('id');
+
+ $('#calendar-users > option:selected').each(function () {
+ users.push($(this).val());
+ });
+
+
+ $.post(requestUpdateUrl, {
+ id: id,
+ start: start,
+ end: end,
+ allday: allday,
+ title: title,
+ location: location,
+ reminder: reminder,
+ type: type,
+ busy: busy,
+ description: description,
+ attachments: attachments,
+ users: users,
+ customer: customer,
+ customer_info_check: customer_info_check,
+ customer_info_text: customer_info_text,
+ customer_info_type: customer_info_type,
+ customer_info_type_text: customer_info_type_text,
+ customer_info_reminder_check: customer_info_reminder_check,
+ newkey: newkey
+ }, function (data) {
+
+ }).done(function (data) {
+ });
+ $('#EventModal').modal('hide');
+ });
+
+ $('body').on('click', '#delete-event', function () {
+ var id = $(this).data('id');
+ var users = [];
+ $('#calendar-users > option:selected').each(function () {
+ users.push($(this).val());
+ });
+
+
+ if (confirm('Eintrag wirklich löschen?')) {
+ $.post(requestDeleteUrl, {
+ id: id,
+ users: users
+ }, function (data) {
+
+ }).done(function (data) {
+ });
+ $('#EventModal').modal('hide');
+ }
+ });
+
+ $('body').on('change', '#allday', function () {
+ if ($(this).is(':checked')) {
+ $('#start-time').prop('disabled', true);
+ $('#end-time').prop('disabled', true);
+ $('#start-time').removeClass('is-require');
+ $('#end-time').removeClass('is-require');
+ } else {
+ $('#start-time').prop('disabled', false);
+ $('#end-time').prop('disabled', false);
+ if ($('#start-time').val() == "") {
+ $('#start-time').val('08:00');
+ }
+ if ($('#end-time').val() == "") {
+ $('#end-time').val('10:00');
+ }
+ }
+ });
+
+ $('body').on('change', '.color-input,.color-text-input', function (event, init = 0) {
+ var bgcolors = [];
+ var txtcolors = [];
+ var calendar_id = [];
+ var thisis = $(this);
+ if (init === 0) {
+ var resourceA = calendar.getResourceById(thisis.data('calendar_id'));
+ if (resourceA) {
+ var events = resourceA.getEvents();
+ events.forEach(function (event) {
+ event.setProp('backgroundColor', thisis.closest('div').find('.color-input').val());
+ event.setProp('textColor', thisis.closest('div').find('.color-text-input').val());
+ });
+ }
+ calendar.render();
+ }
+ $.each($('.color-input'), function (index, value) {
+ if ($(this).data('calendar_id')) {
+ bgcolors.push($(this).closest('div').find('.color-input').val());
+ txtcolors.push($(this).closest('div').find('.color-text-input').val());
+ calendar_id.push($(this).data('calendar_id'));
+ } else {
+ }
+
+ });
+
+
+ var id = $('#calendar-id').data('id');
+ let groups = getGroups();
+ $.post(requestUpdateColorUrl, {
+ id: id,
+ bgcolors: bgcolors,
+ txtcolors: txtcolors,
+ calendar_id: calendar_id,
+ groups: groups
+ }, function (data) {
+
+ })
+ });
+ $('body').on('change', '.calendar-check', function (event, init = 0) {
+
+ if ($(this).prop('checked')) {
+ refreshCalendarEvents()
+ } else {
+ refreshCalendarEvents()
+ }
+ var resources = calendar.getResources();
+ $.each(resources, function (index, value) {
+ value.remove();
+ });
+ var resourceCounter = 0;
+ $.each($('.calendar-check'), function (index, value) {
+ if ($(this).prop('checked')) {
+ rights = true;
+ calendar.addResource({
+ id: $(this).data('calendar_id'),
+ title: $.trim($(this).closest('div').find('label').text()),
+ order: resourceCounter
+ });
+ resourceCounter++;
+ }
+
+ });
+ $(".color-input").eq(0).trigger("change", 1);
+ checkGroupCheckboxes();
+ }
+ )
+ ;
+
+ function uploadajax(ttl, cl) {
+ var fileList = $('#files-input').prop("files");
+ var form_data = "";
+
+ form_data = new FormData();
+ form_data.append("upload_file", fileList[cl]);
+ form_data.append("event_id", $('#EventModalLabel').data('id'));
+ form_data.append("newkey", $('#attachments').data('newkey'));
+
+
+ var request = $.ajax({
+ url: requestEventAttachmentUploadUrl,
+ cache: false,
+ contentType: false,
+ processData: false,
+ async: true,
+ data: form_data,
+ type: 'POST',
+ xhr: function () {
+ var xhr = $.ajaxSettings.xhr();
+ if (xhr.upload) {
+ xhr.upload.addEventListener('progress', function (event) {
+ var percent = 0;
+ if (event.lengthComputable) {
+ percent = Math.ceil(event.loaded / event.total * 100);
+ }
+ $('.pb-' + fileList[cl].size).css('width', percent + '%').attr('aria-valuenow', percent);
+ }, false);
+ }
+ return xhr;
+ },
+ success: function (res, status) {
+ if (status == 'success') {
+ percent = 0;
+ $('.pb-' + fileList[cl].size).closest('.progress').remove();
+ if (cl < ttl) {
+ uploadajax(ttl, cl + 1);
+ } else {
+ }
+ }
+ },
+ fail: function (res) {
+ alert('Failed');
+ }
+ })
+ }
+
+
+ $('body').on('change', '#files-input', function () {
+ var fileList = $('#files-input').prop("files");
+
+ $('#uploadsts').html('');
+ var i;
+ for (i = 0; i < fileList.length; i++) {
+ let newkey = $('#attachments').data('newkey');
+ const filetype = fileList[i].type;
+ const classContentType = fileTypeClasses[filetype] || 'fa-file';
+ // $('#uploadsts').append('
' + fileList[i].name + '
');
+ $('.attachment-div').append(`
+
+
` + formatFileSize(fileList[i].size) + `
+
+`);
+ if (i == fileList.length - 1) {
+ uploadajax(fileList.length - 1, 0);
+ }
+ }
+
+ });
+
+ $('body').on('click', '.fa-del-attachment', function () {
+ if ($(this).closest('.doc-main-div').data('newkey') && $(this).closest('.doc-main-div').data('name')) {
+ let newkey = $(this).closest('.doc-main-div').data('newkey');
+ let name = $(this).closest('.doc-main-div').data('name');
+ $.post(requestEventAttachmentTmpDeleteUrl, {
+ newkey: newkey,
+ name: name
+ }, function (data) {
+
+ }).done(function (data) {
+
+ });
+ }
+ $(this).closest('.doc-main-div').remove();
+ });
+ $('body').on('click', '#customer', function () {
+
+
+ })
+ $('body').on('change', '#type', function () {
+ if ($(this).val() == "1") {
+ $('.customer-div').hide();
+ } else if ($(this).val() == "2") {
+ $('.customer-div').show();
+ $('#customer').select2({
+ placeholder: "Kunden Suche",
+ minimumInputLength: 3,
+ dropdownParent: $('#EventModal'),
+ language: "de",
+ ajax: {
+ url: requestAddressUrl,
+ dataType: 'json',
+ delay: 250,
+ processResults: function (data) {
+ // Transforms the top-level key of the response object from 'items' to 'results'
+ return {
+ results: data.items
+ };
+ }
+ }
+ });
+ }
+ });
+
+ $('body').on('change', '#jumpevent', function () {
+ $('.event-search-result').removeClass('event-search-result');
+ if ($(this).val() == "" || $(this).val() == null) {
+ return;
+ }
+ const valueArray = $(this).val().split(";");
+ let id = valueArray[0];
+ let date = valueArray[1];
+ calendar.gotoDate(date)
+ $('.cal-class-id-' + id).addClass('event-search-result');
+
+ })
+
+ $('#jumpevent').select2({
+ placeholder: "Termin Suche",
+ minimumInputLength: 3,
+ language: "de",
+ ajax: {
+ url: requestEventSearchURL,
+ dataType: 'json',
+ delay: 250,
+ processResults: function (data) {
+ // Transforms the top-level key of the response object from 'items' to 'results'
+ return {
+ results: data.items
+ };
+ }
+ }
+ });
+ $('body').on('click', '.text-template', function () {
+ const date = new Date($('#start-date').val());
+ const formattedDate = date.toLocaleDateString('de-DE', {
+ day: '2-digit',
+ month: '2-digit',
+ year: 'numeric'
+ });
+ let starttime = $('#start-time').val();
+ let [stunden, minuten] = starttime.split(":").map(Number);
+ let endtime = $('#end-time').val();
+ let daytimetext;
+ if (stunden < 12) {
+ daytimetext = "vormittags";
+ } else {
+ daytimetext = "nachmittags";
+ }
+ let textTemplate;
+ if ($(this).data('id') == 1) {
+ textTemplate = `Sehr geehrter Kunde,
+Ihr Technikertermin findet am ` + formattedDate + ` ` + daytimetext + ` statt.
+Mit Freundlichen Grüßen
+Xinon GMbH`;
+ } else if ($(this).data('id') == 2) {
+ textTemplate = `Sehr geehrter Kunde,
+wir möchten Sie daran erinnern, dass Ihr Technikertermin am ` + formattedDate + ` ` + daytimetext + ` stattfindet.
+Mit Freundlichen Grüßen
+Xinon GMbH`;
+ } else if ($(this).data('id') == 3) {
+ textTemplate = formattedDate + ` zwischen ` + starttime + ` und ` + endtime;
+ }
+
+ $('#customer-info-text').val(textTemplate);
+ });
+
+
+ $('body').on('change', '#customer,#customer-info-type', function () {
+
+ if ($('#name').val() == "") {
+ $('#name').val('IBN: ' + $("#customer").select2('data')[0].name);
+ }
+ if ($('#location').val() == "") {
+ $('#location').val($("#customer").select2('data')[0].location);
+ }
+
+ if ($('#customer-info-type').val() == 1) {
+ let data = $("#customer").select2('data')[0];
+ if (data) {
+ $('#customer-info-type-text').val(data.mail);
+ }
+
+ } else if ($('#customer-info-type').val() == 2) {
+ let data = $("#customer").select2('data')[0];
+ if (data) {
+ $('#customer-info-type-text').val(data.mobilenumber);
+ }
+ }
+
+
+ });
+
+ $("body").on("click", "#customer-info-check", function () {
+ if ($(this).prop('checked')) {
+ $('#customer-info-reminder-check').prop('checked', true);
+ }
+
+ });
+ $("body").on("click", ".add-cal-group-div", function () {
+ $('.add-cal-group-div-sub').prepend(`
+
Gruppe
+
+
+
+
+
+ `);
+ $('.calendar-side-borders-sub-inner').sortable({
+ group: 'shared',
+ filter: 'h5',
+ });
+ });
+
+ $("body").on("dblclick", ".cal-group-name", function () {
+ if ($(this).find('.cal-group-name-input').length) {
+ return;
+ }
+ $(this).closest('div').find('.dropdown-group-div').hide();
+ $(this).closest('div').find('.move-group-div').hide();
+ $(this).closest('div').find('.group-checkbox-div').hide();
+
+ let groupname = $.trim($(this).text());
+ $(this).html('
');
+ });
+
+ $("body").on("click", ".group-checkbox", function () {
+ if ($(this).prop('checked')) {
+ $(this).closest('.calendar-side-borders-sub').find('.form-check-input').prop('checked', true);
+
+ refreshCalendarEvents()
+
+
+ } else {
+
+ $(this).closest('.calendar-side-borders-sub').find('.form-check-input').prop('checked', false);
+ refreshCalendarEvents()
+ }
+ var resources = calendar.getResources();
+ $.each(resources, function (index, value) {
+ value.remove();
+ });
+ var resourceCounter = 0;
+ $.each($('.calendar-check'), function (index, value) {
+ if ($(this).prop('checked')) {
+ rights = true;
+ calendar.addResource({
+ id: $(this).data('calendar_id'),
+ title: $.trim($(this).closest('div').find('label').text()),
+ order: resourceCounter
+ });
+ resourceCounter++;
+ }
+
+ });
+ $(".color-input").eq(0).trigger("change", 1);
+ checkGroupCheckboxes();
+ });
+
+ $("body").on("click", ".dropdown-group", function () {
+ if ($(this).hasClass('fa-square-arrow-up')) {
+ $(this).removeClass('fa-square-arrow-up');
+ $(this).addClass('fa-square-arrow-down');
+ $(this).closest('.calendar-side-borders-sub').find('.calendar-side-borders-sub-inner').hide();
+ } else {
+ $(this).removeClass('fa-square-arrow-down');
+ $(this).addClass('fa-square-arrow-up');
+ $(this).closest('.calendar-side-borders-sub').find('.calendar-side-borders-sub-inner').show();
+ }
+ });
+
+ $("body").on("keyup", ".cal-group-name-input", function (e) {
+ if (e.keyCode === 13) {
+ let groupname = $.trim($(this).val());
+ if (groupname.length > 3) {
+ $(this).closest('div').find('.dropdown-group-div').show();
+ $(this).closest('div').find('.move-group-div').show();
+ $(this).closest('div').find('.group-checkbox-div').show();
+ $(this).closest('.cal-group-name').text(groupname);
+ $(".color-input").eq(0).trigger("change", 1);
+ } else if (groupname.length == 0) {
+ if (confirm('Gruppe wirklich löschen?')) {
+ $(this).closest('.calendar-side-borders-sub').find('.form-check').each(function (index, value) {
+ let calendar = $(this).html();
+ $('.data-origin-' + $(this).data('origin')).append(`
` + calendar + `
`);
+ });
+ $(this).closest('.calendar-side-borders-sub').remove();
+ $(".color-input").eq(0).trigger("change", 1);
+ }
+ $(this).closest('div').find('.dropdown-group-div').show();
+ $(this).closest('div').find('.move-group-div').show();
+ $(this).closest('div').find('.group-checkbox-div').show();
+ $(this).closest('.cal-group-name').text($(this).data('oldname'));
+
+ }
+ }
+ });
+
+
+ function getGroups() {
+ const groups = [];
+
+ $('.calendar-side-borders-sub').each(function (index, value) {
+ let show;
+ if ($(this).find('.fa-square-arrow-up').length) {
+ show = 1;
+ } else {
+ show = 0;
+ }
+ const group = {
+ name: $.trim($(this).find('h5').text()),
+ show: show,
+ origin: $(this).data('origin'),
+ calendars: []
+ };
+ $(this).find(('.form-check')).each(function (index, value) {
+ let checkbox = $(this).find('.calendar-check');
+ let checked;
+ if (checkbox.prop('checked')) {
+ checked = 1;
+ } else {
+ checked = 0;
+ }
+ group.calendars[index] = {
+ 'calendar_id': $.trim(checkbox.data('calendar_id')),
+ 'checked': checked,
+ origin: $(this).data('origin')
+ };
+ });
+ groups.push(group);
+ });
+ let groupsJson = JSON.stringify(groups);
+ return groupsJson;
+ }
+
+ function checkGroupCheckboxes() {
+ $('.group-checkbox').each(function (index, value) {
+ let checked = 0;
+ let unchecked = 0;
+ let thisis = $(this);
+ let ok = 0;
+ $(this).closest('.calendar-side-borders-sub').find('.calendar-check').each(function (index, value) {
+ if ($(this).prop('checked')) {
+ checked++;
+ } else {
+ unchecked++;
+ }
+ if (checked > 0 && unchecked > 0) {
+ $(this).closest('.calendar-side-borders-sub').find('.group-checkbox').prop('checked', false);
+ thisis.prop("indeterminate", true);
+ ok = 1;
+ return;
+ }
+ });
+ if (ok == 0) {
+ if (checked == 0) {
+ thisis.prop("indeterminate", false);
+ thisis.prop('checked', false);
+ } else {
+ thisis.prop("indeterminate", false);
+ thisis.prop('checked', true);
+ }
+ }
+ });
+ }
+
+ $('.calendar-side-borders-sub-inner').sortable({
+ group: 'shared',
+ filter: '.no-movable',
+ delay: 0,
+ animation: 0,
+ onSort: function (evt) {
+ $('.calendar-check').eq(0).trigger('change');
+ },
+ });
+ $('.add-cal-group-div-sub').sortable({
+ filter: '.no-movable',
+ handle: '.handle',
+ delay: 0,
+ onSort: function (evt) {
+ $('.calendar-check').eq(0).trigger('change');
+ },
+ });
+ if (firstcall) {
+ $('.color-input').trigger('change', 1);
+ }
+ $('.select2-multiple').select2({
+ dropdownParent: $('#EventModal')
+ });
+ $('.select2-multiple-tag').select2(
+ {
+ tags: true,
+ tokenSeparators: [',', ' ']
+ }
+ );
+
+ checkGroupCheckboxes();
+
+
+ function refreshCalendarEvents() {
+ calendar.removeAllEvents();
+ let checkbox = $(".calendar-check");
+ let visibleCalendars = [];
+ visibleCalendars.push(0);
+ checkbox.each(function () {
+ if ($(this).prop('checked')) {
+ visibleCalendars.push($(this).data('calendar_id'));
+ }
+ });
+
+
+ $.post(requestUrl, {visibleCalendars: visibleCalendars}, function (data) {
+
+ }, 'json').done(function (json) {
+ if (json.success == true) {
+ var userevents = [];
+ var otherevents = [];
+ var resources = [];
+ var category = "";
+ var rights = false;
+ var resourceCounter = 0;
+ $.each($('.calendar-check'), function (index, value) {
+ if ($(this).prop('checked')) {
+ rights = true;
+
+ resources.push({
+ id: $(this).data('calendar_id'),
+ title: $.trim($(this).closest('div').find('label').text()),
+ order: resourceCounter
+ });
+
+ resourceCounter++;
+ }
+ });
+
+
+ $.each(json.data, function (index, value) {
+ category = value.ccategory.ccategory;
+
+ if (value.calendar_id.calendar_id in calendarRights) {
+ if (calendarRights[value.calendar_id.calendar_id] == 'all') {
+ rights = true;
+ } else {
+ rights = false;
+ }
+ userevents.push({
+ id: value.id.id,
+ start: value.cstart.cstart,
+ end: value.cend.cend,
+ title: category,
+ description: value.description.description,
+ location: value.location.location,
+ attachment: value.attachment.attachment,
+ attachments: value.attachments.attachments,
+ calendar_id: value.calendar_id,
+ event_type: value.event_type.event_type,
+ classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id],
+ textColor: value.txtColor.txtColor,
+ backgroundColor: value.bgColor.bgColor,
+ editable: rights,
+ resourceId: value.calendar_id.calendar_id,
+ calendar_name: value.calendar_name.calendar_name,
+ mtime: value.mtime.mtime,
+ mname: value.mname.mname,
+ ctime: value.ctime.ctime,
+ cname: value.cname.cname,
+ busy: value.busy.busy
+ });
+ } else {
+ otherevents.push({
+ id: value.id.id,
+ start: value.cstart.cstart,
+ end: value.cend.cend,
+ title: category,
+ description: category,
+ color: 'red',
+ editable: false,
+ calendar_id: value.calendar_id,
+ event_type: value.event_type.event_type,
+ classNames: ['cal-class-group-' + value.calendar_id.calendar_id, 'cal-class-id-' + value.id.id],
+ attachment: value.attachment.attachment,
+ attachments: value.attachments.attachments,
+ resourceId: value.calendar_id.calendar_id,
+ calendar_name: value.calendar_name.calendar_name,
+ mtime: value.mtime.mtime,
+ mname: value.mname.mname,
+ ctime: value.ctime.ctime,
+ cname: value.cname.cname,
+ busy: value.busy.busy
+ });
+
+ }
+ });
+ calendar.addEventSource(userevents)
+ }
+ ;
+ });
+ }
+
+})
+;