This commit is contained in:
zotlabs 2019-05-03 00:00:00 -07:00
commit b1dec12893
14 changed files with 234 additions and 82 deletions

View File

@ -310,7 +310,7 @@ class Activity {
$ret['attributedTo'] = $i['author']['xchan_url'];
if($i['id'] != $i['parent']) {
$ret['inReplyTo'] = ((strpos($i['parent_mid'],'http') === 0) ? $i['parent_mid'] : z_root() . '/item/' . urlencode($i['parent_mid']));
$ret['inReplyTo'] = ((strpos($i['thr_parent'],'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
}
if($i['mimetype'] === 'text/bbcode') {
@ -509,7 +509,7 @@ class Activity {
}
if($i['id'] != $i['parent']) {
$ret['inReplyTo'] = ((strpos($i['parent_mid'],'http') === 0) ? $i['parent_mid'] : z_root() . '/item/' . urlencode($i['parent_mid']));
$ret['inReplyTo'] = ((strpos($i['thr_parent'],'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
$reply = true;
if($i['item_private']) {

View File

@ -38,6 +38,7 @@ class ThreadItem {
$this->data = $data;
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
$this->threaded = get_config('system','thread_allow');
$observer = \App::get_observer();
@ -305,6 +306,7 @@ class ThreadItem {
if($this->is_commentable() && $observer) {
$like = array( t("I like this \x28toggle\x29"), t("like"));
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
$reply_to = array( t("Reply on this comment"), t("reply"), t("Reply to"));
}
if ($shareable) {
@ -348,9 +350,6 @@ class ThreadItem {
$list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
$children = $this->get_children();
$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
@ -373,13 +372,15 @@ class ThreadItem {
'text' => strip_tags($body['html']),
'id' => $this->get_id(),
'mid' => $item['mid'],
'parent' => $item['parent'],
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
'isevent' => $isevent,
'attend' => $attend,
'consensus' => $consensus,
'conlabels' => $conlabels,
'canvote' => $canvote,
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, $item['author']['xchan_addr']),
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), $item['owner']['xchan_addr']),
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url'])),
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), (($item['owner']['xchan_addr']) ? $item['owner']['xchan_addr'] : $item['owner']['xchan_url'])),
'llink' => $item['llink'],
'viewthread' => $viewthread,
'to' => t('to'),
@ -425,9 +426,10 @@ class ThreadItem {
'has_tags' => $has_tags,
'reactions' => $this->reactions,
// Item toolbar buttons
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
'like' => $like,
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
'reply_to' => (((! $this->is_toplevel()) && feature_enabled($conv->get_profile_owner(),'reply_to')) ? $reply_to : ''),
'share' => $share,
'embed' => $embed,
'rawmid' => $item['mid'],
@ -869,4 +871,3 @@ class ThreadItem {
}

View File

@ -890,7 +890,7 @@ class Cdav extends Controller {
}
//Display calendar(s) here
if(argc() == 2 && argv(1) === 'calendar') {
if(argc() <= 3 && argv(1) === 'calendar') {
head_add_css('/library/fullcalendar/packages/core/main.min.css');
head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
@ -905,6 +905,50 @@ class Cdav extends Controller {
head_add_js('/library/fullcalendar/packages/list/main.min.js');
$sources = '';
$resource_id = '';
$resource = null;
if(argc() == 3)
$resource_id = argv(2);
if($resource_id) {
$r = q("SELECT event.*, item.author_xchan, item.owner_xchan, item.plink, item.id as item_id FROM event LEFT JOIN item ON event.event_hash = item.resource_id
WHERE event.uid = %d AND event.event_hash = '%s' LIMIT 1",
intval(local_channel()),
dbesc($resource_id)
);
if($r) {
xchan_query($r);
$r = fetch_post_tags($r,true);
$r[0]['dtstart'] = (($r[0]['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$r[0]['dtstart'], 'c') : datetime_convert('UTC','UTC',$r[0]['dtstart'],'c'));
$r[0]['dtend'] = (($r[0]['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$r[0]['dtend'], 'c') : datetime_convert('UTC','UTC',$r[0]['dtend'],'c'));
$r[0]['plink'] = [$r[0]['plink'], t('Link to source')];
$resource = $r[0];
$catsenabled = feature_enabled(local_channel(),'categories');
$categories = '';
if($catsenabled){
if($r[0]['term']) {
$cats = get_terms_oftype($r[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if(strlen($categories))
$categories .= ', ';
$categories .= $cat['term'];
}
}
}
if($r[0]['dismissed'] == 0) {
q("UPDATE event SET dismissed = 1 WHERE event.uid = %d AND event.event_hash = '%s'",
intval(local_channel()),
dbesc($resource_id)
);
}
}
}
if(get_pconfig(local_channel(), 'cdav_calendar', 'channel_calendar')) {
$sources .= '{
@ -1005,7 +1049,10 @@ class Cdav extends Controller {
'$deny_cid' => acl2json($permissions['deny_cid']),
'$deny_gid' => acl2json($permissions['deny_gid']),
'$catsenabled' => $catsenabled,
'$categories_label' => t('Categories')
'$categories_label' => t('Categories'),
'$resource' => json_encode($resource),
'$categories' => $categories
]);
return $o;

View File

@ -125,10 +125,6 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
}
//goaway($onerror_url);
}
// $share = ((intval($_POST['distr'])) ? intval($_POST['distr']) : 0);
$share = 1;
$channel = \App::get_channel();
@ -152,23 +148,10 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
$created = $x[0]['created'];
$edited = datetime_convert();
if($x[0]['allow_cid'] === '<' . $channel['channel_hash'] . '>'
&& $x[0]['allow_gid'] === '' && $x[0]['deny_cid'] === '' && $x[0]['deny_gid'] === '') {
$share = false;
}
else {
$share = true;
}
}
else {
$created = $edited = datetime_convert();
if($share) {
$acl->set_from_array($_POST);
}
else {
$acl->set(array('allow_cid' => '<' . $channel['channel_hash'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''));
}
$acl->set_from_array($_POST);
}
$post_tags = array();
@ -239,8 +222,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
}
}
if($share)
\Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
\Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
killme();
@ -524,6 +506,14 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
}
}
$allDay = false;
// allDay event rules
if(!strpos($start, 'T') && !strpos($end, 'T'))
$allDay = true;
if(strpos($start, 'T00:00:00') && strpos($end, 'T00:00:00'))
$allDay = true;
$is_first = ($d !== $last_date);
$last_date = $d;
@ -550,17 +540,18 @@ class Channel_calendar extends \Zotlabs\Web\Controller {
'start'=> $start,
'end' => $end,
'drop' => $drop,
'allDay' => false,
'allDay' => $allDay,
'title' => $title,
'j' => $j,
'd' => $d,
'is_editable' => $edit ? true : false,
'editable' => $edit ? true : false,
'is_first'=>$is_first,
'item'=>$rr,
'html'=>$html,
'plink' => array($rr['plink'],t('Link to Source'),'',''),
'plink' => [$rr['plink'], t('Link to source')],
'description' => $rr['description'],
'location' => $rr['location'],

View File

@ -45,7 +45,7 @@ class Editpost extends \Zotlabs\Web\Controller {
}
if($itm[0]['resource_type'] === 'event' && $itm[0]['resource_id']) {
goaway(z_root() . '/cdav/calendar');
goaway(z_root() . '/cdav/calendar/' . $itm[0]['resource_id']);
//goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
}

View File

@ -447,7 +447,7 @@ class Ping extends \Zotlabs\Web\Controller {
$when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
$result[] = array(
'notify_link' => z_root() . '/cdav/calendar', /// @FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'],
'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],

View File

@ -22,7 +22,7 @@ class Cdav {
$o = '';
if(argc() == 2 && argv(1) === 'calendar') {
if(argc() <= 3 && argv(1) === 'calendar') {
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);

View File

@ -1185,7 +1185,7 @@ function event_store_item($arr, $event) {
// otherwise we'll fallback to /display/$message_id
if($wall)
$item_arr['plink'] = z_root() . '/channel/' . $z[0]['channel_address'] . '/?f=&mid=' . urlencode($item_arr['mid']);
$item_arr['plink'] = z_root() . '/channel/' . $z[0]['channel_address'] . '/?f=&mid=' . gen_link_id($item_arr['mid']);
else
$item_arr['plink'] = z_root() . '/display/' . gen_link_id($item_arr['mid']);

View File

@ -167,6 +167,14 @@ function get_features($filtered = true, $level = (-1)) {
t('Ability to mark special posts with a star indicator'),
false,
get_config('feature_lock','star_posts'),
],
[
'reply_to',
t('Reply on comment'),
t('Ability to reply on selected comment'),
false,
get_config('feature_lock','reply_to'),
]
],

View File

@ -409,7 +409,8 @@ function autoname($len) {
* @return string Escaped text.
*/
function xmlify($str) {
$buffer = '';
//$buffer = '';
if(is_array($str)) {
@ -418,7 +419,7 @@ function xmlify($str) {
btlogger('xmlify called with array: ' . print_r($str,true), LOGGER_NORMAL, LOG_WARNING);
}
/*
$len = mb_strlen($str);
for($x = 0; $x < $len; $x ++) {
$char = mb_substr($str,$x,1);
@ -452,6 +453,11 @@ function xmlify($str) {
$buffer = trim($buffer);
return($buffer);
*/
$buffer = htmlspecialchars($str, ENT_QUOTES, "UTF-8");
$buffer = trim($buffer);
return $buffer;
}
/**
@ -464,9 +470,13 @@ function xmlify($str) {
* @return string
*/
function unxmlify($s) {
/*
$ret = str_replace('&amp;', '&', $s);
$ret = str_replace(array('&lt;', '&gt;', '&quot;', '&apos;'), array('<', '>', '"', "'"), $ret);
return $ret;
*/
$ret = htmlspecialchars_decode($s, ENT_QUOTES);
return $ret;
}

View File

@ -231,6 +231,10 @@ function handle_comment_form(e) {
$('#' + emptyCommentElm).removeAttr('tabindex');
$('#' + emptySubmitElm).removeAttr('tabindex');
form.find(':not(.comment-edit-text)').hide();
form.find(':input[name=parent]').val(emptyCommentElm.replace(/\D/g,''));
var btn = form.find(':button[type=submit]').html();
form.find(':button[type=submit]').html(btn.replace(/<[^>]*>/g, '').trim());
form.find(':button[type=submit]').prop('title', '');
}
});
@ -1144,6 +1148,16 @@ function doprofilelike(ident, verb) {
$.get('like/' + ident + '?verb=' + verb, function() { window.location.href=window.location.href; });
}
function doreply(parent, ident, owner, hint) {
var form = $('#comment-edit-form-' + parent.toString());
form.find('input[name=parent]').val(ident);
var i = form.find('button[type=submit]');
var btn = i.html().replace(/<[^>]*>/g, '').trim();
i.html('<i class="fa fa-reply" ></i> ' + btn);
i.prop('title', hint);
form.find('textarea').val("@{" + owner + "} ");
$('#comment-edit-text-' + parent.toString()).focus();
}
function dropItem(url, object) {

View File

@ -21,7 +21,8 @@ $(document).ready(function() {
$('#left_aside_wrapper, #right_aside_wrapper').stick_in_parent({
offset_top: parseInt($('aside').css('padding-top')),
parent: 'main',
spacer: '.aside_spacer'
spacer: '.aside_spacer',
recalc_every: 10
});
}

View File

@ -6,12 +6,17 @@ var views = {'dayGridMonth' : '{{$month}}', 'timeGridWeek' : '{{$week}}', 'timeG
var event_id;
var event_uri;
var event_xchan;
var contact_allow = [];
var group_allow = [];
var contact_deny = [];
var group_deny = [];
var resource = {{$resource}};
var default_view = resource !== null ? 'timeGridDay' : 'dayGridMonth';
var default_date = resource !== null ? new Date(resource.dtstart) : new Date();
$(document).ready(function() {
var calendarEl = document.getElementById('calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
@ -29,6 +34,9 @@ $(document).ready(function() {
firstDay: {{$first_day}},
defaultView: default_view,
defaultDate: default_date,
monthNames: aStr['monthNames'],
monthNamesShort: aStr['monthNamesShort'],
dayNames: aStr['dayNames'],
@ -75,7 +83,7 @@ $(document).ready(function() {
var event = info.event._def;
var dtstart = new Date(info.event._instance.range.start);
var dtend = new Date(info.event._instance.range.end);
console.log(event.extendedProps.categories);
if(event.extendedProps.plink) {
if(! $('#l2s').length)
$('#id_title_wrapper').prepend('<span id="l2s" class="float-right"></span>');
@ -121,6 +129,7 @@ $(document).ready(function() {
$('#event_submit').val('update_event').html('{{$update}}');
$('#dbtn-acl').addClass('d-none');
event_id = event.extendedProps.item ? event.extendedProps.item.id : 0;
event_xchan = event.extendedProps.item ? event.extendedProps.item.event_xchan : '';
contact_allow = event.extendedProps.contact_allow || [];
group_allow = event.extendedProps.group_allow || [];
@ -137,8 +146,7 @@ $(document).ready(function() {
$('#id_description').attr('disabled', false);
$('#id_location').attr('disabled', false);
if(calendar_id == 'channel_calendar' && !event.extendedProps.is_editable) {
console.log(calendar_id)
if(calendar_id === 'channel_calendar' && !event.ui.startEditable) {
$('#event_submit').hide();
}
}
@ -161,7 +169,7 @@ $(document).ready(function() {
},
eventResize: function(info) {
var event = info.event._def;
var dtstart = new Date(info.event._instance.range.start);
var dtend = new Date(info.event._instance.range.end);
@ -170,16 +178,42 @@ $(document).ready(function() {
$('#id_dtstart').val(dtstart.toUTCString());
$('#id_dtend').val(dtend.toUTCString());
$.post( 'cdav/calendar', {
'update': 'resize',
'id[]': event.extendedProps.calendar_id,
'uri': event.extendedProps.uri,
'dtstart': dtstart ? dtstart.toUTCString() : '',
'dtend': dtend ? dtend.toUTCString() : ''
})
.fail(function() {
info.revert();
});
event_id = event.extendedProps.item ? event.extendedProps.item.id : 0;
event_xchan = event.extendedProps.item ? event.extendedProps.item.event_xchan : '';
if(event.extendedProps.calendar_id === 'channel_calendar') {
$.post( 'channel_calendar', {
'event_id': event_id,
'event_hash': event_uri,
'xchan': event_xchan,
//'mid': mid,
'type': 'event',
'preview': 0,
'summary': event.title,
'dtstart': dtstart.toUTCString(),
'dtend': dtend.toUTCString(),
'adjust': event.extendedProps.item.adjust,
'categories': event.extendedProps.categories,
'desc': event.extendedProps.description,
'location': event.extendedProps.location,
//'submit': $('#event_submit').val()
})
.fail(function() {
info.revert();
});
}
else {
$.post( 'cdav/calendar', {
'update': 'resize',
'id[]': event.extendedProps.calendar_id,
'uri': event.extendedProps.uri,
'dtstart': dtstart ? dtstart.toUTCString() : '',
'dtend': dtend ? dtend.toUTCString() : ''
})
.fail(function() {
info.revert();
});
}
},
eventDrop: function(info) {
@ -191,19 +225,45 @@ $(document).ready(function() {
$('#id_title').val(event.title);
$('#id_dtstart').val(dtstart.toUTCString());
$('#id_dtend').val(dtend.toUTCString());
$.post( 'cdav/calendar', {
'update': 'drop',
'id[]': event.extendedProps.calendar_id,
'uri': event.extendedProps.uri,
'dtstart': dtstart ? dtstart.toUTCString() : '',
'dtend': dtend ? dtend.toUTCString() : ''
})
.fail(function() {
info.revert();
});
event_id = event.extendedProps.item ? event.extendedProps.item.id : 0;
event_xchan = event.extendedProps.item ? event.extendedProps.item.event_xchan : '';
if(event.extendedProps.calendar_id === 'channel_calendar') {
$.post( 'channel_calendar', {
'event_id': event_id,
'event_hash': event_uri,
'xchan': event_xchan,
//'mid': mid,
'type': 'event',
'preview': 0,
'summary': event.title,
'dtstart': dtstart.toUTCString(),
'dtend': dtend.toUTCString(),
'adjust': event.extendedProps.item.adjust,
'categories': event.extendedProps.categories,
'desc': event.extendedProps.description,
'location': event.extendedProps.location,
//'submit': $('#event_submit').val()
})
.fail(function() {
info.revert();
});
}
else {
$.post( 'cdav/calendar', {
'update': 'drop',
'id[]': event.extendedProps.calendar_id,
'uri': event.extendedProps.uri,
'dtstart': dtstart ? dtstart.toUTCString() : '',
'dtend': dtend ? dtend.toUTCString() : ''
})
.fail(function() {
info.revert();
});
}
},
loading: function(isLoading, view) {
$('#events-spinner').show();
$('#today-btn > i').hide();
@ -216,7 +276,7 @@ $(document).ready(function() {
});
calendar.render();
$('#title').text(calendar.view.title);
$('#view_selector').html(views[calendar.view.type]);
@ -250,6 +310,30 @@ $(document).ready(function() {
$(document).on('click','#event_more', on_more);
$(document).on('click','#event_cancel, #event_cancel_recurrent', reset_form);
$(document).on('click','#event_delete, #event_delete_recurrent', on_delete);
if(resource !== null) {
$('.section-content-tools-wrapper, #event_form_wrapper').show();
$('#id_title_wrapper').prepend('<span id="l2s" class="float-right"></span>');
$('#l2s').html('<a href="' + resource.plink[0] + '" target="_blank"><i class="fa fa-external-link"></i> ' + resource.plink[1] + '</a>');
event_id = resource.id;
event_uri = resource.event_hash;
event_xchan = resource.event_xchan;
$('#calendar_select').val('channel_calendar').attr('disabled', true);
$('#id_title').val(resource.summary);
$('#id_dtstart').val(new Date(resource.dtstart).toUTCString());
$('#id_dtend').val(new Date(resource.dtend).toUTCString());
$('#id_categories').tagsinput('add', '{{$categories}}'),
$('#id_description').val(resource.description);
$('#id_location').val(resource.location);
if(event_xchan !== '{{$channel_hash}}')
$('#event_submit').hide();
else
$('#event_submit').html('{{$update}}');
}
});
@ -302,7 +386,7 @@ function updateSize() {
}
function on_submit() {
if($('#calendar_select').val() == 'channel_calendar') {
if($('#calendar_select').val() === 'channel_calendar') {
if(new_event_id) {
$("input[name='contact_allow[]']").each(function() {
contact_allow.push($(this).val());
@ -321,7 +405,7 @@ function on_submit() {
$.post( 'channel_calendar', {
'event_id': event_id,
'event_hash': event_uri,
'xchan': '{{$channel_hash}}',
'xchan': event_xchan,
//'mid': mid,
'type': 'event',
'preview': 0,
@ -332,21 +416,12 @@ function on_submit() {
'categories': $('#id_categories').val(),
'desc': $('#id_description').val(),
'location': $('#id_location').val(),
'submit': $('#event_submit').val(),
//'submit': $('#event_submit').val(),
'contact_allow[]': contact_allow,
'group_allow[]': group_allow,
'contact_deny[]': contact_deny,
'group_deny[]': group_deny
/*
'submit': $('#event_submit').val(),
'target': $('#calendar_select').val(),
'uri': $('#event_uri').val(),
'title': $('#id_title').val(),
'dtstart': $('#id_dtstart').val(),
'dtend': $('#id_dtend').val(),
'description': $('#id_description').val(),
'location': $('#id_location').val()
*/
})
.done(function() {
var eventSource = calendar.getEventSourceById('channel_calendar');
@ -378,7 +453,7 @@ function on_submit() {
}
function on_delete() {
if($('#calendar_select').val() == 'channel_calendar') {
if($('#calendar_select').val() === 'channel_calendar') {
$.get('channel_calendar/drop/' + event_uri, function() {
var eventSource = calendar.getEventSourceById('channel_calendar');
eventSource.refetch();

View File

@ -102,6 +102,11 @@
<i class="fa fa-thumbs-o-down{{if $item.my_responses.dislike}} ivoted{{/if}}" ></i>
</button>
{{/if}}
{{if $item.reply_to}}
<button type="button" title="{{$item.reply_to.0}}" class="btn btn-outline-secondary btn-sm" onclick="doreply({{$item.parent}},{{$item.id}},'{{$item.author_id}}', '{{$item.reply_to.2}} {{$item.name}}'); return false;">
<i class="fa fa-reply" ></i>
</button>
{{/if}}
{{if $item.isevent}}
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-toggle="dropdown" id="wall-item-attend-menu-{{$item.id}}" title="{{$item.attend_title}}">