summaryrefslogtreecommitdiff
path: root/plugins/Bigboard
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Bigboard')
-rw-r--r--plugins/Bigboard/Asset/js/BoardDragAndDrop.js124
-rw-r--r--plugins/Bigboard/Asset/js/BoardPolling.js43
-rw-r--r--plugins/Bigboard/Controller/Bigboard.php103
-rw-r--r--plugins/Bigboard/Controller/BoardAjaxController.php145
-rw-r--r--plugins/Bigboard/Plugin.php70
-rw-r--r--plugins/Bigboard/README.md10
-rw-r--r--plugins/Bigboard/Template/Bigboard.php15
-rw-r--r--plugins/Bigboard/Template/board/dropdown.php32
-rw-r--r--plugins/Bigboard/Template/board/show.php5
-rw-r--r--plugins/Bigboard/Template/board/table_container.php58
-rw-r--r--plugins/Bigboard/Template/board/table_tasks.php38
-rw-r--r--plugins/Bigboard/Template/board/task_private.php66
-rw-r--r--plugins/Bigboard/Template/board/view.php20
-rw-r--r--plugins/Bigboard/UserSession.php29
14 files changed, 758 insertions, 0 deletions
diff --git a/plugins/Bigboard/Asset/js/BoardDragAndDrop.js b/plugins/Bigboard/Asset/js/BoardDragAndDrop.js
new file mode 100644
index 00000000..b6b7b8c3
--- /dev/null
+++ b/plugins/Bigboard/Asset/js/BoardDragAndDrop.js
@@ -0,0 +1,124 @@
+Kanboard.BoardDragAndDrop = function(app) {
+ this.app = app;
+ this.savingInProgress = false;
+};
+
+Kanboard.BoardDragAndDrop.prototype.execute = function() {
+ if (this.app.hasId("board")) {
+ this.executeListeners();
+ this.dragAndDrop();
+ }
+};
+
+Kanboard.BoardDragAndDrop.prototype.dragAndDrop = function() {
+ var self = this;
+ var dropzone = $(".board-task-list");
+
+ // Run for every Board List, connecting the Items within the same project id
+ dropzone.each(function() {
+ // Set dropzone height to the height of the table cell
+ $(this).css("min-height", $(this).parent().height());
+
+ var project_id = $(this).closest("table[id=board]").attr("data-project-id");
+
+ var params = {
+ forcePlaceholderSize: true,
+ tolerance: "pointer",
+ connectWith: ".sortable-column[data-project-id=" + project_id + "]",
+ placeholder: "draggable-placeholder",
+ items: ".draggable-item[data-project-id=" + project_id + "]",
+ stop: function(event, ui) {
+ var task = ui.item;
+ var taskId = task.attr('data-task-id');
+ var taskPosition = task.attr('data-position');
+ var taskColumnId = task.attr('data-column-id');
+ var taskSwimlaneId = task.attr('data-swimlane-id');
+
+ var newColumnId = task.parent().attr("data-column-id");
+ var newSwimlaneId = task.parent().attr('data-swimlane-id');
+ var newPosition = task.index() + 1;
+
+ var boardId = task.closest("table").attr("data-project-id");
+ var saveURL = task.closest("table").attr("data-save-url");
+
+ task.removeClass("draggable-item-selected");
+
+ if (newColumnId != taskColumnId || newSwimlaneId != taskSwimlaneId || newPosition != taskPosition) {
+ self.changeTaskState(taskId);
+ self.save(saveURL, boardId, taskId, taskColumnId, newColumnId, newPosition, newSwimlaneId);
+ }
+ },
+ start: function(event, ui) {
+ ui.item.addClass("draggable-item-selected");
+ ui.placeholder.height(ui.item.height());
+ }
+ };
+
+ if (isMobile.any) {
+ $(".task-board-sort-handle").css("display", "inline");
+ params.handle = ".task-board-sort-handle";
+ }
+
+ $(this).sortable(params);
+ });
+};
+
+Kanboard.BoardDragAndDrop.prototype.changeTaskState = function(taskId) {
+ var task = $("div[data-task-id=" + taskId + "]");
+ task.addClass('task-board-saving-state');
+ task.find('.task-board-saving-icon').show();
+};
+
+Kanboard.BoardDragAndDrop.prototype.save = function(saveURL, boardId, taskId, srcColumnId, dstColumnId, position, swimlaneId) {
+ var self = this;
+ self.app.showLoadingIcon();
+ self.savingInProgress = true;
+
+ $.ajax({
+ cache: false,
+ url: saveURL,
+ contentType: "application/json",
+ type: "POST",
+ processData: false,
+ data: JSON.stringify({
+ "task_id": taskId,
+ "src_column_id": srcColumnId,
+ "dst_column_id": dstColumnId,
+ "swimlane_id": swimlaneId,
+ "position": position
+ }),
+ success: function(data) {
+ self.refresh(boardId,data);
+ self.savingInProgress = false;
+ },
+ error: function() {
+ self.app.hideLoadingIcon();
+ self.savingInProgress = false;
+ },
+ statusCode: {
+ 403: function(data) {
+ window.alert(data.responseJSON.message);
+ document.location.reload(true);
+ }
+ }
+ });
+};
+
+Kanboard.BoardDragAndDrop.prototype.refresh = function(boardId, data) {
+
+ $("div[id=board-container][data-project-id=" + boardId + "]").replaceWith(data);
+
+ this.app.hideLoadingIcon();
+ this.executeListeners();
+ this.dragAndDrop();
+};
+
+Kanboard.BoardDragAndDrop.prototype.executeListeners = function() {
+ for (var className in this.app.controllers) {
+ var controller = this.app.get(className);
+
+ if (typeof controller.onBoardRendered === "function") {
+ controller.onBoardRendered();
+ }
+ }
+};
diff --git a/plugins/Bigboard/Asset/js/BoardPolling.js b/plugins/Bigboard/Asset/js/BoardPolling.js
new file mode 100644
index 00000000..6d5499fd
--- /dev/null
+++ b/plugins/Bigboard/Asset/js/BoardPolling.js
@@ -0,0 +1,43 @@
+Kanboard.BoardPolling = function(app) {
+ this.app = app;
+};
+
+Kanboard.BoardPolling.prototype.execute = function() {
+ if (this.app.hasId("board")) {
+ var interval = parseInt($("#board").attr("data-check-interval"));
+
+ if (interval > 0) {
+ window.setInterval(this.check.bind(this), interval * 1000);
+ }
+ }
+};
+
+Kanboard.BoardPolling.prototype.check = function() {
+ if (KB.utils.isVisible() && !this.app.get("BoardDragAndDrop").savingInProgress) {
+ var self = this;
+ if (!$("#app-loading-icon").length) this.app.showLoadingIcon();
+ var pollsinprogress=0;
+
+ $("table.board-project").each(function() {
+ var boardId = $(this).attr("data-project-id")
+ var url = $(this).attr("data-check-url");
+ pollsinprogress++;
+ $.ajax({
+ cache: false,
+ url: url,
+ statusCode: {
+ 200: function(data) {
+ pollsinprogress--;
+ if (pollsinprogress <= 0) self.app.hideLoadingIcon();
+ self.app.get("BoardDragAndDrop").refresh(boardId, data);
+ },
+ 304: function () {
+ pollsinprogress--;
+ if (pollsinprogress <= 0) self.app.hideLoadingIcon();
+ }
+ }
+ });
+ });
+ if (pollsinprogress <= 0) self.app.hideLoadingIcon();
+ }
+};
diff --git a/plugins/Bigboard/Controller/Bigboard.php b/plugins/Bigboard/Controller/Bigboard.php
new file mode 100644
index 00000000..80573d07
--- /dev/null
+++ b/plugins/Bigboard/Controller/Bigboard.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace Kanboard\Plugin\Bigboard\Controller;
+
+use Kanboard\Controller\BaseController;
+use Kanboard\Formatter\BoardFormatter;
+use Kanboard\Model\UserMetadataModel;
+
+/**
+ * Bigboard Controller.
+ *
+ * @author Thomas Stinner
+ */
+ class Bigboard extends BaseController
+ {
+ /**
+ * Display a Board which contains multiple projects.
+ */
+ public function index()
+ {
+ if ($this->userSession->isAdmin()) {
+ $project_ids = $this->projectModel->getAllIds();
+ } else {
+ $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId());
+ }
+
+ $nb_projects = count($project_ids);
+ // Draw a header First
+ $this->response->html($this->helper->layout->app('bigboard:board/show', array(
+ 'title' => t('Bigboard').' ('.$nb_projects.')',
+ 'board_selector' => false,
+ )));
+
+ echo $this->template->render('bigboard:board/dropdown', array(
+ 'bigboarddisplaymode' => $this->userSession->isBigboardCollapsed(),
+ ));
+
+ $this->showProjects($project_ids);
+
+ }
+
+ /**
+ * Show projects.
+ *
+ * @param $project_ids list of project ids to show
+ *
+ * @return bool
+ */
+ private function showProjects($project_ids)
+ {
+ print "<div id='bigboard'>";
+
+ foreach ($project_ids as $project_id) {
+ $project = $this->projectModel->getByIdWithOwner($project_id);
+ $search = $this->helper->projectHeader->getSearchQuery($project);
+
+ $this->userMetadataCacheDecorator->set(UserMetadataModel::KEY_BOARD_COLLAPSED.$project_id, $this->userSession->isBigboardCollapsed());
+
+ echo $this->template->render('bigboard:board/view', array(
+ 'no_layout' => true,
+ 'board_selector' => false,
+ 'project' => $project,
+ 'title' => $project['name'],
+ 'description' => $this->helper->projectHeader->getDescription($project),
+ 'board_private_refresh_interval' => $this->configModel->get('board_private_refresh_interval'),
+ 'board_highlight_period' => $this->configModel->get('board_highlight_period'),
+ 'swimlanes' => $this->taskLexer
+ ->build($search)
+ ->format(BoardFormatter::getInstance($this->container)->withProjectId($project['id'])),
+ ));
+ }
+
+ print "</div>";
+
+ }
+
+ public function collapseAll()
+ {
+ $this->changeDisplayMode(true);
+ }
+
+ public function expandAll()
+ {
+ $this->changeDisplayMode(false);
+ }
+
+ private function changeDisplayMode($mode)
+ {
+ session_set('bigboardCollapsed', $mode);
+
+ if ($this->userSession->isAdmin()) {
+ $project_ids = $this->projectModel->getAllIds();
+ } else {
+ $project_ids = $this->projectPermissionModel->getActiveProjectIds(session_get('user')['id']);
+ }
+
+ if ($this->request->isAjax()) {
+ $this->showProjects($project_ids);
+ } else {
+ $this->response->redirect($this->helper->url->to('Bigboard', 'index', array('plugin' => 'Bigboard')));
+ }
+ }
+ }
diff --git a/plugins/Bigboard/Controller/BoardAjaxController.php b/plugins/Bigboard/Controller/BoardAjaxController.php
new file mode 100644
index 00000000..57832fd5
--- /dev/null
+++ b/plugins/Bigboard/Controller/BoardAjaxController.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace Kanboard\Plugin\Bigboard\Controller;
+
+use Kanboard\Controller\BaseController;
+use Kanboard\Core\Controller\AccessForbiddenException;
+use Kanboard\Model\UserMetadataModel;
+
+/**
+ * Class BoardAjaxController
+ *
+ * @package Kanboard\Controller
+ * @author Fredric Guillot
+ */
+class BoardAjaxController extends BaseController
+{
+ /**
+ * Save new task positions (Ajax request made by the drag and drop)
+ *
+ * @access public
+ */
+ public function save()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+
+ if (! $project_id || ! $this->request->isAjax()) {
+ throw new AccessForbiddenException();
+ }
+
+ $values = $this->request->getJson();
+
+ if (! $this->helper->projectRole->canMoveTask($project_id, $values['src_column_id'], $values['dst_column_id'])) {
+ throw new AccessForbiddenException(e("You don't have the permission to move this task"));
+ }
+
+ $result =$this->taskPositionModel->movePosition(
+ $project_id,
+ $values['task_id'],
+ $values['dst_column_id'],
+ $values['position'],
+ $values['swimlane_id']
+ );
+
+ if (! $result) {
+ $this->response->status(400);
+ } else {
+ $this->response->html($this->renderBoard($project_id), 201);
+ }
+ }
+
+ /**
+ * Check if the board have been changed
+ *
+ * @access public
+ */
+ public function check()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+ $timestamp = $this->request->getIntegerParam('timestamp');
+
+ if (! $project_id || ! $this->request->isAjax()) {
+ throw new AccessForbiddenException();
+ } elseif (! $this->projectModel->isModifiedSince($project_id, $timestamp)) {
+ $this->response->status(304);
+ } else {
+ $this->response->html($this->renderBoard($project_id));
+ }
+ }
+
+ /**
+ * Reload the board with new filters
+ *
+ * @access public
+ */
+ public function reload()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+
+ if (! $project_id || ! $this->request->isAjax()) {
+ throw new AccessForbiddenException();
+ }
+
+ $values = $this->request->getJson();
+ $this->userSession->setFilters($project_id, empty($values['search']) ? '' : $values['search']);
+
+ $this->response->html($this->renderBoard($project_id));
+ }
+
+ /**
+ * Enable collapsed mode
+ *
+ * @access public
+ */
+ public function collapse()
+ {
+ $this->changeDisplayMode(1);
+ }
+
+ /**
+ * Enable expanded mode
+ *
+ * @access public
+ */
+ public function expand()
+ {
+ $this->changeDisplayMode(0);
+ }
+
+ /**
+ * Change display mode
+ *
+ * @access private
+ * @param int $mode
+ */
+ private function changeDisplayMode($mode)
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+ $this->userMetadataCacheDecorator->set(UserMetadataModel::KEY_BOARD_COLLAPSED.$project_id, $mode);
+
+ if ($this->request->isAjax()) {
+ $this->response->html($this->renderBoard($project_id));
+ } else {
+ $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project_id)));
+ }
+ }
+
+ /**
+ * Render board
+ *
+ * @access protected
+ * @param integer $project_id
+ * @return string
+ */
+ protected function renderBoard($project_id)
+ {
+ return $this->template->render('bigboard:board/table_container', array(
+ 'project' => $this->projectModel->getById($project_id),
+ 'board_private_refresh_interval' => $this->configModel->get('board_private_refresh_interval'),
+ 'board_highlight_period' => $this->configModel->get('board_highlight_period'),
+ 'swimlanes' => $this->taskLexer
+ ->build($this->userSession->getFilters($project_id))
+ ->format($this->boardFormatter->withProjectId($project_id))
+ ));
+ }
+}
diff --git a/plugins/Bigboard/Plugin.php b/plugins/Bigboard/Plugin.php
new file mode 100644
index 00000000..aa43c48a
--- /dev/null
+++ b/plugins/Bigboard/Plugin.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Kanboard\Plugin\Bigboard;
+
+use DateTime;
+use Kanboard\Core\Plugin\Base;
+use Kanboard\Core\Translator;
+use Kanboard\Core\Security\Role;
+
+class Plugin extends Base
+{
+ public function initialize()
+ {
+ $this->template->hook->attach('template:project-list:menu:before', 'bigboard:Bigboard');
+ $this->template->setTemplateOverride('board/table_container','bigboard:board/table_container');
+ $this->template->setTemplateOverride('board/table_tasks','bigboard:board/table_tasks');
+ $this->template->setTemplateOverride('board/table_private','bigboard:board/table_private');
+ $this->hook->on('template:layout:js', array('template' => 'plugins/Bigboard/Asset/js/BoardDragAndDrop.js'));
+ $this->hook->on('template:layout:js', array('template' => 'plugins/Bigboard/Asset/js/BoardPolling.js'));
+ }
+
+ public function getClasses()
+ {
+ return array(
+ 'Plugin\Bigboard' => array(
+ 'UserSession'
+ ),
+ 'Plugin\Bigboard\Controller' => array(
+ 'Bigboard',
+ 'BoardAjaxController'
+ )
+ );
+ }
+
+ public function onStartup()
+ {
+ Translator::load($this->languageModel->getCurrentLanguage(), __DIR__.'/Locale');
+ }
+
+ public function getPluginName()
+ {
+ return 'Bigboard';
+ }
+
+ public function getPluginDescription()
+ {
+ return t('Kanboard that displays multiple projects');
+ }
+
+ public function getPluginAuthor()
+ {
+ return 'Thomas Stinner';
+ }
+
+ public function getPluginVersion()
+ {
+ return '1.0.5';
+ }
+
+ public function getPluginHomepage()
+ {
+ return 'https://github.com/stinnux/kanboard-bigboard';
+ }
+
+ public function getCompatibleVersion()
+ {
+ return '>=1.2.4';
+ }
+
+}
diff --git a/plugins/Bigboard/README.md b/plugins/Bigboard/README.md
new file mode 100644
index 00000000..aca27a38
--- /dev/null
+++ b/plugins/Bigboard/README.md
@@ -0,0 +1,10 @@
+kanboard-bigboard
+=================
+
+A Kanboard that can display multiple projects.
+
+Go To Project-Management->BigBoard. Here you will see all projects you have access to in one page.
+
+All functionality is still available, so you can drag-and-drop tasks, add tasks etc.
+
+Comments Welcome.
diff --git a/plugins/Bigboard/Template/Bigboard.php b/plugins/Bigboard/Template/Bigboard.php
new file mode 100644
index 00000000..6767da64
--- /dev/null
+++ b/plugins/Bigboard/Template/Bigboard.php
@@ -0,0 +1,15 @@
+<?php
+ $routerController = $this->app->getRouterController();
+ $routerPlugin = $this->app->getPluginName();
+
+ $active = $routerController == 'Bigboard' && $routerPlugin == 'Bigboard';
+?>
+<li class="<?= $active ? 'active' : '' ?>">
+ <i class="fa fa-th fa-fw"></i>
+ <?= $this->url->link(
+ 'Bigboard',
+ 'Bigboard',
+ 'index',
+ ['plugin' => 'Bigboard', ]
+ ) ?>
+</li>
diff --git a/plugins/Bigboard/Template/board/dropdown.php b/plugins/Bigboard/Template/board/dropdown.php
new file mode 100644
index 00000000..de64917d
--- /dev/null
+++ b/plugins/Bigboard/Template/board/dropdown.php
@@ -0,0 +1,32 @@
+<div class="project-header">
+ <div class="dropdown-component">
+ <div class="dropdown">
+ <a href="#" class="dropdown-menu action-menu"><?= t('Menu') ?> <i class="fa fa-caret-down"></i></a>
+ <ul>
+ <li>
+ <span class="filter-display-mode" <?= $bigboarddisplaymode ? '' : 'style="display: none;"' ?>>
+ <i class="fa fa-expand fa-fw"></i>
+ <?= $this->url->link(t('Expand tasks'), 'Bigboard', 'expandAll', array('plugin' => 'Bigboard'), false, 'board-display-mode', t('Keyboard shortcut: "%s"', 's')) ?>
+ </span>
+ <span class="filter-display-mode" <?= $bigboarddisplaymode ? 'style="display: none;"' : '' ?>>
+ <i class="fa fa-compress fa-fw"></i>
+ <?= $this->url->link(t('Collapse tasks'), 'Bigboard', 'collapseAll', array('plugin' => 'Bigboard'), false, 'board-display-mode', t('Keyboard shortcut: "%s"', 's')) ?>
+ </span>
+ </li>
+ <li>
+ <span class="filter-compact">
+ <i class="fa fa-th fa-fw"></i> <a href="#" class="filter-toggle-scrolling" title="<?= t('Keyboard shortcut: "%s"', 'c') ?>"><?= t('Compact view') ?></a>
+ </span>
+ <span class="filter-wide" style="display: none">
+ <i class="fa fa-arrows-h fa-fw"></i> <a href="#" class="filter-toggle-scrolling" title="<?= t('Keyboard shortcut: "%s"', 'c') ?>"><?= t('Horizontal scrolling') ?></a>
+ </span>
+ </li>
+
+ <li>
+ <i class="fa fa-folder fa-fw" aria-hidden="true"></i>
+ <?= $this->url->link(t('Manage projects'), 'ProjectListController', 'show') ?>
+ </li>
+ </ul>
+ </div>
+ </div>
+</div>
diff --git a/plugins/Bigboard/Template/board/show.php b/plugins/Bigboard/Template/board/show.php
new file mode 100644
index 00000000..dcc10e71
--- /dev/null
+++ b/plugins/Bigboard/Template/board/show.php
@@ -0,0 +1,5 @@
+<?
+
+// just an empty file by intent
+
+?>
diff --git a/plugins/Bigboard/Template/board/table_container.php b/plugins/Bigboard/Template/board/table_container.php
new file mode 100644
index 00000000..e7fc6116
--- /dev/null
+++ b/plugins/Bigboard/Template/board/table_container.php
@@ -0,0 +1,58 @@
+<div id="board-container" data-project-id='<?= $project['id'] ?>'>
+ <?php if (empty($swimlanes) || empty($swimlanes[0]['nb_columns'])): ?>
+ <p class="alert alert-error"><?= t('There is no column or swimlane activated in your project!') ?></p>
+ <?php else: ?>
+
+ <?php if (isset($not_editable)): ?>
+ <table id="board" class="board-project-<?= $project['id'] ?>">
+ <?php else: ?>
+ <table id="board"
+ class="board-project"
+ data-project-id="<?= $project['id'] ?>"
+ data-check-interval="<?= $board_private_refresh_interval ?>"
+ data-save-url="<?= $this->url->href('BoardAjaxController', 'save', array('plugin' => "Bigboard", 'project_id' => $project['id'])) ?>"
+ data-reload-url="<?= $this->url->href('BoardAjaxController', 'reload', array('plugin' => "Bigboard", 'project_id' => $project['id'])) ?>"
+ data-check-url="<?= $this->url->href('BoardAjaxController', 'check', array('plugin' => "Bigboard", 'project_id' => $project['id'], 'timestamp' => time())) ?>"
+ data-task-creation-url="<?= $this->url->href('TaskCreationController', 'show', array('plugin' => "Bigboard", 'project_id' => $project['id'])) ?>"
+ >
+ <?php endif ?>
+
+ <?php foreach ($swimlanes as $index => $swimlane): ?>
+ <?php if (! ($swimlane['nb_tasks'] === 0 && isset($not_editable))): ?>
+
+ <!-- Note: Do not show swimlane row on the top otherwise we can't collapse columns -->
+ <?php if ($index > 0 && $swimlane['nb_swimlanes'] > 1): ?>
+ <?= $this->render('board/table_swimlane', array(
+ 'project' => $project,
+ 'swimlane' => $swimlane,
+ 'not_editable' => isset($not_editable),
+ )) ?>
+ <?php endif ?>
+
+ <?= $this->render('board/table_column', array(
+ 'swimlane' => $swimlane,
+ 'not_editable' => isset($not_editable),
+ )) ?>
+
+ <?php if ($index === 0 && $swimlane['nb_swimlanes'] > 1): ?>
+ <?= $this->render('board/table_swimlane', array(
+ 'project' => $project,
+ 'swimlane' => $swimlane,
+ 'not_editable' => isset($not_editable),
+ )) ?>
+ <?php endif ?>
+
+ <?= $this->render('bigboard:board/table_tasks', array(
+ 'project' => $project,
+ 'swimlane' => $swimlane,
+ 'not_editable' => isset($not_editable),
+ 'board_highlight_period' => $board_highlight_period,
+ )) ?>
+
+ <?php endif ?>
+ <?php endforeach ?>
+
+ </table>
+
+ <?php endif ?>
+</div>
diff --git a/plugins/Bigboard/Template/board/table_tasks.php b/plugins/Bigboard/Template/board/table_tasks.php
new file mode 100644
index 00000000..3d280489
--- /dev/null
+++ b/plugins/Bigboard/Template/board/table_tasks.php
@@ -0,0 +1,38 @@
+<!-- task row -->
+<tr class="board-swimlane board-swimlane-tasks-<?= $swimlane['id'] ?>">
+ <?php foreach ($swimlane['columns'] as $column): ?>
+ <td class="
+ board-column-<?= $column['id'] ?>
+ <?= $column['task_limit'] > 0 && $column['nb_tasks'] > $column['task_limit'] ? 'board-task-list-limit' : '' ?>
+ "
+ >
+
+ <!-- tasks list -->
+ <div
+ class="board-task-list board-column-expanded <?= $this->projectRole->isSortableColumn($column['project_id'], $column['id']) ? 'sortable-column' : '' ?>"
+ data-project-id="<?= $project['id'] ?>"
+ data-column-id="<?= $column['id'] ?>"
+ data-swimlane-id="<?= $swimlane['id'] ?>"
+ data-task-limit="<?= $column['task_limit'] ?>">
+
+ <?php foreach ($column['tasks'] as $task): ?>
+ <?= $this->render($not_editable ? 'board/task_public' : 'bigboard:board/task_private', array(
+ 'project' => $project,
+ 'task' => $task,
+ 'board_highlight_period' => $board_highlight_period,
+ 'not_editable' => $not_editable,
+ )) ?>
+ <?php endforeach ?>
+ </div>
+
+ <!-- column in collapsed mode (rotated text) -->
+ <div class="board-column-collapsed">
+ <div class="board-rotation-wrapper">
+ <div class="board-column-title board-rotation board-toggle-column-view" data-column-id="<?= $column['id'] ?>" title="<?= t('Show this column') ?>">
+ <i class="fa fa-plus-square tooltip" title="<?= $this->text->e($column['title']) ?>"></i> <?= $this->text->e($column['title']) ?>
+ </div>
+ </div>
+ </div>
+ </td>
+ <?php endforeach ?>
+</tr>
diff --git a/plugins/Bigboard/Template/board/task_private.php b/plugins/Bigboard/Template/board/task_private.php
new file mode 100644
index 00000000..d97e0e2c
--- /dev/null
+++ b/plugins/Bigboard/Template/board/task_private.php
@@ -0,0 +1,66 @@
+<div class="
+ task-board
+ <?= $task['is_draggable'] ? 'draggable-item ' : '' ?>
+ <?= $task['is_active'] == 1 ? 'task-board-status-open '.($task['date_modification'] > (time() - $board_highlight_period) ? 'task-board-recent' : '') : 'task-board-status-closed' ?>
+ color-<?= $task['color_id'] ?>"
+ data-project-id="<?= $task['project_id'] ?>"
+ data-task-id="<?= $task['id'] ?>"
+ data-column-id="<?= $task['column_id'] ?>"
+ data-swimlane-id="<?= $task['swimlane_id'] ?>"
+ data-position="<?= $task['position'] ?>"
+ data-owner-id="<?= $task['owner_id'] ?>"
+ data-category-id="<?= $task['category_id'] ?>"
+ data-due-date="<?= $task['date_due'] ?>"
+ data-task-url="<?= $this->url->href('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>">
+
+ <div class="task-board-sort-handle" style="display: none;"><i class="fa fa-arrows-alt"></i></div>
+
+ <?php if ($this->board->isCollapsed($task['project_id'])): ?>
+ <div class="task-board-collapsed">
+ <div class="task-board-saving-icon" style="display: none;"><i class="fa fa-spinner fa-pulse"></i></div>
+ <?php if ($this->user->hasProjectAccess('TaskModificationController', 'edit', $task['project_id'])): ?>
+ <?= $this->render('task/dropdown', array('task' => $task)) ?>
+ <?php else: ?>
+ <strong><?= '#'.$task['id'] ?></strong>
+ <?php endif ?>
+
+ <?php if (! empty($task['assignee_username'])): ?>
+ <span title="<?= $this->text->e($task['assignee_name'] ?: $task['assignee_username']) ?>">
+ <?= $this->text->e($this->user->getInitials($task['assignee_name'] ?: $task['assignee_username'])) ?>
+ </span> -
+ <?php endif ?>
+ <?= $this->url->link($this->text->e($task['title']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'tooltip', $this->text->e($task['title'])) ?>
+ </div>
+ <?php else: ?>
+ <div class="task-board-expanded">
+ <div class="task-board-saving-icon" style="display: none;"><i class="fa fa-spinner fa-pulse fa-2x"></i></div>
+ <div class="task-board-header">
+ <?php if ($this->user->hasProjectAccess('TaskModificationController', 'edit', $task['project_id'])): ?>
+ <?= $this->render('task/dropdown', array('task' => $task)) ?>
+ <?php else: ?>
+ <strong><?= '#'.$task['id'] ?></strong>
+ <?php endif ?>
+
+ <?php if (! empty($task['owner_id'])): ?>
+ <span class="task-board-assignee">
+ <?= $this->text->e($task['assignee_name'] ?: $task['assignee_username']) ?>
+ </span>
+ <?php endif ?>
+
+ <?= $this->render('board/task_avatar', array('task' => $task)) ?>
+ </div>
+
+ <?= $this->hook->render('template:board:private:task:before-title', array('task' => $task)) ?>
+ <div class="task-board-title">
+ <?= $this->url->link($this->text->e($task['title']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
+ </div>
+ <?= $this->hook->render('template:board:private:task:after-title', array('task' => $task)) ?>
+
+ <?= $this->render('board/task_footer', array(
+ 'task' => $task,
+ 'not_editable' => $not_editable,
+ 'project' => $project,
+ )) ?>
+ </div>
+ <?php endif ?>
+</div>
diff --git a/plugins/Bigboard/Template/board/view.php b/plugins/Bigboard/Template/board/view.php
new file mode 100644
index 00000000..7987e7c2
--- /dev/null
+++ b/plugins/Bigboard/Template/board/view.php
@@ -0,0 +1,20 @@
+<section id="main">
+
+ <span class='header'><h1><?= $this->text->e($project['name']) ?>
+
+ <?php if (! empty($project['description'])): ?>
+ <?= $this->app->tooltipMarkdown($project['description']) ?>
+ <?php endif ?>
+
+ </span>
+ </h1></span>
+
+
+ <?= $this->render('bigboard:board/table_container', array(
+ 'project' => $project,
+ 'swimlanes' => $swimlanes,
+ 'board_private_refresh_interval' => $board_private_refresh_interval,
+ 'board_highlight_period' => $board_highlight_period,
+ )) ?>
+
+</section>
diff --git a/plugins/Bigboard/UserSession.php b/plugins/Bigboard/UserSession.php
new file mode 100644
index 00000000..8bdea501
--- /dev/null
+++ b/plugins/Bigboard/UserSession.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Kanboard\Plugin\Bigboard;
+
+class UserSession extends \Kanboard\Core\User\UserSession
+{
+ /**
+ * is the Bigboard collapsed or expanded
+ *
+ * @access public
+ * @return boolean
+ */
+ public function isBigboardCollapsed()
+ {
+ return session_is_true('bigboardCollapsed');
+ }
+
+ /**
+ * Set Bigboard display mode
+ *
+ * @access public
+ * @param boolean $is_collapsed
+ */
+ public function setBigboardDisplayMode($is_collapsed)
+ {
+ session_set('bigboardCollapsed', true);
+ }
+
+}