feature : persistent sort

This commit is contained in:
2026-07-13 10:25:28 -03:00
parent 7ba4348de1
commit d079198103
7 changed files with 335 additions and 1 deletions

View File

@@ -3,6 +3,7 @@
namespace Kanboard\Plugin\OrganonTweaks;
use Kanboard\Core\Plugin\Base;
use Kanboard\Model\TaskModel;
class Plugin extends Base
{
@@ -77,6 +78,39 @@ class Plugin extends Base
$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
@@ -107,7 +141,7 @@ class Plugin extends Base
public function getHelpers()
{
return array(
'Plugin\OrganonTweaks\Helper' => array('OrganonColumnHelper', 'OrganonProjectHelper'),
'Plugin\OrganonTweaks\Helper' => array('OrganonColumnHelper', 'OrganonProjectHelper', 'OrganonSortHelper'),
);
}