Hide total in columns
This commit is contained in:
59
Asset/js/relocate.js
Normal file
59
Asset/js/relocate.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* FinanceBuddy -- place the "Hide/Show column total" entry inside the native column menu.
|
||||||
|
*
|
||||||
|
* Kanboard only exposes the template:board:column:dropdown hook AFTER the column menu <ul>, and its
|
||||||
|
* dropdown JS clones just that <ul> when the menu opens. So the hook item cannot reach the menu on
|
||||||
|
* its own. column_dropdown.php renders the item hidden next to the menu; this script moves each such
|
||||||
|
* item into that column's real <ul> so it appears alongside "Hide this column", etc.
|
||||||
|
*
|
||||||
|
* BoardDragAndDrop.refresh() does $("#board-container").replaceWith(data) on every drag-and-drop and
|
||||||
|
* poll refresh, so the observer is bound to the STABLE parent of #board-container (which survives the
|
||||||
|
* swap), not to #board-container itself -- otherwise it would be left watching a detached node and
|
||||||
|
* the entry would vanish until a full page reload.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function relocate() {
|
||||||
|
var items = document.querySelectorAll(".financebuddy-menu-item");
|
||||||
|
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var li = items[i];
|
||||||
|
|
||||||
|
// Already moved into a menu list: just make sure it is visible.
|
||||||
|
if (li.closest("ul")) {
|
||||||
|
li.style.display = "";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The hook renders the item as a child of the column's dropdown wrapper; its first <ul>
|
||||||
|
// is the native menu.
|
||||||
|
var menu = li.parentNode ? li.parentNode.querySelector("ul") : null;
|
||||||
|
|
||||||
|
if (menu) {
|
||||||
|
menu.appendChild(li);
|
||||||
|
li.style.display = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
var container = document.getElementById("board-container");
|
||||||
|
|
||||||
|
if (!container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
relocate();
|
||||||
|
|
||||||
|
if (window.MutationObserver && container.parentNode) {
|
||||||
|
new MutationObserver(relocate).observe(container.parentNode, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === "loading") {
|
||||||
|
document.addEventListener("DOMContentLoaded", init);
|
||||||
|
} else {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
})();
|
||||||
34
Controller/FinanceColumnController.php
Normal file
34
Controller/FinanceColumnController.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\FinanceBuddy\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Controller\BaseController;
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
use Kanboard\Plugin\FinanceBuddy\Helper\FinanceHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle a board column's header total on/off from the column dropdown menu. The per-column flag
|
||||||
|
* lives in project metadata; project-manager gated (same scope as enabling FinanceBuddy). Returns
|
||||||
|
* to the board, whose reload re-renders the header with or without the total.
|
||||||
|
*/
|
||||||
|
class FinanceColumnController extends BaseController
|
||||||
|
{
|
||||||
|
public function toggleTotal()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
if (! $this->helper->user->hasProjectAccess('ProjectEditController', 'edit', $project['id'])) {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = FinanceHelper::HIDE_TOTAL_PREFIX.$this->request->getIntegerParam('column_id');
|
||||||
|
|
||||||
|
// Store the literal 'on'/'off' (both non-empty) rather than 1/0, so the flag is never lost
|
||||||
|
// to PHP's empty("0") === true on the metadata save.
|
||||||
|
$hidden = $this->projectMetadataModel->get($project['id'], $key, FinanceHelper::HIDE_TOTAL_OFF) === FinanceHelper::HIDE_TOTAL_ON;
|
||||||
|
$this->projectMetadataModel->save($project['id'], array($key => $hidden ? FinanceHelper::HIDE_TOTAL_OFF : FinanceHelper::HIDE_TOTAL_ON));
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id'])));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,13 @@ class FinanceHelper extends Base
|
|||||||
const INSTALLMENT_CURRENT_KEY = 'financebuddy_installment_current';
|
const INSTALLMENT_CURRENT_KEY = 'financebuddy_installment_current';
|
||||||
const INSTALLMENT_TOTAL_KEY = 'financebuddy_installment_total';
|
const INSTALLMENT_TOTAL_KEY = 'financebuddy_installment_total';
|
||||||
|
|
||||||
|
// Per-column opt-out of the header total. Stored per column in PROJECT metadata as
|
||||||
|
// financebuddy_hide_total_<column_id> = 'on' (hidden) or 'off' (shown, the default). Literal
|
||||||
|
// on/off, never 1/0, so the flag is never dropped by the metadata save (PHP empty("0") === true).
|
||||||
|
const HIDE_TOTAL_PREFIX = 'financebuddy_hide_total_';
|
||||||
|
const HIDE_TOTAL_ON = 'on';
|
||||||
|
const HIDE_TOTAL_OFF = 'off';
|
||||||
|
|
||||||
// Hidden marker present only when the task form was submitted with the finance fieldset, so
|
// Hidden marker present only when the task form was submitted with the finance fieldset, so
|
||||||
// non-finance task updates (moves, API calls) are ignored by the persistence hooks.
|
// non-finance task updates (moves, API calls) are ignored by the persistence hooks.
|
||||||
const FORM_MARKER = 'financebuddy_form';
|
const FORM_MARKER = 'financebuddy_form';
|
||||||
@@ -110,6 +117,18 @@ class FinanceHelper extends Base
|
|||||||
return $net;
|
return $net;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has this column's header total been hidden (per-column opt-out)?
|
||||||
|
*
|
||||||
|
* @param integer $project_id
|
||||||
|
* @param integer $column_id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isTotalHidden($project_id, $column_id)
|
||||||
|
{
|
||||||
|
return $this->projectMetadataModel->get((int) $project_id, self::HIDE_TOTAL_PREFIX.(int) $column_id, self::HIDE_TOTAL_OFF) === self::HIDE_TOTAL_ON;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Values to prefill the task-form fields: a re-post (after a validation error) wins, then the
|
* Values to prefill the task-form fields: a re-post (after a validation error) wins, then the
|
||||||
* stored metadata for an existing task, otherwise blanks for a new task.
|
* stored metadata for an existing task, otherwise blanks for a new task.
|
||||||
|
|||||||
@@ -47,6 +47,14 @@ class Plugin extends Base
|
|||||||
// Per-column net total (credits - debits) in the column header.
|
// Per-column net total (credits - debits) in the column header.
|
||||||
$this->template->hook->attach('template:board:column:header', 'financeBuddy:board/column_total');
|
$this->template->hook->attach('template:board:column:header', 'financeBuddy:board/column_total');
|
||||||
|
|
||||||
|
// "Hide/Show column total" toggle in the column dropdown menu. The only column-menu hook
|
||||||
|
// renders after the native <ul>, so column_dropdown.php emits the item hidden and relocate.js
|
||||||
|
// moves it into the menu (same technique as BulkMoveTasks, with the stable-parent observer).
|
||||||
|
$this->template->hook->attach('template:board:column:dropdown', 'financeBuddy:board/column_dropdown');
|
||||||
|
$this->hook->on('template:layout:js', array(
|
||||||
|
'template' => 'plugins/FinanceBuddy/Asset/js/relocate.js',
|
||||||
|
));
|
||||||
|
|
||||||
// The same money badge at the top of the opened card (task view), under the title, so a
|
// The same money badge at the top of the opened card (task view), under the title, so a
|
||||||
// card shows its money whether you are on the board or reading the card. Reuses the board
|
// card shows its money whether you are on the board or reading the card. Reuses the board
|
||||||
// badge template (both hooks pass $task).
|
// badge template (both hooks pass $task).
|
||||||
|
|||||||
17
Template/board/column_dropdown.php
Normal file
17
Template/board/column_dropdown.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php if ($this->FinanceHelper->isEnabled($column['project_id']) && $this->user->hasProjectAccess('ProjectEditController', 'edit', $column['project_id'])): ?>
|
||||||
|
<?php /* Rendered here (outside the menu <ul>) by the only column-menu hook, then moved into the
|
||||||
|
column's real dropdown <ul> by Asset/js/relocate.js so it sits next to the native
|
||||||
|
entries. Hidden until relocated to avoid a flash in the header. */ ?>
|
||||||
|
<?php $hidden = $this->FinanceHelper->isTotalHidden($column['project_id'], $column['id']); ?>
|
||||||
|
<li class="financebuddy-menu-item" style="display: none;">
|
||||||
|
<?= $this->url->link(
|
||||||
|
$hidden
|
||||||
|
? '<i class="fa fa-eye fa-fw"></i> '.t('Show column total')
|
||||||
|
: '<i class="fa fa-eye-slash fa-fw"></i> '.t('Hide column total'),
|
||||||
|
'FinanceColumnController',
|
||||||
|
'toggleTotal',
|
||||||
|
array('plugin' => 'FinanceBuddy', 'project_id' => $column['project_id'], 'column_id' => $column['id']),
|
||||||
|
true
|
||||||
|
) ?>
|
||||||
|
</li>
|
||||||
|
<?php endif ?>
|
||||||
@@ -7,6 +7,11 @@ if (empty($column['project_id']) || ! $this->FinanceHelper->isEnabled($column['p
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Per-column opt-out, toggled from the column dropdown menu.
|
||||||
|
if ($this->FinanceHelper->isTotalHidden($column['project_id'], $column['id'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$net = $this->FinanceHelper->columnNet($column);
|
$net = $this->FinanceHelper->columnNet($column);
|
||||||
|
|
||||||
if ($net > 0) {
|
if ($net > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user