Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: elmarbransch/official-plancake
base: c317652d89
...
head fork: elmarbransch/official-plancake
compare: 140952ebf6
  • 5 commits
  • 3 files changed
  • 0 commit comments
  • 1 contributor
191 lib/model/PcTask.php
View
@@ -116,6 +116,186 @@ public function setDescription($v)
return parent::setDescription($v);
}
+ static function PcListGetWeekdayExpressions() {
+ // regexps to match weekday names, starting with sunday
+ static $weekDayExpressions = Array(
+ '(?:Sonntag|So\.)',
+ '(?:Montag|Mo\.)',
+ '(?:Dienstag|Di\.)',
+ '(?:Mittwoch|Mi\.)',
+ '(?:Donnerstag|Do\.)',
+ '(?:Freitag|Fr\.)',
+ '(?:Samstag|Sa\.)'
+ );
+ return $weekDayExpressions;
+ }
+
+
+ static function PcListGetRecurrencyExpressions() {
+ static $recurrencyPatterns;
+
+ if( isset( $recurrencyPatterns ) ) {
+ return $recurrencyPatterns;
+ }
+
+ // build the patterns one time
+
+ // 1. fixed simple patterns
+ $recurrencyPatterns = Array(
+ '(?:jeden|an jedem) Sonntag' => 1,
+ 'immer sonntags' => 1,
+ '(?:jeden|an jedem) Montag' => 2,
+ 'immer montags' => 2,
+ '(?:jeden|an jedem) Dienstag' => 3,
+ 'immer dienstags' => 3,
+ '(?:jeden|an jedem) Mittwoch' => 4,
+ 'immer mittwochs' => 4,
+ '(?:jeden|an jedem) Donnerstag' => 5,
+ 'immer donnerstags' => 5,
+ '(?:jeden|an jedem) Freitag' => 6,
+ 'immer freitags' => 6,
+ '(?:jeden|an jedem) Samstag' => 7,
+ 'immer samstags' => 7,
+
+ 'jeden Tag' => 8,
+ '(?:jeden|an jedem) Tag' => 8,
+ 'täglich' => 8,
+
+ 'an jedem Wochentag' => 9,
+ 'jeden Wochentag' => 9,
+ 'an allen Wochentagen' => 9,
+
+ 'alle (\d+) Tage' => 10,
+ 'an jedem (\d+)\. Tag' => 10,
+ 'jeden (\d+)\. Tag' => 10,
+ 'jeder (\d+)\. Tag' => 10,
+ 'jede Woche' => 11,
+ 'wöchentlich' => 11,
+ 'jede (\d+). Woche' => 12,
+ 'alle (\d+) Wochen' => 12
+ // ... 13-19
+ // from here onwards the default param should be set to 1
+ );
+
+ // now on to the more complex patterns
+
+
+ // make sure the german word "jede(r|s)" (=each) or "alle" (=all) is in the expression to make sure a
+ // recurrence is meant by the expression and not a due date
+ // e.g. "each 1. Sunday of the month", or "first Sunday of each month",
+ // BUT: "first Sunday of the month" is a due date, not a recurrency expression
+
+ // first weekday in a month, iterate weekdays
+
+ $recId = 20;
+ foreach( self::PcListGetWeekdayExpressions() as $wdayExp ) {
+
+
+ $recurrencyPatterns["(?:an jedem|jeden) (?:ersten|1\.) $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["jeder (?:erste|1\.) $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:am )(?:ersten|1\.) $wdayExp (?:jedes|jeden|alle) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) Monat (?:der erste|der 1\.|am ersten) $wdayExp"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) (\d+)\. Monat(?:s|e)? (?:der erste|der 1\.|am ersten) $wdayExp"] = $recId;
+
+ $recId++;
+ }
+
+ // last weekday in a month, iterate weekdays
+
+ $recId = 27;
+ foreach( self::PcListGetWeekdayExpressions() as $wdayExp ) {
+
+ $recurrencyPatterns["(?:an jedem|jeden) letzten $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["jeder letzte $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:am |den )letzten $wdayExp (?:jedes|jeden|alle) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) Monat (?:der letzte|am letzten) $wdayExp"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) (\d+)\. Monat(?:s|e)? (?:der letzte|am letzten) $wdayExp"] = $recId;
+
+ $recId++;
+ }
+
+ // second weekday in a month, iterate weekdays
+
+ $recId = 40;
+ foreach( self::PcListGetWeekdayExpressions() as $wdayExp ) {
+
+ $recurrencyPatterns["(?:an jedem|jeden) (?:zweiten|2\.) $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["jeder (?:zweite|2\.) $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:am )(?:zweiten|2\.) $wdayExp (?:jedes|jeden|alle) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) Monat (?:der zweite|der 2\.|am zweiten) $wdayExp"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) (\d+)\. Monat(?:s|e)? (?:der zweite|der 2\.|am zweiten) $wdayExp"] = $recId;
+
+ $recId++;
+ }
+
+ // third weekday in a month, iterate weekdays
+
+ $recId = 50;
+ foreach( self::PcListGetWeekdayExpressions() as $wdayExp ) {
+
+ $recurrencyPatterns["(?:an jedem|jeden) (?:dritten|3\.) $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["jeder (?:dritte|3\.) $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:am )(?:dritten|3\.) $wdayExp (?:jedes|jeden|alle) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) Monat (?:der dritte|der 3\.|am dritten) $wdayExp"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) (\d+)\. Monat(?:s|e)? (?:der dritte|der 3\.|am dritten) $wdayExp"] = $recId;
+
+ $recId++;
+ }
+
+ // fourth weekday in a month, iterate weekdays
+
+ $recId = 60;
+ foreach( self::PcListGetWeekdayExpressions() as $wdayExp ) {
+
+ $recurrencyPatterns["(?:an jedem|jeden) (?:vierten|4\.) $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["jeder (?:vierte|4\.) $wdayExp (?:jedes|jeden|alle|im|des) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:am )(?:vierten|4\.) $wdayExp (?:jedes|jeden|alle) (\d+)?\.?\s?Monat(?:s|e)?"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) Monat (?:der vierte|der 4\.|am vierten) $wdayExp"] = $recId;
+ $recurrencyPatterns["(?:jeder|jeden|an jedem|in jedem) (\d+)\. Monat(?:s|e)? (?:der vierte|der 4\.|am vierten) $wdayExp"] = $recId;
+
+ $recId++;
+ }
+
+
+ return $recurrencyPatterns;
+ }
+
+
+ private function extractRecurrencyFromTaskDescription( $taskDescription ) {
+
+ $potentialRecurrenceId = 0;
+ $potentialRecurrenceParam = 0;
+
+ // find the most complete match (longest matching string) - if any
+ $longestMatch = '';
+ foreach( self::PcListGetRecurrencyExpressions() as $recPattern => $recurrenceID ) {
+ // make a regexp pattern and encode the non-ASCII characters
+ $recPattern = '°' . utf8_encode( $recPattern ) . '°i';
+ if( preg_match( $recPattern, $taskDescription, $matches ) ) {
+ // only accept pattern, if it captures more text than the one we already saw
+ // in this case we assume, it is more complex and the potential previous match
+ // has been only a subset of the current pattern
+ if( strlen( $matches[0] ) > strlen( $longestMatch ) ) {
+ $longestMatch = $matches[0];
+ $potentialRecurrenceId = $recurrenceID;
+ if( isset($matches[1]) ) {
+ $potentialRecurrenceParam = (int)$matches[1];
+ }
+ else {
+ // no param, but from rule 20 onwards a param is required,
+ // so we assume it will be 1
+ if( $recurrenceID>=20 ) {
+ $potentialRecurrenceParam = 1;
+ }
+ } // end if matches[1]
+ } // end if longest match
+ } // end if preg_match
+ } // end foreach
+
+ return Array( $potentialRecurrenceId, $potentialRecurrenceParam, $longestMatch );
+ }
+
+
/**
* @return PcList
*/
@@ -139,6 +319,15 @@ public function getList()
*/
public function extractInfoFromTaskDescription(&$taskDescription)
{
+
+ list( $potentialRecurrenceId, $potentialRecurrenceParam, $longestMatch ) = $this->extractRecurrencyFromTaskDescription($taskDescription);
+ if( $potentialRecurrenceId>0 ) {
+ // replace the found pattern, so it is being cut off the description and
+ // won't be parsed by any of the other functions further down
+ $taskDescription = str_replace( $longestMatch, '', $taskDescription );
+ }
+
+
preg_match('!@([0-9]+)([\.:]([0-9]+))? ?([ap]m\b)?!i', $taskDescription, $matches);
$potentialDueTime = null;
if (count($matches))
@@ -188,7 +377,7 @@ public function extractInfoFromTaskDescription(&$taskDescription)
}
}
- return array($listId, $contextIds, $potentialDueDates, $potentialDueTime);
+ return array($listId, $contextIds, $potentialDueDates, $potentialDueTime, $potentialRecurrenceId, $potentialRecurrenceParam);
}
/**
14 lib/model/PcTaskPeer.php
View
@@ -188,11 +188,21 @@ public static function createOrEdit($description, $listId=0, $taskId=0, $context
throw new sfException('User '.$loggedInUser->getId().' trying to access the task ' . $task->getId() . ' illegitimately');
}
- list( $listIdFromShortcut, $contextIdsFromShortcut, $potentialDueDateExpressionsFromShortcut, $potentialDueTimeExpressionsFromShortcut) =
- $task->extractInfoFromTaskDescription($description);
+ list(
+ $listIdFromShortcut,
+ $contextIdsFromShortcut,
+ $potentialDueDateExpressionsFromShortcut,
+ $potentialDueTimeExpressionsFromShortcut,
+ $potentialRepetitionIdFromShortcut,
+ $potentialRepetitionParamFromShortcut
+ ) = $task->extractInfoFromTaskDescription($description);
$listId = ($listIdFromShortcut > 0) ? $listIdFromShortcut : $listId;
+ // smart recognized repition/recurrence expressions have precedence
+ $repetitionId = ( $potentialRepetitionIdFromShortcut>0 ) ? $potentialRepetitionIdFromShortcut : $repetitionId;
+ $repetitionParam = ( $potentialRepetitionParamFromShortcut>0 ) ? $potentialRepetitionParamFromShortcut : $repetitionParam;
+
// if we are here all the contexts (if any) are valid
if (count($contextIdsFromShortcut))
{
143 web/app/desktop/js/plancake.ajaxNotificationFunctions.js
View
@@ -20,6 +20,140 @@
var PLANCAKE = PLANCAKE || {};
+
+$.extend($.easing,
+{
+ def: 'easeOutQuad',
+ swing: function (x, t, b, c, d) {
+ //alert($.easing.default);
+ return $.easing[$.easing.def](x, t, b, c, d);
+ },
+ easeInQuad: function (x, t, b, c, d) {
+ return c*(t/=d)*t + b;
+ },
+ easeOutQuad: function (x, t, b, c, d) {
+ return -c *(t/=d)*(t-2) + b;
+ },
+ easeInOutQuad: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return c/2*t*t + b;
+ return -c/2 * ((--t)*(t-2) - 1) + b;
+ },
+ easeInCubic: function (x, t, b, c, d) {
+ return c*(t/=d)*t*t + b;
+ },
+ easeOutCubic: function (x, t, b, c, d) {
+ return c*((t=t/d-1)*t*t + 1) + b;
+ },
+ easeInOutCubic: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return c/2*t*t*t + b;
+ return c/2*((t-=2)*t*t + 2) + b;
+ },
+ easeInQuart: function (x, t, b, c, d) {
+ return c*(t/=d)*t*t*t + b;
+ },
+ easeOutQuart: function (x, t, b, c, d) {
+ return -c * ((t=t/d-1)*t*t*t - 1) + b;
+ },
+ easeInOutQuart: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
+ return -c/2 * ((t-=2)*t*t*t - 2) + b;
+ },
+ easeInQuint: function (x, t, b, c, d) {
+ return c*(t/=d)*t*t*t*t + b;
+ },
+ easeOutQuint: function (x, t, b, c, d) {
+ return c*((t=t/d-1)*t*t*t*t + 1) + b;
+ },
+ easeInOutQuint: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
+ return c/2*((t-=2)*t*t*t*t + 2) + b;
+ },
+ easeInSine: function (x, t, b, c, d) {
+ return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
+ },
+ easeOutSine: function (x, t, b, c, d) {
+ return c * Math.sin(t/d * (Math.PI/2)) + b;
+ },
+ easeInOutSine: function (x, t, b, c, d) {
+ return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
+ },
+ easeInExpo: function (x, t, b, c, d) {
+ return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+ },
+ easeOutExpo: function (x, t, b, c, d) {
+ return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+ },
+ easeInOutExpo: function (x, t, b, c, d) {
+ if (t==0) return b;
+ if (t==d) return b+c;
+ if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+ return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+ },
+ easeInCirc: function (x, t, b, c, d) {
+ return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
+ },
+ easeOutCirc: function (x, t, b, c, d) {
+ return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
+ },
+ easeInOutCirc: function (x, t, b, c, d) {
+ if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
+ return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
+ },
+ easeInElastic: function (x, t, b, c, d) {
+ var s=1.70158;var p=0;var a=c;
+ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+ },
+ easeOutElastic: function (x, t, b, c, d) {
+ var s=1.70158;var p=0;var a=c;
+ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
+ },
+ easeInOutElastic: function (x, t, b, c, d) {
+ var s=1.70158;var p=0;var a=c;
+ if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+ return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
+ },
+ easeInBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ return c*(t/=d)*t*((s+1)*t - s) + b;
+ },
+ easeOutBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+ },
+ easeInOutBack: function (x, t, b, c, d, s) {
+ if (s == undefined) s = 1.70158;
+ if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
+ return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+ },
+ easeInBounce: function (x, t, b, c, d) {
+ return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
+ },
+ easeOutBounce: function (x, t, b, c, d) {
+ if ((t/=d) < (1/2.75)) {
+ return c*(7.5625*t*t) + b;
+ } else if (t < (2/2.75)) {
+ return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
+ } else if (t < (2.5/2.75)) {
+ return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
+ } else {
+ return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
+ }
+ },
+ easeInOutBounce: function (x, t, b, c, d) {
+ if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
+ return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
+ }
+});
+
/**
* Notifies the start of an AJAX operation (for lists).
*
@@ -105,10 +239,15 @@ PLANCAKE.showFeedback = function(message, error)
$('div#feedback').addClass(cssClass)
.css('left', feedbackDivOffset + 'px')
.html(message);
- $('div#feedback').fadeIn(400); // chaining this with the above line was unexpectedly causing problems
+ // $('div#feedback').fadeIn(400); // chaining this with the above line was unexpectedly causing problems
+ $('div#feedback').stop(true,true);
+ $('div#feedback').css( {top:'-' + 3*($('div#feedback').height()) + 'px'} );
+ $('div#feedback').show();
+ $('div#feedback').animate( {top: '0px'}, 250, 'easeInOutSine' ); // chaining this with the above line was unexpectedly causing problems
setTimeout( function() {
- $('div#feedback').fadeOut(fadeOutLength);
+ // $('div#feedback').fadeOut(fadeOutLength);
+ $('div#feedback').animate( {top: '-' + 2*($('div#feedback').height()) + 'px'}, 250, 'easeOutCubic' ); // chaining this with the above line was unexpectedly causing problems
}, fadeOutDelay);
}

No commit comments for this range

Something went wrong with that request. Please try again.