/** * View a taskboard */ public function index($f3, $params) { // Require a valid numeric sprint ID if (!intval($params["id"])) { $f3->error(404); return; } // Default to showing group tasks if (empty($params["filter"])) { $params["filter"] = "groups"; } // Load the requested sprint $sprint = new \Model\Sprint(); $sprint->load($params["id"]); if (!$sprint->id) { $f3->error(404); return; } $f3->set("sprint", $sprint); $f3->set("title", $sprint->name . " " . date('n/j', strtotime($sprint->start_date)) . "-" . date('n/j', strtotime($sprint->end_date))); $f3->set("menuitem", "backlog"); // Get list of all users in the user's groups $filter_users = $this->_filterUsers($params); // Load issue statuses $status = new \Model\Issue\Status(); $statuses = $status->find(array('taskboard > 0'), null, $f3->get("cache_expire.db")); $mapped_statuses = array(); $visible_status_ids = array(); $column_count = 0; foreach ($statuses as $s) { $visible_status_ids[] = $s->id; $mapped_statuses[$s->id] = $s; $column_count += $s->taskboard; } $visible_status_ids = implode(",", $visible_status_ids); $f3->set("statuses", $mapped_statuses); $f3->set("column_count", $column_count); // Load issue priorities $priority = new \Model\Issue\Priority(); $f3->set("priorities", $priority->find(null, array("order" => "value DESC"), $f3->get("cache_expire.db"))); // Load project list $issue = new \Model\Issue\Detail(); // Find all visible tasks $tasks = $issue->find(array("sprint_id = ? AND type_id != ? AND deleted_date IS NULL AND status IN ({$visible_status_ids})" . (empty($filter_users) ? "" : " AND owner_id IN (" . implode(",", $filter_users) . ")"), $sprint->id, $f3->get("issue_type.project")), array("order" => "priority DESC")); $task_ids = array(); $parent_ids = array(0); foreach ($tasks as $task) { $task_ids[] = $task->id; if ($task->parent_id) { $parent_ids[] = $task->parent_id; } } $task_ids_str = implode(",", $task_ids); $parent_ids_str = implode(",", $parent_ids); $f3->set("tasks", $task_ids_str); // Find all visible projects or parent tasks $projects = $issue->find(array("id IN ({$parent_ids_str}) OR (sprint_id = ? AND type_id = ? AND deleted_date IS NULL" . (empty($filter_users) ? ")" : " AND owner_id IN (" . implode(",", $filter_users) . "))"), $sprint->id, $f3->get("issue_type.project")), array("order" => "owner_id ASC")); // Build multidimensional array of all tasks and projects $taskboard = array(); foreach ($projects as $project) { // Build array of statuses to put tasks under $columns = array(); foreach ($statuses as $status) { $columns[$status["id"]] = array(); } // Add current project's tasks foreach ($tasks as $task) { if ($task->parent_id == $project->id || $project->id == 0 && (!$task->parent_id || !in_array($task->parent_id, $parent_ids))) { $columns[$task->status][] = $task; } } // Add hierarchical structure to taskboard array $taskboard[] = array("project" => $project, "columns" => $columns); } $f3->set("taskboard", array_values($taskboard)); $f3->set("filter", $params["filter"]); // Get user list for select $users = new \Model\User(); $f3->set("users", $users->getAll()); $f3->set("groups", $users->getAllGroups()); $this->_render("taskboard/index.html"); }
/** * View a taskboard * * @param \Base $f3 * @param array $params */ public function index($f3, $params) { $sprint = new \Model\Sprint(); // Load current sprint if no sprint ID is given if (!intval($params["id"])) { $localDate = date('Y-m-d', \Helper\View::instance()->utc2local()); $sprint->load(array("? BETWEEN start_date AND end_date", $localDate)); if (!$sprint->id) { $f3->error(404); return; } } // Default to showing group tasks if (empty($params["filter"])) { $params["filter"] = "groups"; } // Load the requested sprint if (!$sprint->id) { $sprint->load($params["id"]); if (!$sprint->id) { $f3->error(404); return; } } $f3->set("sprint", $sprint); $f3->set("title", $sprint->name . " " . date('n/j', strtotime($sprint->start_date)) . "-" . date('n/j', strtotime($sprint->end_date))); $f3->set("menuitem", "backlog"); // Get list of all users in the user's groups $filter_users = $this->_filterUsers($params); // Load issue statuses $status = new \Model\Issue\Status(); $statuses = $status->find(array('taskboard > 0'), array('order' => 'taskboard_sort ASC')); $mapped_statuses = array(); $visible_status_ids = array(); $column_count = 0; foreach ($statuses as $s) { $visible_status_ids[] = $s->id; $mapped_statuses[$s->id] = $s; $column_count += $s->taskboard; } $visible_status_ids = implode(",", $visible_status_ids); $f3->set("statuses", $mapped_statuses); $f3->set("column_count", $column_count); // Load issue priorities $priority = new \Model\Issue\Priority(); $f3->set("priorities", $priority->find(null, array("order" => "value DESC"), $f3->get("cache_expire.db"))); // Load project list $issue = new \Model\Issue\Detail(); // Find all visible tasks $tasks = $issue->find(array("sprint_id = ? AND type_id != ? AND deleted_date IS NULL AND status IN ({$visible_status_ids})" . (empty($filter_users) ? "" : " AND owner_id IN (" . implode(",", $filter_users) . ")"), $sprint->id, $f3->get("issue_type.project")), array("order" => "priority DESC")); $task_ids = array(); $parent_ids = array(0); foreach ($tasks as $task) { $task_ids[] = $task->id; if ($task->parent_id) { $parent_ids[] = $task->parent_id; } } $task_ids_str = implode(",", $task_ids); $parent_ids_str = implode(",", $parent_ids); $f3->set("tasks", $task_ids_str); // Find all visible projects or parent tasks $projects = $issue->find(array("id IN ({$parent_ids_str}) OR (sprint_id = ? AND type_id = ? AND deleted_date IS NULL" . (empty($filter_users) ? ")" : " AND owner_id IN (" . implode(",", $filter_users) . "))"), $sprint->id, $f3->get("issue_type.project")), array("order" => "owner_id ASC, priority DESC")); // Sort projects if a filter is given if (!empty($params["filter"]) && is_numeric($params["filter"])) { $sortModel = new \Model\Issue\Backlog(); $sortModel->load(array("user_id = ? AND sprint_id = ?", $params["filter"], $sprint->id)); $sortArray = array(); if ($sortModel->id) { $sortArray = json_decode($sortModel->issues); usort($projects, function (\Model\Issue $a, \Model\Issue $b) use($sortArray) { $ka = array_search($a->id, $sortArray); $kb = array_search($b->id, $sortArray); if ($ka === false && $kb !== false) { return -1; } if ($ka !== false && $kb === false) { return 1; } if ($ka === $kb) { return 0; } if ($ka > $kb) { return 1; } if ($ka < $kb) { return -1; } }); } } // Build multidimensional array of all tasks and projects $taskboard = array(); foreach ($projects as $project) { // Build array of statuses to put tasks under $columns = array(); foreach ($statuses as $status) { $columns[$status["id"]] = array(); } // Add current project's tasks foreach ($tasks as $task) { if ($task->parent_id == $project->id || $project->id == 0 && (!$task->parent_id || !in_array($task->parent_id, $parent_ids))) { $columns[$task->status][] = $task; } } // Add hierarchical structure to taskboard array $taskboard[] = array("project" => $project, "columns" => $columns); } $f3->set("taskboard", array_values($taskboard)); $f3->set("filter", $params["filter"]); // Get user list for select $users = new \Model\User(); $f3->set("users", $users->getAll()); $f3->set("groups", $users->getAllGroups()); $this->_render("taskboard/index.html"); }
public function single($f3, $params) { $this->_requireLogin(); $user = new \Model\User(); $user->load(array("username = ? AND deleted_date IS NULL", $params["username"])); if ($user->id) { $f3->set("title", $user->name); $f3->set("this_user", $user); // Extra arrays required for bulk update $status = new \Model\Issue\Status(); $f3->set("statuses", $status->find(null, null, $f3->get("cache_expire.db"))); $f3->set("users", $user->getAll()); $f3->set("groups", $user->getAllGroups()); $priority = new \Model\Issue\Priority(); $f3->set("priorities", $priority->find(null, array("order" => "value DESC"), $f3->get("cache_expire.db"))); $type = new \Model\Issue\Type(); $f3->set("types", $type->find(null, null, $f3->get("cache_expire.db"))); $issue = new \Model\Issue\Detail(); $f3->set("created_issues", $issue->paginate(0, 200, array("status_closed = '0' AND deleted_date IS NULL AND author_id = ?", $user->id), array("order" => "priority DESC, due_date DESC"))); $f3->set("assigned_issues", $issue->paginate(0, 200, array("status_closed = '0' AND deleted_date IS NULL AND owner_id = ?", $user->id), array("order" => "priority DESC, due_date DESC"))); $f3->set("overdue_issues", $issue->paginate(0, 200, array("status_closed = '0' AND deleted_date IS NULL AND owner_id = ? AND due_date IS NOT NULL AND due_date < ?", $user->id, date("Y-m-d", \Helper\View::instance()->utc2local())), array("order" => "due_date ASC"))); $this->_render("user/single.html"); } else { $f3->error(404); } }
/** * GET /issues/@id * View an issue * * @param \Base $f3 * @param array $params * @throws \Exception */ public function single($f3, $params) { $issue = new \Model\Issue\Detail(); $issue->load(array("id=?", $params["id"])); $user = $f3->get("user_obj"); if (!$issue->id || $issue->deleted_date && !($user->role == 'admin' || $user->rank >= \Model\User::RANK_MANAGER || $issue->author_id == $user->id)) { $f3->error(404); return; } $type = new \Model\Issue\Type(); $type->load($issue->type_id); $f3->set("title", $type->name . " #" . $issue->id . ": " . $issue->name); $f3->set("menuitem", "browse"); $author = new \Model\User(); $author->load($issue->author_id); $owner = new \Model\User(); if ($issue->owner_id) { $owner->load($issue->owner_id); } $files = new \Model\Issue\File\Detail(); $f3->set("files", $files->find(array("issue_id = ? AND deleted_date IS NULL", $issue->id))); if ($issue->sprint_id) { $sprint = new \Model\Sprint(); $sprint->load($issue->sprint_id); $f3->set("sprint", $sprint); } $watching = new \Model\Issue\Watcher(); $watching->load(array("issue_id = ? AND user_id = ?", $issue->id, $this->_userId)); $f3->set("watching", !!$watching->id); $f3->set("issue", $issue); $f3->set("ancestors", $issue->getAncestors()); $f3->set("type", $type); $f3->set("author", $author); $f3->set("owner", $owner); $comments = new \Model\Issue\Comment\Detail(); $f3->set("comments", $comments->find(array("issue_id = ?", $issue->id), array("order" => "created_date DESC"))); // Extra data needed for inline edit form $status = new \Model\Issue\Status(); $f3->set("statuses", $status->find(null, null, $f3->get("cache_expire.db"))); $priority = new \Model\Issue\Priority(); $f3->set("priorities", $priority->find(null, array("order" => "value DESC"), $f3->get("cache_expire.db"))); $sprint = new \Model\Sprint(); $f3->set("sprints", $sprint->find(array("end_date >= ? OR id = ?", $this->now(false), $issue->sprint_id), array("order" => "start_date ASC"))); $users = new \Model\User(); $f3->set("users", $users->find("deleted_date IS NULL AND role != 'group'", array("order" => "name ASC"))); $f3->set("groups", $users->find("deleted_date IS NULL AND role = 'group'", array("order" => "name ASC"))); $this->_render("issues/single.html"); }
/** * @param \Base $f3 * @param array $params * @throws \Exception */ public function single($f3, $params) { $issue = new \Model\Issue\Detail(); $issue->load(array("id=?", $f3->get("PARAMS.id"))); $user = $f3->get("user_obj"); if (!$issue->id || $issue->deleted_date && !($user->role == 'admin' || $user->rank >= \Model\User::RANK_MANAGER || $issue->author_id == $user->id)) { $f3->error(404); return; } $type = new \Model\Issue\Type(); $type->load($issue->type_id); // Run actions if passed $post = $f3->get("POST"); if (!empty($post)) { switch ($post["action"]) { case "add_watcher": $watching = new \Model\Issue\Watcher(); // Loads just in case the user is already a watcher $watching->load(array("issue_id = ? AND user_id = ?", $issue->id, $post["user_id"])); if (!$watching->id) { $watching->issue_id = $issue->id; $watching->user_id = $post["user_id"]; $watching->save(); } if ($f3->get("AJAX")) { return; } break; case "remove_watcher": $watching = new \Model\Issue\Watcher(); $watching->load(array("issue_id = ? AND user_id = ?", $issue->id, $post["user_id"])); $watching->delete(); if ($f3->get("AJAX")) { return; } break; case "add_dependency": $dependencies = new \Model\Issue\Dependency(); // Loads just in case the task is already a dependency $dependencies->load(array("issue_id = ? AND dependency_id = ?", $issue->id, $post["id"])); $dependencies->issue_id = $issue->id; $dependencies->dependency_id = $post["id"]; $dependencies->dependency_type = $post["type_id"]; $dependencies->save(); if ($f3->get("AJAX")) { return; } break; case "add_dependent": $dependencies = new \Model\Issue\Dependency(); // Loads just in case the task is already a dependency $dependencies->load(array("issue_id = ? AND dependency_id = ?", $post["id"], $issue->id)); $dependencies->dependency_id = $issue->id; $dependencies->issue_id = $post["id"]; $dependencies->dependency_type = $post["type_id"]; $dependencies->save(); if ($f3->get("AJAX")) { return; } break; case "remove_dependency": $dependencies = new \Model\Issue\Dependency(); $dependencies->load($post["id"]); $dependencies->delete(); if ($f3->get("AJAX")) { return; } break; } } $f3->set("title", $type->name . " #" . $issue->id . ": " . $issue->name); $f3->set("menuitem", "browse"); $author = new \Model\User(); $author->load($issue->author_id); $owner = new \Model\User(); if ($issue->owner_id) { $owner->load($issue->owner_id); } $files = new \Model\Issue\File\Detail(); $f3->set("files", $files->find(array("issue_id = ? AND deleted_date IS NULL", $issue->id))); if ($issue->sprint_id) { $sprint = new \Model\Sprint(); $sprint->load($issue->sprint_id); $f3->set("sprint", $sprint); } $watching = new \Model\Issue\Watcher(); $watching->load(array("issue_id = ? AND user_id = ?", $issue->id, $this->_userId)); $f3->set("watching", !!$watching->id); $f3->set("issue", $issue); $f3->set("ancestors", $issue->getAncestors()); $f3->set("type", $type); $f3->set("author", $author); $f3->set("owner", $owner); $comments = new \Model\Issue\Comment\Detail(); $f3->set("comments", $comments->find(array("issue_id = ?", $issue->id), array("order" => "created_date DESC"))); // Extra data needed for inline edit form $status = new \Model\Issue\Status(); $f3->set("statuses", $status->find(null, null, $f3->get("cache_expire.db"))); $priority = new \Model\Issue\Priority(); $f3->set("priorities", $priority->find(null, array("order" => "value DESC"), $f3->get("cache_expire.db"))); $sprint = new \Model\Sprint(); $f3->set("sprints", $sprint->find(array("end_date >= ? OR id = ?", $this->now(false), $issue->sprint_id), array("order" => "start_date ASC"))); $users = new \Model\User(); $f3->set("users", $users->find("deleted_date IS NULL AND role != 'group'", array("order" => "name ASC"))); $f3->set("groups", $users->find("deleted_date IS NULL AND role = 'group'", array("order" => "name ASC"))); $this->_render("issues/single.html"); }