First commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.zip
|
||||||
35
.travis.yml
Normal file
35
.travis.yml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
language: php
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
php:
|
||||||
|
- 7.1
|
||||||
|
- 7.0
|
||||||
|
- 5.6
|
||||||
|
- 5.5
|
||||||
|
- 5.4
|
||||||
|
- 5.3
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- PLUGIN=Calendar
|
||||||
|
- KANBOARD_REPO=https://github.com/kanboard/kanboard.git
|
||||||
|
matrix:
|
||||||
|
- DB=sqlite
|
||||||
|
- DB=mysql
|
||||||
|
- DB=postgres
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
|
install:
|
||||||
|
- git clone --depth 1 $KANBOARD_REPO
|
||||||
|
- ln -s $TRAVIS_BUILD_DIR kanboard/plugins/$PLUGIN
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- cd kanboard
|
||||||
|
- phpenv config-add tests/php.ini
|
||||||
|
- composer install
|
||||||
|
- ls -la plugins/
|
||||||
|
|
||||||
|
script:
|
||||||
|
- phpunit -c tests/units.$DB.xml plugins/$PLUGIN/Test/
|
||||||
121
Controller/CalendarController.php
Normal file
121
Controller/CalendarController.php
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\Calendar\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Controller\BaseController;
|
||||||
|
use Kanboard\Filter\TaskAssigneeFilter;
|
||||||
|
use Kanboard\Filter\TaskProjectFilter;
|
||||||
|
use Kanboard\Filter\TaskStatusFilter;
|
||||||
|
use Kanboard\Model\TaskModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calendar Controller
|
||||||
|
*
|
||||||
|
* @package Kanboard\Controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
* @author Timo Litzbarski
|
||||||
|
*/
|
||||||
|
class CalendarController extends BaseController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Show calendar view for a user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$this->response->html($this->helper->layout->app('Calendar:calendar/user', array(
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show calendar view for a project
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function project()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
$this->response->html($this->helper->layout->app('Calendar:calendar/project', array(
|
||||||
|
'project' => $project,
|
||||||
|
'title' => $project['name'],
|
||||||
|
'description' => $this->helper->projectHeader->getDescription($project),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tasks to display on the calendar (project view)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function projectEvents()
|
||||||
|
{
|
||||||
|
$project_id = $this->request->getIntegerParam('project_id');
|
||||||
|
$start = $this->request->getStringParam('start');
|
||||||
|
$end = $this->request->getStringParam('end');
|
||||||
|
$search = $this->userSession->getFilters($project_id);
|
||||||
|
$queryBuilder = $this->taskLexer->build($search)->withFilter(new TaskProjectFilter($project_id));
|
||||||
|
|
||||||
|
$events = $this->helper->calendar->getTaskDateDueEvents(clone($queryBuilder), $start, $end);
|
||||||
|
$events = array_merge($events, $this->helper->calendar->getTaskEvents(clone($queryBuilder), $start, $end));
|
||||||
|
|
||||||
|
$events = $this->hook->merge('controller:calendar:project:events', $events, array(
|
||||||
|
'project_id' => $project_id,
|
||||||
|
'start' => $start,
|
||||||
|
'end' => $end,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->response->json($events);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tasks to display on the calendar (user view)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function userEvents()
|
||||||
|
{
|
||||||
|
$user_id = $this->request->getIntegerParam('user_id');
|
||||||
|
$start = $this->request->getStringParam('start');
|
||||||
|
$end = $this->request->getStringParam('end');
|
||||||
|
$queryBuilder = $this->taskQuery
|
||||||
|
->withFilter(new TaskAssigneeFilter($user_id))
|
||||||
|
->withFilter(new TaskStatusFilter(TaskModel::STATUS_OPEN));
|
||||||
|
|
||||||
|
$events = $this->helper->calendar->getTaskDateDueEvents(clone($queryBuilder), $start, $end);
|
||||||
|
$events = array_merge($events, $this->helper->calendar->getTaskEvents(clone($queryBuilder), $start, $end));
|
||||||
|
|
||||||
|
if ($this->configModel->get('calendar_user_subtasks_time_tracking') == 1) {
|
||||||
|
$events = array_merge($events, $this->helper->calendar->getSubtaskTimeTrackingEvents($user_id, $start, $end));
|
||||||
|
}
|
||||||
|
|
||||||
|
$events = $this->hook->merge('controller:calendar:user:events', $events, array(
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'start' => $start,
|
||||||
|
'end' => $end,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->response->json($events);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update task due date
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
if ($this->request->isAjax() && $this->request->isPost()) {
|
||||||
|
$values = $this->request->getJson();
|
||||||
|
|
||||||
|
$this->taskModificationModel->update(array(
|
||||||
|
'id' => $values['task_id'],
|
||||||
|
'date_due' => substr($values['date_due'], 0, 10),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
Controller/ConfigController.php
Normal file
32
Controller/ConfigController.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\Calendar\Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ConfigController
|
||||||
|
*
|
||||||
|
* @package Kanboard\Plugin\Calendar\Controller
|
||||||
|
*/
|
||||||
|
class ConfigController extends \Kanboard\Controller\ConfigController
|
||||||
|
{
|
||||||
|
public function show()
|
||||||
|
{
|
||||||
|
$this->response->html($this->helper->layout->config('Calendar:config/calendar', array(
|
||||||
|
'title' => t('Settings').' > '.t('Calendar settings'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
$values += array('calendar_user_subtasks_time_tracking' => 0);
|
||||||
|
|
||||||
|
if ($this->configModel->save($values)) {
|
||||||
|
$this->flash->success(t('Settings saved successfully.'));
|
||||||
|
} else {
|
||||||
|
$this->flash->failure(t('Unable to save your settings.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('ConfigController', 'show', array('plugin' => 'Calendar')));
|
||||||
|
}
|
||||||
|
}
|
||||||
45
Formatter/BaseTaskCalendarFormatter.php
Normal file
45
Formatter/BaseTaskCalendarFormatter.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\Calendar\Formatter;
|
||||||
|
|
||||||
|
use Kanboard\Formatter\BaseFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common class to handle calendar events
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
abstract class BaseTaskCalendarFormatter extends BaseFormatter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Column used for event start date
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $startColumn = 'date_started';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column used for event end date
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $endColumn = 'date_completed';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform results to calendar events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $start_column Column name for the start date
|
||||||
|
* @param string $end_column Column name for the end date
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setColumns($start_column, $end_column = '')
|
||||||
|
{
|
||||||
|
$this->startColumn = $start_column;
|
||||||
|
$this->endColumn = $end_column ?: $start_column;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
74
Formatter/TaskCalendarFormatter.php
Normal file
74
Formatter/TaskCalendarFormatter.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\Calendar\Formatter;
|
||||||
|
|
||||||
|
use Kanboard\Core\Filter\FormatterInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calendar event formatter for task filter
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskCalendarFormatter extends BaseTaskCalendarFormatter implements FormatterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Full day event flag
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $fullDay = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When called calendar events will be full day
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return FormatterInterface
|
||||||
|
*/
|
||||||
|
public function setFullDay()
|
||||||
|
{
|
||||||
|
$this->fullDay = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform tasks to calendar events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function format()
|
||||||
|
{
|
||||||
|
$events = array();
|
||||||
|
|
||||||
|
foreach ($this->query->findAll() as $task) {
|
||||||
|
$events[] = array(
|
||||||
|
'timezoneParam' => $this->timezoneModel->getCurrentTimezone(),
|
||||||
|
'id' => $task['id'],
|
||||||
|
'title' => t('#%d', $task['id']).' '.$task['title'],
|
||||||
|
'backgroundColor' => $this->colorModel->getBackgroundColor($task['color_id']),
|
||||||
|
'borderColor' => $this->colorModel->getBorderColor($task['color_id']),
|
||||||
|
'textColor' => 'black',
|
||||||
|
'url' => $this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
|
||||||
|
'start' => date($this->getDateTimeFormat(), $task[$this->startColumn]),
|
||||||
|
'end' => date($this->getDateTimeFormat(), $task[$this->endColumn] ?: time()),
|
||||||
|
'editable' => $this->fullDay,
|
||||||
|
'allday' => $this->fullDay,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get DateTime format for event
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getDateTimeFormat()
|
||||||
|
{
|
||||||
|
return $this->fullDay ? 'Y-m-d' : 'Y-m-d\TH:i:s';
|
||||||
|
}
|
||||||
|
}
|
||||||
127
Helper/CalendarHelper.php
Normal file
127
Helper/CalendarHelper.php
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\Calendar\Helper;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
use Kanboard\Core\Filter\QueryBuilder;
|
||||||
|
use Kanboard\Filter\TaskDueDateRangeFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calendar Helper
|
||||||
|
*
|
||||||
|
* @package helper
|
||||||
|
* @author Frederic Guillot
|
||||||
|
* @property \Kanboard\Plugin\Calendar\Formatter\TaskCalendarFormatter $taskCalendarFormatter
|
||||||
|
*/
|
||||||
|
class CalendarHelper extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Render calendar component
|
||||||
|
*
|
||||||
|
* @param string $checkUrl
|
||||||
|
* @param string $saveUrl
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function render($checkUrl, $saveUrl)
|
||||||
|
{
|
||||||
|
$params = array(
|
||||||
|
'checkUrl' => $checkUrl,
|
||||||
|
'saveUrl' => $saveUrl,
|
||||||
|
);
|
||||||
|
|
||||||
|
return '<div class="js-calendar" data-params=\''.json_encode($params, JSON_HEX_APOS).'\'></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get formatted calendar task due events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param QueryBuilder $queryBuilder
|
||||||
|
* @param string $start
|
||||||
|
* @param string $end
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTaskDateDueEvents(QueryBuilder $queryBuilder, $start, $end)
|
||||||
|
{
|
||||||
|
$formatter = $this->taskCalendarFormatter;
|
||||||
|
$formatter->setFullDay();
|
||||||
|
$formatter->setColumns('date_due');
|
||||||
|
|
||||||
|
return $queryBuilder
|
||||||
|
->withFilter(new TaskDueDateRangeFilter(array($start, $end)))
|
||||||
|
->format($formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get formatted calendar task events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param QueryBuilder $queryBuilder
|
||||||
|
* @param string $start
|
||||||
|
* @param string $end
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTaskEvents(QueryBuilder $queryBuilder, $start, $end)
|
||||||
|
{
|
||||||
|
$startColumn = $this->configModel->get('calendar_project_tasks', 'date_started');
|
||||||
|
|
||||||
|
$queryBuilder->getQuery()->addCondition($this->getCalendarCondition(
|
||||||
|
$this->dateParser->getTimestampFromIsoFormat($start),
|
||||||
|
$this->dateParser->getTimestampFromIsoFormat($end),
|
||||||
|
$startColumn,
|
||||||
|
'date_due'
|
||||||
|
));
|
||||||
|
|
||||||
|
$formatter = $this->taskCalendarFormatter;
|
||||||
|
$formatter->setColumns($startColumn, 'date_due');
|
||||||
|
|
||||||
|
return $queryBuilder->format($formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get formatted calendar subtask time tracking events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $user_id
|
||||||
|
* @param string $start
|
||||||
|
* @param string $end
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSubtaskTimeTrackingEvents($user_id, $start, $end)
|
||||||
|
{
|
||||||
|
return $this->subtaskTimeTrackingCalendarFormatter
|
||||||
|
->withQuery($this->subtaskTimeTrackingModel->getUserQuery($user_id)
|
||||||
|
->addCondition($this->getCalendarCondition(
|
||||||
|
$this->dateParser->getTimestampFromIsoFormat($start),
|
||||||
|
$this->dateParser->getTimestampFromIsoFormat($end),
|
||||||
|
'start',
|
||||||
|
'end'
|
||||||
|
))
|
||||||
|
)
|
||||||
|
->format();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build SQL condition for a given time range
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $start_time Start timestamp
|
||||||
|
* @param string $end_time End timestamp
|
||||||
|
* @param string $start_column Start column name
|
||||||
|
* @param string $end_column End column name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCalendarCondition($start_time, $end_time, $start_column, $end_column)
|
||||||
|
{
|
||||||
|
$start_column = $this->db->escapeIdentifier($start_column);
|
||||||
|
$end_column = $this->db->escapeIdentifier($end_column);
|
||||||
|
|
||||||
|
$conditions = array(
|
||||||
|
"($start_column >= '$start_time' AND $start_column <= '$end_time')",
|
||||||
|
"($start_column <= '$start_time' AND $end_column >= '$start_time')",
|
||||||
|
"($start_column <= '$start_time' AND ($end_column = '0' OR $end_column IS NULL))",
|
||||||
|
);
|
||||||
|
|
||||||
|
return $start_column.' IS NOT NULL AND '.$start_column.' > 0 AND ('.implode(' OR ', $conditions).')';
|
||||||
|
}
|
||||||
|
}
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016 Frédéric Guillot
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
3
Locale/fr_FR/translations.php
Normal file
3
Locale/fr_FR/translations.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return array();
|
||||||
5
Makefile
Normal file
5
Makefile
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
plugin=Calendar
|
||||||
|
|
||||||
|
all:
|
||||||
|
@ echo "Build archive for plugin ${plugin} version=${version}"
|
||||||
|
@ git archive HEAD --prefix=${plugin}/ --format=zip -o ${plugin}-${version}.zip
|
||||||
55
Plugin.php
Normal file
55
Plugin.php
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\Calendar;
|
||||||
|
|
||||||
|
use Kanboard\Core\Plugin\Base;
|
||||||
|
use Kanboard\Core\Translator;
|
||||||
|
use Kanboard\Plugin\Calendar\Formatter\TaskCalendarFormatter;
|
||||||
|
|
||||||
|
class Plugin extends Base
|
||||||
|
{
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
$this->helper->register('calendar', '\Kanboard\Plugin\Calendar\Helper\CalendarHelper');
|
||||||
|
|
||||||
|
$this->container['taskCalendarFormatter'] = $this->container->factory(function ($c) {
|
||||||
|
return new TaskCalendarFormatter($c);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->template->hook->attach('template:dashboard:page-header:menu', 'Calendar:dashboard/menu');
|
||||||
|
$this->template->hook->attach('template:project:dropdown', 'Calendar:project/dropdown');
|
||||||
|
$this->template->hook->attach('template:project-header:view-switcher', 'Calendar:project_header/views');
|
||||||
|
$this->template->hook->attach('template:config:sidebar', 'Calendar:config/sidebar');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onStartup()
|
||||||
|
{
|
||||||
|
Translator::load($this->languageModel->getCurrentLanguage(), __DIR__.'/Locale');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginName()
|
||||||
|
{
|
||||||
|
return 'Calendar';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginDescription()
|
||||||
|
{
|
||||||
|
return t('Calendar view for Kanboard');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginAuthor()
|
||||||
|
{
|
||||||
|
return 'Frédéric Guillot';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginVersion()
|
||||||
|
{
|
||||||
|
return '1.0.0';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginHomepage()
|
||||||
|
{
|
||||||
|
return 'https://github.com/kanboard/plugin-calendar';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
26
README.md
Normal file
26
README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
Calendar Plugin
|
||||||
|
===============
|
||||||
|
|
||||||
|
Embedded calendar view for Kanboard.
|
||||||
|
|
||||||
|
Author
|
||||||
|
------
|
||||||
|
|
||||||
|
- Frédéric Guillot
|
||||||
|
- License MIT
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
- Kanboard >= 1.0.42
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
You have the choice between 3 methods:
|
||||||
|
|
||||||
|
1. Install the plugin from the Kanboard plugin manager in one click
|
||||||
|
2. Download the zip file and decompress everything under the directory `plugins/Calendar`
|
||||||
|
3. Clone this repository into the folder `plugins/Calendar`
|
||||||
|
|
||||||
|
Note: Plugin folder is case-sensitive.
|
||||||
6
Template/calendar/project.php
Normal file
6
Template/calendar/project.php
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?= $this->projectHeader->render($project, 'CalendarController', 'project', false, 'Calendar') ?>
|
||||||
|
|
||||||
|
<?= $this->calendar->render(
|
||||||
|
$this->url->href('CalendarController', 'projectEvents', array('project_id' => $project['id'], 'plugin' => 'Calendar')),
|
||||||
|
$this->url->href('CalendarController', 'save', array('project_id' => $project['id'], 'plugin' => 'Calendar'))
|
||||||
|
) ?>
|
||||||
4
Template/calendar/user.php
Normal file
4
Template/calendar/user.php
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?= $this->calendar->render(
|
||||||
|
$this->url->href('CalendarController', 'userEvents', array('user_id' => $user['id'], 'plugin' => 'Calendar')),
|
||||||
|
$this->url->href('CalendarController', 'save', array('plugin' => 'Calendar'))
|
||||||
|
) ?>
|
||||||
36
Template/config/calendar.php
Normal file
36
Template/config/calendar.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('Calendar settings') ?></h2>
|
||||||
|
</div>
|
||||||
|
<form method="post" action="<?= $this->url->href('ConfigController', 'save', array('plugin' => 'Calendar')) ?>" autocomplete="off">
|
||||||
|
|
||||||
|
<?= $this->form->csrf() ?>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend><?= t('Project calendar view') ?></legend>
|
||||||
|
<?= $this->form->radios('calendar_project_tasks', array(
|
||||||
|
'date_creation' => t('Show tasks based on the creation date'),
|
||||||
|
'date_started' => t('Show tasks based on the start date'),
|
||||||
|
),
|
||||||
|
$values
|
||||||
|
) ?>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend><?= t('User calendar view') ?></legend>
|
||||||
|
<?= $this->form->radios('calendar_user_tasks', array(
|
||||||
|
'date_creation' => t('Show tasks based on the creation date'),
|
||||||
|
'date_started' => t('Show tasks based on the start date'),
|
||||||
|
),
|
||||||
|
$values
|
||||||
|
) ?>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend><?= t('Subtasks time tracking') ?></legend>
|
||||||
|
<?= $this->form->checkbox('calendar_user_subtasks_time_tracking', t('Show subtasks based on the time tracking'), 1, $values['calendar_user_subtasks_time_tracking'] == 1) ?>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
3
Template/config/sidebar.php
Normal file
3
Template/config/sidebar.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<li <?= $this->app->checkMenuSelection('ConfigController', 'show', 'Calendar') ?>>
|
||||||
|
<?= $this->url->link(t('Calendar settings'), 'ConfigController', 'show', array('plugin' => 'Calendar')) ?>
|
||||||
|
</li>
|
||||||
3
Template/dashboard/menu.php
Normal file
3
Template/dashboard/menu.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<li>
|
||||||
|
<?= $this->modal->medium('calendar', t('My calendar'), 'CalendarController', 'user', array('plugin' => 'Calendar')) ?>
|
||||||
|
</li>
|
||||||
3
Template/project/dropdown.php
Normal file
3
Template/project/dropdown.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<li>
|
||||||
|
<?= $this->url->icon('calendar', t('Calendar'), 'CalendarController', 'project', array('project_id' => $project['id'], 'plugin' => 'Calendar')) ?>
|
||||||
|
</li>
|
||||||
3
Template/project_header/views.php
Normal file
3
Template/project_header/views.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<li <?= $this->app->checkMenuSelection('CalendarController') ?>>
|
||||||
|
<?= $this->url->icon('calendar', t('Calendar'), 'CalendarController', 'project', array('project_id' => $project['id'], 'search' => $filters['search'], 'plugin' => 'Calendar'), false, 'view-calendar', t('Keyboard shortcut: "%s"', 'v c')) ?>
|
||||||
|
</li>
|
||||||
20
Test/PluginTest.php
Normal file
20
Test/PluginTest.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'tests/units/Base.php';
|
||||||
|
|
||||||
|
use Kanboard\Plugin\Calendar\Plugin;
|
||||||
|
|
||||||
|
class PluginTest extends Base
|
||||||
|
{
|
||||||
|
public function testPlugin()
|
||||||
|
{
|
||||||
|
$plugin = new Plugin($this->container);
|
||||||
|
$this->assertSame(null, $plugin->initialize());
|
||||||
|
$this->assertSame(null, $plugin->onStartup());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginName());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginDescription());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginAuthor());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginVersion());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginHomepage());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user