diff options
author | mattab <matthieu.aubry@gmail.com> | 2013-03-28 03:42:39 +0400 |
---|---|---|
committer | mattab <matthieu.aubry@gmail.com> | 2013-03-28 03:42:40 +0400 |
commit | ae4b03163792f0b6e933933e5d37df87dc3fd566 (patch) | |
tree | d1d7510a9728f587d3d63ebd03e4ecf3d904838b /plugins/Annotations | |
parent | 158c2150f5f2e13ece459b8d131244c11b763997 (diff) |
Mass conversion of all files to the newly agreed coding standard: PSR 1/2
Converting Piwik core source files, PHP, JS, TPL, CSS
More info: http://piwik.org/participate/coding-standards/
Diffstat (limited to 'plugins/Annotations')
-rwxr-xr-x | plugins/Annotations/API.php | 691 | ||||
-rwxr-xr-x | plugins/Annotations/AnnotationList.php | 824 | ||||
-rwxr-xr-x | plugins/Annotations/Annotations.php | 96 | ||||
-rwxr-xr-x | plugins/Annotations/Controller.php | 406 | ||||
-rwxr-xr-x | plugins/Annotations/templates/annotation.tpl | 83 | ||||
-rwxr-xr-x | plugins/Annotations/templates/annotationManager.tpl | 36 | ||||
-rwxr-xr-x | plugins/Annotations/templates/annotations.js | 1194 | ||||
-rwxr-xr-x | plugins/Annotations/templates/annotations.tpl | 47 | ||||
-rwxr-xr-x | plugins/Annotations/templates/evolutionAnnotations.tpl | 18 | ||||
-rwxr-xr-x | plugins/Annotations/templates/styles.css | 216 |
10 files changed, 1764 insertions, 1847 deletions
diff --git a/plugins/Annotations/API.php b/plugins/Annotations/API.php index e03f5f5dba..7750c816e3 100755 --- a/plugins/Annotations/API.php +++ b/plugins/Annotations/API.php @@ -12,365 +12,350 @@ /** * @see plugins/Annotations/AnnotationList.php */ -require_once PIWIK_INCLUDE_PATH.'/plugins/Annotations/AnnotationList.php'; +require_once PIWIK_INCLUDE_PATH . '/plugins/Annotations/AnnotationList.php'; /** * API for annotations plugin. Provides methods to create, modify, delete & query * annotations. - * + * * @package Piwik_Annotations */ class Piwik_Annotations_API { - static private $instance = null; - - /** - * Returns this API's singleton instance. - * - * @return Piwik_Annotations_API - */ - static public function getInstance() - { - if (self::$instance == null) - { - self::$instance = new self; - } - return self::$instance; - } - - /** - * Create a new annotation for a site. - * - * @param string $idSite The site ID to add the annotation to. - * @param string $date The date the annotation is attached to. - * @param string $note The text of the annotation. - * @param string $starred Either 0 or 1. Whether the annotation should be starred. - * @return array Returns an array of two elements. The first element (indexed by - * 'annotation') is the new annotation. The second element (indexed - * by 'idNote' is the new note's ID). - */ - public function add( $idSite, $date, $note, $starred = 0 ) - { - $this->checkSingleIdSite($idSite, $extraMessage = "Note: Cannot add one note to multiple sites."); - $this->checkDateIsValid($date); - $this->checkUserCanAddNotesFor($idSite); - - // add, save & return a new annotation - $annotations = new Piwik_Annotations_AnnotationList($idSite); - - $newAnnotation = $annotations->add($idSite, $date, $note, $starred); - $annotations->save($idSite); - - return $newAnnotation; - } - - /** - * Modifies an annotation for a site and returns the modified annotation - * and its ID. - * - * If the current user is not allowed to modify an annotation, an exception - * will be thrown. A user can modify a note if: - * - the user has admin access for the site, OR - * - the user has view access, is not the anonymous user and is the user that - * created the note - * - * @param string $idSite The site ID to add the annotation to. - * @param string $idNote The ID of the note. - * @param string|null $date The date the annotation is attached to. If null, the annotation's - * date is not modified. - * @param string|null $note The text of the annotation. If null, the annotation's text - * is not modified. - * @param string|null $starred Either 0 or 1. Whether the annotation should be starred. - * If null, the annotation is not starred/un-starred. - * @return array Returns an array of two elements. The first element (indexed by - * 'annotation') is the new annotation. The second element (indexed - * by 'idNote' is the new note's ID). - */ - public function save( $idSite, $idNote, $date = null, $note = null, $starred = null ) - { - $this->checkSingleIdSite($idSite, $extraMessage = "Note: Cannot modify more than one note at a time."); - $this->checkDateIsValid($date, $canBeNull = true); - - // get the annotations for the site - $annotations = new Piwik_Annotations_AnnotationList($idSite); - - // check permissions - $this->checkUserCanModifyOrDelete($idSite, $annotations->get($idSite, $idNote)); - - // modify the annotation, and save the whole list - $annotations->update($idSite, $idNote, $date, $note, $starred); - $annotations->save($idSite); - - return $annotations->get($idSite, $idNote); - } - - /** - * Removes an annotation from a site's list of annotations. - * - * If the current user is not allowed to delete the annotation, an exception - * will be thrown. A user can delete a note if: - * - the user has admin access for the site, OR - * - the user has view access, is not the anonymous user and is the user that - * created the note - * - * @param string $idSite The site ID to add the annotation to. - * @param string $idNote The ID of the note to delete. - */ - public function delete( $idSite, $idNote ) - { - $this->checkSingleIdSite($idSite, $extraMessage = "Note: Cannot delete multiple notes."); - - $annotations = new Piwik_Annotations_AnnotationList($idSite); - - // check permissions - $this->checkUserCanModifyOrDelete($idSite, $annotations->get($idSite, $idNote)); - - // remove the note & save the list - $annotations->remove($idSite, $idNote); - $annotations->save($idSite); - } - - /** - * Returns a single note for one site. - * - * @param string $idSite The site ID to add the annotation to. - * @param string $idNote The ID of the note to get. - * @return array The annotation. It will contain the following properties: - * - date: The date the annotation was recorded for. - * - note: The note text. - * - starred: Whether the note is starred or not. - * - user: The user that created the note. - * - canEditOrDelete: Whether the user that called this method can edit or - * delete the annotation returned. - */ - public function get( $idSite, $idNote ) - { - $this->checkSingleIdSite($idSite, $extraMessage = "Note: Specify only one site ID when getting ONE note."); - Piwik::checkUserHasViewAccess($idSite); - - // get single annotation - $annotations = new Piwik_Annotations_AnnotationList($idSite); - return $annotations->get($idSite, $idNote); - } - - /** - * Returns every annotation for a specific site within a specific date range. - * The date range is specified by a date, the period type (day/week/month/year) - * and an optional number of N periods in the past to include. - * - * @param string $idSite The site ID to add the annotation to. Can be one ID or - * a list of site IDs. - * @param string|false $date The date of the period. - * @param string $period The period type. - * @param int|false $lastN Whether to include the last N number of periods in the - * date range or not. - * @return array An array that indexes arrays of annotations by site ID. ie, - * array( - * 5 => array( - * array(...), // annotation #1 - * array(...), // annotation #2 - * ), - * 8 => array(...) - * ) - */ - public function getAll( $idSite, $date = false, $period = 'day', $lastN = false ) - { - Piwik::checkUserHasViewAccess($idSite); - - $annotations = new Piwik_Annotations_AnnotationList($idSite); - - // if date/period are supplied, determine start/end date for search - list($startDate, $endDate) = self::getDateRangeForPeriod($date, $period, $lastN); - - return $annotations->search($startDate, $endDate); - } - - /** - * Returns the count of annotations for a list of periods, including the count of - * starred annotations. - * - * @param string $idSite The site ID to add the annotation to. - * @param string|false $date The date of the period. - * @param string $period The period type. - * @param int|false $lastN Whether to get counts for the last N number of periods or not. - * @return array An array mapping site IDs to arrays holding dates & the count of - * annotations made for those dates. eg, - * array( - * 5 => array( - * array('2012-01-02', array('count' => 4, 'starred' => 2)), - * array('2012-01-03', array('count' => 0, 'starred' => 0)), - * array('2012-01-04', array('count' => 2, 'starred' => 0)), - * ), - * 6 => array( - * array('2012-01-02', array('count' => 1, 'starred' => 0)), - * array('2012-01-03', array('count' => 4, 'starred' => 3)), - * array('2012-01-04', array('count' => 2, 'starred' => 0)), - * ), - * ... - * ) - */ - public function getAnnotationCountForDates( $idSite, $date, $period, $lastN = false, $getAnnotationText = false ) - { - Piwik::checkUserHasViewAccess($idSite); - - // get start & end date for request. lastN is ignored if $period == 'range' - list($startDate, $endDate) = self::getDateRangeForPeriod($date, $period, $lastN); - if ($period == 'range') - { - $period = 'day'; - } - - // create list of dates - $dates = array(); - for (; $startDate->getTimestamp() <= $endDate->getTimestamp(); $startDate = $startDate->addPeriod(1, $period)) - { - $dates[] = $startDate; - } - // we add one for the end of the last period (used in for loop below to bound annotation dates) - $dates[] = $startDate; - - // get annotations for the site - $annotations = new Piwik_Annotations_AnnotationList($idSite); - - // create result w/ 0-counts - $result = array(); - for ($i = 0; $i != count($dates) - 1; ++$i) - { - $date = $dates[$i]; - $nextDate = $dates[$i + 1]; - $strDate = $date->toString(); - - foreach ($annotations->getIdSites() as $idSite) - { - $result[$idSite][$strDate] = $annotations->count($idSite, $date, $nextDate); - - // if only one annotation, return the one annotation's text w/ the counts - if ($getAnnotationText - && $result[$idSite][$strDate]['count'] == 1) - { - $annotationsForSite = $annotations->search( - $date, Piwik_Date::factory($nextDate->getTimestamp() - 1), $idSite); - $annotation = reset($annotationsForSite[$idSite]); - - $result[$idSite][$strDate]['note'] = $annotation['note']; - } - } - } - - // convert associative array into array of pairs (so it can be traversed by index) - $pairResult = array(); - foreach ($result as $idSite => $counts) - { - foreach ($counts as $date => $count) - { - $pairResult[$idSite][] = array($date, $count); - } - } - return $pairResult; - } - - /** - * Throws if the current user is not allowed to modify or delete an annotation. - * - * @param int $idSite The site ID the annotation belongs to. - * @param array $annotation The annotation. - * @throws Exception if the current user is not allowed to modify/delete $annotation. - */ - private function checkUserCanModifyOrDelete( $idSite, $annotation ) - { - if (!$annotation['canEditOrDelete']) - { - throw new Exception(Piwik_Translate('Annotations_YouCannotModifyThisNote')); - } - } - - /** - * Throws if the current user is not allowed to create annotations for a site. - * - * @param int $idSite The site ID. - * @throws Exception if the current user is anonymous or does not have view access - * for site w/ id=$idSite. - */ - private static function checkUserCanAddNotesFor( $idSite ) - { - if (!Piwik_Annotations_AnnotationList::canUserAddNotesFor($idSite)) - { - throw new Exception("The current user is not allowed to add notes for site #$idSite."); - } - } - - /** - * Returns start & end dates for the range described by a period and optional lastN - * argument. - * - * @param string $date|false The start date of the period (or the date range of a range - * period). - * @param string $period The period type ('day', 'week', 'month', 'year' or 'range'). - * @param int|false $lastN Whether to include the last N periods in the range or not. - * Ignored if period == range. - * - * @ignore - */ - public static function getDateRangeForPeriod( $date, $period, $lastN = false ) - { - if ($date === false) - { - return array(false, false); - } - - // if the range is just a normal period (or the period is a range in which case lastN is ignored) - if ($lastN === false - || $period == 'range') - { - if ($period == 'range') - { - $oPeriod = new Piwik_Period_Range('day', $date); - } - else - { - $oPeriod = Piwik_Period::factory($period, Piwik_Date::factory($date)); - } - - $startDate = $oPeriod->getDateStart(); - $endDate = $oPeriod->getDateEnd(); - } - else // if the range includes the last N periods - { - list($date, $lastN) = - Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution::getDateRangeAndLastN($period, $date, $lastN); - list($startDate, $endDate) = explode(',', $date); - - $startDate = Piwik_Date::factory($startDate); - $endDate = Piwik_Date::factory($endDate); - } - return array($startDate, $endDate); - } - - /** - * Utility function, makes sure idSite string has only one site ID and throws if - * otherwise. - */ - private function checkSingleIdSite( $idSite, $extraMessage ) - { - // can only add a note to one site - if (!is_numeric($idSite)) - { - throw new Exception("Invalid idSite: '$idSite'. $extraMessage"); - } - } - - /** - * Utility function, makes sure date string is valid date, and throws if - * otherwise. - */ - private function checkDateIsValid( $date, $canBeNull = false ) - { - if ($date === null - && $canBeNull) - { - return; - } - - Piwik_Date::factory($date); - } + static private $instance = null; + + /** + * Returns this API's singleton instance. + * + * @return Piwik_Annotations_API + */ + static public function getInstance() + { + if (self::$instance == null) { + self::$instance = new self; + } + return self::$instance; + } + + /** + * Create a new annotation for a site. + * + * @param string $idSite The site ID to add the annotation to. + * @param string $date The date the annotation is attached to. + * @param string $note The text of the annotation. + * @param string $starred Either 0 or 1. Whether the annotation should be starred. + * @return array Returns an array of two elements. The first element (indexed by + * 'annotation') is the new annotation. The second element (indexed + * by 'idNote' is the new note's ID). + */ + public function add($idSite, $date, $note, $starred = 0) + { + $this->checkSingleIdSite($idSite, $extraMessage = "Note: Cannot add one note to multiple sites."); + $this->checkDateIsValid($date); + $this->checkUserCanAddNotesFor($idSite); + + // add, save & return a new annotation + $annotations = new Piwik_Annotations_AnnotationList($idSite); + + $newAnnotation = $annotations->add($idSite, $date, $note, $starred); + $annotations->save($idSite); + + return $newAnnotation; + } + + /** + * Modifies an annotation for a site and returns the modified annotation + * and its ID. + * + * If the current user is not allowed to modify an annotation, an exception + * will be thrown. A user can modify a note if: + * - the user has admin access for the site, OR + * - the user has view access, is not the anonymous user and is the user that + * created the note + * + * @param string $idSite The site ID to add the annotation to. + * @param string $idNote The ID of the note. + * @param string|null $date The date the annotation is attached to. If null, the annotation's + * date is not modified. + * @param string|null $note The text of the annotation. If null, the annotation's text + * is not modified. + * @param string|null $starred Either 0 or 1. Whether the annotation should be starred. + * If null, the annotation is not starred/un-starred. + * @return array Returns an array of two elements. The first element (indexed by + * 'annotation') is the new annotation. The second element (indexed + * by 'idNote' is the new note's ID). + */ + public function save($idSite, $idNote, $date = null, $note = null, $starred = null) + { + $this->checkSingleIdSite($idSite, $extraMessage = "Note: Cannot modify more than one note at a time."); + $this->checkDateIsValid($date, $canBeNull = true); + + // get the annotations for the site + $annotations = new Piwik_Annotations_AnnotationList($idSite); + + // check permissions + $this->checkUserCanModifyOrDelete($idSite, $annotations->get($idSite, $idNote)); + + // modify the annotation, and save the whole list + $annotations->update($idSite, $idNote, $date, $note, $starred); + $annotations->save($idSite); + + return $annotations->get($idSite, $idNote); + } + + /** + * Removes an annotation from a site's list of annotations. + * + * If the current user is not allowed to delete the annotation, an exception + * will be thrown. A user can delete a note if: + * - the user has admin access for the site, OR + * - the user has view access, is not the anonymous user and is the user that + * created the note + * + * @param string $idSite The site ID to add the annotation to. + * @param string $idNote The ID of the note to delete. + */ + public function delete($idSite, $idNote) + { + $this->checkSingleIdSite($idSite, $extraMessage = "Note: Cannot delete multiple notes."); + + $annotations = new Piwik_Annotations_AnnotationList($idSite); + + // check permissions + $this->checkUserCanModifyOrDelete($idSite, $annotations->get($idSite, $idNote)); + + // remove the note & save the list + $annotations->remove($idSite, $idNote); + $annotations->save($idSite); + } + + /** + * Returns a single note for one site. + * + * @param string $idSite The site ID to add the annotation to. + * @param string $idNote The ID of the note to get. + * @return array The annotation. It will contain the following properties: + * - date: The date the annotation was recorded for. + * - note: The note text. + * - starred: Whether the note is starred or not. + * - user: The user that created the note. + * - canEditOrDelete: Whether the user that called this method can edit or + * delete the annotation returned. + */ + public function get($idSite, $idNote) + { + $this->checkSingleIdSite($idSite, $extraMessage = "Note: Specify only one site ID when getting ONE note."); + Piwik::checkUserHasViewAccess($idSite); + + // get single annotation + $annotations = new Piwik_Annotations_AnnotationList($idSite); + return $annotations->get($idSite, $idNote); + } + + /** + * Returns every annotation for a specific site within a specific date range. + * The date range is specified by a date, the period type (day/week/month/year) + * and an optional number of N periods in the past to include. + * + * @param string $idSite The site ID to add the annotation to. Can be one ID or + * a list of site IDs. + * @param string|false $date The date of the period. + * @param string $period The period type. + * @param int|false $lastN Whether to include the last N number of periods in the + * date range or not. + * @return array An array that indexes arrays of annotations by site ID. ie, + * array( + * 5 => array( + * array(...), // annotation #1 + * array(...), // annotation #2 + * ), + * 8 => array(...) + * ) + */ + public function getAll($idSite, $date = false, $period = 'day', $lastN = false) + { + Piwik::checkUserHasViewAccess($idSite); + + $annotations = new Piwik_Annotations_AnnotationList($idSite); + + // if date/period are supplied, determine start/end date for search + list($startDate, $endDate) = self::getDateRangeForPeriod($date, $period, $lastN); + + return $annotations->search($startDate, $endDate); + } + + /** + * Returns the count of annotations for a list of periods, including the count of + * starred annotations. + * + * @param string $idSite The site ID to add the annotation to. + * @param string|false $date The date of the period. + * @param string $period The period type. + * @param int|false $lastN Whether to get counts for the last N number of periods or not. + * @return array An array mapping site IDs to arrays holding dates & the count of + * annotations made for those dates. eg, + * array( + * 5 => array( + * array('2012-01-02', array('count' => 4, 'starred' => 2)), + * array('2012-01-03', array('count' => 0, 'starred' => 0)), + * array('2012-01-04', array('count' => 2, 'starred' => 0)), + * ), + * 6 => array( + * array('2012-01-02', array('count' => 1, 'starred' => 0)), + * array('2012-01-03', array('count' => 4, 'starred' => 3)), + * array('2012-01-04', array('count' => 2, 'starred' => 0)), + * ), + * ... + * ) + */ + public function getAnnotationCountForDates($idSite, $date, $period, $lastN = false, $getAnnotationText = false) + { + Piwik::checkUserHasViewAccess($idSite); + + // get start & end date for request. lastN is ignored if $period == 'range' + list($startDate, $endDate) = self::getDateRangeForPeriod($date, $period, $lastN); + if ($period == 'range') { + $period = 'day'; + } + + // create list of dates + $dates = array(); + for (; $startDate->getTimestamp() <= $endDate->getTimestamp(); $startDate = $startDate->addPeriod(1, $period)) { + $dates[] = $startDate; + } + // we add one for the end of the last period (used in for loop below to bound annotation dates) + $dates[] = $startDate; + + // get annotations for the site + $annotations = new Piwik_Annotations_AnnotationList($idSite); + + // create result w/ 0-counts + $result = array(); + for ($i = 0; $i != count($dates) - 1; ++$i) { + $date = $dates[$i]; + $nextDate = $dates[$i + 1]; + $strDate = $date->toString(); + + foreach ($annotations->getIdSites() as $idSite) { + $result[$idSite][$strDate] = $annotations->count($idSite, $date, $nextDate); + + // if only one annotation, return the one annotation's text w/ the counts + if ($getAnnotationText + && $result[$idSite][$strDate]['count'] == 1 + ) { + $annotationsForSite = $annotations->search( + $date, Piwik_Date::factory($nextDate->getTimestamp() - 1), $idSite); + $annotation = reset($annotationsForSite[$idSite]); + + $result[$idSite][$strDate]['note'] = $annotation['note']; + } + } + } + + // convert associative array into array of pairs (so it can be traversed by index) + $pairResult = array(); + foreach ($result as $idSite => $counts) { + foreach ($counts as $date => $count) { + $pairResult[$idSite][] = array($date, $count); + } + } + return $pairResult; + } + + /** + * Throws if the current user is not allowed to modify or delete an annotation. + * + * @param int $idSite The site ID the annotation belongs to. + * @param array $annotation The annotation. + * @throws Exception if the current user is not allowed to modify/delete $annotation. + */ + private function checkUserCanModifyOrDelete($idSite, $annotation) + { + if (!$annotation['canEditOrDelete']) { + throw new Exception(Piwik_Translate('Annotations_YouCannotModifyThisNote')); + } + } + + /** + * Throws if the current user is not allowed to create annotations for a site. + * + * @param int $idSite The site ID. + * @throws Exception if the current user is anonymous or does not have view access + * for site w/ id=$idSite. + */ + private static function checkUserCanAddNotesFor($idSite) + { + if (!Piwik_Annotations_AnnotationList::canUserAddNotesFor($idSite)) { + throw new Exception("The current user is not allowed to add notes for site #$idSite."); + } + } + + /** + * Returns start & end dates for the range described by a period and optional lastN + * argument. + * + * @param string $date|false The start date of the period (or the date range of a range + * period). + * @param string $period The period type ('day', 'week', 'month', 'year' or 'range'). + * @param int|false $lastN Whether to include the last N periods in the range or not. + * Ignored if period == range. + * + * @ignore + */ + public static function getDateRangeForPeriod($date, $period, $lastN = false) + { + if ($date === false) { + return array(false, false); + } + + // if the range is just a normal period (or the period is a range in which case lastN is ignored) + if ($lastN === false + || $period == 'range' + ) { + if ($period == 'range') { + $oPeriod = new Piwik_Period_Range('day', $date); + } else { + $oPeriod = Piwik_Period::factory($period, Piwik_Date::factory($date)); + } + + $startDate = $oPeriod->getDateStart(); + $endDate = $oPeriod->getDateEnd(); + } else // if the range includes the last N periods + { + list($date, $lastN) = + Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution::getDateRangeAndLastN($period, $date, $lastN); + list($startDate, $endDate) = explode(',', $date); + + $startDate = Piwik_Date::factory($startDate); + $endDate = Piwik_Date::factory($endDate); + } + return array($startDate, $endDate); + } + + /** + * Utility function, makes sure idSite string has only one site ID and throws if + * otherwise. + */ + private function checkSingleIdSite($idSite, $extraMessage) + { + // can only add a note to one site + if (!is_numeric($idSite)) { + throw new Exception("Invalid idSite: '$idSite'. $extraMessage"); + } + } + + /** + * Utility function, makes sure date string is valid date, and throws if + * otherwise. + */ + private function checkDateIsValid($date, $canBeNull = false) + { + if ($date === null + && $canBeNull + ) { + return; + } + + Piwik_Date::factory($date); + } } diff --git a/plugins/Annotations/AnnotationList.php b/plugins/Annotations/AnnotationList.php index 47d897f2dc..daed59a554 100755 --- a/plugins/Annotations/AnnotationList.php +++ b/plugins/Annotations/AnnotationList.php @@ -12,440 +12,418 @@ /** * This class can be used to query & modify annotations for multiple sites * at once. - * + * * Example use: * $annotations = new Piwik_Annotations_AnnotationList($idSites = "1,2,5"); * $annotation = $annotations->get($idSite = 1, $idNote = 4); * // do stuff w/ annotation * $annotations->update($idSite = 2, $idNote = 4, $note = "This is the new text."); * $annotations->save($idSite); - * + * * Note: There is a concurrency issue w/ this code. If two users try to save * an annotation for the same site, it's possible one of their changes will * never get made (as it will be overwritten by the other's). - * + * * @package Piwik_Annotations */ class Piwik_Annotations_AnnotationList { - const ANNOTATION_COLLECTION_OPTION_SUFFIX = '_annotations'; - - /** - * List of site IDs this instance holds annotations for. - * - * @var array - */ - private $idSites; - - /** - * Array that associates lists of annotations with site IDs. - * - * @var array - */ - private $annotations; - - /** - * Constructor. Loads annotations from the database. - * - * @param string|int $idSites The list of site IDs to load annotations for. - */ - public function __construct( $idSites ) - { - $this->idSites = Piwik_Site::getIdSitesFromIdSitesString($idSites); - $this->annotations = $this->getAnnotationsForSite(); - } - - /** - * Returns the list of site IDs this list contains annotations for. - * - * @return array - */ - public function getIdSites() - { - return $this->idSites; - } - - /** - * Creates a new annotation for a site. This method does not perist the result. - * To save the new annotation in the database, call $this->save. - * - * @param int $idSite The ID of the site to add an annotation to. - * @param string $date The date the annotation is in reference to. - * @param string $note The text of the new annotation. - * @param int $starred Either 1 or 0. If 1, the new annotation has been starred, - * otherwise it will start out unstarred. - * @return array The added annotation. - * @throws Exception if $idSite is not an ID that was supplied upon construction. - */ - public function add($idSite, $date, $note, $starred = 0) - { - $this->checkIdSiteIsLoaded($idSite); - - $this->annotations[$idSite][] = self::makeAnnotation($date, $note, $starred); - - // get the id of the new annotation - end($this->annotations[$idSite]); - $newNoteId = key($this->annotations[$idSite]); - - return $this->get($idSite, $newNoteId); - } - - /** - * Persists the annotations list for a site, overwriting whatever exists. - * - * @param int $idSite The ID of the site to save annotations for. - * @throws Exception if $idSite is not an ID that was supplied upon construction. - */ - public function save($idSite) - { - $this->checkIdSiteIsLoaded($idSite); - - $optionName = self::getAnnotationCollectionOptionName($idSite); - Piwik_SetOption($optionName, serialize($this->annotations[$idSite])); - } - - /** - * Modifies an annotation in this instance's collection of annotations. - * - * Note: This method does not perist the change in the DB. The save method must - * be called for that. - * - * @param int $idSite The ID of the site whose annotation will be updated. - * @param int $idNote The ID of the note. - * @param string|null $date The new date of the annotation, eg '2012-01-01'. If - * null, no change is made. - * @param string|null $note The new text of the annotation. If null, no change - * is made. - * @param int|null $starred Either 1 or 0, whether the annotation should be - * starred or not. If null, no change is made. - * @throws Exception if $idSite is not an ID that was supplied upon construction. - * @throws Exception if $idNote does not refer to valid note for the site. - */ - public function update( $idSite, $idNote, $date = null, $note = null, $starred = null ) - { - $this->checkIdSiteIsLoaded($idSite); - $this->checkNoteExists($idSite, $idNote); - - $annotation =& $this->annotations[$idSite][$idNote]; - if ($date !== null) - { - $annotation['date'] = $date; - } - if ($note !== null) - { - $annotation['note'] = $note; - } - if ($starred !== null) - { - $annotation['starred'] = $starred; - } - } - - /** - * Removes a note from a site's collection of annotations. - * - * Note: This method does not perist the change in the DB. The save method must - * be called for that. - * - * @param int $idSite The ID of the site whose annotation will be updated. - * @param int $idNote The ID of the note. - * @throws Exception if $idSite is not an ID that was supplied upon construction. - * @throws Exception if $idNote does not refer to valid note for the site. - */ - public function remove( $idSite, $idNote ) - { - $this->checkIdSiteIsLoaded($idSite); - $this->checkNoteExists($idSite, $idNote); - - unset($this->annotations[$idSite][$idNote]); - } - - /** - * Retrieves an annotation by ID. - * - * This function returns an array with the following elements: - * - idNote: The ID of the annotation. - * - date: The date of the annotation. - * - note: The text of the annotation. - * - starred: 1 or 0, whether the annotation is stared; - * - user: (unless current user is anonymous) The user that created the annotation. - * - canEditOrDelete: True if the user can edit/delete the annotation. - * - * @param int $idSite The ID of the site to get an annotation for. - * @param int $idNote The ID of the note to get. - * @param array The annotation. - * @throws Exception if $idSite is not an ID that was supplied upon construction. - * @throws Exception if $idNote does not refer to valid note for the site. - */ - public function get( $idSite, $idNote ) - { - $this->checkIdSiteIsLoaded($idSite); - $this->checkNoteExists($idSite, $idNote); - - $annotation = $this->annotations[$idSite][$idNote]; - $this->augmentAnnotationData($idSite, $idNote, $annotation); - return $annotation; - } - - /** - * Returns all annotations within a specific date range. The result is - * an array that maps site IDs with arrays of annotations within the range. - * - * Note: The date range is inclusive. - * - * @see self::get for info on what attributes stored within annotations. - * - * @param Piwik_Date|false $startDate The start of the date range. - * @param Piwik_Date|false $endDate The end of the date range. - * @param string|int|array|false $idSite IDs of the sites whose annotations to - * search through. - * @return array Array mapping site IDs with arrays of annotations, eg: - * array( - * '5' => array( - * array(...), // annotation - * array(...), // annotation - * ... - * ), - * '6' => array( - * array(...), // annotation - * array(...), // annotation - * ... - * ), - * ) - */ - public function search( $startDate, $endDate, $idSite = false ) - { - if ($idSite) - { - $idSites = Piwik_Site::getIdSitesFromIdSitesString($idSite); - } - else - { - $idSites = array_keys($this->annotations); - } - - // collect annotations that are within the right date range & belong to the right - // site - $result = array(); - foreach ($idSites as $idSite) - { - if (!isset($this->annotations[$idSite])) - { - continue; - } - - foreach ($this->annotations[$idSite] as $idNote => $annotation) - { - if ($startDate !== false) - { - $annotationDate = Piwik_Date::factory($annotation['date']); - if ($annotationDate->getTimestamp() < $startDate->getTimestamp() - || $annotationDate->getTimestamp() > $endDate->getTimestamp()) - { - continue; - } - } - - $this->augmentAnnotationData($idSite, $idNote, $annotation); - $result[$idSite][] = $annotation; - } - - // sort by annotation date - if (!empty($result[$idSite])) - { - uasort($result[$idSite], array($this, 'compareAnnotationDate')); - } - } - return $result; - } - - /** - * Counts annotations & starred annotations within a date range and returns - * the counts. The date range includes the start date, but not the end date. - * - * @param int $idSite The ID of the site to count annotations for. - * @param string|false $startDate The start date of the range or false if no - * range check is desired. - * @param string|false $endDate The end date of the range or false if no - * range check is desired. - * @return array eg, array('count' => 5, 'starred' => 2) - */ - public function count( $idSite, $startDate, $endDate ) - { - $this->checkIdSiteIsLoaded($idSite); - - // search includes end date, and count should not, so subtract one from the timestamp - $annotations = $this->search($startDate, Piwik_Date::factory($endDate->getTimestamp() - 1)); - - // count the annotations - $count = $starred = 0; - if (!empty($annotations[$idSite])) - { - $count = count($annotations[$idSite]); - foreach ($annotations[$idSite] as $annotation) - { - if ($annotation['starred']) - { - ++$starred; - } - } - } - - return array('count' => $count, 'starred' => $starred); - } - - /** - * Utility function. Creates a new annotation. - * - * @param string $date - * @param string $note - * @param int $starred - */ - private function makeAnnotation( $date, $note, $starred = 0 ) - { - return array('date' => $date, - 'note' => $note, - 'starred' => (int)$starred, - 'user' => Piwik::getCurrentUserLogin()); - } - - /** - * Retrieves annotations from the database for the sites supplied to the - * constructor. - * - * @return array Lists of annotations mapped by site ID. - */ - private function getAnnotationsForSite() - { - $result = array(); - foreach ($this->idSites as $id) - { - $optionName = self::getAnnotationCollectionOptionName($id); - $serialized = Piwik_GetOption($optionName); - - if ($serialized !== false) - { - $result[$id] = unserialize($serialized); - } - else - { - $result[$id] = array(); - } - } - return $result; - } - - /** - * Utility function that checks if a site ID was supplied and if not, - * throws an exception. - * - * We can only modify/read annotations for sites that we've actually - * loaded the annotations for. - * - * @param int $idSite - * @throws Exception - */ - private function checkIdSiteIsLoaded( $idSite ) - { - if (!in_array($idSite, $this->idSites)) - { - throw new Exception("This AnnotationList was not initialized with idSite '$idSite'."); - } - } - - /** - * Utility function that checks if a note exists for a site, and if not, - * throws an exception. - * - * @param int $idSite - * @param int $idNote - * @throws Exception - */ - private function checkNoteExists( $idSite, $idNote ) - { - if (empty($this->annotations[$idSite][$idNote])) - { - throw new Exception("There is no note with id '$idNote' for site with id '$idSite'."); - } - } - - /** - * Returns true if the current user can modify or delete a specific annotation. - * - * A user can modify/delete a note if the user has admin access for the site OR - * the user has view access, is not the anonymous user and is the user that - * created the note in question. - * - * @param int $idSite The site ID the annotation belongs to. - * @param array $annotation The annotation. - * @return bool - */ - public static function canUserModifyOrDelete( $idSite, $annotation ) - { - // user can save if user is admin or if has view access, is not anonymous & is user who wrote note - $canEdit = Piwik::isUserHasAdminAccess($idSite) - || (!Piwik::isUserIsAnonymous() - && Piwik::getCurrentUserLogin() == $annotation['user']); - return $canEdit; - } - - /** - * Adds extra data to an annotation, including the annotation's ID and whether - * the current user can edit or delete it. - * - * Also, if the current user is anonymous, the user attribute is removed. - * - * @param int $idSite - * @param int $idNote - * @param array $annotation - */ - private function augmentAnnotationData( $idSite, $idNote, &$annotation ) - { - $annotation['idNote'] = $idNote; - $annotation['canEditOrDelete'] = self::canUserModifyOrDelete($idSite, $annotation); - - // we don't supply user info if the current user is anonymous - if (Piwik::isUserIsAnonymous()) - { - unset($annotation['user']); - } - } - - /** - * Utility function that compares two annotations. - * - * @param array $lhs An annotation. - * @param array $rhs An annotation. - * @return int -1, 0 or 1 - */ - public function compareAnnotationDate( $lhs, $rhs ) - { - if ($lhs['date'] == $rhs['date']) - { - return $lhs['idNote'] <= $rhs['idNote'] ? -1 : 1; - } - - return $lhs['date'] < $rhs['date'] ? -1 : 1; // string comparison works because date format should be YYYY-MM-DD - } - - /** - * Returns true if the current user can add notes for a specific site. - * - * @param int $idSite The site to add notes to. - */ - public static function canUserAddNotesFor( $idSite ) - { - return Piwik::isUserHasViewAccess($idSite) - && !Piwik::isUserIsAnonymous($idSite); - } - - /** - * Returns the option name used to store annotations for a site. - * - * @param int $idSite The site ID. - */ - public static function getAnnotationCollectionOptionName( $idSite ) - { - return $idSite.self::ANNOTATION_COLLECTION_OPTION_SUFFIX; - } + const ANNOTATION_COLLECTION_OPTION_SUFFIX = '_annotations'; + + /** + * List of site IDs this instance holds annotations for. + * + * @var array + */ + private $idSites; + + /** + * Array that associates lists of annotations with site IDs. + * + * @var array + */ + private $annotations; + + /** + * Constructor. Loads annotations from the database. + * + * @param string|int $idSites The list of site IDs to load annotations for. + */ + public function __construct($idSites) + { + $this->idSites = Piwik_Site::getIdSitesFromIdSitesString($idSites); + $this->annotations = $this->getAnnotationsForSite(); + } + + /** + * Returns the list of site IDs this list contains annotations for. + * + * @return array + */ + public function getIdSites() + { + return $this->idSites; + } + + /** + * Creates a new annotation for a site. This method does not perist the result. + * To save the new annotation in the database, call $this->save. + * + * @param int $idSite The ID of the site to add an annotation to. + * @param string $date The date the annotation is in reference to. + * @param string $note The text of the new annotation. + * @param int $starred Either 1 or 0. If 1, the new annotation has been starred, + * otherwise it will start out unstarred. + * @return array The added annotation. + * @throws Exception if $idSite is not an ID that was supplied upon construction. + */ + public function add($idSite, $date, $note, $starred = 0) + { + $this->checkIdSiteIsLoaded($idSite); + + $this->annotations[$idSite][] = self::makeAnnotation($date, $note, $starred); + + // get the id of the new annotation + end($this->annotations[$idSite]); + $newNoteId = key($this->annotations[$idSite]); + + return $this->get($idSite, $newNoteId); + } + + /** + * Persists the annotations list for a site, overwriting whatever exists. + * + * @param int $idSite The ID of the site to save annotations for. + * @throws Exception if $idSite is not an ID that was supplied upon construction. + */ + public function save($idSite) + { + $this->checkIdSiteIsLoaded($idSite); + + $optionName = self::getAnnotationCollectionOptionName($idSite); + Piwik_SetOption($optionName, serialize($this->annotations[$idSite])); + } + + /** + * Modifies an annotation in this instance's collection of annotations. + * + * Note: This method does not perist the change in the DB. The save method must + * be called for that. + * + * @param int $idSite The ID of the site whose annotation will be updated. + * @param int $idNote The ID of the note. + * @param string|null $date The new date of the annotation, eg '2012-01-01'. If + * null, no change is made. + * @param string|null $note The new text of the annotation. If null, no change + * is made. + * @param int|null $starred Either 1 or 0, whether the annotation should be + * starred or not. If null, no change is made. + * @throws Exception if $idSite is not an ID that was supplied upon construction. + * @throws Exception if $idNote does not refer to valid note for the site. + */ + public function update($idSite, $idNote, $date = null, $note = null, $starred = null) + { + $this->checkIdSiteIsLoaded($idSite); + $this->checkNoteExists($idSite, $idNote); + + $annotation =& $this->annotations[$idSite][$idNote]; + if ($date !== null) { + $annotation['date'] = $date; + } + if ($note !== null) { + $annotation['note'] = $note; + } + if ($starred !== null) { + $annotation['starred'] = $starred; + } + } + + /** + * Removes a note from a site's collection of annotations. + * + * Note: This method does not perist the change in the DB. The save method must + * be called for that. + * + * @param int $idSite The ID of the site whose annotation will be updated. + * @param int $idNote The ID of the note. + * @throws Exception if $idSite is not an ID that was supplied upon construction. + * @throws Exception if $idNote does not refer to valid note for the site. + */ + public function remove($idSite, $idNote) + { + $this->checkIdSiteIsLoaded($idSite); + $this->checkNoteExists($idSite, $idNote); + + unset($this->annotations[$idSite][$idNote]); + } + + /** + * Retrieves an annotation by ID. + * + * This function returns an array with the following elements: + * - idNote: The ID of the annotation. + * - date: The date of the annotation. + * - note: The text of the annotation. + * - starred: 1 or 0, whether the annotation is stared; + * - user: (unless current user is anonymous) The user that created the annotation. + * - canEditOrDelete: True if the user can edit/delete the annotation. + * + * @param int $idSite The ID of the site to get an annotation for. + * @param int $idNote The ID of the note to get. + * @param array The annotation. + * @throws Exception if $idSite is not an ID that was supplied upon construction. + * @throws Exception if $idNote does not refer to valid note for the site. + */ + public function get($idSite, $idNote) + { + $this->checkIdSiteIsLoaded($idSite); + $this->checkNoteExists($idSite, $idNote); + + $annotation = $this->annotations[$idSite][$idNote]; + $this->augmentAnnotationData($idSite, $idNote, $annotation); + return $annotation; + } + + /** + * Returns all annotations within a specific date range. The result is + * an array that maps site IDs with arrays of annotations within the range. + * + * Note: The date range is inclusive. + * + * @see self::get for info on what attributes stored within annotations. + * + * @param Piwik_Date|false $startDate The start of the date range. + * @param Piwik_Date|false $endDate The end of the date range. + * @param string|int|array|false $idSite IDs of the sites whose annotations to + * search through. + * @return array Array mapping site IDs with arrays of annotations, eg: + * array( + * '5' => array( + * array(...), // annotation + * array(...), // annotation + * ... + * ), + * '6' => array( + * array(...), // annotation + * array(...), // annotation + * ... + * ), + * ) + */ + public function search($startDate, $endDate, $idSite = false) + { + if ($idSite) { + $idSites = Piwik_Site::getIdSitesFromIdSitesString($idSite); + } else { + $idSites = array_keys($this->annotations); + } + + // collect annotations that are within the right date range & belong to the right + // site + $result = array(); + foreach ($idSites as $idSite) { + if (!isset($this->annotations[$idSite])) { + continue; + } + + foreach ($this->annotations[$idSite] as $idNote => $annotation) { + if ($startDate !== false) { + $annotationDate = Piwik_Date::factory($annotation['date']); + if ($annotationDate->getTimestamp() < $startDate->getTimestamp() + || $annotationDate->getTimestamp() > $endDate->getTimestamp() + ) { + continue; + } + } + + $this->augmentAnnotationData($idSite, $idNote, $annotation); + $result[$idSite][] = $annotation; + } + + // sort by annotation date + if (!empty($result[$idSite])) { + uasort($result[$idSite], array($this, 'compareAnnotationDate')); + } + } + return $result; + } + + /** + * Counts annotations & starred annotations within a date range and returns + * the counts. The date range includes the start date, but not the end date. + * + * @param int $idSite The ID of the site to count annotations for. + * @param string|false $startDate The start date of the range or false if no + * range check is desired. + * @param string|false $endDate The end date of the range or false if no + * range check is desired. + * @return array eg, array('count' => 5, 'starred' => 2) + */ + public function count($idSite, $startDate, $endDate) + { + $this->checkIdSiteIsLoaded($idSite); + + // search includes end date, and count should not, so subtract one from the timestamp + $annotations = $this->search($startDate, Piwik_Date::factory($endDate->getTimestamp() - 1)); + + // count the annotations + $count = $starred = 0; + if (!empty($annotations[$idSite])) { + $count = count($annotations[$idSite]); + foreach ($annotations[$idSite] as $annotation) { + if ($annotation['starred']) { + ++$starred; + } + } + } + + return array('count' => $count, 'starred' => $starred); + } + + /** + * Utility function. Creates a new annotation. + * + * @param string $date + * @param string $note + * @param int $starred + */ + private function makeAnnotation($date, $note, $starred = 0) + { + return array('date' => $date, + 'note' => $note, + 'starred' => (int)$starred, + 'user' => Piwik::getCurrentUserLogin()); + } + + /** + * Retrieves annotations from the database for the sites supplied to the + * constructor. + * + * @return array Lists of annotations mapped by site ID. + */ + private function getAnnotationsForSite() + { + $result = array(); + foreach ($this->idSites as $id) { + $optionName = self::getAnnotationCollectionOptionName($id); + $serialized = Piwik_GetOption($optionName); + + if ($serialized !== false) { + $result[$id] = unserialize($serialized); + } else { + $result[$id] = array(); + } + } + return $result; + } + + /** + * Utility function that checks if a site ID was supplied and if not, + * throws an exception. + * + * We can only modify/read annotations for sites that we've actually + * loaded the annotations for. + * + * @param int $idSite + * @throws Exception + */ + private function checkIdSiteIsLoaded($idSite) + { + if (!in_array($idSite, $this->idSites)) { + throw new Exception("This AnnotationList was not initialized with idSite '$idSite'."); + } + } + + /** + * Utility function that checks if a note exists for a site, and if not, + * throws an exception. + * + * @param int $idSite + * @param int $idNote + * @throws Exception + */ + private function checkNoteExists($idSite, $idNote) + { + if (empty($this->annotations[$idSite][$idNote])) { + throw new Exception("There is no note with id '$idNote' for site with id '$idSite'."); + } + } + + /** + * Returns true if the current user can modify or delete a specific annotation. + * + * A user can modify/delete a note if the user has admin access for the site OR + * the user has view access, is not the anonymous user and is the user that + * created the note in question. + * + * @param int $idSite The site ID the annotation belongs to. + * @param array $annotation The annotation. + * @return bool + */ + public static function canUserModifyOrDelete($idSite, $annotation) + { + // user can save if user is admin or if has view access, is not anonymous & is user who wrote note + $canEdit = Piwik::isUserHasAdminAccess($idSite) + || (!Piwik::isUserIsAnonymous() + && Piwik::getCurrentUserLogin() == $annotation['user']); + return $canEdit; + } + + /** + * Adds extra data to an annotation, including the annotation's ID and whether + * the current user can edit or delete it. + * + * Also, if the current user is anonymous, the user attribute is removed. + * + * @param int $idSite + * @param int $idNote + * @param array $annotation + */ + private function augmentAnnotationData($idSite, $idNote, &$annotation) + { + $annotation['idNote'] = $idNote; + $annotation['canEditOrDelete'] = self::canUserModifyOrDelete($idSite, $annotation); + + // we don't supply user info if the current user is anonymous + if (Piwik::isUserIsAnonymous()) { + unset($annotation['user']); + } + } + + /** + * Utility function that compares two annotations. + * + * @param array $lhs An annotation. + * @param array $rhs An annotation. + * @return int -1, 0 or 1 + */ + public function compareAnnotationDate($lhs, $rhs) + { + if ($lhs['date'] == $rhs['date']) { + return $lhs['idNote'] <= $rhs['idNote'] ? -1 : 1; + } + + return $lhs['date'] < $rhs['date'] ? -1 : 1; // string comparison works because date format should be YYYY-MM-DD + } + + /** + * Returns true if the current user can add notes for a specific site. + * + * @param int $idSite The site to add notes to. + */ + public static function canUserAddNotesFor($idSite) + { + return Piwik::isUserHasViewAccess($idSite) + && !Piwik::isUserIsAnonymous($idSite); + } + + /** + * Returns the option name used to store annotations for a site. + * + * @param int $idSite The site ID. + */ + public static function getAnnotationCollectionOptionName($idSite) + { + return $idSite . self::ANNOTATION_COLLECTION_OPTION_SUFFIX; + } } diff --git a/plugins/Annotations/Annotations.php b/plugins/Annotations/Annotations.php index 1b0503862a..937500053a 100755 --- a/plugins/Annotations/Annotations.php +++ b/plugins/Annotations/Annotations.php @@ -12,58 +12,58 @@ /** * Annotations plugins. Provides the ability to attach text notes to * dates for each sites. Notes can be viewed, modified, deleted or starred. - * + * * @package Piwik_Annotations */ class Piwik_Annotations extends Piwik_Plugin { - /** - * Returns information about this plugin. - * - * @return array - */ - public function getInformation() - { - return array( - 'description' => Piwik_Translate('Annotations_PluginDescription'), - 'author' => 'Piwik', - 'author_homepage' => 'http://piwik.org/', - 'version' => Piwik_Version::VERSION, - ); - } - - /** - * Returns list of event hooks. - * - * @return array - */ - public function getListHooksRegistered() - { - return array( - 'AssetManager.getCssFiles' => 'getCssFiles', - 'AssetManager.getJsFiles' => 'getJsFiles' - ); - } + /** + * Returns information about this plugin. + * + * @return array + */ + public function getInformation() + { + return array( + 'description' => Piwik_Translate('Annotations_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + } + + /** + * Returns list of event hooks. + * + * @return array + */ + public function getListHooksRegistered() + { + return array( + 'AssetManager.getCssFiles' => 'getCssFiles', + 'AssetManager.getJsFiles' => 'getJsFiles' + ); + } - /** - * Adds css files for this plugin to the list in the event notification. - * - * @param Piwik_Event_Notification $notification notification object - */ - function getCssFiles( $notification ) - { - $cssFiles = &$notification->getNotificationObject(); - $cssFiles[] = "plugins/Annotations/templates/styles.css"; - } + /** + * Adds css files for this plugin to the list in the event notification. + * + * @param Piwik_Event_Notification $notification notification object + */ + function getCssFiles($notification) + { + $cssFiles = & $notification->getNotificationObject(); + $cssFiles[] = "plugins/Annotations/templates/styles.css"; + } - /** - * Adds js files for this plugin to the list in the event notification. - * - * @param Piwik_Event_Notification $notification notification object - */ - function getJsFiles( $notification ) - { - $jsFiles = &$notification->getNotificationObject(); - $jsFiles[] = "plugins/Annotations/templates/annotations.js"; - } + /** + * Adds js files for this plugin to the list in the event notification. + * + * @param Piwik_Event_Notification $notification notification object + */ + function getJsFiles($notification) + { + $jsFiles = & $notification->getNotificationObject(); + $jsFiles[] = "plugins/Annotations/templates/annotations.js"; + } } diff --git a/plugins/Annotations/Controller.php b/plugins/Annotations/Controller.php index 0a235a2200..9b9f9e352c 100755 --- a/plugins/Annotations/Controller.php +++ b/plugins/Annotations/Controller.php @@ -11,216 +11,206 @@ /** * Controller for the Annotations plugin. - * + * * @package Piwik_Annotations */ class Piwik_Annotations_Controller extends Piwik_Controller { - /** - * Controller action that returns HTML displaying annotations for a site and - * specific date range. - * - * Query Param Input: - * - idSite: The ID of the site to get annotations for. Only one allowed. - * - date: The date to get annotations for. If lastN is not supplied, this is the start date, - * otherwise the start date in the last period. - * - period: The period type. - * - lastN: If supplied, the last N # of periods will be included w/ the range specified - * by date + period. - * - * Output: - * - HTML displaying annotations for a specific range. - * - * @param bool $fetch True if the annotation manager should be returned as a string, - * false if it should be echo-ed. - * @param string $date Override for 'date' query parameter. - * @param string $period Override for 'period' query parameter. - * @param string $lastN Override for 'lastN' query parameter. - * @return string|void - */ - public function getAnnotationManager( $fetch = false, $date = false, $period = false, $lastN = false ) - { - $idSite = Piwik_Common::getRequestVar('idSite'); - - if ($date === false) - { - $date = Piwik_Common::getRequestVar('date', false); - } - - if ($period === false) - { - $period = Piwik_Common::getRequestVar('period', 'day'); - } - - if ($lastN === false) - { - $lastN = Piwik_Common::getRequestVar('lastN', false); - } - - // create & render the view - $view = Piwik_View::factory('annotationManager'); - - $allAnnotations = Piwik_API_Request::processRequest( - 'Annotations.getAll', array('date' => $date, 'period' => $period, 'lastN' => $lastN)); - $view->annotations = empty($allAnnotations[$idSite]) ? array() : $allAnnotations[$idSite]; - - $view->period = $period; - $view->lastN = $lastN; - - list($startDate, $endDate) = Piwik_Annotations_API::getDateRangeForPeriod($date, $period, $lastN); - $view->startDate = $startDate->toString(); - $view->endDate = $endDate->toString(); - - $dateFormat = Piwik_Translate('CoreHome_ShortDateFormatWithYear'); - $view->startDatePretty = $startDate->getLocalized($dateFormat); - $view->endDatePretty = $endDate->getLocalized($dateFormat); - - $view->canUserAddNotes = Piwik_Annotations_AnnotationList::canUserAddNotesFor($idSite); - - if ($fetch) - { - return $view->render(); - } - else - { - echo $view->render(); - } - } - - /** - * Controller action that modifies an annotation and returns HTML displaying - * the modified annotation. - * - * Query Param Input: - * - idSite: The ID of the site the annotation belongs to. Only one ID is allowed. - * - idNote: The ID of the annotation. - * - date: The new date value for the annotation. (optional) - * - note: The new text for the annotation. (optional) - * - starred: Either 1 or 0. Whether the note should be starred or not. (optional) - * - * Output: - * - HTML displaying modified annotation. - * - * If an optional query param is not supplied, that part of the annotation is - * not modified. - */ - public function saveAnnotation() - { - if ($_SERVER["REQUEST_METHOD"] == "POST") - { - $this->checkTokenInUrl(); - - $view = Piwik_View::factory('annotation'); - - // NOTE: permissions checked in API method - // save the annotation - $view->annotation = Piwik_API_Request::processRequest("Annotations.save"); - - echo $view->render(); - } - } - - /** - * Controller action that adds a new annotation for a site and returns new - * annotation manager HTML for the site and date range. - * - * Query Param Input: - * - idSite: The ID of the site to add an annotation to. - * - date: The date for the new annotation. - * - note: The text of the annotation. - * - starred: Either 1 or 0, whether the annotation should be starred or not. - * Defaults to 0. - * - managerDate: The date for the annotation manager. If a range is given, the start - * date is used for the new annotation. - * - managerPeriod: For rendering the annotation manager. @see self::getAnnotationManager - * for more info. - * - lastN: For rendering the annotation manager. @see self::getAnnotationManager - * for more info. - * Output: - * - @see self::getAnnotationManager - */ - public function addAnnotation() - { - if ($_SERVER["REQUEST_METHOD"] == "POST") - { - $this->checkTokenInUrl(); - - // the date used is for the annotation manager HTML that gets echo'd. we - // use this date for the new annotation, unless it is a date range, in - // which case we use the first date of the range. - $date = Piwik_Common::getRequestVar('date'); - if (strpos($date, ',') !== false) - { - $date = reset(explode(',', $date)); - } - - // add the annotation. NOTE: permissions checked in API method - Piwik_API_Request::processRequest("Annotations.add", array('date' => $date)); - - $managerDate = Piwik_Common::getRequestVar('managerDate', false); - $managerPeriod = Piwik_Common::getRequestVar('managerPeriod', false); - echo $this->getAnnotationManager($fetch = true, $managerDate, $managerPeriod); - } - } - - /** - * Controller action that deletes an annotation and returns new annotation - * manager HTML for the site & date range. - * - * Query Param Input: - * - idSite: The ID of the site this annotation belongs to. - * - idNote: The ID of the annotation to delete. - * - date: For rendering the annotation manager. @see self::getAnnotationManager - * for more info. - * - period: For rendering the annotation manager. @see self::getAnnotationManager - * for more info. - * - lastN: For rendering the annotation manager. @see self::getAnnotationManager - * for more info. - * - * Output: - * - @see self::getAnnotationManager - */ - public function deleteAnnotation() - { - if ($_SERVER["REQUEST_METHOD"] == "POST") - { - $this->checkTokenInUrl(); - - // delete annotation. NOTE: permissions checked in API method - Piwik_API_Request::processRequest("Annotations.delete"); - - echo $this->getAnnotationManager($fetch = true); - } - } - - /** - * Controller action that echo's HTML that displays marker icons for an - * evolution graph's x-axis. The marker icons still need to be positioned - * by the JavaScript. - * - * Query Param Input: - * - idSite: The ID of the site this annotation belongs to. Only one is allowed. - * - date: The date to check for annotations. If lastN is not supplied, this is - * the start of the date range used to check for annotations. If supplied, - * this is the start of the last period in the date range. - * - period: The period type. - * - lastN: If supplied, the last N # of periods are included in the date range - * used to check for annotations. - * - * Output: - * - HTML that displays marker icons for an evolution graph based on the - * number of annotations & starred annotations in the graph's date range. - */ - public function getEvolutionIcons() - { - // get annotation the count - $annotationCounts = Piwik_API_Request::processRequest( - "Annotations.getAnnotationCountForDates", array('getAnnotationText' => 1)); - - // create & render the view - $view = Piwik_View::factory('evolutionAnnotations'); - $view->annotationCounts = reset($annotationCounts); // only one idSite allowed for this action - - echo $view->render(); - } + /** + * Controller action that returns HTML displaying annotations for a site and + * specific date range. + * + * Query Param Input: + * - idSite: The ID of the site to get annotations for. Only one allowed. + * - date: The date to get annotations for. If lastN is not supplied, this is the start date, + * otherwise the start date in the last period. + * - period: The period type. + * - lastN: If supplied, the last N # of periods will be included w/ the range specified + * by date + period. + * + * Output: + * - HTML displaying annotations for a specific range. + * + * @param bool $fetch True if the annotation manager should be returned as a string, + * false if it should be echo-ed. + * @param string $date Override for 'date' query parameter. + * @param string $period Override for 'period' query parameter. + * @param string $lastN Override for 'lastN' query parameter. + * @return string|void + */ + public function getAnnotationManager($fetch = false, $date = false, $period = false, $lastN = false) + { + $idSite = Piwik_Common::getRequestVar('idSite'); + + if ($date === false) { + $date = Piwik_Common::getRequestVar('date', false); + } + + if ($period === false) { + $period = Piwik_Common::getRequestVar('period', 'day'); + } + + if ($lastN === false) { + $lastN = Piwik_Common::getRequestVar('lastN', false); + } + + // create & render the view + $view = Piwik_View::factory('annotationManager'); + + $allAnnotations = Piwik_API_Request::processRequest( + 'Annotations.getAll', array('date' => $date, 'period' => $period, 'lastN' => $lastN)); + $view->annotations = empty($allAnnotations[$idSite]) ? array() : $allAnnotations[$idSite]; + + $view->period = $period; + $view->lastN = $lastN; + + list($startDate, $endDate) = Piwik_Annotations_API::getDateRangeForPeriod($date, $period, $lastN); + $view->startDate = $startDate->toString(); + $view->endDate = $endDate->toString(); + + $dateFormat = Piwik_Translate('CoreHome_ShortDateFormatWithYear'); + $view->startDatePretty = $startDate->getLocalized($dateFormat); + $view->endDatePretty = $endDate->getLocalized($dateFormat); + + $view->canUserAddNotes = Piwik_Annotations_AnnotationList::canUserAddNotesFor($idSite); + + if ($fetch) { + return $view->render(); + } else { + echo $view->render(); + } + } + + /** + * Controller action that modifies an annotation and returns HTML displaying + * the modified annotation. + * + * Query Param Input: + * - idSite: The ID of the site the annotation belongs to. Only one ID is allowed. + * - idNote: The ID of the annotation. + * - date: The new date value for the annotation. (optional) + * - note: The new text for the annotation. (optional) + * - starred: Either 1 or 0. Whether the note should be starred or not. (optional) + * + * Output: + * - HTML displaying modified annotation. + * + * If an optional query param is not supplied, that part of the annotation is + * not modified. + */ + public function saveAnnotation() + { + if ($_SERVER["REQUEST_METHOD"] == "POST") { + $this->checkTokenInUrl(); + + $view = Piwik_View::factory('annotation'); + + // NOTE: permissions checked in API method + // save the annotation + $view->annotation = Piwik_API_Request::processRequest("Annotations.save"); + + echo $view->render(); + } + } + + /** + * Controller action that adds a new annotation for a site and returns new + * annotation manager HTML for the site and date range. + * + * Query Param Input: + * - idSite: The ID of the site to add an annotation to. + * - date: The date for the new annotation. + * - note: The text of the annotation. + * - starred: Either 1 or 0, whether the annotation should be starred or not. + * Defaults to 0. + * - managerDate: The date for the annotation manager. If a range is given, the start + * date is used for the new annotation. + * - managerPeriod: For rendering the annotation manager. @see self::getAnnotationManager + * for more info. + * - lastN: For rendering the annotation manager. @see self::getAnnotationManager + * for more info. + * Output: + * - @see self::getAnnotationManager + */ + public function addAnnotation() + { + if ($_SERVER["REQUEST_METHOD"] == "POST") { + $this->checkTokenInUrl(); + + // the date used is for the annotation manager HTML that gets echo'd. we + // use this date for the new annotation, unless it is a date range, in + // which case we use the first date of the range. + $date = Piwik_Common::getRequestVar('date'); + if (strpos($date, ',') !== false) { + $date = reset(explode(',', $date)); + } + + // add the annotation. NOTE: permissions checked in API method + Piwik_API_Request::processRequest("Annotations.add", array('date' => $date)); + + $managerDate = Piwik_Common::getRequestVar('managerDate', false); + $managerPeriod = Piwik_Common::getRequestVar('managerPeriod', false); + echo $this->getAnnotationManager($fetch = true, $managerDate, $managerPeriod); + } + } + + /** + * Controller action that deletes an annotation and returns new annotation + * manager HTML for the site & date range. + * + * Query Param Input: + * - idSite: The ID of the site this annotation belongs to. + * - idNote: The ID of the annotation to delete. + * - date: For rendering the annotation manager. @see self::getAnnotationManager + * for more info. + * - period: For rendering the annotation manager. @see self::getAnnotationManager + * for more info. + * - lastN: For rendering the annotation manager. @see self::getAnnotationManager + * for more info. + * + * Output: + * - @see self::getAnnotationManager + */ + public function deleteAnnotation() + { + if ($_SERVER["REQUEST_METHOD"] == "POST") { + $this->checkTokenInUrl(); + + // delete annotation. NOTE: permissions checked in API method + Piwik_API_Request::processRequest("Annotations.delete"); + + echo $this->getAnnotationManager($fetch = true); + } + } + + /** + * Controller action that echo's HTML that displays marker icons for an + * evolution graph's x-axis. The marker icons still need to be positioned + * by the JavaScript. + * + * Query Param Input: + * - idSite: The ID of the site this annotation belongs to. Only one is allowed. + * - date: The date to check for annotations. If lastN is not supplied, this is + * the start of the date range used to check for annotations. If supplied, + * this is the start of the last period in the date range. + * - period: The period type. + * - lastN: If supplied, the last N # of periods are included in the date range + * used to check for annotations. + * + * Output: + * - HTML that displays marker icons for an evolution graph based on the + * number of annotations & starred annotations in the graph's date range. + */ + public function getEvolutionIcons() + { + // get annotation the count + $annotationCounts = Piwik_API_Request::processRequest( + "Annotations.getAnnotationCountForDates", array('getAnnotationText' => 1)); + + // create & render the view + $view = Piwik_View::factory('evolutionAnnotations'); + $view->annotationCounts = reset($annotationCounts); // only one idSite allowed for this action + + echo $view->render(); + } } diff --git a/plugins/Annotations/templates/annotation.tpl b/plugins/Annotations/templates/annotation.tpl index e1cd5f6013..cc0d909a3b 100755 --- a/plugins/Annotations/templates/annotation.tpl +++ b/plugins/Annotations/templates/annotation.tpl @@ -1,43 +1,46 @@ <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}">{'General_Delete'|translate}</a> - {/if} - </td> - {/if} + <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}">{'General_Delete'|translate}</a> + {/if} + </td> + {/if} </tr> diff --git a/plugins/Annotations/templates/annotationManager.tpl b/plugins/Annotations/templates/annotationManager.tpl index 852c09bbc4..401c2458c9 100755 --- a/plugins/Annotations/templates/annotationManager.tpl +++ b/plugins/Annotations/templates/annotationManager.tpl @@ -1,27 +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}> + {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="annotations-header"> + <span>{'Annotations_Annotations'|translate}</span> + </div> -<div class="annotation-list-range">{$startDatePretty}{if $startDate neq $endDate} — {$endDatePretty}{/if}</div> + <div class="annotation-list-range">{$startDatePretty}{if $startDate neq $endDate} — {$endDatePretty}{/if}</div> -<div class="annotation-list"> -{include file="Annotations/templates/annotations.tpl"} + <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> + <span class="loadingPiwik" style="display:none"><img src="themes/default/images/loading-blue.gif"/>{'General_Loading_js'|translate}</span> -</div> + </div> -<div class="annotation-controls"> - {if $canUserAddNotes} - <a href="#" class="add-annotation" title="{'Annotations_CreateNewAnnotation'|translate}">{'Annotations_CreateNewAnnotation'|translate}</a> - {elseif $userLogin eq 'anonymous'} - <a href="index.php?module=Login">{'Annotations_LoginToAnnotate'|translate}</a> - {/if} -</div> + <div class="annotation-controls"> + {if $canUserAddNotes} + <a href="#" class="add-annotation" title="{'Annotations_CreateNewAnnotation'|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 index 62f63a59aa..85097ad1d6 100755 --- a/plugins/Annotations/templates/annotations.js +++ b/plugins/Annotations/templates/annotations.js @@ -5,628 +5,586 @@ * @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); - $('.datepicker', annotation).hide(); - }; - - 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'); - $(this).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'); - $(this).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) { - replaceAnnotationManager(manager, response); - - // 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(); - } - }); -}; +(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); + $('.datepicker', annotation).hide(); + }; + + 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'); + $(this).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'); + $(this).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) { + replaceAnnotationManager(manager, response); + + // 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(); + } + }); + }; // used in below function -var loadingAnnotationManager = false; - -/** - * 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; - if(newStarCount > 0) { - var newImg = 'themes/default/images/yellow_marker.png'; - } else { - var newImg = 'themes/default/images/grey_marker.png'; + var loadingAnnotationManager = false; + + /** + * 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; + if (newStarCount > 0) { + var newImg = 'themes/default/images/yellow_marker.png'; + } else { + var newImg = 'themes/default/images/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); + } + } + }); + } } - $(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 - { - // if we are already loading the annotation manager, don't load it again - if (loadingAnnotationManager) - { - return; - } - - loadingAnnotationManager = true; - - 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'); - loadingAnnotationManager = false; - - if (callback) callback(manager) - }); - }); - } -}; - -/** - * Determines the x-coordinates of a set of evolution annotation icons. - * - * @param {Element} annotations The '.evolution-annotations' element. - * @param {Element} graphElem The evolution graph's datatable element. - */ -var placeEvolutionIcons = function (annotations, graphElem) -{ - var canvases = $('.piwik-graph .jqplot-xaxis canvas', graphElem), - noteSize = 16; - - // if no graph available, hide all icons - if (!canvases || canvases.length == 0) { - $('span', annotations).hide(); - return true; - } - - // set position of each individual icon - $('span', annotations).each(function(i) { - var canvas = $(canvases[i]), - canvasCenterX = canvas.position().left + (canvas.width() / 2); - $(this).css({ - left: canvasCenterX - noteSize / 2, - // show if there are annotations for this x-axis tick - opacity: +$(this).attr('data-count') > 0 ? 1 : 0 - }); - }); -}; + else { + // if we are already loading the annotation manager, don't load it again + if (loadingAnnotationManager) { + return; + } + + loadingAnnotationManager = true; + + 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'); + loadingAnnotationManager = false; + + if (callback) callback(manager) + }); + }); + } + }; + + /** + * Determines the x-coordinates of a set of evolution annotation icons. + * + * @param {Element} annotations The '.evolution-annotations' element. + * @param {Element} graphElem The evolution graph's datatable element. + */ + var placeEvolutionIcons = function (annotations, graphElem) { + var canvases = $('.piwik-graph .jqplot-xaxis canvas', graphElem), + noteSize = 16; + + // if no graph available, hide all icons + if (!canvases || canvases.length == 0) { + $('span', annotations).hide(); + return true; + } + + // set position of each individual icon + $('span', annotations).each(function (i) { + var canvas = $(canvases[i]), + canvasCenterX = canvas.position().left + (canvas.width() / 2); + $(this).css({ + left: canvasCenterX - noteSize / 2, + // show if there are annotations for this x-axis tick + opacity: +$(this).attr('data-count') > 0 ? 1 : 0 + }); + }); + }; // make showAnnotationViewer, placeEvolutionIcons & annotationsApi globally accessible -piwik.annotations = { - showAnnotationViewer: showAnnotationViewer, - placeEvolutionIcons: placeEvolutionIcons, - api: annotationsApi -}; + piwik.annotations = { + showAnnotationViewer: showAnnotationViewer, + placeEvolutionIcons: placeEvolutionIcons, + api: annotationsApi + }; }(jQuery, piwik)); diff --git a/plugins/Annotations/templates/annotations.tpl b/plugins/Annotations/templates/annotations.tpl index f15750e548..26c1f708f1 100755 --- a/plugins/Annotations/templates/annotations.tpl +++ b/plugins/Annotations/templates/annotations.tpl @@ -1,30 +1,29 @@ <div class="annotations"> -{if empty($annotations)} + {if empty($annotations)} + <div class="empty-annotation-list">{'Annotations_NoAnnotations'|translate}</div> + {/if} -<div class="empty-annotation-list">{'Annotations_NoAnnotations'|translate}</div> + <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"> </div> + <div class="annotation-period-edit"> + <a href="#">{$startDate}</a> -{/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"> </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 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 index 8da13d35f0..eaf6f9d9d3 100755 --- a/plugins/Annotations/templates/evolutionAnnotations.tpl +++ b/plugins/Annotations/templates/evolutionAnnotations.tpl @@ -1,15 +1,15 @@ <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="{'Annotations_AddAnnotationsFor_js'|translate:$date}" - {elseif $counts.count eq 1}title="{'Annotations_AnnotationOnDate'|translate:$date:$counts.note} + {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="{'Annotations_AddAnnotationsFor_js'|translate:$date}" + {elseif $counts.count eq 1}title="{'Annotations_AnnotationOnDate'|translate:$date:$counts.note} {'Annotations_ClickToEditOrAdd'|translate}" - {else}title="{'Annotations_ViewAndAddAnnotations_js'|translate:$date}" - {/if}> + {else}title="{'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} + {/foreach} </div> diff --git a/plugins/Annotations/templates/styles.css b/plugins/Annotations/templates/styles.css index 4831bafcb1..089a8ef6c3 100755 --- a/plugins/Annotations/templates/styles.css +++ b/plugins/Annotations/templates/styles.css @@ -1,194 +1,198 @@ .evolution-annotations { - position: relative; - height: 16px; - width: 100%; - margin-top: 12px; - margin-bottom: -28px; - cursor: pointer; + position: relative; + height: 16px; + width: 100%; + margin-top: 12px; + margin-bottom: -28px; + cursor: pointer; } .evolution-annotations > span { - position: absolute; + position: absolute; } .annotation-manager { - text-align: left; - margin-top: -18px; + 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; + 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; + 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; + 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; + text-decoration: none; } .annotation-list { - margin-left: 8px; + margin-left: 8px; } .annotation-list table { - width: 100%; + width: 100%; } .annotation-list-range { - display: inline-block; - font-size: 12px; - font-style: italic; - color: #666; - vertical-align: top; - margin: 0 0 8px 8px; + 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; +.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; + width: 128px; + text-align: right; + vertical-align: top; + font-size: 14px; } .annotation-user { - font-style: italic; - font-size: 11px; - color:#444; + font-style: italic; + font-size: 11px; + color: #444; } .annotation-user-cell { - vertical-align: top; - width: 92px; + vertical-align: top; + width: 92px; } .annotation-period { - display:inline-block; - font-style: italic; - margin: 0 8px 8px 8px; - vertical-align: top; + 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; + margin: 0 12px 12px 8px; + vertical-align: top; + position: relative; + font-size: 14px; } .annotation-enter-edit-mode { - cursor: pointer; + cursor: pointer; } -.annotation-edit,.new-annotation-edit { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - width:98%; +.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; + display: inline-block; + margin: 0 8px 8px 0; + width: 16px; } .annotation-star-changeable { - cursor: pointer; + cursor: pointer; } .delete-annotation { - font-size:12px; - font-style: italic; - color: red; - text-decoration: none; - display: inline-block; + font-size: 12px; + font-style: italic; + color: red; + text-decoration: none; + display: inline-block; } .delete-annotation:hover { - text-decoration: underline; + text-decoration: underline; } .annotation-manager .submit { - float:none; + float: none; } .edit-annotation { - font-size:10px; - color:#666; - font-style:italic; + font-size: 10px; + color: #666; + font-style: italic; } + .edit-annotation:hover { - text-decoration:none; + text-decoration: none; } .annotationView { - float: right; + float: right; margin-left: 5px; position: relative; - cursor:pointer; + cursor: pointer; } .annotationView > span { - font-style: italic; - display: inline-block; - margin: 4px 4px 0 4px; + 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; + 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; + background: #f1f0eb; + border-color: #a9a399; } + .annotation-period-edit>a { - text-decoration:none; - cursor:pointer; - display:block; + 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; + 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; } |