tra('Tracker Timeline'),
'documentation' => 'PluginTrackerTimeline',
'description' => tra('Show a timeline view of a tracker'),
'prefs' => [ 'wikiplugin_trackertimeline', 'feature_trackers' ],
'iconname' => 'history',
'introduced' => 3,
'format' => 'html',
'params' => [
'tracker' => [
'required' => true,
'name' => tra('Tracker ID'),
'description' => tra('Numeric value representing the tracker ID'),
'since' => '3.0',
'filter' => 'digits',
'default' => '',
'profile_reference' => 'tracker',
],
'title' => [
'required' => true,
'name' => tra('Title Field'),
'description' => tra('Tracker Field ID containing the item title.'),
'since' => '3.0',
'filter' => 'digits',
'default' => '',
'profile_reference' => 'tracker_field',
'parent' => 'input[name="params[tracker]"]',
'parentkey' => 'tracker_id',
],
'summary' => [
'required' => true,
'name' => tra('Summary Field'),
'description' => tra('Tracker Field ID containing the summary of the item. The summary will be displayed
on the timeline when the item is focused.'),
'since' => '3.0',
'filter' => 'digits',
'default' => '',
'profile_reference' => 'tracker_field',
'parent' => 'input[name="params[tracker]"]',
'parentkey' => 'tracker_id',
],
'start' => [
'required' => true,
'name' => tra('Start Date'),
'description' => tra('Tracker Field ID containing the element start date. The field must be a
datetime/jscalendar field.'),
'since' => '3.0',
'filter' => 'digits',
'default' => '',
'profile_reference' => 'tracker_field',
'parent' => 'input[name="params[tracker]"]',
'parentkey' => 'tracker_id',
],
'end' => [
'required' => true,
'name' => tra('End Date'),
'description' => tra('Tracker Field ID containing the element end date. The field must be a
datetime/jscalendar field.'),
'since' => '3.0',
'filter' => 'digits',
'default' => '',
'profile_reference' => 'tracker_field',
'parent' => 'input[name="params[tracker]"]',
'parentkey' => 'tracker_id',
],
'group' => [
'required' => true,
'name' => tra('Element Group'),
'description' => tra('Tracker Field ID containing the element\'s group. Elements of a same group are
displayed on the same row.'),
'since' => '3.0',
'filter' => 'digits',
'default' => '',
'profile_reference' => 'tracker_field',
'parent' => 'input[name="params[tracker]"]',
'parentkey' => 'tracker_id',
],
'lower' => [
'required' => true,
'name' => tra('Lower Bound'),
'description' => tr('Date from which element should be displayed. Date must be provided in
%0YYYY-MM-DD HH:mm:ss%1 format.', '', ''),
'since' => '3.0',
'filter' => 'datetime',
'default' => '',
'accepted' => 'Date in YYYY-MM-DD HH:mm:ss format',
],
'upper' => [
'required' => true,
'name' => tra('Upper Bound'),
'description' => tr('Date until which element should be displayed. Date must be provided in
%0YYYY-MM-DD HH:mm:ss%1 format.', '', ''),
'since' => '3.0',
'filter' => 'datetime',
'default' => '',
'accepted' => 'Date in YYYY-MM-DD HH:mm:ss format',
],
'scale1' => [
'required' => false,
'name' => tra('Primary Scale Unit'),
'description' => tra('Unit of time to use for the primary scale (default to hour - * SIMILE only)'),
'since' => '3.0',
'filter' => 'alpha',
'default' => 'hour',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Hour'), 'value' => 'hour'],
['text' => tra('Day'), 'value' => 'day'],
['text' => tra('Week'), 'value' => 'week'],
['text' => tra('Month'), 'value' => 'month'],
['text' => tra('Year'), 'value' => 'year'],
['text' => tra('Decade *'), 'value' => 'decade'],
['text' => tra('Century *'), 'value' => 'century'],
]
],
'scale2' => [
'required' => false,
'name' => tra('Secondary Scale Unit'),
'description' => tra('Unit of time to use for the secondary scale (default to empty - * SIMILE only)'),
'since' => '3.0',
'filter' => 'alpha',
'default' => '',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Hour'), 'value' => 'hour'],
['text' => tra('Day'), 'value' => 'day'],
['text' => tra('Week'), 'value' => 'week'],
['text' => tra('Month'), 'value' => 'month'],
['text' => tra('Year'), 'value' => 'year'],
['text' => tra('Decade *'), 'value' => 'decade'],
['text' => tra('Century *'), 'value' => 'century'],
]
],
'height' => [
'required' => false,
'name' => tra('Timeline height'),
'description' => tr(
'Height of the timeline band as a CSS unit (default: %0 - - * SIMILE only)',
'250p'
),
'since' => '9.0',
'filter' => 'text',
'default' => '250px',
],
'band2_height' => [
'required' => false,
'name' => tra('Lower band height'),
'description' => tr(
'Height of the lower timeline band as a percentage (default: %0 - - * SIMILE only)',
'250p'
),
'since' => '9.0',
'filter' => 'int',
'default' => '30',
],
'link_group' => [
'required' => false,
'name' => tra('Link Group Name'),
'description' => tra('Convert the group name to a link'),
'since' => '3.0',
'filter' => 'alpha',
'default' => '',
'options' => [
['text' => '', 'value' => ''],
['text' => tra('Yes'), 'value' => 'y'],
['text' => tra('No'), 'value' => 'n']
]
],
'link_page' => [
'required' => false,
'name' => tra('Page Link Field'),
'description' => tra('Tracker Field ID containing the page name for item details.'),
'since' => '3.0',
'filter' => 'digits',
'default' => '',
'profile_reference' => 'tracker_field',
'parent' => 'input[name="params[tracker]"]',
'parentkey' => 'tracker_id',
],
'simile_timeline' => [
'required' => false,
'name' => tra('SIMILE Timeline'),
'description' => tra('Use the SIMILE Timeline Widget.'),
'since' => '7.0',
'filter' => 'alpha',
'default' => 'n',
'options' => [
['text' => tra('Yes'), 'value' => 'y'],
['text' => tra('No'), 'value' => 'n'],
],
],
'image_field' => [
'required' => false,
'name' => tra('Image Field'),
'description' => tra('Tracker Field ID containing in image.'),
'since' => '7.0',
'filter' => 'digits',
'default' => '',
'profile_reference' => 'tracker_field',
'parent' => 'input[name="params[tracker]"]',
'parentkey' => 'tracker_id',
],
]
];
}
function wikiplugin_trackertimeline($data, $params)
{
$trklib = TikiLib::lib('trk');
$smarty = TikiLib::lib('smarty');
static $instance = 0;
$instance++;
if (! isset($params['tracker'])) {
return "^" . tr("Missing parameter: %0", 'tracker') . "^";
}
$default = ['scale1' => 'hour', 'simile_timeline' => 'n', 'height' => '250px', 'band2_height' => 30];
$params = array_merge($default, $params);
$formats = ['hour' => 'H:i', 'day' => 'jS', 'week' => 'jS', 'month' => 'm', 'year' => 'y'];
$start = strtotime($params['lower']);
$end = strtotime($params['upper']);
$size = $end - $start;
if ($size <= 0) {
return "^" . tr("Start date after end date.") . "^";
}
$fieldIds = [
$params['title'] => 'title',
$params['summary'] => 'summary',
$params['start'] => 'start',
$params['end'] => 'end',
$params['group'] => 'group',
];
if (isset($params['link_page'])) {
$fieldIds[ $params['link_page'] ] = 'link';
}
if (! empty($params['image_field'])) {
$fieldIds[ $params['image_field'] ] = 'image';
}
$fields = [];
foreach ($fieldIds as $id => $label) {
$fields[$id] = $trklib->get_tracker_field($id);
}
$items = $trklib->list_items($params['tracker'], 0, -1, '', $fields);
$data = [];
foreach ($items['data'] as $item) {
// Collect data
$detail = [ 'item' => $item['itemId'] ];
foreach ($item['field_values'] as $field) {
$detail[ $fieldIds[$field['fieldId']] ] = $field['value'];
}
// Filter elements
if ($params['simile_timeline'] !== 'y') {
if ($detail['start'] >= $detail['end']) {
continue;
}
if ($detail['end'] <= $start || $detail['start'] > $end) {
continue;
}
} else {
if (! empty($detail['end']) && $detail['start'] > $detail['end']) {
continue;
}
if ((! empty($detail['end']) && $detail['end'] < $start) || $detail['start'] > $end) {
continue;
}
}
$detail['lstart'] = max($start, $detail['start']);
$detail['lend'] = min($end, $detail['end']);
$detail['lsize'] = round(( $detail['lend'] - $detail['lstart'] ) / $size * 80);
$detail['fstart'] = date($formats[$params['scale1']], $detail['start']);
$detail['fend'] = date($formats[$params['scale1']], $detail['end']);
$detail['psummary'] = TikiLib::lib('parser')->parse_data($detail['summary']);
$detail['encoded'] = json_encode($detail);
// Add to data list
if (! array_key_exists($detail['group'], $data)) {
$data[$detail['group']] = [];
}
$data[ $detail['group'] ][] = $detail;
}
if ($params['simile_timeline'] !== 'y') {
$new = [];
foreach ($data as $group => &$list) {
wp_ttl_organize($group, $start, $size, $list, $new);
}
$data = array_merge($data, $new);
ksort($data);
$smarty->assign('wp_ttl_data', $data);
$layouts = [];
if (isset($params['scale2']) && $layout = wp_ttl_genlayout($start, $end, $size, $params['scale2'])) {
$layouts[] = $layout;
}
$layouts[] = wp_ttl_genlayout($start, $end, $size, isset($params['scale1']) ? $params['scale1'] : 'hour');
$smarty->assign('layouts', $layouts);
$smarty->assign('link_group_names', isset($params['link_group']) && $params['link_group'] == 'y');
return $smarty->fetch('wiki-plugins/wikiplugin_trackertimeline.tpl');
} else { // SIMILE Timeline Widget setup
$headerlib = TikiLib::lib('header');
$smarty->loadPlugin('smarty_modifier_sefurl');
// static js moved to lib
$headerlib->add_jsfile('lib/simile_tiki/tiki-timeline.js');
// prepare the data for SIMILE widget - to be included in the page for now (ajax feed to come)
$ttl_data = [];
$events = [];
foreach ($data as $group => $list) { // ignoring group for now
foreach ($list as $item) {
$event = [
'title' => $item['title'],
'start' => date('r', $item['start']),
'description' => $item['summary'],
];
if (! empty($item['end'])) {
$event['end'] = date('r', $item['end']);
$event['isDuration'] = true;
}
if (! empty($item['link'])) {
$event['link'] = $item['link'];
}
$image = $item['image'];
if (! empty($image)) {
if (strpos($image, ',') !== false) {
// just the first one
$image = substr($image, 0, strpos($image, ','));
}
if (is_numeric($image)) {
// a fileId
$image = smarty_modifier_sefurl($image, 'thumbnail');
}
$event['image'] = $image;
}
$events[] = $event;
}
$ttl_data = [
'dateTimeFormat' => '', // iso8601
// 'wikiURL' => '',
// 'wikiSection' => '',
'events' => $events,
];
}
$js = 'var ttl_eventData_' . $instance . ' = ' . json_encode($ttl_data) . ";\n";
$js .= '
setTimeout( function(){ ttlInit("ttl_timeline_' . $instance . '",ttl_eventData_' . $instance . ',"' . $params['scale1'] . '","' . $params['scale2'] . '","' . $params['band2_height'] . '"); }, 1000);
';
$headerlib->add_jq_onready($js, 10);
$out = '