From b810380d56b41ebad4fd67a30d6789744c69deb3 Mon Sep 17 00:00:00 2001 From: Georg Ehrke Date: Sat, 4 Feb 2012 21:23:31 +0100 Subject: [PATCH] add sharing management for calendars --- apps/calendar/ajax/changepermission.php | 40 +++++ apps/calendar/ajax/share.dropdown.php | 18 ++ apps/calendar/ajax/share.php | 51 ++++++ apps/calendar/ajax/unshare.php | 44 +++++ apps/calendar/appinfo/app.php | 3 + apps/calendar/appinfo/database.xml | 4 +- apps/calendar/css/style.css | 4 + apps/calendar/js/calendar.js | 103 ++++++++++- apps/calendar/lib/share.php | 163 ++++++++++++++++++ apps/calendar/share.php | 1 + .../templates/part.choosecalendar.php | 23 ++- .../part.choosecalendar.rowfields.php | 10 +- .../part.choosecalendar.rowfields.shared.php | 4 + apps/calendar/templates/part.eventform.php | 6 +- apps/calendar/templates/share.dropdown.php | 71 ++++++++ 15 files changed, 535 insertions(+), 10 deletions(-) create mode 100644 apps/calendar/ajax/changepermission.php create mode 100644 apps/calendar/ajax/share.dropdown.php create mode 100644 apps/calendar/ajax/share.php create mode 100644 apps/calendar/ajax/unshare.php create mode 100644 apps/calendar/lib/share.php create mode 100644 apps/calendar/share.php create mode 100644 apps/calendar/templates/part.choosecalendar.rowfields.shared.php create mode 100644 apps/calendar/templates/share.dropdown.php diff --git a/apps/calendar/ajax/changepermission.php b/apps/calendar/ajax/changepermission.php new file mode 100644 index 0000000000..caee894521 --- /dev/null +++ b/apps/calendar/ajax/changepermission.php @@ -0,0 +1,40 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../lib/base.php'); +$id = strip_tags($_GET['id']); +$idtype = strip_tags($_GET['idtype']); +$permission = (int) strip_tags($_GET['permission']); +switch($idtype){ + case 'calendar': + case 'event': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +$sharewith = $_GET['sharewith']; +$sharetype = strip_tags($_GET['sharetype']); +switch($sharetype){ + case 'user': + case 'group': + case 'public': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +if($sharetype == 'user' && !OC_User::userExists($sharewith)){ + OC_JSON::error(array('message'=>'user not found')); + exit; +} +if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){ + OC_JSON::error(array('message'=>'group not found')); + exit; +} +$success = OC_Calendar_Share::changepermission($sharewith, $sharetype, $id, $permission, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event)); +OC_JSON::success(); \ No newline at end of file diff --git a/apps/calendar/ajax/share.dropdown.php b/apps/calendar/ajax/share.dropdown.php new file mode 100644 index 0000000000..7e78521a76 --- /dev/null +++ b/apps/calendar/ajax/share.dropdown.php @@ -0,0 +1,18 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../lib/base.php'); +$user = OC_USER::getUser(); +$calid = $_GET['calid']; +$calendar = OC_Calendar_Calendar::find($calid); +if($calendar['userid'] != $user){ + OC_JSON::error(); + exit; +} +$tmpl = new OC_Template('calendar', 'share.dropdown'); +$tmpl->assign('calid', $calid); +$tmpl->printPage(); \ No newline at end of file diff --git a/apps/calendar/ajax/share.php b/apps/calendar/ajax/share.php new file mode 100644 index 0000000000..1b75c1731b --- /dev/null +++ b/apps/calendar/ajax/share.php @@ -0,0 +1,51 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../lib/base.php'); +$id = strip_tags($_GET['id']); +$idtype = strip_tags($_GET['idtype']); +switch($idtype){ + case 'calendar': + case 'event': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +$sharewith = $_GET['sharewith']; +$sharetype = strip_tags($_GET['sharetype']); +switch($sharetype){ + case 'user': + case 'group': + case 'public': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +if($sharetype == 'user' && !OC_User::userExists($sharewith)){ + OC_JSON::error(array('message'=>'user not found')); + exit; +} +if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){ + OC_JSON::error(array('message'=>'group not found')); + exit; +} +if($sharetype == 'user' && OC_User::getUser() == $sharewith){ + OC_JSON::error(array('meesage'=>'you can not share with yourself')); +} +$success = OC_Calendar_Share::share(OC_User::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event)); +if($success){ + if($sharetype == 'public'){ + OC_JSON::success(array('message'=>$success)); + }else{ + OC_JSON::success(array('message'=>'shared')); + } +}else{ + OC_JSON::error(array('message'=>'can not share')); + exit; +} \ No newline at end of file diff --git a/apps/calendar/ajax/unshare.php b/apps/calendar/ajax/unshare.php new file mode 100644 index 0000000000..f69295fd07 --- /dev/null +++ b/apps/calendar/ajax/unshare.php @@ -0,0 +1,44 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../lib/base.php'); +$id = strip_tags($_GET['id']); +$idtype = strip_tags($_GET['idtype']); +switch($idtype){ + case 'calendar': + case 'event': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +$sharewith = $_GET['sharewith']; +$sharetype = strip_tags($_GET['sharetype']); +switch($sharetype){ + case 'user': + case 'group': + case 'public': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +if($sharetype == 'user' && !OC_User::userExists($sharewith)){ + OC_JSON::error(array('message'=>'user not found')); + exit; +} +if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){ + OC_JSON::error(array('message'=>'group not found')); + exit; +} +$success = OC_Calendar_Share::unshare(OC_User::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event)); +if($success){ + OC_JSON::success(); +}else{ + OC_JSON::error(array('message'=>'can not unshare')); + exit; +} \ No newline at end of file diff --git a/apps/calendar/appinfo/app.php b/apps/calendar/appinfo/app.php index 9c95768895..a684adb679 100644 --- a/apps/calendar/appinfo/app.php +++ b/apps/calendar/appinfo/app.php @@ -6,8 +6,11 @@ if(version_compare(PHP_VERSION, '5.3.0', '>=')){ OC::$CLASSPATH['OC_Calendar_Object'] = 'apps/calendar/lib/object.php'; OC::$CLASSPATH['OC_Calendar_Hooks'] = 'apps/calendar/lib/hooks.php'; OC::$CLASSPATH['OC_Connector_Sabre_CalDAV'] = 'apps/calendar/lib/connector_sabre.php'; + OC::$CLASSPATH['OC_Calendar_Share'] = 'apps/calendar/lib/share.php'; OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Calendar_Hooks', 'deleteUser'); OC_Util::addScript('calendar','loader'); + OC_Util::addScript('3rdparty', 'chosen/chosen.jquery.min'); + OC_Util::addStyle('3rdparty', 'chosen/chosen'); OC_App::register( array( 'order' => 10, 'id' => 'calendar', diff --git a/apps/calendar/appinfo/database.xml b/apps/calendar/appinfo/database.xml index ee672574a0..b065ab3f94 100644 --- a/apps/calendar/appinfo/database.xml +++ b/apps/calendar/appinfo/database.xml @@ -212,7 +212,7 @@ sharetype text true - 5 + 6 @@ -259,7 +259,7 @@ sharetype text true - 5 + 6 diff --git a/apps/calendar/css/style.css b/apps/calendar/css/style.css index 1701a36a1f..373a456563 100644 --- a/apps/calendar/css/style.css +++ b/apps/calendar/css/style.css @@ -58,6 +58,10 @@ button.category{margin:0 3px;} #event {padding: 0;margin: 0;margin-top:-5px} +.calendar_share_dropdown{ display:block; position:absolute; z-index:100; width:16em; right:0; margin-right:7em; background:#F8F8F8; padding:1em; +-moz-box-shadow:0 1px 1px #777; -webkit-box-shadow:0 1px 1px #777; box-shadow:0 1px 1px #777; +-moz-border-radius:0 0 1em 1em; -webkit-border-radius:0 0 1em 1em; border-radius:0 0 1em 1em;} + .fc-list-table { margin: 10px; diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js index 6b24fbc2f9..bbefa1bcf2 100644 --- a/apps/calendar/js/calendar.js +++ b/apps/calendar/js/calendar.js @@ -454,7 +454,7 @@ Calendar={ $('#calendar_holder').fullCalendar('removeEventSource', data.eventSource.url); $('#calendar_holder').fullCalendar('addEventSource', data.eventSource); if (calendarid == 'new'){ - $('#choosecalendar_dialog > table').append(''); + $('#choosecalendar_dialog > table:first').append(''); } }else{ $("#displayname_"+calendarid).css('background-color', '#FF2626'); @@ -493,6 +493,106 @@ Calendar={ left: -10000 }); } + }, + Share:{ + currentid: 'false', + idtype: '', + dropdown:function(userid, calid){ + $('.calendar_share_dropdown').remove(); + $('
').appendTo('#'+userid+'_'+calid); + $.get(OC.filePath('calendar', 'ajax', 'share.dropdown.php') + '?calid=' + calid, function(data){ + $('#'+userid+'_'+calid+' > .calendar_share_dropdown').html(data); + $('#'+userid+'_'+calid+' > .calendar_share_dropdown').show('blind'); + $('#share_user').chosen(); + $('#share_group').chosen(); + }); + Calendar.UI.Share.currentid = calid; + Calendar.UI.Share.idtype = 'calendar'; + }, + share:function(id, idtype, sharewith, sharetype){ + $.getJSON(OC.filePath('calendar', 'ajax', 'share.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(data){ + if(sharetype == 'public'){ + $('#public_token').val(OC.linkTo('calendar', 'share.php?t=' + data.message)); + $('#public_token').css('display', 'block'); + } + }); + }, + unshare:function(id, idtype, sharewith, sharetype){ + $.getJSON(OC.filePath('calendar', 'ajax', 'unshare.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(){ + if(sharetype == 'public'){ + $('#public_token').val(''); + $('#public_token').css('display', 'none'); + } + }); + }, + changepermission:function(id, idtype, sharewith, sharetype, permission){ + $.getJSON(OC.filePath('calendar', 'ajax', 'changepermission.php'),{id:id, idtype:idtype, sharewith: sharewith, sharetype:sharetype, permission: (permission?1:0)}); + }, + init:function(){ + $('.calendar_share_dropdown').live('mouseleave', function(){ + $('.calendar_share_dropdown').hide('blind', function(){ + $('.calendar_share_dropdown').remove(); + }); + }); + $('#share_user').live('change', function(){ + if($('#sharewithuser_' + $('#share_user option:selected').text()).length == 0){ + Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $('#share_user option:selected').text(), 'user'); + var newitem = '
  • ' + $('#share_user option:selected').text() + '
  • '; + $('#sharewithuser_list').append(newitem); + $('#sharewithuser_' + $('#share_user option:selected').text() + ' > img').click(function(){ + $('#share_user option[value="' + $(this).parent().text() + '"]').attr('disabled', 'false'); + Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'user' ); + $(this).parent().remove(); + }); + $('#share_user option:selected').attr('disabled', 'disabled'); + $("#share_user").trigger("liszt:updated"); + } + }); + $('#share_group').live('change', function(){ + if($('#sharewithgroup_' + $('#share_group option:selected').text()).length == 0){ + Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $('#share_group option:selected').text(), 'group'); + var newitem = '
  • ' + $('#share_group option:selected').text() + '
  • '; + $('#sharewithgroup_list').append(newitem); + $('#sharewithgroup_' + $('#share_user option:selected').text() + ' > img').click(function(){ + $('#share_group option[value="' + $(this).parent().text() + '"]').attr('disabled', 'false'); + Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'group'); + $(this).parent().remove(); + }); + $('#share_group option:selected').attr('disabled', 'disabled'); + $("#share_group").trigger("liszt:updated"); + } + }); + $('#sharewithuser_list > li > input:checkbox').live('change', function(){ + Calendar.UI.Share.changepermission(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'user', this.checked); + }); + $('#sharewithgroup_list > li > input:checkbox').live('change', function(){ + Calendar.UI.Share.changepermission(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'group', this.checked); + }); + $('#publish').live('change', function(){ + if(this.checked == 1){ + Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, '', 'public'); + }else{ + Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, '', 'public'); + } + }); + $('#sharewithuser_list').live('mouseenter', function(){ + $('#sharewithuser_list > li > img').css('display', 'block'); + $('#sharewithuser_list > li > input').css('visibility', 'visible'); + }); + $('#sharewithuser_list').live('mouseleave', function(){ + $('#sharewithuser_list > li > img').css('display', 'none'); + $('#sharewithuser_list > li > input').css('visibility', 'hidden'); + }); + $('#sharewithgroup_list').live('mouseenter', function(){ + $('#sharewithgroup_list > li > img').css('display', 'block'); + $('#sharewithgroup_list > li > input').css('visibility', 'visible'); + }); + $('#sharewithgroup_list').live('mouseleave', function(){ + $('#sharewithgroup_list > li > img').css('display', 'none'); + $('#sharewithgroup_list > li > input').css('visibility', 'hidden'); + }); + /*var permissions = (this.checked) ? 1 : 0;*/ + } } } } @@ -732,4 +832,5 @@ $(document).ready(function(){ $('#datecontrol_right').click(function(){ $('#calendar_holder').fullCalendar('next'); }); + Calendar.UI.Share.init(); }); diff --git a/apps/calendar/lib/share.php b/apps/calendar/lib/share.php new file mode 100644 index 0000000000..bbc8770f65 --- /dev/null +++ b/apps/calendar/lib/share.php @@ -0,0 +1,163 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +/* + * This class manages shared calendars + */ +class OC_Calendar_Share{ + const CALENDAR = 'calendar'; + const EVENT = 'event'; + /* + * @brief: returns informations about all calendar or events which users are sharing with the user - userid + * @param: (string) $userid - id of the user + * @param: (string) $type - use const self::CALENDAR or self::EVENT + * @return: (array) $return - information about calendars + */ + public static function allSharedwithuser($userid, $type){ + $group_where = 'false'; + $groups = OC_Group::getUserGroups($userid); + $i = 0; + foreach($groups as $group){ + if($i == 0){ + $group_where = ''; + }else{ + $group_where .= ' OR '; + } + $group_where .= ' (share = "' . $group . '" and sharetype = "group") '; + $i++; + } + $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE (share = ? AND sharetype = "user") OR (' . $group_where . ')'); + $result = $stmt->execute(array($userid)); + $return = array(); + while( $row = $result->fetchRow()){ + $return[] = $row; + } + return $return; + } + /* + * @brief: returns all users a calendar / event is shared with + * @param: (int) id - id of the calendar / event + * @param: (string) $type - use const self::CALENDAR or self::EVENT + * @return: (array) $users - information about users a calendar / event is shared with + */ + public static function allUsersSharedwith($id, $type){ + $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE ' . $type . 'id = ? ORDER BY share'); + $result = $stmt->execute(array($id)); + $users = array(); + while( $row = $result->fetchRow()){ + $users[] = $row; + } + return $users; + } + /* + * @brief: shares a calendar / event + * @param: (string) $owner - userid of the owner + * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public) + * @param: (string) $sharetype - type of sharing (can be: user/group/public) + * @param: (string) $id - id of the calendar / event + * @param: (string) $type - use const self::CALENDAR or self::EVENT + * @return (mixed) - token (if $sharetype == public) / bool (if $sharetype != public) + */ + public static function share($owner, $share, $sharetype, $id, $type){ + if(self::is_already_shared($owner, $share, $sharetype, $id, $type)){ + return false; + } + switch($sharetype){ + case 'user': + case 'group': + case 'public': + break; + default: + return false; + } + if($sharetype == 'public'){ + $share = self::generate_token(); + } + $stmt = OC_DB::prepare('INSERT INTO *PREFIX*calendar_share_' . $type . ' (owner,share,sharetype,' . $type . 'id,permissions' . (($type == self::CALENDAR)?', active':'') . ') VALUES(?,?,?,?,0' . (($type == self::CALENDAR)?', 1':'') . ')' ); + $result = $stmt->execute(array($owner,$share,$sharetype,$id)); + if($sharetype == 'public'){ + return $share; + }else{ + return true; + } + } + /* + * @brief: stops sharing a calendar / event + * @param: (string) $owner - userid of the owner + * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public) + * @param: (string) $sharetype - type of sharing (can be: user/group/public) + * @param: (string) $id - id of the calendar / event + * @param: (string) $type - use const self::CALENDAR or self::EVENT + * @return (bool) + */ + public static function unshare($owner, $share, $sharetype, $id, $type){ + $stmt = OC_DB::prepare('DELETE FROM *PREFIX*calendar_share_' . $type . ' WHERE owner = ? ' . (($sharetype != 'public')?'AND share = ?':'') . ' AND sharetype = ? AND ' . $type . 'id = ?'); + if($sharetype != 'public'){ + $stmt->execute(array($owner,$share,$sharetype,$id)); + }else{ + $stmt->execute(array($owner,$sharetype,$id)); + } + return true; + } + /* + * @brief: changes the permission for a calendar / event + * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public) + * @param: (string) $sharetype - type of sharing (can be: user/group/public) + * @param: (string) $id - id of the calendar / event + * @param: (int) $permission - permission of user the calendar / event is shared with (if $sharetype == public then $permission = 0) + * @param: (string) $type - use const self::CALENDAR or self::EVENT + * @return (bool) + */ + public static function changepermission($share, $sharetype, $id, $permission, $type){ + if($sharetype == 'public' && $permission == 1){ + $permission = 0; + } + $stmt = OC_DB::prepare('UPDATE *PREFIX*calendar_share_' . $type . ' SET permissions = ? WHERE share = ? AND sharetype = ? AND ' . $type . 'id = ?'); + $stmt->execute(array($permission, $share, $sharetype, $id)); + return true; + } + /* + * @brief: generates a token for public calendars / events + * @return: (string) $token + */ + private static function generate_token($id, $type){ + $uniqid = uniqid(); + if($type == self::CALENDAR){ + $events = OC_Calendar_Objects::all($id); + $string = ''; + foreach($events as $event){ + $string .= $event['calendardata']; + } + }else{ + $string = OC_Calendar_Object::find($id); + } + $string = sha1($string); + $id = sha1($id); + $array = array($uniqid,$string,$id); + shuffle($array); + $string = implode('', $array); + $token = md5($string); + return substr($token, rand(0,16), 15); + } + /* + * @brief: checks if it is already shared + * @param: (string) $owner - userid of the owner + * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public) + * @param: (string) $sharetype - type of sharing (can be: user/group/public) + * @param: (string) $id - id of the calendar / event + * @param: (string) $type - use const self::CALENDAR or self::EVENT + * @return (bool) + */ + private static function is_already_shared($owner, $share, $sharetype, $id, $type){ + $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE owner = ? AND share = ? AND sharetype = ? AND ' . $type . 'id = ?'); + $result = $stmt->execute(array($owner, $share, $sharetype, $id)); + if($result->numRows() > 0){ + return true; + } + return false; + } +} \ No newline at end of file diff --git a/apps/calendar/share.php b/apps/calendar/share.php new file mode 100644 index 0000000000..8d1c8b69c3 --- /dev/null +++ b/apps/calendar/share.php @@ -0,0 +1 @@ + diff --git a/apps/calendar/templates/part.choosecalendar.php b/apps/calendar/templates/part.choosecalendar.php index 86f09d6207..21da5dd7cd 100644 --- a/apps/calendar/templates/part.choosecalendar.php +++ b/apps/calendar/templates/part.choosecalendar.php @@ -1,4 +1,5 @@
    "> +

    t('Your calendars'); ?>:

    +
    -

    ">

    +

    ">


    +

    t('Shared calendars'); ?>:

    + +'; + $tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields.shared'); + $tmpl->assign('share', $share[$i]); + $tmpl->printpage(); + echo ''; +} +?>
    +' . $l->t('No shared calendars') . '

    '; +} +?> +
    \ No newline at end of file diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.php b/apps/calendar/templates/part.choosecalendar.rowfields.php index a789be45a4..156d50bc48 100644 --- a/apps/calendar/templates/part.choosecalendar.rowfields.php +++ b/apps/calendar/templates/part.choosecalendar.rowfields.php @@ -1,4 +1,8 @@ "; - echo ""; - echo "t("CalDav Link") . "\" class=\"action\">t("Download") . "\" class=\"action\">t("Edit") . "\" class=\"action\" onclick=\"Calendar.UI.Calendar.edit(this, " . $_['calendar']["id"] . ");\">t("Delete") . "\" class=\"action\">"; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.shared.php b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php new file mode 100644 index 0000000000..2e1210415b --- /dev/null +++ b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php @@ -0,0 +1,4 @@ +'; +echo ''; +echo '' . $l->t('shared with you by') . ' ' . $_['share']['owner'] . ''; \ No newline at end of file diff --git a/apps/calendar/templates/part.eventform.php b/apps/calendar/templates/part.eventform.php index 1b7aa1acb4..4a9a467549 100644 --- a/apps/calendar/templates/part.eventform.php +++ b/apps/calendar/templates/part.eventform.php @@ -231,6 +231,6 @@ t('Summary'); ?>: -
    -
    -
    \ No newline at end of file +
    //Alarm
    +
    //Attendees
    +
    //Share
    \ No newline at end of file diff --git a/apps/calendar/templates/share.dropdown.php b/apps/calendar/templates/share.dropdown.php new file mode 100644 index 0000000000..6a944f1f09 --- /dev/null +++ b/apps/calendar/templates/share.dropdown.php @@ -0,0 +1,71 @@ + +t('Users');?>:
    +
    + +t('Groups');?>:
    +
    + +
    + >
    + +
    \ No newline at end of file