102 lines
3.6 KiB
PHP
102 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace Kanboard\Plugin\QualKard;
|
|
|
|
use Kanboard\Core\Plugin\Base;
|
|
use Kanboard\Model\TaskModel;
|
|
|
|
/**
|
|
* QualKard -- flashcard spaced repetition on Kanboard cards.
|
|
*
|
|
* Each card is a flashcard (title = prompt, description = answer). You grade a due card by dragging
|
|
* it into a grade column (Hairy/Hard/Medium/Easy); QualKard turns the grade into a due date via the
|
|
* qualcard average + interval, and the companion RecoReco plugin does all the card movement.
|
|
*
|
|
* Requires RecoReco (the move engine). Grading math is ported from Ruben's C program "qualcard".
|
|
*/
|
|
class Plugin extends Base
|
|
{
|
|
public function initialize()
|
|
{
|
|
$container = $this->container;
|
|
|
|
// Per-board setup/reset/disable on Settings -> Integrations.
|
|
$this->template->hook->attach('template:project:integrations', 'qualKard:project/integration');
|
|
|
|
// New card on a QualKard board -> reset it (unread, armed inert, moved to Drafts).
|
|
$this->hook->on('model:task:creation:aftersave', function ($task_id) use ($container) {
|
|
$helper = new \Kanboard\Plugin\QualKard\Helper\QualKardHelper($container);
|
|
$task = $container['taskFinderModel']->getById($task_id);
|
|
if (! empty($task) && $helper->isEnabled($task['project_id'])) {
|
|
$helper->resetCard($task_id, (int) $task['project_id']);
|
|
}
|
|
});
|
|
|
|
// Card dragged INTO a grade column -> grade it (RecoReco then handles the movement). The
|
|
// plugin on() wrapper drops the event, so we subscribe on the dispatcher to get the TaskEvent.
|
|
$this->dispatcher->addListener(TaskModel::EVENT_MOVE_COLUMN, function ($event) use ($container) {
|
|
$task = $event['task'];
|
|
$helper = new \Kanboard\Plugin\QualKard\Helper\QualKardHelper($container);
|
|
if (! $helper->isEnabled($task['project_id'])) {
|
|
return;
|
|
}
|
|
$dst = (int) $event['dst_column_id'];
|
|
foreach (array('hairy', 'hard', 'medium', 'easy') as $role) {
|
|
if ($dst === $helper->col($task['project_id'], $role)) {
|
|
$helper->grade($task['id'], \Kanboard\Plugin\QualKard\Helper\QualKardHelper::SCORE[$role]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Dropped back into Drafts -> surgically un-study this one card (new badge, no due, inert).
|
|
if ($dst === $helper->col($task['project_id'], 'draft')) {
|
|
$helper->park($task['id']);
|
|
}
|
|
});
|
|
|
|
// Mastery badge under the card title on the board, plus its stylesheet.
|
|
$this->template->hook->attach('template:board:private:task:after-title', 'qualKard:board/badge');
|
|
$this->template->hook->attach('template:board:public:task:after-title', 'qualKard:board/badge');
|
|
$this->hook->on('template:layout:css', array(
|
|
'template' => 'plugins/QualKard/Asset/css/qualkard.css',
|
|
));
|
|
}
|
|
|
|
public function getHelpers()
|
|
{
|
|
return array(
|
|
'Plugin\QualKard\Helper' => array('QualKardHelper'),
|
|
);
|
|
}
|
|
|
|
public function getPluginName()
|
|
{
|
|
return 'QualKard';
|
|
}
|
|
|
|
public function getPluginDescription()
|
|
{
|
|
return t('Flashcard spaced repetition: grade a card by dragging it to a column, and it comes back when due (needs RecoReco).');
|
|
}
|
|
|
|
public function getPluginAuthor()
|
|
{
|
|
return 'Ruben (drbeco)';
|
|
}
|
|
|
|
public function getPluginVersion()
|
|
{
|
|
return '1.1.4';
|
|
}
|
|
|
|
public function getPluginHomepage()
|
|
{
|
|
return 'https://code.beco.cc/beco/QualKard';
|
|
}
|
|
|
|
public function getCompatibleVersion()
|
|
{
|
|
return '>=1.2.0';
|
|
}
|
|
}
|