Add new search attributes: created, modified and updated

This commit is contained in:
Frederic Guillot
2015-07-18 17:22:49 -04:00
parent 7d9f3e7bc4
commit e7ff62f5e3
4 changed files with 167 additions and 69 deletions

View File

@@ -28,6 +28,9 @@ class Lexer
"/^(assignee:)/" => 'T_ASSIGNEE', "/^(assignee:)/" => 'T_ASSIGNEE',
"/^(color:)/" => 'T_COLOR', "/^(color:)/" => 'T_COLOR',
"/^(due:)/" => 'T_DUE', "/^(due:)/" => 'T_DUE',
"/^(updated:)/" => 'T_UPDATED',
"/^(modified:)/" => 'T_UPDATED',
"/^(created:)/" => 'T_CREATED',
"/^(status:)/" => 'T_STATUS', "/^(status:)/" => 'T_STATUS',
"/^(description:)/" => 'T_DESCRIPTION', "/^(description:)/" => 'T_DESCRIPTION',
"/^(category:)/" => 'T_CATEGORY', "/^(category:)/" => 'T_CATEGORY',
@@ -128,6 +131,8 @@ class Lexer
case 'T_STATUS': case 'T_STATUS':
case 'T_DUE': case 'T_DUE':
case 'T_UPDATED':
case 'T_CREATED':
case 'T_DESCRIPTION': case 'T_DESCRIPTION':
case 'T_REFERENCE': case 'T_REFERENCE':
$next = next($tokens); $next = next($tokens);

View File

@@ -50,6 +50,12 @@ class TaskFilter extends Base
case 'T_DUE': case 'T_DUE':
$this->filterByDueDate($value); $this->filterByDueDate($value);
break; break;
case 'T_UPDATED':
$this->filterByModificationDate($value);
break;
case 'T_CREATED':
$this->filterByCreationDate($value);
break;
case 'T_TITLE': case 'T_TITLE':
$this->filterByTitle($value); $this->filterByTitle($value);
break; break;
@@ -576,6 +582,22 @@ class TaskFilter extends Base
return $this; return $this;
} }
/**
* Filter by creation date
*
* @access public
* @param string $date ISO8601 date format
* @return TaskFilter
*/
public function filterByCreationDate($date)
{
if ($date === 'recently') {
return $this->filterRecentlyDate(Task::TABLE.'.date_creation');
}
return $this->filterWithOperator(Task::TABLE.'.date_creation', $date, true);
}
/** /**
* Filter by creation date * Filter by creation date
* *
@@ -596,6 +618,22 @@ class TaskFilter extends Base
return $this; return $this;
} }
/**
* Filter by modification date
*
* @access public
* @param string $date ISO8601 date format
* @return TaskFilter
*/
public function filterByModificationDate($date)
{
if ($date === 'recently') {
return $this->filterRecentlyDate(Task::TABLE.'.date_modification');
}
return $this->filterWithOperator(Task::TABLE.'.date_modification', $date, true);
}
/** /**
* Get all results of the filter * Get all results of the filter
* *
@@ -826,7 +864,6 @@ class TaskFilter extends Base
); );
foreach ($operators as $operator => $method) { foreach ($operators as $operator => $method) {
if (strpos($value, $operator) === 0) { if (strpos($value, $operator) === 0) {
$value = substr($value, strlen($operator)); $value = substr($value, strlen($operator));
$this->query->$method($field, $is_date ? $this->dateParser->getTimestampFromIsoFormat($value) : $value); $this->query->$method($field, $is_date ? $this->dateParser->getTimestampFromIsoFormat($value) : $value);
@@ -834,7 +871,32 @@ class TaskFilter extends Base
} }
} }
$this->query->eq($field, $is_date ? $this->dateParser->getTimestampFromIsoFormat($value) : $value); if ($is_date) {
$timestamp = $this->dateParser->getTimestampFromIsoFormat($value);
$this->query->gte($field, $timestamp);
$this->query->lte($field, $timestamp + 86399);
}
else {
$this->query->eq($field, $value);
}
return $this;
}
/**
* Use the board_highlight_period for the "recently" keyword
*
* @access private
* @param string $field
* @return TaskFilter
*/
private function filterRecentlyDate($field)
{
$duration = $this->config->get('board_highlight_period', 0);
if ($duration > 0) {
$this->query->gte($field, time() - $duration);
}
return $this; return $this;
} }

View File

@@ -31,95 +31,61 @@ Search by assignee
Attribute: **assignee** Attribute: **assignee**
Query with the full name: - Query with the full name: `assignee:"Frederic Guillot"`
- Query with the username: `assignee:fguillot`
- Multiple assignee lookup: `assignee:user1 assignee:"John Doe"`
- Query for unassigned tasks: `assignee:nobody`
- Query for my assigned tasks: `assignee:me`
``` Note: Kanboard will also search in assigned subtasks with the status todo and in progress.
assignee:"Frederic Guillot"
```
Query with the username:
```
assignee:fguillot
```
Multiple assignee lookup:
```
assignee:user1 assignee:"John Doe"
```
Kanboard will search tasks assigned to the "user1" or "John Doe".
Query for unassigned tasks:
```
assignee:nobody
```
Query for my assigned tasks
```
assignee:me
```
Note: Results will also include subtasks assignee with the status todo or in progress.
Search by color Search by color
--------------- ---------------
Attribute: **color** Attribute: **color**
Query to search by color id: - Query to search by color id: `color:blue`
- Query to search by color name: `color:"Deep Orange"`
```
color:blue
```
Query to search by color name:
```
color:"Deep Orange"
```
Search by due date Search by due date
------------------ ------------------
Attribute: **due** Attribute: **due**
Query to search tasks due today: - Search tasks due today: `due:today`
- Search tasks due tomorrow: `due:tomorrow`
``` - Search tasks due yesterday: `due:yesterday`
due:today - Search tasks due with the exact date: `due:2015-06-29`
```
Query to search tasks due tomorrow:
```
due:tomorrow
```
Query to search tasks due yesterday:
```
due:yesterday
```
Query to search tasks due with the exact date:
```
due:2015-06-29
```
The date must use the ISO8601 format: **YYYY-MM-DD**. The date must use the ISO8601 format: **YYYY-MM-DD**.
Operators supported: All string formats supported by the `strtotime()` function are supported, by example `next Thursday`, `-2 days`, `+2 months`, `tomorrow`, etc...
Operators supported with a date:
- Greater than: **due:>2015-06-29** - Greater than: **due:>2015-06-29**
- Lower than: **due:<2015-06-29** - Lower than: **due:<2015-06-29**
- Greater than or equal: **due:>=2015-06-29** - Greater than or equal: **due:>=2015-06-29**
- Lower than or equal: **due:<=2015-06-29** - Lower than or equal: **due:<=2015-06-29**
Search by modification date
---------------------------
Attribute: **modified** or **updated**
The date formats are the same as the due date.
There is also a filter by recently modified tasks: `modified:recently`.
This query will use the same value as the board highlight period configured in settings.
Search by creation date
-----------------------
Attribute: **created**
Works in the same way as the modification date queries.
Search by description Search by description
--------------------- ---------------------

View File

@@ -311,6 +311,71 @@ class LexerTest extends Base
); );
} }
public function testModifiedQuery()
{
$lexer = new Lexer;
$this->assertEquals(
array(array('match' => 'modified:', 'token' => 'T_UPDATED'), array('match' => '2015-05-01', 'token' => 'T_DATE')),
$lexer->tokenize('modified:2015-05-01')
);
$this->assertEquals(
array(array('match' => 'modified:', 'token' => 'T_UPDATED'), array('match' => '<2015-05-01', 'token' => 'T_DATE')),
$lexer->tokenize('modified:<2015-05-01')
);
$this->assertEquals(
array(array('match' => 'modified:', 'token' => 'T_UPDATED'), array('match' => '>2015-05-01', 'token' => 'T_DATE')),
$lexer->tokenize('modified:>2015-05-01')
);
$this->assertEquals(
array(array('match' => 'updated:', 'token' => 'T_UPDATED'), array('match' => '<=2015-05-01', 'token' => 'T_DATE')),
$lexer->tokenize('updated:<=2015-05-01')
);
$this->assertEquals(
array(array('match' => 'updated:', 'token' => 'T_UPDATED'), array('match' => '>=2015-05-01', 'token' => 'T_DATE')),
$lexer->tokenize('updated:>=2015-05-01')
);
$this->assertEquals(
array(array('match' => 'updated:', 'token' => 'T_UPDATED'), array('match' => 'yesterday', 'token' => 'T_DATE')),
$lexer->tokenize('updated:yesterday')
);
$this->assertEquals(
array(array('match' => 'updated:', 'token' => 'T_UPDATED'), array('match' => 'tomorrow', 'token' => 'T_DATE')),
$lexer->tokenize('updated:tomorrow')
);
$this->assertEquals(
array(),
$lexer->tokenize('updated:#2015-05-01')
);
$this->assertEquals(
array(),
$lexer->tokenize('modified:01-05-1024')
);
$this->assertEquals(
array('T_UPDATED' => '2015-05-01'),
$lexer->map($lexer->tokenize('modified:2015-05-01'))
);
$this->assertEquals(
array('T_UPDATED' => '<2015-05-01'),
$lexer->map($lexer->tokenize('modified:<2015-05-01'))
);
$this->assertEquals(
array('T_UPDATED' => 'today'),
$lexer->map($lexer->tokenize('modified:today'))
);
}
public function testMultipleCriterias() public function testMultipleCriterias()
{ {
$lexer = new Lexer; $lexer = new Lexer;