178 lines
9.1 KiB
PHP
178 lines
9.1 KiB
PHP
<?php
|
|
|
|
namespace Kanboard\Plugin\OrganonTweaks;
|
|
|
|
use Kanboard\Core\Plugin\Base;
|
|
use Kanboard\Model\TaskModel;
|
|
|
|
class Plugin extends Base
|
|
{
|
|
public function initialize()
|
|
{
|
|
// "Remove this Column" entry in the board column header dropdown. The only
|
|
// column hook renders outside the native menu <ul>, so the item is rendered
|
|
// hidden and relocate.js moves it into the menu (like BulkMoveTasks).
|
|
$this->template->hook->attach('template:board:column:dropdown', 'organonTweaks:board/column_dropdown');
|
|
|
|
$this->hook->on('template:layout:js', array(
|
|
'template' => 'plugins/OrganonTweaks/Asset/js/relocate.js',
|
|
));
|
|
|
|
// Settings page for the plugin's tweaks.
|
|
$this->template->hook->attach('template:config:sidebar', 'organonTweaks:config/sidebar');
|
|
|
|
// Per-board tweak: emphasize the due date on the board. Configured with 3-state radios on the
|
|
// board's Settings -> Integrations (Use default / Always on / Always off); the global default
|
|
// (for "Use default" boards) lives in the plugin settings above. The emphasis <style> is
|
|
// emitted into the head only on enabled board pages (gated by OrganonProjectHelper).
|
|
$this->template->hook->attach('template:project:integrations', 'organonTweaks:project/integration');
|
|
$this->template->hook->attach('template:layout:head', 'organonTweaks:layout/emphasize_duedate');
|
|
|
|
// Tweak: always show a comment icon on board cards. When a card has no comments
|
|
// yet, add a bubble "+" that opens the same comment modal (add the first comment
|
|
// straight from the board). Cards with comments already show the native count.
|
|
if ((int) $this->configModel->get('organon_tweaks_always_comment_icon', 1) === 1) {
|
|
$this->template->hook->attach('template:board:task:icons', 'organonTweaks:board/task_comment_icon');
|
|
}
|
|
|
|
// Tweak: keep the board horizontal scroll position across refreshes (Kanboard
|
|
// rebuilds #board-container on card drop / polling, resetting scrollLeft to 0).
|
|
if ((int) $this->configModel->get('organon_tweaks_keep_scroll', 1) === 1) {
|
|
$this->hook->on('template:layout:js', array(
|
|
'template' => 'plugins/OrganonTweaks/Asset/js/keep-scroll.js',
|
|
));
|
|
}
|
|
|
|
// Tweak: only open a card on a quick click (a press held > 100ms is a drag, so the
|
|
// trailing click is swallowed and the card does not open).
|
|
if ((int) $this->configModel->get('organon_tweaks_quick_click_only', 1) === 1) {
|
|
$this->hook->on('template:layout:js', array(
|
|
'template' => 'plugins/OrganonTweaks/Asset/js/click-guard.js',
|
|
));
|
|
}
|
|
|
|
// Tweak: enhance the native "Edit recurrence" dialog (Yes/No radios + a [+7] button
|
|
// on the factor). No template hook there, so it is done in JS.
|
|
if ((int) $this->configModel->get('organon_tweaks_enhance_recurrence', 1) === 1) {
|
|
$this->hook->on('template:layout:js', array(
|
|
'template' => 'plugins/OrganonTweaks/Asset/js/enhance-recurrence.js',
|
|
));
|
|
}
|
|
|
|
// Tweak: show the keyboard shortcuts Kanboard already binds next to the task Actions menu
|
|
// items (display only -- no new bindings). Done in JS since those menu <li> have no hook.
|
|
if ((int) $this->configModel->get('organon_tweaks_shortcut_labels', 1) === 1) {
|
|
$this->hook->on('template:layout:js', array(
|
|
'template' => 'plugins/OrganonTweaks/Asset/js/shortcut-labels.js',
|
|
));
|
|
}
|
|
|
|
// Tweak: clicking a task title opens the edit modal (instead of the read-only card view).
|
|
// JS reuses Kanboard's own modal opener. On the board the title is a link, so a hidden marker
|
|
// (rendered by the hook below, only when the user may edit) carries the server-generated edit
|
|
// URL for the JS to open; on the card view the JS reads #task-view's data-edit-url.
|
|
if ((int) $this->configModel->get('organon_tweaks_title_click_edit', 1) === 1) {
|
|
$this->hook->on('template:layout:js', array(
|
|
'template' => 'plugins/OrganonTweaks/Asset/js/title-click-edit.js',
|
|
));
|
|
$this->template->hook->attach('template:board:private:task:before-title', 'organonTweaks:board/title_edit');
|
|
}
|
|
|
|
// Tweak: per-column persistent sort. A sort control (number-aware title sort + a
|
|
// "Persistent sort: ON/OFF" toggle) replaces the native column sort. Sorting always reorders
|
|
// physically (writes positions, like native); when persistent is ON, the column is re-sorted
|
|
// whenever a card is dropped in or created, so it stays sorted. Persistent OFF = native
|
|
// one-shot. Control injected via the column dropdown hook + relocate.js (which also hides the
|
|
// native fa-sort menu).
|
|
if ((int) $this->configModel->get('organon_tweaks_persistent_sort', 1) === 1) {
|
|
$this->template->hook->attach('template:board:column:dropdown', 'organonTweaks:board/sort_control');
|
|
|
|
$container = $this->container;
|
|
$reapply = function ($project_id, $swimlane_id, $column_id) use ($container) {
|
|
$helper = new \Kanboard\Plugin\OrganonTweaks\Helper\OrganonSortHelper($container);
|
|
if ($helper->isSticky($project_id, $column_id)) {
|
|
$helper->reapply($project_id, $swimlane_id, $column_id);
|
|
}
|
|
};
|
|
|
|
// Card dropped into a column -> re-apply that column's sort (the plugin on() wrapper drops
|
|
// the event, so subscribe on the dispatcher to receive the TaskEvent).
|
|
$this->dispatcher->addListener(TaskModel::EVENT_MOVE_COLUMN, function ($event) use ($reapply) {
|
|
$task = $event['task'];
|
|
$reapply((int) $task['project_id'], (int) $task['swimlane_id'], (int) $event['dst_column_id']);
|
|
});
|
|
|
|
// New card created in a column -> re-apply that column's sort.
|
|
$this->hook->on('model:task:creation:aftersave', function ($task_id) use ($container, $reapply) {
|
|
$task = $container['taskFinderModel']->getById($task_id);
|
|
if (! empty($task)) {
|
|
$reapply((int) $task['project_id'], (int) $task['swimlane_id'], (int) $task['column_id']);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Auto-managed shared custom filters (v1.5 "Show all tasks", v1.6 month filters, v1.7
|
|
// recurring filters). Ensured lazily whenever a project header renders (covers old + new
|
|
// boards); each group is gated by its own config toggle inside
|
|
// OrganonProjectHelper::ensureBoardFilters(). The toggles also bulk add/remove the filters.
|
|
$showAllFilters = (int) $this->configModel->get('organon_tweaks_show_all_filter', 1) === 1;
|
|
$monthFilters = (int) $this->configModel->get('organon_tweaks_month_filters', 1) === 1;
|
|
$recurringFilters = (int) $this->configModel->get('organon_tweaks_recurring_filters', 1) === 1;
|
|
if ($showAllFilters || $monthFilters || $recurringFilters) {
|
|
$this->template->hook->attach('template:project:header:before', 'organonTweaks:project_header/board_filters');
|
|
}
|
|
|
|
// Custom board-search keywords, registered into the task lexer by extending its factory
|
|
// service (Pimple preserves factory status on extend, so the lexer stays per-request fresh).
|
|
// `duemonth:VALUE` / `aroundmonth:VALUE` = a calendar month (padded by 10 days for around);
|
|
// `recurring:XY` = classify recurrence (X system evt/cal/any, Y role ori/dup/all). Always
|
|
// available to type, independent of the bookmark toggles above. Guarded so a future Kanboard
|
|
// service rename no-ops (keyword absent) instead of breaking.
|
|
if (isset($this->container['taskLexer'])) {
|
|
$this->container->extend('taskLexer', function ($builder, $c) {
|
|
return $builder
|
|
->withFilter((new \Kanboard\Plugin\OrganonTweaks\Filter\TaskMonthRangeFilter())->setAttribute('duemonth')->setPadDays(0))
|
|
->withFilter((new \Kanboard\Plugin\OrganonTweaks\Filter\TaskMonthRangeFilter())->setAttribute('aroundmonth')->setPadDays(10))
|
|
->withFilter((new \Kanboard\Plugin\OrganonTweaks\Filter\TaskRecurringFilter())->setDatabase($c['db']));
|
|
});
|
|
}
|
|
}
|
|
|
|
public function getHelpers()
|
|
{
|
|
return array(
|
|
'Plugin\OrganonTweaks\Helper' => array('OrganonColumnHelper', 'OrganonProjectHelper', 'OrganonSortHelper'),
|
|
);
|
|
}
|
|
|
|
public function getPluginName()
|
|
{
|
|
return 'OrganonTweaks';
|
|
}
|
|
|
|
public function getPluginDescription()
|
|
{
|
|
return t('Umbrella plugin for small Kanboard tweaks: remove an empty board column, always show the card comment icon, and more.');
|
|
}
|
|
|
|
public function getPluginAuthor()
|
|
{
|
|
return 'Ruben (drbeco)';
|
|
}
|
|
|
|
public function getPluginVersion()
|
|
{
|
|
return '1.9.1';
|
|
}
|
|
|
|
public function getPluginHomepage()
|
|
{
|
|
return 'https://code.beco.cc/beco/OrganonTweaks';
|
|
}
|
|
|
|
public function getCompatibleVersion()
|
|
{
|
|
return '>=1.2.0';
|
|
}
|
|
}
|