From 857078428b952de8aa8537ec1e2238198ab50f12 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Thu, 15 May 2014 15:53:35 +0200 Subject: [PATCH] Toggle IMAP subscriptions directly from the calendars/folders list (#3042) --- plugins/calendar/calendar.php | 2 +- plugins/calendar/calendar_ui.js | 18 +++++++++-- .../calendar/drivers/kolab/kolab_calendar.php | 14 +------- .../calendar/drivers/kolab/kolab_driver.php | 15 ++++++--- .../drivers/kolab/kolab_user_calendar.php | 1 + plugins/calendar/lib/calendar_ui.php | 9 ++++-- plugins/calendar/localization/en_US.inc | 1 + plugins/calendar/skins/larry/calendar.css | 25 ++++++++++++++- .../calendar/skins/larry/images/calendars.png | Bin 2239 -> 1915 bytes plugins/libkolab/js/folderlist.js | 30 +++++++++++++++--- 10 files changed, 87 insertions(+), 28 deletions(-) diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index fc0069d4..f910b2b6 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -725,7 +725,7 @@ class calendar extends rcube_plugin $this->rc->output->command('plugin.destroy_source', array('id' => $cal['id'])); break; case "subscribe": - if (!$this->driver->subscribe_calendar($cal, intval(get_input_value('perm', RCUBE_INPUT_GPC)))) + if (!$this->driver->subscribe_calendar($cal)) $this->rc->output->show_message($this->gettext('errorsaving'), 'error'); return; case "search": diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js index 38a32a8c..68ae94f3 100644 --- a/plugins/calendar/calendar_ui.js +++ b/plugins/calendar/calendar_ui.js @@ -2697,9 +2697,14 @@ function rcube_calendar_ui(settings) me.calendars[id].color = color; } - if (fc && cal.active) { - fc.fullCalendar('addEventSource', me.calendars[id]); - rcmail.http_post('calendar', { action:'subscribe', c:{ id:id, active:cal.active?1:0 } }); + if (fc && (cal.active || cal.subscribed)) { + if (cal.active) + fc.fullCalendar('addEventSource', me.calendars[id]); + + var submit = { id: id, active: cal.active ? 1 : 0 }; + if (cal.subscribed !== undefined) + submit.permanent = cal.subscribed ? 1 : 0; + rcmail.http_post('calendar', { action:'subscribe', c:submit }); } // insert to #calendar-select options if writeable @@ -2761,6 +2766,13 @@ function rcube_calendar_ui(settings) } } }); + calendars_list.addEventListener('subscribe', function(p) { + var cal; + if ((cal = me.calendars[p.id])) { + cal.subscribed = p.subscribed || false; + rcmail.http_post('calendar', { action:'subscribe', c:{ id:p.id, active:cal.active?1:0, permanent:cal.subscribed?1:0 } }); + } + }); // init (delegate) event handler on calendar list checkboxes $(rcmail.gui_objects.calendarslist).on('click', 'input[type=checkbox]', function(e){ diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php index c4b7dbb9..3f74f0f6 100644 --- a/plugins/calendar/drivers/kolab/kolab_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_calendar.php @@ -30,6 +30,7 @@ class kolab_calendar extends kolab_storage_folder_api public $readonly = true; public $attachments = true; public $alarms = false; + public $subscriptions = true; public $categories = array(); public $storage; @@ -102,19 +103,6 @@ class kolab_calendar extends kolab_storage_folder_api } - /** - * Getter for a nice and human readable name for this calendar - * See http://wiki.kolab.org/UI-Concepts/Folder-Listing for reference - * - * @return string Name of this calendar - */ - public function get_name() - { - $folder = kolab_storage::object_name($this->name, $this->namespace); - return $folder; - } - - /** * Getter for the IMAP folder name * diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php index d1bb6554..ff8372b1 100644 --- a/plugins/calendar/drivers/kolab/kolab_driver.php +++ b/plugins/calendar/drivers/kolab/kolab_driver.php @@ -180,6 +180,10 @@ class kolab_driver extends calendar_driver 'caldavurl' => $cal->get_caldav_url(), ); } + + if ($cal->subscriptions) { + $calendars[$cal->id]['subscribed'] = (bool)$cal->is_subscribed(); + } } // append the virtual birthdays calendar @@ -258,7 +262,6 @@ class kolab_driver extends calendar_driver // create calendar object if necesary if (!$this->calendars[$id] && $id !== self::BIRTHDAY_CALENDAR_ID) { $calendar = kolab_calendar::factory($id, $this->cal); - console($id, $calendar->id, $calendar->ready); if ($calendar->ready) $this->calendars[$calendar->id] = $calendar; } @@ -342,11 +345,15 @@ class kolab_driver extends calendar_driver * * @see calendar_driver::subscribe_calendar() */ - public function subscribe_calendar($prop, $permanent = false) + public function subscribe_calendar($prop) { if ($prop['id'] && ($cal = $this->get_calendar($prop['id']))) { - if ($permanent) $cal->storage->subscribe($prop['active']); - return $cal->storage->activate($prop['active']); + $ret = false; + if (isset($prop['permanent'])) + $ret |= $cal->storage->subscribe($prop['permanent']); + if (isset($prop['active'])) + $ret |= $cal->storage->activate($prop['active']); + return $ret; } else { // save state in local prefs diff --git a/plugins/calendar/drivers/kolab/kolab_user_calendar.php b/plugins/calendar/drivers/kolab/kolab_user_calendar.php index 3add82a0..a41e0654 100644 --- a/plugins/calendar/drivers/kolab/kolab_user_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_user_calendar.php @@ -27,6 +27,7 @@ class kolab_user_calendar extends kolab_calendar public $ready = false; public $readonly = true; public $attachments = false; + public $subscriptions = false; protected $userdata = array(); diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php index 4584f192..4d411947 100644 --- a/plugins/calendar/lib/calendar_ui.php +++ b/plugins/calendar/lib/calendar_ui.php @@ -296,6 +296,8 @@ class calendar_ui $class = 'folder virtual'; else if ($prop['readonly']) $class .= ' readonly'; + if ($prop['subscribed']) + $class .= ' subscribed'; if ($prop['class_name']) $class .= ' '.$prop['class_name']; @@ -303,8 +305,11 @@ class calendar_ui if (!$attrib['activeonly'] || $prop['active']) { $content = html::div($class, html::span(array('class' => 'calname', 'title' => $title), $prop['editname'] ? Q($prop['editname']) : $prop['listname']) . - ($prop['virtual'] ? '' : html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active']), '') . - html::span(array('class' => 'handle', 'style' => "background-color: #" . ($prop['color'] ?: 'f00')), ' ')) + ($prop['virtual'] ? '' : + html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active']), '') . + (isset($prop['subscribed']) ? html::a(array('href' => '#', 'class' => 'subscribed', 'title' => $this->cal->gettext('calendarsubscribe')), $this->cal->gettext('subscribed')) : '') . + html::span(array('class' => 'handle', 'style' => "background-color: #" . ($prop['color'] ?: 'f00')), ' ') + ) ); } diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc index 92b4fb57..67675bfe 100644 --- a/plugins/calendar/localization/en_US.inc +++ b/plugins/calendar/localization/en_US.inc @@ -87,6 +87,7 @@ $labels['showurl'] = 'Show calendar URL'; $labels['showurldescription'] = 'Use the following address to access (read only) your calendar from other applications. You can copy and paste this into any calendar software that supports the iCal format.'; $labels['caldavurldescription'] = 'Copy this address to a CalDAV client application (e.g. Evolution or Mozilla Thunderbird) to fully synchronize this specific calendar with your computer or mobile device.'; $labels['calsearchresults'] = 'Available Calendars'; +$labels['calendarsubscribe'] = 'Listed permanently'; // agenda view $labels['listrange'] = 'Range to display:'; diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css index 71dd106a..cca70e63 100644 --- a/plugins/calendar/skins/larry/calendar.css +++ b/plugins/calendar/skins/larry/calendar.css @@ -190,7 +190,7 @@ pre { position: absolute; top: 7px; left: 38px; - right: 22px; + right: 40px; cursor: default; background: url(images/calendars.png) right 20px no-repeat; overflow: hidden; @@ -207,6 +207,7 @@ pre { #calendars .treelist.flat li span.calname { left: 24px; + right: 22px; } #calendars .treelist li span.handle { @@ -225,6 +226,28 @@ pre { box-shadow: inset 0px 0 1px 1px rgba(0, 0, 0, 0.3); } +#calendars .treelist li a.subscribed { + display: inline-block; + position: absolute; + top: 7px; + right: 24px; + height: 16px; + width: 16px; + padding: 0; + background: url(images/calendars.png) -100px 0 no-repeat; + overflow: hidden; + text-indent: -5000px; + cursor: pointer; +} + +#calendars .treelist div:hover > a.subscribed { + background-position: 1px -110px; +} + +#calendars .treelist div.subscribed a.subscribed { + background-position: -15px -110px; +} + #calendars .treelist li input { position: absolute; top: 5px; diff --git a/plugins/calendar/skins/larry/images/calendars.png b/plugins/calendar/skins/larry/images/calendars.png index c2de67de1a650e46c022d078378a4825dc988b62..1f97abcec480115d545478940e14ae8f30880db7 100644 GIT binary patch delta 1913 zcmV-<2Zs2+5&I617k_>T1^@s6Mg9|W000LIOB{n&N$Gpqeh=6L%atAV#3bT!}Q<|(oD@&h|>5s>XJo~ML00xp5!Hix5=;FP)+ zTD$&)gu*g#jY@>w?%vcnG3qxZM#Rwtm-rPIG?0C=73C>G zn0g9`-?#+MR=Nps&_LNQi$Km3ztJ<`iSJZ|Gw>=r*?-7DPMOM0kdh6@a*G#%oF{&x z5}2Bq**rZv3)8c6OJEje=H@mVl>naet1--%0lV)7&NzE#X2bKa{>jr z$G5B!;6;iny;Jdml$j606H*YypU7dAfZxdih${yWtLh-CvIDJ`>IMicP@ZR%K!v8IBB8QjAp@6hbh4X)uAbhYn6esO z77{CJp?hG^nN|Q=Jy2zply71s@Qy=n=6eK3ZC%3RDtyy(Rmxwl z%E)wd4Ubci^Tcngz-D^{J_3ipa1bP`hxD5oF{%Vj*MrNKw)*QEt&fy7^(c%f%wTd zGM-Ta&z?X3>e=%b@chNfAmhk*rlpuEhS^)dlzU}!X4F0pZAC=4&qG@g(e3llRz!6B zJb$zm5#2ryEk(pcpNEzrVxrGOOA#^A=b@#D==6CQQAAYwJd7$LDt#VC6%my_52K2R zN}q>QM4bH>g^Vf28rJ_|HE%mz`QPpF@YM;K-R?r^c4s$sdqi!2bnd*+_8X*?sezxE z4hMsyh?t4o>fmC|3IUHOvGci0SC8T8CV#m*I0Q*0=YSV`0`~a?WD~h()Zp7)+|3V& z!gQ~2$Kx^b)Z((kn21z)K?6s`shC7ywowTbRo1L;x_Jw7tLuQDlmUk##NZGd<&R1D z=hf8fGGW8_aWWbK*T66-RE#JKA4iDQ+kc#m z)U0p}2$S0fMu0<5WO?6H^Nq4ZL};z4^97?zZuHXCj}>%x0Hg zX#pO7_aBak4|_QN_^=>Z3P+POOMi*d4$6{&SXNxhY=ioUSIl0&5U>x9hJzu|*}X## z{P;L%aKDG(+X(#v=XOQ;reID1rS!k-*14!-#5f3>WKuQ{1`N4--$OQuINc zFl>!h{dtuD-cmUn%~n7J)`0q;7Ub?(S^da7pMCliOSY%*^5skEJ9!CV5`Swj)^du6 zGsYAV)gBRTMMSqpL|YNj?Ge#dM09#Yj3^>HJtEqQh;EOFwj!e2BciQ{==O+cD(pjeO_f?E4g&VTI(i0o6n`#uaU6#{*ebN-(ebs+l--GqQY6#_hr3_a}L z_WF{)MztRmv?A-OPSid!sii_dfnlkKVwqIi-58nB%%gSqv8JK#q2>T|qBT+t`l7HM zrTpHH49DCYoz&bKd!ixN8s6Bx1RD#lAsbZ(s_hvYC)XN2Z;d|P>sF`>g`UtlgDk9T8hE7nM&5+X zk^rqrIFC%kH9C-ea&CcCkd*DMvlpA;QQ`w~7&z3;UJ)jvKR>tClu zCXwZfusXT|MO^Aa!+(>ru`4}$%cUw`pLWYPn0~P)!9~artB)6>PvR?(&i4kzXGb2z zs|%4n^;RpY;_Ka76W=^!h_!*I(bvf;)YLPqeVgjHnqLR>`wPUDTYUIM7m=w)23qBj zi9)Md#zWODMMq$(FtmRG)?!T&*|lm`00000NkvXXu0mjf_xGC^ literal 2239 zcmaJ@2~-o;8lJF-vIu#EVq|fMT2Rc+mIxvw0ztzX1d9S8nLxxWB!dJH1r-Se9#~67 z0Y!M#xPS;+upp~GL<`EMf)uILina&}VpXDVVnyG1=g~Q5=HCC_@BjYgelusX0{py< z^q1-b0AR%OVFn>1h}=6CE}QJdzU$bRrYTR0n5g z=QSXOL?#hQ6e5{|Cp*)r6gr6ne!OrtaBx1eVBSB~p+P>#_nL%}=k;xm#9xfi9GzydI>_VfFXdcdUzDx-(K?I56IbZ%~U&_3`8YzgRNMt4? z6YhlgUNVUY{7^DoIBzbVUi0#O^ySZ=3u#_oB9aVIbFlw)&~rSc+zG04eq`AP8|kShS_Qdvw7PVDe_;S+xg z?Pr-kNjN+N%qgEX;b0(nZ_l%f_novht!X z0h9Pbvlgu?U=3i<{CR-YlkFYY!0wL6F0m>51Jg{OZ1vmp&wC~L;R~~Zup=Tv|33tV zV0h)X$Id&fzdypRn|N&v@3fWnCo4xcnqpBVAr_%iPw^w_*RS#LPvLLkQ&G!q<`@O% z0FwzXK~YudHpQN%aYoi@vu_2z)5n4My$y--?v52>Uz@I|9vc-7bT10pag5TTyK0!^L_She+Lq zyxQs+>-@q&;8m}|D+AwTQ9;* zA$3--di6&h4Ehcj>O@hi)aGVs731TWA0KE>ls=qgSaIFk*EGM^2EVg?n2IAvZGH8B zR#>!|uB7NUpS>++vBxs{`cU5t3i4yOH}No~lfJf`SGj33|6Za>$!v~FY>dK`UhG9J zxGPd&8?^`D#Rr62p}bIrSN2H&c%Ny&oq;L)a^UVnXJenyriLTw^^xxUoeNyEH(ohh z($=!&c4X5c1N*q8UZ^hxkE562&wETvYlls*ds$?adLaiW?z-{IRfDPQ>YHaHziuuGBfvrE{&~?#MTn%zY~s+ttuK#25AjL>kvE z%WE6W(vq5;>DB5yRXR3yz;}9RR96}5zT0?A&vsus(w@EELZhc1?X7lCLwnZdr~0SAl9=b!&K? zt95Z!m`8+}2-upGB)D~5F?C=M^2O{oxP}i+&(?7cIdNui@~t-{fY0@akN-5Q?%iYw zmeT_lIpJwJKjq1#khDATL?$E8c^cEYKcF*8)IVWO3(~Vb2FYr}*J9p++k2enw56^N_jq=LqGv1@zjQx&f zj1Hxp1-d^+S&a_t)JzL