Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbenakamoorthi <benaka.moorthi@gmail.com>2012-12-14 12:56:21 +0400
committerbenakamoorthi <benaka.moorthi@gmail.com>2012-12-14 12:56:21 +0400
commit043fc882559e3ed31c1387fbd5ef158510c5668f (patch)
treee899ada11325b777e79de2b89997a943b21d3f34 /plugins/Annotations/templates
parent6720c8ae82f2f914a682c4c741fd6adc768dd230 (diff)
Fixes #1253, added annotations plugin that allows attaching notes to different days.
Notes: * Modified renderers so they would render arrays better. Before, arrays were added to DataTables and array keys were either lost or ignored, now they are rendered. * Fixed issue w/ JSON rendering that rendered arrays when the PHP arrays didn't have contiguous keys. * Augmented some exception messages. * Added utility method processRequest to Piwik_API_Request to ease use of the class. git-svn-id: http://dev.piwik.org/svn/trunk@7612 59fd770c-687e-43c8-a1e3-f5a4ff64c105
Diffstat (limited to 'plugins/Annotations/templates')
-rwxr-xr-xplugins/Annotations/templates/annotation.tpl43
-rwxr-xr-xplugins/Annotations/templates/annotationManager.tpl27
-rwxr-xr-xplugins/Annotations/templates/annotations.js583
-rwxr-xr-xplugins/Annotations/templates/annotations.tpl30
-rwxr-xr-xplugins/Annotations/templates/evolutionAnnotations.tpl12
-rwxr-xr-xplugins/Annotations/templates/styles.css194
6 files changed, 889 insertions, 0 deletions
diff --git a/plugins/Annotations/templates/annotation.tpl b/plugins/Annotations/templates/annotation.tpl
new file mode 100755
index 0000000000..1a94cf60d6
--- /dev/null
+++ b/plugins/Annotations/templates/annotation.tpl
@@ -0,0 +1,43 @@
+<tr class="annotation" data-id="{$annotation.idNote}" data-date="{$annotation.date}">
+ <td class="annotation-meta">
+ <div class="annotation-star{if $annotation.canEditOrDelete} annotation-star-changeable{/if}" data-starred="{$annotation.starred}" {if $annotation.canEditOrDelete}title="{'Annotations_ClickToStarOrUnstar'|translate}"{/if}>
+ {if $annotation.starred}
+ <img src="themes/default/images/star.png"/>
+ {else}
+ <img src="themes/default/images/star_empty.png"/>
+ {/if}
+ </div>
+ <div class="annotation-period {if $annotation.canEditOrDelete}annotation-enter-edit-mode{/if}">({$annotation.date})</div>
+ {if $annotation.canEditOrDelete}
+ <div class="annotation-period-edit" style="display:none">
+ <a href="#">{$annotation.date}</a>
+ <div class="datepicker" style="display:none"/>
+ </div>
+ {/if}
+ </td>
+ <td class="annotation-value">
+ <div class="annotation-view-mode">
+ <span {if $annotation.canEditOrDelete}title="{'Annotations_ClickToEdit'|translate}" class="annotation-enter-edit-mode"{/if}>{$annotation.note|unescape|escape:'html'}</span>
+ {if $annotation.canEditOrDelete}
+ <a href="#" class="edit-annotation annotation-enter-edit-mode" title="{'Annotations_ClickToEdit'|translate}">{'General_Edit'|translate}...</a>
+ {/if}
+ </div>
+ {if $annotation.canEditOrDelete}
+ <div class="annotation-edit-mode" style="display:none">
+ <input class="annotation-edit" type="text" value="{$annotation.note|unescape|escape:'html'}"/>
+ <br/>
+ <input class="annotation-save submit" type="button" value="{'General_Save'|translate}"/>
+ <input class="annotation-cancel submit" type="button" value="{'General_Cancel'|translate}"/>
+ </div>
+ {/if}
+ </td>
+ {if isset($annotation.user) && $userLogin != 'anonymous'}
+ <td class="annotation-user-cell">
+ <span class="annotation-user">{$annotation.user|unescape|escape:'html'}</span><br/>
+ {if $annotation.canEditOrDelete}
+ <a href="#" class="delete-annotation" style="display:none" title="{'Annotations_ClickToDelete'|translate}">Delete</a>
+ {/if}
+ </td>
+ {/if}
+</tr>
+
diff --git a/plugins/Annotations/templates/annotationManager.tpl b/plugins/Annotations/templates/annotationManager.tpl
new file mode 100755
index 0000000000..4afa631cfd
--- /dev/null
+++ b/plugins/Annotations/templates/annotationManager.tpl
@@ -0,0 +1,27 @@
+<div class="annotation-manager"
+ {if $startDate neq $endDate}data-date="{$startDate},{$endDate}" data-period="range"
+ {else}data-date="{$startDate}" data-period="{$period}"
+ {/if}>
+
+<div class="annotations-header">
+ <span>{'Annotations_Annotations'|translate}</span>
+</div>
+
+<div class="annotation-list-range">{$startDatePretty}{if $startDate neq $endDate} &mdash; {$endDatePretty}{/if}</div>
+
+<div class="annotation-list">
+{include file="Annotations/templates/annotations.tpl"}
+
+<span class="loadingPiwik" style="display:none"><img src="themes/default/images/loading-blue.gif"/>{'General_Loading_js'|translate}</span>
+
+</div>
+
+<div class="annotation-controls">
+ {if $canUserAddNotes}
+ <a href="#" class="add-annotation" title="{'Annotations_ClickToAdd'|translate}">{'Annotations_CreateNewAnnotation'|translate}</a>
+ {elseif $userLogin eq 'anonymous'}
+ <a href="index.php?module=Login">{'Annotations_LoginToAnnotate'|translate}</a>
+ {/if}
+</div>
+
+</div>
diff --git a/plugins/Annotations/templates/annotations.js b/plugins/Annotations/templates/annotations.js
new file mode 100755
index 0000000000..0a7ed20edd
--- /dev/null
+++ b/plugins/Annotations/templates/annotations.js
@@ -0,0 +1,583 @@
+/*!
+ * Piwik - Web Analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+(function($, piwik) {
+
+var annotationsApi = {
+
+ // calls Annotations.getAnnotationManager
+ getAnnotationManager: function(idSite, date, period, lastN, callback)
+ {
+ var ajaxParams =
+ {
+ module: 'Annotations',
+ action: 'getAnnotationManager',
+ idSite: idSite,
+ date: date,
+ period: period,
+ };
+ if (lastN)
+ {
+ ajaxParams.lastN = lastN;
+ }
+
+ var ajaxRequest = new ajaxHelper();
+ ajaxRequest.addParams(ajaxParams, 'get');
+ ajaxRequest.setCallback(callback);
+ ajaxRequest.setFormat('html');
+ ajaxRequest.send(false);
+ },
+
+ // calls Annotations.addAnnotation
+ addAnnotation: function(idSite, managerDate, managerPeriod, date, note, callback)
+ {
+ var ajaxParams =
+ {
+ module: 'Annotations',
+ action: 'addAnnotation',
+ idSite: idSite,
+ date: date,
+ managerDate: managerDate,
+ managerPeriod: managerPeriod,
+ note: note
+ };
+
+ var ajaxRequest = new ajaxHelper();
+ ajaxRequest.addParams(ajaxParams, 'get');
+ ajaxRequest.addParams({token_auth: piwik.token_auth}, 'post');
+ ajaxRequest.setCallback(callback);
+ ajaxRequest.setFormat('html');
+ ajaxRequest.send(false);
+ },
+
+ // calls Annotations.saveAnnotation
+ saveAnnotation: function(idSite, idNote, date, noteData, callback)
+ {
+ var ajaxParams =
+ {
+ module: 'Annotations',
+ action: 'saveAnnotation',
+ idSite: idSite,
+ idNote: idNote,
+ date: date
+ };
+
+ for (var key in noteData)
+ {
+ ajaxParams[key] = noteData[key];
+ }
+
+ var ajaxRequest = new ajaxHelper();
+ ajaxRequest.addParams(ajaxParams, 'get');
+ ajaxRequest.addParams({token_auth: piwik.token_auth}, 'post');
+ ajaxRequest.setCallback(callback);
+ ajaxRequest.setFormat('html');
+ ajaxRequest.send(false);
+ },
+
+ // calls Annotations.deleteAnnotation
+ deleteAnnotation: function(idSite, idNote, managerDate, managerPeriod, callback)
+ {
+ var ajaxParams =
+ {
+ module: 'Annotations',
+ action: 'deleteAnnotation',
+ idSite: idSite,
+ idNote: idNote,
+ date: managerDate,
+ period: managerPeriod
+ };
+
+ var ajaxRequest = new ajaxHelper();
+ ajaxRequest.addParams(ajaxParams, 'get');
+ ajaxRequest.addParams({token_auth: piwik.token_auth}, 'post');
+ ajaxRequest.setCallback(callback);
+ ajaxRequest.setFormat('html');
+ ajaxRequest.send(false);
+ },
+
+ // calls Annotations.getEvolutionIcons
+ getEvolutionIcons: function(idSite, date, period, lastN, callback)
+ {
+ var ajaxParams =
+ {
+ module: 'Annotations',
+ action: 'getEvolutionIcons',
+ idSite: idSite,
+ date: date,
+ period: period,
+ };
+ if (lastN)
+ {
+ ajaxParams.lastN = lastN;
+ }
+
+ var ajaxRequest = new ajaxHelper();
+ ajaxRequest.addParams(ajaxParams, 'get');
+ ajaxRequest.setFormat('html');
+ ajaxRequest.setCallback(callback);
+ ajaxRequest.send(false);
+ },
+};
+
+var today = new Date();
+
+/**
+ * Returns options to configure an annotation's datepicker shown in edit mode.
+ *
+ * @param {Element} annotation The annotation element.
+ */
+var getDatePickerOptions = function(annotation)
+{
+ var annotationDateStr = annotation.attr('data-date'),
+ parts = annotationDateStr.split('-'),
+ annotationDate = new Date(parts[0], parts[1] - 1, parts[2]);
+
+ var result = piwik.getBaseDatePickerOptions(annotationDate);
+
+ // make sure days before site start & after today cannot be selected
+ var piwikMinDate = result.minDate;
+ result.beforeShowDay = function (date)
+ {
+ var valid = true;
+
+ // if date is after today or before date of site creation, it cannot be selected
+ if (date > today
+ || date < piwikMinDate)
+ {
+ valid = false;
+ }
+
+ return [valid, ''];
+ };
+
+ // on select a date, change the text of the edit date link
+ result.onSelect = function (dateText)
+ {
+ $('.annotation-period-edit>a', annotation).text(dateText);
+ };
+
+ return result;
+};
+
+/**
+ * Switches the current mode of an annotation between the view/edit modes.
+ *
+ * @param {Element} inAnnotationElement An element within the annotation to toggle the mode of.
+ * Should be two levels nested in the .annotation-value
+ * element.
+ * @return {Element} The .annotation-value element.
+ */
+var toggleAnnotationMode = function(inAnnotationElement)
+{
+ var annotation = $(inAnnotationElement).closest('.annotation');
+ $('.annotation-period,.annotation-period-edit,.delete-annotation,' +
+ '.annotation-edit-mode,.annotation-view-mode', annotation).toggle();
+
+ return $(inAnnotationElement).find('.annotation-value');
+};
+
+/**
+ * Creates the datepicker for an annotation element.
+ *
+ * @param {Element} annotation The annotation element.
+ */
+var createDatePicker = function ( annotation )
+{
+ $('.datepicker', annotation).datepicker(getDatePickerOptions(annotation)).hide();
+};
+
+/**
+ * Creates datepickers for every period edit in an annotation manager.
+ *
+ * @param {Element} manager The annotation manager element.
+ */
+var createDatePickers = function ( manager )
+{
+ $('.annotation-period-edit', manager).each(function() {
+ createDatePicker($(this).parent().parent());
+ });
+}
+
+/**
+ * Replaces the HTML of an annotation manager element, and resets date/period
+ * attributes.
+ *
+ * @param {Element} manager The annotation manager.
+ * @param {string} tml The HTML of the new annotation manager.
+ */
+var replaceAnnotationManager = function(manager, html)
+{
+ var newManager = $(html);
+ manager.html(newManager.html())
+ .attr('data-date', newManager.attr('data-date'))
+ .attr('data-period', newManager.attr('data-period'));
+ createDatePickers(manager);
+};
+
+/**
+ * Returns true if an annotation element is starred, false if otherwise.
+ *
+ * @param {Element} annotation The annotation element.
+ * @return {bool}
+ */
+var isAnnotationStarred = function(annotation)
+{
+ return +$('.annotation-star', annotation).attr('data-starred') == 1 ? true : false;
+};
+
+/**
+ * Replaces the HTML of an annotation element with HTML returned from Piwik, and
+ * makes sure the data attributes are correct.
+ *
+ * @param {Element} annotation The annotation element.
+ * @param {string} html The replacement HTML (or alternatively, the replacement
+ * element/jQuery object).
+ */
+var replaceAnnotationHtml = function ( annotation, html )
+{
+ var newHtml = $(html);
+ annotation.html(newHtml.html()).attr('data-date', newHtml.attr('data-date'));
+ createDatePicker(annotation);
+}
+
+/**
+ * Binds events to an annotation manager element.
+ *
+ * @param {Element} manager The annotation manager.
+ * @param {int} idSite The site ID the manager is showing annotations for.
+ * @param {function} onAnnotationCountChange Callback that is called when there is a change
+ * in the number of annotations and/or starred annotations,
+ * eg, when a user adds a new one or deletes an existing one.
+ */
+var bindAnnotationManagerEvents = function(manager, idSite, onAnnotationCountChange)
+{
+ if (!onAnnotationCountChange)
+ {
+ onAnnotationCountChange = function() {};
+ }
+
+ // show new annotation row if create new annotation link is clicked
+ manager.on('click', '.add-annotation', function(e) {
+ e.preventDefault();
+
+ $('.new-annotation-row', manager).show();
+ $(this).hide();
+
+ return false;
+ });
+
+ // hide new annotation row if cancel button clicked
+ manager.on('click', '.new-annotation-cancel', function() {
+ var newAnnotationRow = $(this).parent().parent();
+ newAnnotationRow.hide();
+
+ $('.add-annotation', newAnnotationRow.closest('.annotation-manager')).show();
+ });
+
+ // save new annotation when new annotation row save is clicked
+ manager.on('click', '.new-annotation-save', function() {
+ var addRow = $(this).parent().parent(),
+ addNoteInput = addRow.find('.new-annotation-edit'),
+ noteDate = addRow.find('.annotation-period-edit>a').text();
+
+ // do nothing if input is empty
+ if (!addNoteInput.val())
+ {
+ return;
+ }
+
+ // disable input & link
+ addNoteInput.attr('disabled', 'disabled');
+
+ // add a new annotation for the site, date & period
+ annotationsApi.addAnnotation(
+ idSite,
+ manager.attr('data-date'),
+ manager.attr('data-period'),
+ noteDate,
+ addNoteInput.val(),
+ function(response) {
+ replaceAnnotationManager(manager, response);
+
+ // increment annotation count for this date
+ onAnnotationCountChange(noteDate, 1, 0);
+ }
+ );
+ });
+
+ // add new annotation when enter key pressed on new annotation input
+ manager.on('keypress', '.new-annotation-edit', function(e) {
+ if (e.which == 13)
+ {
+ $(this).parent().find('.new-annotation-save').click();
+ }
+ });
+
+ // show annotation editor if edit link, annotation text or period text is clicked
+ manager.on('click', '.annotation-enter-edit-mode', function(e) {
+ e.preventDefault();
+
+ var annotationContent = toggleAnnotationMode(this);
+ annotationContent.find('.annotation-edit').focus();
+
+ return false;
+ });
+
+ // hide annotation editor if cancel button is clicked
+ manager.on('click', '.annotation-cancel', function() {
+ toggleAnnotationMode(this);
+ });
+
+ // save annotation if save button clicked
+ manager.on('click', '.annotation-edit-mode .annotation-save', function() {
+ var annotation = $(this).parent().parent().parent(),
+ input = $('.annotation-edit', annotation),
+ dateEditText = $('.annotation-period-edit>a', annotation).text();
+
+ // if annotation value/date has not changed, just show the view mode instead of edit
+ if (input[0].defaultValue == input.val()
+ && dateEditText == annotation.attr('data-date'))
+ {
+ toggleAnnotationMode(this);
+ return;
+ }
+
+ // disable input while ajax is happening
+ input.attr('disabled', 'disabled');
+
+ // save the note w/ the new note text & date
+ annotationsApi.saveAnnotation(
+ idSite,
+ annotation.attr('data-id'),
+ dateEditText,
+ {
+ note: input.val()
+ },
+ function(response) {
+ response = $(response);
+
+ var newDate = response.attr('data-date'),
+ isStarred = isAnnotationStarred(response),
+ originalDate = annotation.attr('data-date');
+
+ replaceAnnotationHtml(annotation, response);
+
+ // if the date has been changed, update the evolution icon counts to reflect the change
+ if (originalDate != newDate)
+ {
+ // reduce count for original date
+ onAnnotationCountChange(originalDate, -1, isStarred ? -1 : 0);
+
+ // increase count for new date
+ onAnnotationCountChange(newDate, 1, isStarred ? 1 : 0);
+ }
+ }
+ );
+ });
+
+ // save annotation if 'enter' pressed on input
+ manager.on('keypress', '.annotation-value input', function(e) {
+ if (e.which == 13)
+ {
+ $(this).parent().find('.annotation-save').click();
+ }
+ });
+
+ // delete annotation if delete link clicked
+ manager.on('click', '.delete-annotation', function(e) {
+ e.preventDefault();
+
+ var annotation = $(this).parent().parent();
+ $(this).attr('disabled', 'disabled');
+
+ // delete annotation by ajax
+ annotationsApi.deleteAnnotation(
+ idSite,
+ annotation.attr('data-id'),
+ manager.attr('data-date'),
+ manager.attr('data-period'),
+ function (response) {
+ manager.html($(response).html());
+
+ // update evolution icons
+ var isStarred = isAnnotationStarred(annotation);
+ onAnnotationCountChange(annotation.attr('data-date'), -1, isStarred ? -1 : 0);
+ }
+ );
+
+ return false;
+ });
+
+ // star/unstar annotation if star clicked
+ manager.on('click', '.annotation-star-changeable', function(e) {
+ var annotation = $(this).parent().parent(),
+ newStarredVal = $(this).attr('data-starred') == 0 ? 1 : 0 // flip existing 'starred' value
+ ;
+
+ // perform ajax request to star annotation
+ annotationsApi.saveAnnotation(
+ idSite,
+ annotation.attr('data-id'),
+ annotation.attr('data-date'),
+ {
+ starred: newStarredVal
+ },
+ function (response) {
+ replaceAnnotationHtml(annotation, response);
+
+ // change starred count for this annotation in evolution graph based on what we're
+ // changing the starred value to
+ onAnnotationCountChange(annotation.attr('data-date'), 0, newStarredVal == 0 ? -1 : 1);
+ }
+ );
+ });
+
+ // when period edit is clicked, show datepicker
+ manager.on('click', '.annotation-period-edit>a', function(e) {
+ e.preventDefault();
+ $('.datepicker', $(this).parent()).toggle();
+ return false;
+ });
+
+ // make sure datepicker popups are closed if someone clicks elsewhere
+ $('body').on('mouseup', function(e) {
+ var container = $('.annotation-period-edit>.datepicker:visible').parent();
+
+ if (!container.has(e.target).length)
+ {
+ container.find('.datepicker').hide();
+ }
+ });
+};
+
+/**
+ * Shows an annotation manager under a report for a specific site & date range.
+ *
+ * @param {Element} domElem The element of the report to show the annotation manger
+ * under.
+ * @param {int} idSite The ID of the site to show the annotations of.
+ * @param {string} date The start date of the period.
+ * @param {string} period The period type.
+ * @param {int} Whether to include the last N periods in the date range or not. Can
+ * be undefined.
+ */
+var showAnnotationViewer = function(domElem, idSite, date, period, lastN, callback)
+{
+ var addToAnnotationCount = function(date, amt, starAmt)
+ {
+ if (date.indexOf(',') != -1)
+ {
+ date = date.split(',')[0];
+ }
+
+ $('.evolution-annotations>span', domElem).each(function() {
+ if ($(this).attr('data-date') == date)
+ {
+ // get counts from attributes (and convert them to ints)
+ var starredCount = +$(this).attr('data-starred'),
+ annotationCount = +$(this).attr('data-count');
+
+ // modify the starred count & make sure the correct image is used
+ var newStarCount = starredCount + starAmt,
+ newImg = 'themes/default/images/' + (newStarCount > 0 ? 'yellow_marker.png' : 'grey_marker.png');
+ $(this).attr('data-starred', newStarCount).find('img').attr('src', newImg);
+
+ // modify the annotation count & hide/show based on new count
+ var newCount = annotationCount + amt;
+ $(this).attr('data-count', newCount).css('opacity', newCount > 0 ? 1 : 0);
+
+ return false;
+ }
+ });
+ };
+
+ var manager = $('.annotation-manager', domElem);
+ if (manager.length)
+ {
+ // if annotations for the requested date + period are already loaded, then just toggle the
+ // visibility of the annotation viewer. otherwise, we reload the annotations.
+ if (manager.attr('data-date') == date
+ && manager.attr('data-period') == period)
+ {
+ // toggle manager view
+ if (manager.is(':hidden'))
+ {
+ manager.slideDown('slow', function () { if (callback) callback(manager) });
+ }
+ else
+ {
+ manager.slideUp('slow', function () { if (callback) callback(manager) });
+ }
+ }
+ else
+ {
+ // show nothing but the loading gif
+ $('.annotations', manager).html('');
+ $('.loadingPiwik', manager).show();
+
+ // reload annotation manager for new date/period
+ annotationsApi.getAnnotationManager(idSite, date, period, lastN, function(response) {
+ replaceAnnotationManager(manager, response);
+
+ createDatePickers(manager);
+
+ // show if hidden
+ if (manager.is(':hidden'))
+ {
+ manager.slideDown('slow', function () { if (callback) callback(manager) });
+ }
+ else
+ {
+ if (callback)
+ {
+ callback(manager);
+ }
+ }
+ });
+ }
+ }
+ else
+ {
+ var loading = $('.loadingPiwikBelow', domElem).css({display: 'block'});
+
+ // the annotations for this report have not been retrieved yet, so do an ajax request
+ // & show the result
+ annotationsApi.getAnnotationManager(idSite, date, period, lastN, function(response) {
+ var manager = $(response).hide();
+
+ // if an error occurred (and response does not contain the annotation manager), do nothing
+ if (!manager.hasClass('annotation-manager'))
+ {
+ return;
+ }
+
+ // create datepickers for each shown annotation
+ createDatePickers(manager);
+
+ bindAnnotationManagerEvents(manager, idSite, addToAnnotationCount);
+
+ loading.css('visibility', 'hidden');
+
+ // add & show annotation manager
+ $('.dataTableFeatures', domElem).append(manager);
+ manager.slideDown('slow', function() {
+ loading.hide().css('visibility', 'visible');
+
+ if (callback) callback(manager)
+ });
+ });
+ }
+};
+
+// make showAnnotationViewer & annotationsApi globally accessible
+piwik.annotations = {
+ showAnnotationViewer: showAnnotationViewer,
+ api: annotationsApi
+};
+
+}(jQuery, piwik));
diff --git a/plugins/Annotations/templates/annotations.tpl b/plugins/Annotations/templates/annotations.tpl
new file mode 100755
index 0000000000..f15750e548
--- /dev/null
+++ b/plugins/Annotations/templates/annotations.tpl
@@ -0,0 +1,30 @@
+<div class="annotations">
+
+{if empty($annotations)}
+
+<div class="empty-annotation-list">{'Annotations_NoAnnotations'|translate}</div>
+
+{/if}
+
+<table>
+{foreach from=$annotations item=annotation}
+{include file="Annotations/templates/annotation.tpl"}
+{/foreach}
+<tr class="new-annotation-row" style="display:none" data-date="{$startDate}">
+ <td class="annotation-meta">
+ <div class="annotation-star">&nbsp;</div>
+ <div class="annotation-period-edit">
+ <a href="#">{$startDate}</a>
+ <div class="datepicker" style="display:none"/>
+ </div>
+ </td>
+ <td class="annotation-value">
+ <input type="text" value="" class="new-annotation-edit" placeholder="{'Annotations_EnterAnnotationText'|translate}"/><br/>
+ <input type="button" class="submit new-annotation-save" value="{'General_Save'|translate}"/>
+ <input type="button" class="submit new-annotation-cancel" value="{'General_Cancel'|translate}"/>
+ </td>
+ <td class="annotation-user-cell"><span class="annotation-user">{$userLogin}</span></td>
+</tr>
+</table>
+
+</div>
diff --git a/plugins/Annotations/templates/evolutionAnnotations.tpl b/plugins/Annotations/templates/evolutionAnnotations.tpl
new file mode 100755
index 0000000000..5248bddbf2
--- /dev/null
+++ b/plugins/Annotations/templates/evolutionAnnotations.tpl
@@ -0,0 +1,12 @@
+<div class="evolution-annotations">
+{foreach from=$annotationCounts item=dateCountPair}
+ {assign var=date value=$dateCountPair[0]}
+ {assign var=counts value=$dateCountPair[1]}
+ <span data-date="{$date}" data-count="{$counts.count}" data-starred="{$counts.starred}"
+ {if $counts.count eq 0}title="{'CoreHome_Annotations_AddAnnotationsFor_js'|translate:$date}"
+ {else}title="{'CoreHome_Annotations_ViewAndAddAnnotations_js'|translate:$date}"
+ {/if}>
+ <img src="themes/default/images/{if $counts.starred > 0}yellow_marker.png{else}grey_marker.png{/if}" width="16" height="16"/>
+ </span>
+{/foreach}
+</div>
diff --git a/plugins/Annotations/templates/styles.css b/plugins/Annotations/templates/styles.css
new file mode 100755
index 0000000000..4831bafcb1
--- /dev/null
+++ b/plugins/Annotations/templates/styles.css
@@ -0,0 +1,194 @@
+.evolution-annotations {
+ position: relative;
+ height: 16px;
+ width: 100%;
+ margin-top: 12px;
+ margin-bottom: -28px;
+ cursor: pointer;
+}
+
+.evolution-annotations > span {
+ position: absolute;
+}
+
+.annotation-manager {
+ text-align: left;
+ margin-top: -18px;
+}
+
+.annotations-header {
+ display: inline-block;
+ width: 128px;
+ text-align: right;
+ font-size: 12px;
+ font-style: italic;
+ margin-bottom: 8px;
+ vertical-align: top;
+ color: #666;
+}
+
+.annotation-controls {
+ display:inline-block;
+ margin-left: 132px;
+}
+
+.annotation-controls>a {
+ font-size: 11px;
+ font-style: italic;
+ color: #666;
+ cursor:pointer;
+ padding:3px 0 6px 0;
+ display:inline-block;
+}
+
+.annotation-controls>a:hover {
+ text-decoration:none;
+}
+
+.annotation-list {
+ margin-left: 8px;
+}
+
+.annotation-list table {
+ width: 100%;
+}
+
+.annotation-list-range {
+ display: inline-block;
+ font-size: 12px;
+ font-style: italic;
+ color: #666;
+ vertical-align: top;
+ margin: 0 0 8px 8px;
+}
+
+.empty-annotation-list,.annotation-list .loadingPiwik {
+ display: block;
+
+ font-style: italic;
+ color: #666;
+ margin: 0 0 12px 140px;
+}
+
+.annotation-meta {
+ width: 128px;
+ text-align: right;
+ vertical-align: top;
+ font-size:14px;
+}
+
+.annotation-user {
+ font-style: italic;
+ font-size: 11px;
+ color:#444;
+}
+
+.annotation-user-cell {
+ vertical-align: top;
+ width: 92px;
+}
+
+.annotation-period {
+ display:inline-block;
+ font-style: italic;
+ margin: 0 8px 8px 8px;
+ vertical-align: top;
+}
+
+.annotation-value {
+ margin: 0 12px 12px 8px;
+ vertical-align: top;
+ position: relative;
+ font-size:14px;
+}
+
+.annotation-enter-edit-mode {
+ cursor: pointer;
+}
+
+.annotation-edit,.new-annotation-edit {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width:98%;
+}
+
+.annotation-star {
+ display: inline-block;
+ margin: 0 8px 8px 0;
+ width: 16px;
+}
+
+.annotation-star-changeable {
+ cursor: pointer;
+}
+
+.delete-annotation {
+ font-size:12px;
+ font-style: italic;
+ color: red;
+ text-decoration: none;
+ display: inline-block;
+}
+
+.delete-annotation:hover {
+ text-decoration: underline;
+}
+
+.annotation-manager .submit {
+ float:none;
+}
+
+.edit-annotation {
+ font-size:10px;
+ color:#666;
+ font-style:italic;
+}
+.edit-annotation:hover {
+ text-decoration:none;
+}
+
+.annotationView {
+ float: right;
+ margin-left: 5px;
+ position: relative;
+ cursor:pointer;
+}
+
+.annotationView > span {
+ font-style: italic;
+ display: inline-block;
+ margin: 4px 4px 0 4px;
+}
+
+.annotation-period-edit {
+ display:inline-block;
+ background:white;
+ color:#444;
+ font-size:12px;
+ border: 1px solid #e4e5e4;
+ padding:5px 5px 6px 3px;
+ border-radius:4px;
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
+}
+.annotation-period-edit:hover {
+ background:#f1f0eb;
+ border-color:#a9a399;
+}
+.annotation-period-edit>a {
+ text-decoration:none;
+ cursor:pointer;
+ display:block;
+}
+.annotation-period-edit>.datepicker {
+ position:absolute;
+ margin-top:6px;
+ margin-left:-5px;
+ z-index:15;
+ background:white;
+ border: 1px solid #e4e5e4;
+ border-radius:4px;
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
+}