From 2fd177363b1359566ad0078fbb8ec9138eea170c Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 16 Aug 2015 22:17:45 -0400 Subject: Add project users overview --- app/Controller/Gantt.php | 2 +- app/Controller/Project.php | 2 +- app/Controller/Projectuser.php | 136 ++++++++++++++++++++++++++++++++++ app/Model/Acl.php | 1 + app/Model/Project.php | 37 +++++++++ app/Model/ProjectPermission.php | 77 +++++++++++++------ app/Model/TaskFinder.php | 37 +++++++++ app/Model/User.php | 11 ++- app/Template/layout.php | 10 ++- app/Template/project/index.php | 44 ++++++++--- app/Template/project_user/layout.php | 28 +++++++ app/Template/project_user/roles.php | 33 +++++++++ app/Template/project_user/sidebar.php | 28 +++++++ app/Template/project_user/tasks.php | 46 ++++++++++++ app/Template/user/edit.php | 4 +- 15 files changed, 455 insertions(+), 41 deletions(-) create mode 100644 app/Controller/Projectuser.php create mode 100644 app/Template/project_user/layout.php create mode 100644 app/Template/project_user/roles.php create mode 100644 app/Template/project_user/sidebar.php create mode 100644 app/Template/project_user/tasks.php (limited to 'app') diff --git a/app/Controller/Gantt.php b/app/Controller/Gantt.php index 1ea5e957..6f3fb5c7 100644 --- a/app/Controller/Gantt.php +++ b/app/Controller/Gantt.php @@ -42,7 +42,7 @@ class Gantt extends Base */ public function saveDate() { - $project = $this->getProject(); + $this->getProject(); $values = $this->request->getJson(); $result = $this->taskModification->update(array( diff --git a/app/Controller/Project.php b/app/Controller/Project.php index 9309cfae..3e3e47ce 100644 --- a/app/Controller/Project.php +++ b/app/Controller/Project.php @@ -30,7 +30,7 @@ class Project extends Base ->setUrl('project', 'index') ->setMax(20) ->setOrder('name') - ->setQuery($this->project->getQueryColumnStats($project_ids)) + ->setQuery($this->project->getQueryProjectDetails($project_ids)) ->calculate(); $this->response->html($this->template->layout('project/index', array( diff --git a/app/Controller/Projectuser.php b/app/Controller/Projectuser.php new file mode 100644 index 00000000..dba069c9 --- /dev/null +++ b/app/Controller/Projectuser.php @@ -0,0 +1,136 @@ +projectPermission->getAllowedProjects($this->userSession->getId()); + $params['content_for_sublayout'] = $this->template->render($template, $params); + $params['filter'] = array('user_id' => $params['user_id']); + + return $this->template->layout('project_user/layout', $params); + } + + private function common() + { + $user_id = $this->request->getIntegerParam('user_id', UserModel::EVERYBODY_ID); + + if ($this->userSession->isAdmin()) { + $project_ids = $this->project->getAllIds(); + } + else { + $project_ids = $this->projectPermission->getMemberProjectIds($this->userSession->getId()); + } + + return array($user_id, $project_ids, $this->user->getList(true)); + } + + private function role($is_owner, $action, $title, $title_user) + { + list($user_id, $project_ids, $users) = $this->common(); + + $query = $this->projectPermission->getQueryByRole($project_ids, $is_owner)->callback(array($this->project, 'applyColumnStats')); + + if ($user_id !== UserModel::EVERYBODY_ID) { + $query->eq(UserModel::TABLE.'.id', $user_id); + $title = t($title_user, $users[$user_id]); + } + + $paginator = $this->paginator + ->setUrl('projectuser', $action, array('user_id' => $user_id)) + ->setMax(30) + ->setOrder('projects.name') + ->setQuery($query) + ->calculate(); + + $this->response->html($this->layout('project_user/roles', array( + 'paginator' => $paginator, + 'title' => $title, + 'action' => $action, + 'user_id' => $user_id, + 'users' => $users, + ))); + } + + private function tasks($is_active, $action, $title, $title_user) + { + list($user_id, $project_ids, $users) = $this->common(); + + $query = $this->taskFinder->getProjectUserOverviewQuery($project_ids, $is_active); + + if ($user_id !== UserModel::EVERYBODY_ID) { + $query->eq(TaskModel::TABLE.'.owner_id', $user_id); + $title = t($title_user, $users[$user_id]); + } + + $paginator = $this->paginator + ->setUrl('projectuser', $action, array('user_id' => $user_id)) + ->setMax(50) + ->setOrder(TaskModel::TABLE.'.id') + ->setQuery($query) + ->calculate(); + + $this->response->html($this->layout('project_user/tasks', array( + 'paginator' => $paginator, + 'title' => $title, + 'action' => $action, + 'user_id' => $user_id, + 'users' => $users, + ))); + } + + /** + * Display the list of project managers + * + */ + public function managers() + { + $this->role(1, 'managers', t('People who are project managers'), 'Projects where "%s" is manager'); + } + + /** + * Display the list of project members + * + */ + public function members() + { + $this->role(0, 'members', t('People who are project members'), 'Projects where "%s" is member'); + } + + /** + * Display the list of open taks + * + */ + public function opens() + { + $this->tasks(TaskModel::STATUS_OPEN, 'opens', t('Open tasks'), 'Open tasks assigned to "%s"'); + } + + /** + * Display the list of closed tasks + * + */ + public function closed() + { + $this->tasks(TaskModel::STATUS_CLOSED, 'closed', t('Closed tasks'), 'Closed tasks assigned to "%s"'); + } +} diff --git a/app/Model/Acl.php b/app/Model/Acl.php index 312ae7d4..b1e9eb07 100644 --- a/app/Model/Acl.php +++ b/app/Model/Acl.php @@ -76,6 +76,7 @@ class Acl extends Base */ private $project_admin_acl = array( 'project' => array('remove'), + 'projectuser' => '*', ); /** diff --git a/app/Model/Project.php b/app/Model/Project.php index 3c864e5d..fedc41ac 100644 --- a/app/Model/Project.php +++ b/app/Model/Project.php @@ -260,6 +260,24 @@ class Project extends Base return $projects; } + /** + * Fetch more information for each project + * + * @access public + * @param array $projects + * @return array + */ + public function applyProjectDetails(array $projects) + { + foreach ($projects as &$project) { + $this->getColumnStats($project); + $project['managers'] = $this->projectPermission->getManagers($project['id']); + $project['members'] = $this->projectPermission->getOnlyMembers($project['id']); + } + + return $projects; + } + /** * Get project summary for a list of project * @@ -279,6 +297,25 @@ class Project extends Base ->callback(array($this, 'applyColumnStats')); } + /** + * Get project details (users + columns) for a list of project + * + * @access public + * @param array $project_ids List of project id + * @return \PicoDb\Table + */ + public function getQueryProjectDetails(array $project_ids) + { + if (empty($project_ids)) { + return $this->db->table(Project::TABLE)->limit(0); + } + + return $this->db + ->table(Project::TABLE) + ->in('id', $project_ids) + ->callback(array($this, 'applyProjectDetails')); + } + /** * Create a project * diff --git a/app/Model/ProjectPermission.php b/app/Model/ProjectPermission.php index bc752dda..03e9bea6 100644 --- a/app/Model/ProjectPermission.php +++ b/app/Model/ProjectPermission.php @@ -66,18 +66,19 @@ class ProjectPermission extends Base } /** - * Get a list of people associated to the project + * Get a list of standard user members for a project * * @access public * @param integer $project_id Project id * @return array */ - public function getAssociatedUsers($project_id) + public function getOnlyMembers($project_id) { $users = $this->db ->table(self::TABLE) ->join(User::TABLE, 'id', 'user_id') ->eq('project_id', $project_id) + ->eq('is_owner', 0) ->asc('username') ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name') ->findAll(); @@ -106,6 +107,57 @@ class ProjectPermission extends Base return $this->user->prepareList($users); } + /** + * Get query for project users overview + * + * @access public + * @param array $project_ids + * @param integer $is_owner + * @return \PicoDb\Table + */ + public function getQueryByRole(array $project_ids, $is_owner = 0) + { + if (empty($project_ids)) { + $project_ids = array(-1); + } + + return $this + ->db + ->table(self::TABLE) + ->join(User::TABLE, 'id', 'user_id') + ->join(Project::TABLE, 'id', 'project_id') + ->eq(self::TABLE.'.is_owner', $is_owner) + ->eq(Project::TABLE.'.is_private', 0) + ->in(Project::TABLE.'.id', $project_ids) + ->columns( + User::TABLE.'.id', + User::TABLE.'.username', + User::TABLE.'.name', + Project::TABLE.'.name AS project_name', + Project::TABLE.'.id' + ); + } + + /** + * Get a list of people associated to the project + * + * @access public + * @param integer $project_id Project id + * @return array + */ + public function getAssociatedUsers($project_id) + { + $users = $this->db + ->table(self::TABLE) + ->join(User::TABLE, 'id', 'user_id') + ->eq('project_id', $project_id) + ->asc('username') + ->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name') + ->findAll(); + + return $this->user->prepareList($users); + } + /** * Get allowed and not allowed users for a project * @@ -127,7 +179,6 @@ class ProjectPermission extends Base $users['managers'] = $this->getManagers($project_id); foreach ($all_users as $user_id => $username) { - if (! isset($users['allowed'][$user_id])) { $users['not_allowed'][$user_id] = $username; } @@ -269,26 +320,6 @@ class ProjectPermission extends Base ->exists(); } - /** - * Filter a list of projects for a given user - * - * @access public - * @param array $projects Project list: ['project_id' => 'project_name'] - * @param integer $user_id User id - * @param string $filter Method name to apply - * @return array - */ - public function filterProjects(array $projects, $user_id, $filter = 'isUserAllowed') - { - foreach ($projects as $project_id => $project_name) { - if (! $this->$filter($project_id, $user_id)) { - unset($projects[$project_id]); - } - } - - return $projects; - } - /** * Return a list of allowed active projects for a given user * diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index 6cf79d1f..b98e3bd5 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -12,6 +12,43 @@ use PDO; */ class TaskFinder extends Base { + /** + * Get query for project user overview + * + * @access public + * @param array $project_ids + * @param integer $is_active + * @return \PicoDb\Table + */ + public function getProjectUserOverviewQuery(array $project_ids, $is_active) + { + if (empty($project_ids)) { + $project_ids = array(-1); + } + + return $this->db + ->table(Task::TABLE) + ->columns( + Task::TABLE.'.id', + Task::TABLE.'.title', + Task::TABLE.'.date_due', + Task::TABLE.'.date_started', + Task::TABLE.'.project_id', + Task::TABLE.'.color_id', + Task::TABLE.'.time_spent', + Task::TABLE.'.time_estimated', + Project::TABLE.'.name AS project_name', + Board::TABLE.'.title AS column_name', + User::TABLE.'.username AS assignee_username', + User::TABLE.'.name AS assignee_name' + ) + ->eq(Task::TABLE.'.is_active', $is_active) + ->in(Project::TABLE.'.id', $project_ids) + ->join(Project::TABLE, 'id', 'project_id') + ->join(Board::TABLE, 'id', 'column_id', Task::TABLE) + ->join(User::TABLE, 'id', 'owner_id', Task::TABLE); + } + /** * Get query for assigned user tasks * diff --git a/app/Model/User.php b/app/Model/User.php index 76af342d..1a7a0666 100644 --- a/app/Model/User.php +++ b/app/Model/User.php @@ -208,12 +208,19 @@ class User extends Base * List all users (key-value pairs with id/username) * * @access public + * @param boolean $prepend Prepend "All users" * @return array */ - public function getList() + public function getList($prepend = false) { $users = $this->db->table(self::TABLE)->columns('id', 'username', 'name')->findAll(); - return $this->prepareList($users); + $listing = $this->prepareList($users); + + if ($prepend) { + return array(User::EVERYBODY_ID => t('Everybody')) + $listing; + } + + return $listing; } /** diff --git a/app/Template/layout.php b/app/Template/layout.php index 7d986309..fcdc23a0 100644 --- a/app/Template/layout.php +++ b/app/Template/layout.php @@ -12,7 +12,7 @@ - asset->js('assets/js/app.js', true) ?> + asset->js('assets/js/app.js') ?> asset->colorCss() ?> @@ -48,7 +48,13 @@
isEmpty()): ?>

- +
- - - + + + user->isAdmin() || $this->user->isProjectAdmin()): ?> + + + getCollection() as $project): ?> @@ -32,16 +38,14 @@ - + user->isAdmin() || $this->user->isProjectAdmin()): ?> + + +
order(t('Id'), 'id') ?>order(t('Status'), 'is_active') ?>order(t('Identifier'), 'identifier') ?>order(t('Id'), 'id') ?>order(t('Status'), 'is_active') ?> order(t('Project'), 'name') ?>
- e($project['identifier']) ?> - - url->link('', 'board', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Board')) ?>  + url->link('', 'board', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Board')) ?> + url->link('', 'gantt', 'project', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Gantt chart')) ?> - + - + url->link($this->e($project['name']), 'project', 'show', array('project_id' => $project['id'])) ?> @@ -51,6 +55,26 @@ +
    + $user_name): ?> +
  • url->link($this->e($user_name), 'projectuser', 'opens', array('user_id' => $user_id)) ?>
  • + +
+
+ + + +
    + $user_name): ?> +
  • url->link($this->e($user_name), 'projectuser', 'opens', array('user_id' => $user_id)) ?>
  • + +
+ +
diff --git a/app/Template/project_user/layout.php b/app/Template/project_user/layout.php new file mode 100644 index 00000000..23486cb7 --- /dev/null +++ b/app/Template/project_user/layout.php @@ -0,0 +1,28 @@ +
+ + +
\ No newline at end of file diff --git a/app/Template/project_user/roles.php b/app/Template/project_user/roles.php new file mode 100644 index 00000000..35d16241 --- /dev/null +++ b/app/Template/project_user/roles.php @@ -0,0 +1,33 @@ +isEmpty()): ?> +

+ + + + + + + + getCollection() as $project): ?> + + + + + + +
order(t('User'), 'users.username') ?>order(t('Project'), 'projects.name') ?>
+ e($this->user->getFullname($project)) ?> + + url->link('', 'board', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Board')) ?> + url->link('', 'gantt', 'project', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Gantt chart')) ?> + url->link('', 'project', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Project settings')) ?> + + e($project['project_name']) ?> + + + + e($column['title']) ?> + +
+ + + \ No newline at end of file diff --git a/app/Template/project_user/sidebar.php b/app/Template/project_user/sidebar.php new file mode 100644 index 00000000..f57323d5 --- /dev/null +++ b/app/Template/project_user/sidebar.php @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/app/Template/project_user/tasks.php b/app/Template/project_user/tasks.php new file mode 100644 index 00000000..f4fc2723 --- /dev/null +++ b/app/Template/project_user/tasks.php @@ -0,0 +1,46 @@ +isEmpty()): ?> +

+isEmpty()): ?> + + + + + + + + + + + getCollection() as $task): ?> + + + + + + + + + + +
order(t('Id'), 'tasks.id') ?>order(t('Project'), 'projects.name') ?>order(t('Column'), 'tasks.column_id') ?>order(t('Title'), 'tasks.title') ?>order(t('Assignee'), 'users.username') ?>order(t('Start date'), 'tasks.date_started') ?>order(t('Due date'), 'tasks.date_due') ?>
+ url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> + + url->link($this->e($task['project_name']), 'board', 'show', array('project_id' => $task['project_id'])) ?> + + e($task['column_name']) ?> + + url->link($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> + + + e($task['assignee_name'] ?: $task['assignee_username']) ?> + + + + + + + +
+ + + diff --git a/app/Template/user/edit.php b/app/Template/user/edit.php index a60ee681..cd10b2ab 100644 --- a/app/Template/user/edit.php +++ b/app/Template/user/edit.php @@ -23,8 +23,8 @@ form->select('language', $languages, $values, $errors) ?>
user->isAdmin()): ?> - form->checkbox('is_admin', t('Administrator'), 1, isset($values['is_admin']) && $values['is_admin'] == 1) ?>
- form->checkbox('is_project_admin', t('Project Administrator'), 1, isset($values['is_project_admin']) && $values['is_project_admin'] == 1) ?>
+ form->checkbox('is_admin', t('Administrator'), 1, isset($values['is_admin']) && $values['is_admin'] == 1) ?> + form->checkbox('is_project_admin', t('Project Administrator'), 1, isset($values['is_project_admin']) && $values['is_project_admin'] == 1) ?>
-- cgit v1.2.3