From a1a4c40c4ce8d6253a4912b0ad94c28052a7d372 Mon Sep 17 00:00:00 2001 From: Joey Schulze Date: Thu, 27 Jul 2017 23:08:57 +0200 Subject: [PATCH] Add lots of JS magic to make calendar usable . 2-month view . 1-month view . add comments . add urls . display, and comments and urls . colorise events --- class/calendar.class.php | 238 ++++++++++++++++++++++++- class/calendar_item.class.php | 139 +++++++++++++++ class/databasetable.class.php | 9 + src/Infodrom/calendar/index.wml | 296 +++++++++++++++++++++++++++++++- src/infodrom.css | 6 +- 5 files changed, 682 insertions(+), 6 deletions(-) create mode 100644 class/calendar_item.class.php diff --git a/class/calendar.class.php b/class/calendar.class.php index 68ca9b8..8fc45ca 100644 --- a/class/calendar.class.php +++ b/class/calendar.class.php @@ -6,7 +6,7 @@ class Calendar extends DatabaseTable { { $db = new Database(DBDRIVER, DBHOST, DAV_DBNAME, DBUSER, DBPASS); - parent::__construct('calendar_item', $id, $db, 'dav_id'); + parent::__construct('calendar_item', false, $db); } public static function pgTimestamp($timestamp) @@ -72,4 +72,240 @@ class Calendar extends DatabaseTable { return $this->db->fetchObjectList($sql); } + public function ajaxMonths(Array $data) + { + $monthname = array('','Jan','Feb','Mär', 'Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'); + $sql = sprintf("SELECT DISTINCT extract(year from dtstart) AS year,extract(month from dtstart) AS month " . + "FROM calendar_item WHERE user_no = %d ORDER BY year DESC,month DESC", + DAV_USER_NO); + $out = ''; + $now = array(date('Y'), date('m')); + foreach ($this->db->fetchObjectList($sql) as $row) { + $out .= sprintf('', + $row->year, $row->month, + $row->year == $now[0] && $row->month == $now[1] ? ' selected' : '', + utf8_encode($monthname[$row->month]), $row->year); + } + + return array('values' => array('thismonth' => date('Y-m')), + 'html' => array('month' => $out)); + } + + private function getMonthData($year, $month) + { + $numdays = cal_days_in_month(CAL_GREGORIAN, $month, $year); + + $areaDates = array(); + for ($i=1; $i < 8; $i++) { + $date = sprintf('%04d-%02d-%02d', $year, $month, 1); + $sql = sprintf("SELECT dav_id FROM calendar_item WHERE user_no = %d AND dtstart::date = '%s'::date - INTERVAL '%d DAY' ORDER BY dtstart", + DAV_USER_NO, $date, $i); + foreach ($this->fetchObjectList($sql) as $row) { + $item = new Calendar_Item($row->dav_id); + if ($item->isRegular()) continue; + + foreach ($item->getDays() as $adate) { + if (!array_key_exists($adate, $areaDates)) + $areaDates[$adate] = array(); + $areaDates[$adate][] = $item; + } + } + } + + $regDates = array(); + for ($day=1; $day <= $numdays; $day++) { + $timestamp = mktime (0, 0, 0, $month, $day, $year); + $date = sprintf('%04d-%02d-%02d', $year, $month, $day); + $sql = sprintf("SELECT dav_id FROM calendar_item WHERE user_no = %d AND dtstart::date = '%s'::date ORDER BY dtstart", + DAV_USER_NO, $date); + + foreach ($this->fetchObjectList($sql) as $row) { + $item = new Calendar_Item($row->dav_id); + + if (!$item->isRegular()) { + foreach ($item->getDays() as $adate) { + if (!array_key_exists($adate, $areaDates)) + $areaDates[$adate] = array(); + $areaDates[$adate][] = $item; + } + } else { + if (!array_key_exists($date, $regDates)) + $regDates[$date] = array(); + $regDates[$date][] = $item; + } + } + } + + return array($areaDates, $regDates); + } + + private function formatOneMonth($year, $month) + { + $weekday = array('', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'); + $monthname = array('','Jan','Feb','Mär', 'Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'); + $numdays = cal_days_in_month(CAL_GREGORIAN, $month, $year); + + $out = sprintf('
%s %04d
', + $year, $month, $monthname[intval($month)], $year); + + list($areaDates, $regDates) = $this->getMonthData($year, $month); + + $today = date('Y-m-d'); + for ($day=1; $day <= $numdays; $day++) { + $timestamp = mktime (0, 0, 0, $month, $day, $year); + $date = sprintf('%04d-%02d-%02d', $year, $month, $day); + $items = array(); + + if (array_key_exists($date, $areaDates)) + foreach ($areaDates[$date] as $item) + $items[] = $item->toSpan(); + + if (array_key_exists($date, $regDates)) + foreach ($regDates[$date] as $item) + $items[] = $item->toSpan(); + + $class = date('N', $timestamp) == 7 ? 'sunday' : 'day'; + if ($today == $date) $class .= ' today'; + $kw = date('N', $timestamp) == 1 ? sprintf('
%d
', date('W', $timestamp)) : ''; + $out .= sprintf('
%s
%d.
%s%s
', + $class, + $day, + $weekday[intval(date('N', $timestamp))], + $day, + count($items) ? implode('', $items) : ' ', + $kw); + } + return $out; + } + + public function ajaxBiMonth(Array $data) + { + list($year, $month) = explode('-', $data['month']); + if (!empty($data['direction'])) { + switch ($data['direction']) { + case 'prev': + if ($month > 1) $month--; + else {$year--; $month = 12;} + break; + case 'next': + if ($month < 12) $month++; + else {$year++; $month = 1;} + break; + } + } + + $monthStr = sprintf('%04d-%02d', $year, $month); + $right = $this->formatOneMonth($year, $month); + + if ($month < 12) $month++; + else {$year++; $month = 1;} + $left = $this->formatOneMonth($year, $month); + + $out = '
'; + + $out .= '
'; + $out .= $right; + $out .= '
'; + + $out .= '
'; + $out .= $left; + $out .= '
'; + + $out .= '
'; + + return array('values' => array('thismonth' => $monthStr), + 'html' => array('termine' => $out)); + } + + public function ajaxMonth(Array $data) + { + $monthname = array('','Januar','Februar','März', 'April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'); + + list($year, $month) = explode('-', $data['month']); + if (!empty($data['direction'])) { + switch ($data['direction']) { + case 'prev': + if ($month > 1) $month--; + else {$year--; $month = 12;} + break; + case 'next': + if ($month < 12) $month++; + else {$year++; $month = 1;} + break; + } + } + + $monthStr = sprintf('%04d-%02d', $year, $month); + $monthText = utf8_encode($monthname[intval($month)] . ' ' . $year); + $numdays = cal_days_in_month(CAL_GREGORIAN, $month, $year); + + list($areaDates, $regDates) = $this->getMonthData($year, $month); + + $out = '
'; + + $out .= << + +{$monthText} + +   + Montag + Dienstag + Mittwoch + Donnerstag + Freitag + Samstag + Sonntag + + + +EOT; + + $timestamp = mktime (4, 0, 0, $month, 1, $year); + if (date('N', $timestamp) != 1) { + $out .= ''; + $out .= sprintf('%d', date('W', $timestamp)); + for ($i=1; $i < date('N', $timestamp); $i++) + $out .= ' '; + } + + $today = date('Y-m-d'); + for ($day=1; $day <= $numdays; $day++) { + $timestamp = mktime (4, 0, 0, $month, $day, $year); + $date = sprintf('%04d-%02d-%02d', $year, $month, $day); + if (date('N', $timestamp) == 1) + $out .= sprintf('%d', date('W', $timestamp)); + + $items = array(); + + if (array_key_exists($date, $areaDates)) + foreach ($areaDates[$date] as $item) + $items[] = $item->toSpan(); + + if (array_key_exists($date, $regDates)) + foreach ($regDates[$date] as $item) + $items[] = $item->toSpan(); + + $out .= sprintf('
%d
%s
', + date('d', $timestamp), + count($items) ? implode('
', $items) : ' '); + + if (date('N', $timestamp) == 7) + $out .= ''; + } + + if (date('N', $timestamp) != 7) { + for ($i=date('N', $timestamp); $i < 7; $i++) + $out .= ' '; + $out .= ''; + } + + $out .= ''; + + $out .= '
'; + + return array('values' => array('thismonth' => $monthStr), + 'html' => array('termine' => $out)); + } + } diff --git a/class/calendar_item.class.php b/class/calendar_item.class.php new file mode 100644 index 0000000..99f0cf1 --- /dev/null +++ b/class/calendar_item.class.php @@ -0,0 +1,139 @@ +idcolumn = 'dav_id'; + $db = new Database(DBDRIVER, DBHOST, DAV_DBNAME, DBUSER, DBPASS); + + parent::__construct('calendar_item', $id, $db); + } + + protected function postLoad() + { + $start = explode(' ', $this->data->dtstart); + $starttime = explode(':', $start[1]); + $end = explode(' ', $this->data->dtend); + $endtime = explode(':', $end[1]); + + $this->isRegular = $start[0] == $end[0]; + + if ($this->isRegular) { + if ($starttime[1] == '00' && $endtime[1] == '00') { + if ($starttime[0] == $endtime[0]) + $this->timespan = $starttime[0]; + else + $this->timespan = $starttime[0] .'-'. $endtime[0]; + } else { + $this->timespan = sprintf('%d:%02d-%d:%02d', + $starttime[0], $starttime[1], + $endtime[0], $endtime[1]); + } + } else { + $startTimeStamp = strtotime($start[0]) + (3*60*60); + $endTimeStamp = strtotime($end[0]); + + while ($startTimeStamp < $endTimeStamp) { + $this->timeDays[] = date('Y-m-d', $startTimeStamp); + $startTimeStamp += (24*60*60); + } + } + + } + + public function isRegular() + { + return $this->isRegular; + } + + public function timespan() + { + return $this->timespan; + } + + public function getDays() + { + return $this->timeDays; + } + + public function toSpan() + { + $tooltip = ''; + if ($this->data->description) + $tooltip .= (strlen($tooltip)?', ':'').$this->data->description; + if ($this->data->location) + $tooltip .= (strlen($tooltip)?', ':'').'Ort: '.$this->data->location; + + if (strlen($tooltip)) + $tooltip = sprintf(' title="%s"', $tooltip); + + $sql = sprintf("SELECT color FROM calendar_item_data WHERE dav_id = %d", $this->id); + $bgcolor = $this->fetchValue($sql); + if ($bgcolor) $bgcolor = sprintf(' style="background:%s;"', $bgcolor); + + return sprintf('%s %s', + $this->id, + $tooltip, $bgcolor, + $this->timespan(), + $this->data->summary); + } + + public function ajaxSetColor(Array $data) + { + $sql = sprintf("SELECT id FROM calendar_item_data WHERE dav_id = %d", $this->id); + $id = $this->fetchValue($sql); + + if ($id) + $sql = sprintf("UPDATE calendar_item_data SET color = %s WHERE id = %d", + $this->quote($data['color']), $id); + else + $sql = sprintf("INSERT INTO calendar_item_data (dav_id, color) VALUES (%d,%s)", + $this->id, $this->quote($data['color'])); + + return $this->execute($sql); + } + + public function ajaxLog(Array $data) + { + $title = $this->data->summary; + if ($this->data->location) + $title .= ', ' . $this->data->location; + + $out = sprintf('
%s
', $title); + $out .= sprintf('
%s: Item created
', substr($this->data->created,0,16)); + # $out .= sprintf('
Last modified %s
', $this->data->last_modified); + + $sql = sprintf("SELECT name,url,comment,sys_edit,sys_user " . + "FROM calendar_item_log WHERE dav_id = %d ORDER BY sys_edit", $this->id); + foreach ($this->fetchObjectList($sql) as $row) { + if (strlen($row->url)) + $out .= sprintf('
%s: %s
', + substr($row->sys_edit,0,16), + $row->url, + $row->name ? $row->name : 'Link'); + if (strlen($row->comment)) + $out .= sprintf('
%s: %s
', substr($row->sys_edit,0,16), $row->comment); + } + + return array('html' => array('log' => $out)); + } + + public function ajaxAddLog(Array $data) + { + if (!strlen($data['name']) && !strlen($data['url']) && !strlen($data['comment'])) return true; + + $item = array('dav_id' => $this->id, + 'name' => strlen($data['name']) ? $data['name'] : NULL, + 'url' => strlen($data['url']) ? $data['url'] : NULL, + 'comment' => strlen($data['comment']) ? $data['comment'] : NULL, + 'sys_user' => $_SERVER['REMOTE_USER'], + 'sys_edit' => 'now()'); + + return $this->db->insertInto('calendar_item_log', $item); + } + +} diff --git a/class/databasetable.class.php b/class/databasetable.class.php index 246d012..de2038a 100644 --- a/class/databasetable.class.php +++ b/class/databasetable.class.php @@ -91,6 +91,15 @@ abstract class DatabaseTable { $this->db->delete($this->table, $this->idcolumn, $id === false ? $this->id : $id); } + public function getAttribute($attr) + { + if ($this->data === false) return NULL; + if (property_exists($this->data, $attr)) + return $this->data->$attr; + + return NULL; + } + public function quote($string) { return $this->db->quote($string); } public function execute($sql) { return $this->db->execute($sql); } public function fetchValue($sql) { return $this->db->fetchValue($sql); } diff --git a/src/Infodrom/calendar/index.wml b/src/Infodrom/calendar/index.wml index 7a71044..ceb4b41 100644 --- a/src/Infodrom/calendar/index.wml +++ b/src/Infodrom/calendar/index.wml @@ -4,7 +4,12 @@ +
@@ -66,13 +164,13 @@ table#calendar tr.current { if (strlen($kw) && $kw != $row->kw) $class .= ' newkw'; - printf('%s', + $item = new Calendar_Item($row->dav_id); + printf('', $row->dav_id, $class, $kw != $row->kw ? $row->kw : ' ', Calendar::formatTimespan($row->dtstart, $row->dtend), - utf8_decode($tooltip), - utf8_decode($row->summary), + utf8_decode($item->toSpan()), utf8_decode($row->location)); $kw = $row->kw; } @@ -81,7 +179,197 @@ table#calendar tr.current {
%s%s%s
%s%s%s%s
+
+ + + + +
# Local variables: diff --git a/src/infodrom.css b/src/infodrom.css index ad15cbe..850eeb1 100644 --- a/src/infodrom.css +++ b/src/infodrom.css @@ -154,7 +154,7 @@ input.button:hover { */ div.popup { background: white; - border: 1px solid #CCC; + border: 1px solid #777; height: auto; position: absolute; } @@ -213,6 +213,10 @@ table#fc { z-index: 100; } +div.popup div.caltitle { + font-weight: bold; +} + /* * jQuery & Co. */ -- 2.20.1