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