diff options
author | Frederic Guillot <fred@kanboard.net> | 2016-01-31 17:46:19 -0500 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2016-01-31 17:46:19 -0500 |
commit | fc21d3873e3ac63222ad4065a593c715bef4c251 (patch) | |
tree | b1795031eda0774aeb1af9fb20606fe38611e0eb /app | |
parent | 1500ff92b2dc3d3932c8e06755bec23f9017e8a4 (diff) |
When creating a new project, have the possibility to select another project to duplicate
Diffstat (limited to 'app')
-rw-r--r-- | app/Console/Base.php | 25 | ||||
-rw-r--r-- | app/Controller/Project.php | 60 | ||||
-rw-r--r-- | app/Controller/ProjectCreation.php | 126 | ||||
-rw-r--r-- | app/Controller/ProjectEdit.php | 4 | ||||
-rw-r--r-- | app/Controller/ProjectPermission.php | 56 | ||||
-rw-r--r-- | app/Controller/Taskduplication.php | 2 | ||||
-rw-r--r-- | app/Core/ExternalLink/ExternalLinkManager.php | 2 | ||||
-rw-r--r-- | app/Model/ProjectDuplication.php | 140 | ||||
-rw-r--r-- | app/Model/Task.php | 21 | ||||
-rw-r--r-- | app/Model/TaskFinder.php | 17 | ||||
-rw-r--r-- | app/ServiceProvider/AuthenticationProvider.php | 3 | ||||
-rw-r--r-- | app/ServiceProvider/RouteProvider.php | 6 | ||||
-rw-r--r-- | app/Template/app/layout.php | 6 | ||||
-rw-r--r-- | app/Template/gantt/projects.php | 6 | ||||
-rw-r--r-- | app/Template/header.php | 18 | ||||
-rw-r--r-- | app/Template/project/duplicate.php | 6 | ||||
-rw-r--r-- | app/Template/project/index.php | 4 | ||||
-rw-r--r-- | app/Template/project/new.php | 24 | ||||
-rw-r--r-- | app/Template/project_creation/create.php | 42 | ||||
-rw-r--r-- | app/Template/project_edit/general.php | 2 | ||||
-rw-r--r-- | app/Template/project_user/layout.php | 7 |
21 files changed, 386 insertions, 191 deletions
diff --git a/app/Console/Base.php b/app/Console/Base.php index 4c5caf73..ac89207d 100644 --- a/app/Console/Base.php +++ b/app/Console/Base.php @@ -11,18 +11,19 @@ use Symfony\Component\Console\Command\Command; * @package console * @author Frederic Guillot * - * @property \Kanboard\Model\Notification $notification - * @property \Kanboard\Model\Project $project - * @property \Kanboard\Model\ProjectPermission $projectPermission - * @property \Kanboard\Model\ProjectAnalytic $projectAnalytic - * @property \Kanboard\Model\ProjectDailyColumnStats $projectDailyColumnStats - * @property \Kanboard\Model\ProjectDailyStats $projectDailyStats - * @property \Kanboard\Model\SubtaskExport $subtaskExport - * @property \Kanboard\Model\OverdueNotification $overdueNotification - * @property \Kanboard\Model\Task $task - * @property \Kanboard\Model\TaskExport $taskExport - * @property \Kanboard\Model\TaskFinder $taskFinder - * @property \Kanboard\Model\Transition $transition + * @property \Kanboard\Model\Notification $notification + * @property \Kanboard\Model\Project $project + * @property \Kanboard\Model\ProjectPermission $projectPermission + * @property \Kanboard\Model\ProjectAnalytic $projectAnalytic + * @property \Kanboard\Model\ProjectDailyColumnStats $projectDailyColumnStats + * @property \Kanboard\Model\ProjectDailyStats $projectDailyStats + * @property \Kanboard\Model\SubtaskExport $subtaskExport + * @property \Kanboard\Model\OverdueNotification $overdueNotification + * @property \Kanboard\Model\Task $task + * @property \Kanboard\Model\TaskExport $taskExport + * @property \Kanboard\Model\TaskFinder $taskFinder + * @property \Kanboard\Model\Transition $transition + * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher */ abstract class Base extends Command { diff --git a/app/Controller/Project.php b/app/Controller/Project.php index ffd62b09..661fd68b 100644 --- a/app/Controller/Project.php +++ b/app/Controller/Project.php @@ -171,14 +171,15 @@ class Project extends Base $project = $this->getProject(); if ($this->request->getStringParam('duplicate') === 'yes') { - $values = array_keys($this->request->getValues()); - if ($this->projectDuplication->duplicate($project['id'], $values) !== false) { + $project_id = $this->projectDuplication->duplicate($project['id'], array_keys($this->request->getValues()), $this->userSession->getId()); + + if ($project_id !== false) { $this->flash->success(t('Project cloned successfully.')); } else { $this->flash->failure(t('Unable to clone this project.')); } - $this->response->redirect($this->helper->url->to('project', 'index')); + $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id))); } $this->response->html($this->projectLayout('project/duplicate', array( @@ -240,57 +241,4 @@ class Project extends Base 'title' => t('Project activation') ))); } - - /** - * Display a form to create a new project - * - * @access public - */ - public function create(array $values = array(), array $errors = array()) - { - $is_private = isset($values['is_private']) && $values['is_private'] == 1; - - $this->response->html($this->template->layout('project/new', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), - 'values' => $values, - 'errors' => $errors, - 'is_private' => $is_private, - 'title' => $is_private ? t('New private project') : t('New project'), - ))); - } - - /** - * Display a form to create a private project - * - * @access public - */ - public function createPrivate(array $values = array(), array $errors = array()) - { - $values['is_private'] = 1; - $this->create($values, $errors); - } - - /** - * Validate and save a new project - * - * @access public - */ - public function save() - { - $values = $this->request->getValues(); - list($valid, $errors) = $this->projectValidator->validateCreation($values); - - if ($valid) { - $project_id = $this->project->create($values, $this->userSession->getId(), true); - - if ($project_id > 0) { - $this->flash->success(t('Your project have been created successfully.')); - $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id))); - } - - $this->flash->failure(t('Unable to create your project.')); - } - - $this->create($values, $errors); - } } diff --git a/app/Controller/ProjectCreation.php b/app/Controller/ProjectCreation.php new file mode 100644 index 00000000..a3154034 --- /dev/null +++ b/app/Controller/ProjectCreation.php @@ -0,0 +1,126 @@ +<?php + +namespace Kanboard\Controller; + +/** + * Project Creation Controller + * + * @package controller + * @author Frederic Guillot + */ +class ProjectCreation extends Base +{ + /** + * Display a form to create a new project + * + * @access public + */ + public function create(array $values = array(), array $errors = array()) + { + $is_private = isset($values['is_private']) && $values['is_private'] == 1; + $projects_list = array(0 => t('Do not duplicate anything')) + $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); + + $this->response->html($this->template->layout('project_creation/create', array( + 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + 'values' => $values, + 'errors' => $errors, + 'is_private' => $is_private, + 'projects_list' => $projects_list, + 'title' => $is_private ? t('New private project') : t('New project'), + ))); + } + + /** + * Display a form to create a private project + * + * @access public + */ + public function createPrivate(array $values = array(), array $errors = array()) + { + $values['is_private'] = 1; + $this->create($values, $errors); + } + + /** + * Validate and save a new project + * + * @access public + */ + public function save() + { + $values = $this->request->getValues(); + list($valid, $errors) = $this->projectValidator->validateCreation($values); + + if ($valid) { + $project_id = $this->createOrDuplicate($values); + + if ($project_id > 0) { + $this->flash->success(t('Your project have been created successfully.')); + return $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id))); + } + + $this->flash->failure(t('Unable to create your project.')); + } + + $this->create($values, $errors); + } + + /** + * Create or duplicate a project + * + * @access private + * @param array $values + * @return boolean|integer + */ + private function createOrDuplicate(array $values) + { + if ($values['src_project_id'] == 0) { + return $this->createNewProject($values); + } + + return $this->duplicateNewProject($values); + } + + /** + * Save a new project + * + * @access private + * @param array $values + * @return boolean|integer + */ + private function createNewProject(array $values) + { + $project = array( + 'name' => $values['name'], + 'is_private' => $values['is_private'], + ); + + return $this->project->create($project, $this->userSession->getId(), true); + } + + /** + * Creatte from another project + * + * @access private + * @param array $values + * @return boolean|integer + */ + private function duplicateNewProject(array $values) + { + $selection = array(); + + foreach ($this->projectDuplication->getOptionalSelection() as $item) { + if (isset($values[$item]) && $values[$item] == 1) { + $selection[] = $item; + } + } + + return $this->projectDuplication->duplicate( + $values['src_project_id'], + $selection, + $this->userSession->getId(), + $values['name'], + $values['is_private'] == 1 + ); + } +} diff --git a/app/Controller/ProjectEdit.php b/app/Controller/ProjectEdit.php index 0dfc7de3..29793c47 100644 --- a/app/Controller/ProjectEdit.php +++ b/app/Controller/ProjectEdit.php @@ -89,11 +89,11 @@ class ProjectEdit extends Base { if ($redirect === 'edit') { if (isset($values['is_private'])) { - if (! $this->helper->user->hasProjectAccess('project', 'create', $project['id'])) { + if (! $this->helper->user->hasProjectAccess('ProjectCreation', 'create', $project['id'])) { unset($values['is_private']); } } elseif ($project['is_private'] == 1 && ! isset($values['is_private'])) { - if ($this->helper->user->hasProjectAccess('project', 'create', $project['id'])) { + if ($this->helper->user->hasProjectAccess('ProjectCreation', 'create', $project['id'])) { $values += array('is_private' => 0); } } diff --git a/app/Controller/ProjectPermission.php b/app/Controller/ProjectPermission.php index 4434d017..e0e58240 100644 --- a/app/Controller/ProjectPermission.php +++ b/app/Controller/ProjectPermission.php @@ -13,6 +13,24 @@ use Kanboard\Core\Security\Role; class ProjectPermission extends Base { /** + * Permissions are only available for team projects + * + * @access protected + * @param integer $project_id Default project id + * @return array + */ + protected function getProject($project_id = 0) + { + $project = parent::getProject($project_id); + + if ($project['is_private'] == 1) { + $this->forbidden(); + } + + return $project; + } + + /** * Show all permissions * * @access public @@ -62,6 +80,7 @@ class ProjectPermission extends Base */ public function addUser() { + $project = $this->getProject(); $values = $this->request->getValues(); if ($this->projectUserRole->addUser($values['project_id'], $values['user_id'], $values['role'])) { @@ -70,7 +89,7 @@ class ProjectPermission extends Base $this->flash->failure(t('Unable to update this project.')); } - $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $values['project_id']))); + $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id']))); } /** @@ -81,19 +100,16 @@ class ProjectPermission extends Base public function removeUser() { $this->checkCSRFParam(); + $project = $this->getProject(); + $user_id = $this->request->getIntegerParam('user_id'); - $values = array( - 'project_id' => $this->request->getIntegerParam('project_id'), - 'user_id' => $this->request->getIntegerParam('user_id'), - ); - - if ($this->projectUserRole->removeUser($values['project_id'], $values['user_id'])) { + if ($this->projectUserRole->removeUser($project['id'], $user_id)) { $this->flash->success(t('Project updated successfully.')); } else { $this->flash->failure(t('Unable to update this project.')); } - $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $values['project_id']))); + $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id']))); } /** @@ -103,10 +119,10 @@ class ProjectPermission extends Base */ public function changeUserRole() { - $project_id = $this->request->getIntegerParam('project_id'); + $project = $this->getProject(); $values = $this->request->getJson(); - if (! empty($project_id) && ! empty($values) && $this->projectUserRole->changeUserRole($project_id, $values['id'], $values['role'])) { + if (! empty($project) && ! empty($values) && $this->projectUserRole->changeUserRole($project['id'], $values['id'], $values['role'])) { $this->response->json(array('status' => 'ok')); } else { $this->response->json(array('status' => 'error')); @@ -120,19 +136,20 @@ class ProjectPermission extends Base */ public function addGroup() { + $project = $this->getProject(); $values = $this->request->getValues(); if (empty($values['group_id']) && ! empty($values['external_id'])) { $values['group_id'] = $this->group->create($values['name'], $values['external_id']); } - if ($this->projectGroupRole->addGroup($values['project_id'], $values['group_id'], $values['role'])) { + if ($this->projectGroupRole->addGroup($project['id'], $values['group_id'], $values['role'])) { $this->flash->success(t('Project updated successfully.')); } else { $this->flash->failure(t('Unable to update this project.')); } - $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $values['project_id']))); + $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id']))); } /** @@ -143,19 +160,16 @@ class ProjectPermission extends Base public function removeGroup() { $this->checkCSRFParam(); + $project = $this->getProject(); + $group_id = $this->request->getIntegerParam('group_id'); - $values = array( - 'project_id' => $this->request->getIntegerParam('project_id'), - 'group_id' => $this->request->getIntegerParam('group_id'), - ); - - if ($this->projectGroupRole->removeGroup($values['project_id'], $values['group_id'])) { + if ($this->projectGroupRole->removeGroup($project['id'], $group_id)) { $this->flash->success(t('Project updated successfully.')); } else { $this->flash->failure(t('Unable to update this project.')); } - $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $values['project_id']))); + $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id']))); } /** @@ -165,10 +179,10 @@ class ProjectPermission extends Base */ public function changeGroupRole() { - $project_id = $this->request->getIntegerParam('project_id'); + $project = $this->getProject(); $values = $this->request->getJson(); - if (! empty($project_id) && ! empty($values) && $this->projectGroupRole->changeGroupRole($project_id, $values['id'], $values['role'])) { + if (! empty($project) && ! empty($values) && $this->projectGroupRole->changeGroupRole($project['id'], $values['id'], $values['role'])) { $this->response->json(array('status' => 'ok')); } else { $this->response->json(array('status' => 'error')); diff --git a/app/Controller/Taskduplication.php b/app/Controller/Taskduplication.php index ae8bfcbc..a41183a7 100644 --- a/app/Controller/Taskduplication.php +++ b/app/Controller/Taskduplication.php @@ -109,7 +109,7 @@ class Taskduplication extends Base private function chooseDestination(array $task, $template) { $values = array(); - $projects_list = $this->projectUserRole->getProjectsByUser($this->userSession->getId(), array(ProjectModel::ACTIVE)); + $projects_list = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); unset($projects_list[$task['project_id']]); diff --git a/app/Core/ExternalLink/ExternalLinkManager.php b/app/Core/ExternalLink/ExternalLinkManager.php index cd3476ca..59f36e54 100644 --- a/app/Core/ExternalLink/ExternalLinkManager.php +++ b/app/Core/ExternalLink/ExternalLinkManager.php @@ -120,8 +120,6 @@ class ExternalLinkManager extends Base */ public function find() { - $provider = null; - if ($this->userInputType === self::TYPE_AUTO) { $provider = $this->findProvider(); } else { diff --git a/app/Model/ProjectDuplication.php b/app/Model/ProjectDuplication.php index f0c66834..16e4f7c2 100644 --- a/app/Model/ProjectDuplication.php +++ b/app/Model/ProjectDuplication.php @@ -2,6 +2,8 @@ namespace Kanboard\Model; +use Kanboard\Core\Security\Role; + /** * Project Duplication * @@ -12,6 +14,28 @@ namespace Kanboard\Model; class ProjectDuplication extends Base { /** + * Get list of optional models to duplicate + * + * @access public + * @return array + */ + public function getOptionalSelection() + { + return array('category', 'projectPermission', 'action', 'swimlane', 'task'); + } + + /** + * Get list of all possible models to duplicate + * + * @access public + * @return array + */ + public function getPossibleSelection() + { + return array('board', 'category', 'projectPermission', 'action', 'swimlane', 'task'); + } + + /** * Get a valid project name for the duplication * * @access public @@ -31,78 +55,106 @@ class ProjectDuplication extends Base } /** - * Create a project from another one - * - * @param integer $project_id Project Id - * @return integer Cloned Project Id - */ - public function copy($project_id) - { - $project = $this->project->getById($project_id); - - $values = array( - 'name' => $this->getClonedProjectName($project['name']), - 'is_active' => true, - 'last_modified' => 0, - 'token' => '', - 'is_public' => 0, - 'is_private' => empty($project['is_private']) ? 0 : 1, - ); - - if (! $this->db->table(Project::TABLE)->save($values)) { - return 0; - } - - return $this->db->getLastId(); - } - - /** * Clone a project with all settings * - * @param integer $project_id Project Id - * @param array $part_selection Selection of optional project parts to duplicate. Possible options: 'swimlane', 'action', 'category', 'task' - * @return integer Cloned Project Id + * @param integer $src_project_id Project Id + * @param array $selection Selection of optional project parts to duplicate + * @param integer $owner_id Owner of the project + * @param string $name Name of the project + * @param boolean $private Force the project to be private + * @return integer Cloned Project Id */ - public function duplicate($project_id, $part_selection = array('category', 'action')) + public function duplicate($src_project_id, $selection = array('projectPermission', 'category', 'action'), $owner_id = 0, $name = null, $private = null) { $this->db->startTransaction(); // Get the cloned project Id - $clone_project_id = $this->copy($project_id); + $dst_project_id = $this->copy($src_project_id, $owner_id, $name, $private); - if (! $clone_project_id) { + if (! $dst_project_id) { $this->db->cancelTransaction(); return false; } // Clone Columns, Categories, Permissions and Actions - $optional_parts = array('swimlane', 'action', 'category'); - foreach (array('board', 'category', 'projectPermission', 'action', 'swimlane') as $model) { + foreach ($this->getPossibleSelection() as $model) { // Skip if optional part has not been selected - if (in_array($model, $optional_parts) && ! in_array($model, $part_selection)) { + if (in_array($model, $this->getOptionalSelection()) && ! in_array($model, $selection)) { continue; } - if (! $this->$model->duplicate($project_id, $clone_project_id)) { + // Skip permissions for private projects + if ($private && $model === 'projectPermission') { + continue; + } + + if (! $this->$model->duplicate($src_project_id, $dst_project_id)) { $this->db->cancelTransaction(); return false; } } + if (! $this->makeOwnerManager($dst_project_id, $owner_id)) { + $this->db->cancelTransaction(); + return false; + } + $this->db->closeTransaction(); - // Clone Tasks if in $part_selection - if (in_array('task', $part_selection)) { - $tasks = $this->taskFinder->getAll($project_id); + return (int) $dst_project_id; + } + + /** + * Create a project from another one + * + * @access private + * @param integer $src_project_id + * @param integer $owner_id + * @param string $name + * @param boolean $private + * @return integer + */ + private function copy($src_project_id, $owner_id = 0, $name = null, $private = null) + { + $project = $this->project->getById($src_project_id); + $is_private = empty($project['is_private']) ? 0 : 1; + + $values = array( + 'name' => $name ?: $this->getClonedProjectName($project['name']), + 'is_active' => 1, + 'last_modified' => time(), + 'token' => '', + 'is_public' => 0, + 'is_private' => $private ? 1 : $is_private, + 'owner_id' => $owner_id, + ); + + if (! $this->db->table(Project::TABLE)->save($values)) { + return false; + } + + return $this->db->getLastId(); + } + + /** + * Make sure that the creator of the duplicated project is alsp owner + * + * @access private + * @param integer $dst_project_id + * @param integer $owner_id + * @return boolean + */ + private function makeOwnerManager($dst_project_id, $owner_id) + { + if ($owner_id > 0) { + $this->projectUserRole->removeUser($dst_project_id, $owner_id); - foreach ($tasks as $task) { - if (! $this->taskDuplication->duplicateToProject($task['id'], $clone_project_id)) { - return false; - } + if (! $this->projectUserRole->addUser($dst_project_id, $owner_id, Role::PROJECT_MANAGER)) { + return false; } } - return (int) $clone_project_id; + return true; } } diff --git a/app/Model/Task.php b/app/Model/Task.php index 94b23ec2..38fdd0d5 100644 --- a/app/Model/Task.php +++ b/app/Model/Task.php @@ -199,4 +199,25 @@ class Task extends Base return round(($position * 100) / count($columns), 1); } + + /** + * Helper method to duplicate all tasks to another project + * + * @access public + * @param integer $src_project_id + * @param integer $dst_project_id + * @return boolean + */ + public function duplicate($src_project_id, $dst_project_id) + { + $task_ids = $this->taskFinder->getAllIds($src_project_id, array(Task::STATUS_OPEN, Task::STATUS_CLOSED)); + + foreach ($task_ids as $task_id) { + if (! $this->taskDuplication->duplicateToProject($task_id, $dst_project_id)) { + return false; + } + } + + return true; + } } diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index ab290bce..4d673097 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -180,6 +180,23 @@ class TaskFinder extends Base } /** + * Get all tasks for a given project and status + * + * @access public + * @param integer $project_id + * @param array $status + * @return array + */ + public function getAllIds($project_id, array $status = array(Task::STATUS_OPEN)) + { + return $this->db + ->table(Task::TABLE) + ->eq(Task::TABLE.'.project_id', $project_id) + ->in(Task::TABLE.'.is_active', $status) + ->findAllByColumn('id'); + } + + /** * Get overdue tasks query * * @access public diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index 144abb0e..aaf23083 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -128,8 +128,7 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('Gantt', array('projects', 'saveProjectDate'), Role::APP_MANAGER); $acl->add('Group', '*', Role::APP_ADMIN); $acl->add('Link', '*', Role::APP_ADMIN); - $acl->add('Project', array('users', 'allowEverybody', 'allow', 'role', 'revoke', 'create'), Role::APP_MANAGER); - $acl->add('ProjectPermission', '*', Role::APP_USER); + $acl->add('ProjectCreation', 'create', Role::APP_MANAGER); $acl->add('Projectuser', '*', Role::APP_MANAGER); $acl->add('Twofactor', 'disable', Role::APP_ADMIN); $acl->add('UserImport', '*', Role::APP_ADMIN); diff --git a/app/ServiceProvider/RouteProvider.php b/app/ServiceProvider/RouteProvider.php index ebe087ae..78c46bc4 100644 --- a/app/ServiceProvider/RouteProvider.php +++ b/app/ServiceProvider/RouteProvider.php @@ -43,10 +43,12 @@ class RouteProvider implements ServiceProviderInterface $container['route']->addRoute('search', 'search', 'index'); $container['route']->addRoute('search/:search', 'search', 'index'); + // ProjectCreation routes + $container['route']->addRoute('project/create', 'ProjectCreation', 'create'); + $container['route']->addRoute('project/create/private', 'ProjectCreation', 'createPrivate'); + // Project routes $container['route']->addRoute('projects', 'project', 'index'); - $container['route']->addRoute('project/create', 'project', 'create'); - $container['route']->addRoute('project/create/private', 'project', 'createPrivate'); $container['route']->addRoute('project/:project_id', 'project', 'show'); $container['route']->addRoute('p/:project_id', 'project', 'show'); $container['route']->addRoute('project/:project_id/customer-filter', 'customfilter', 'index'); diff --git a/app/Template/app/layout.php b/app/Template/app/layout.php index ad1d5a9e..d5bb1d8e 100644 --- a/app/Template/app/layout.php +++ b/app/Template/app/layout.php @@ -1,15 +1,15 @@ <section id="main"> <div class="page-header page-header-mobile"> <ul> - <?php if ($this->user->hasAccess('project', 'create')): ?> + <?php if ($this->user->hasAccess('ProjectCreation', 'create')): ?> <li> <i class="fa fa-plus fa-fw"></i> - <?= $this->url->link(t('New project'), 'project', 'create') ?> + <?= $this->url->link(t('New project'), 'ProjectCreation', 'create') ?> </li> <?php endif ?> <li> <i class="fa fa-lock fa-fw"></i> - <?= $this->url->link(t('New private project'), 'project', 'createPrivate') ?> + <?= $this->url->link(t('New private project'), 'ProjectCreation', 'createPrivate') ?> </li> <li> <i class="fa fa-search fa-fw"></i> diff --git a/app/Template/gantt/projects.php b/app/Template/gantt/projects.php index 46d2af91..84b260bb 100644 --- a/app/Template/gantt/projects.php +++ b/app/Template/gantt/projects.php @@ -1,12 +1,6 @@ <section id="main"> <div class="page-header"> <ul> - <?php if ($this->user->hasAccess('project', 'create')): ?> - <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New project'), 'project', 'create') ?></li> - <?php endif ?> - <li> - <i class="fa fa-lock fa-fw"></i><?= $this->url->link(t('New private project'), 'project', 'create', array('private' => 1)) ?> - </li> <li> <i class="fa fa-folder fa-fw"></i><?= $this->url->link(t('Projects list'), 'project', 'index') ?> </li> diff --git a/app/Template/header.php b/app/Template/header.php index 405d07b3..074f8fd3 100644 --- a/app/Template/header.php +++ b/app/Template/header.php @@ -31,14 +31,26 @@ </select> </li> <?php endif ?> - <li> + <li class="user-links"> <?php if ($this->user->hasNotifications()): ?> <span class="notification"> <?= $this->url->link('<i class="fa fa-bell web-notification-icon"></i>', 'app', 'notifications', array('user_id' => $this->user->getId()), false, '', t('Unread notifications')) ?> </span> <?php endif ?> - <span class="dropdown"> + <div class="dropdown"> + <a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-plus fa-fw"></i><i class="fa fa-caret-down"></i></a> + <ul> + <?php if ($this->user->hasAccess('ProjectCreation', 'create')): ?> + <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New project'), 'ProjectCreation', 'create') ?></li> + <?php endif ?> + <li> + <i class="fa fa-lock fa-fw"></i><?= $this->url->link(t('New private project'), 'ProjectCreation', 'createPrivate') ?> + </li> + </ul> + </div> + + <div class="dropdown"> <a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-user fa-fw"></i><i class="fa fa-caret-down"></i></a> <ul> <li class="no-hover"><strong><?= $this->e($this->user->getFullname()) ?></strong></li> @@ -46,7 +58,7 @@ <li><?= $this->url->link(t('My profile'), 'user', 'show', array('user_id' => $this->user->getId())) ?></li> <li><?= $this->url->link(t('Logout'), 'auth', 'logout') ?></li> </ul> - </span> + </div> </li> </ul> </nav> diff --git a/app/Template/project/duplicate.php b/app/Template/project/duplicate.php index 8967c306..ca7d3302 100644 --- a/app/Template/project/duplicate.php +++ b/app/Template/project/duplicate.php @@ -10,13 +10,17 @@ <?= $this->form->csrf() ?> + <?php if ($project['is_private'] == 0): ?> + <?= $this->form->checkbox('projectPermission', t('Permissions'), 1, true) ?> + <?php endif ?> + <?= $this->form->checkbox('category', t('Categories'), 1, true) ?> <?= $this->form->checkbox('action', t('Actions'), 1, true) ?> <?= $this->form->checkbox('swimlane', t('Swimlanes'), 1, false) ?> <?= $this->form->checkbox('task', t('Tasks'), 1, false) ?> <div class="form-actions"> - <input type="submit" value="<?= t('Duplicate') ?>" class="btn btn-red"/> + <input type="submit" value="<?= t('Duplicate') ?>" class="btn btn-red"> <?= t('or') ?> <?= $this->url->link(t('cancel'), 'project', 'show', array('project_id' => $project['id'])) ?> </div> </form> diff --git a/app/Template/project/index.php b/app/Template/project/index.php index 3d2a33ea..c5dd267c 100644 --- a/app/Template/project/index.php +++ b/app/Template/project/index.php @@ -1,10 +1,6 @@ <section id="main"> <div class="page-header"> <ul> - <?php if ($this->user->hasAccess('project', 'create')): ?> - <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New project'), 'project', 'create') ?></li> - <?php endif ?> - <li><i class="fa fa-lock fa-fw"></i><?= $this->url->link(t('New private project'), 'project', 'createPrivate') ?></li> <?php if ($this->user->hasAccess('projectuser', 'managers')): ?> <li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('Users overview'), 'projectuser', 'managers') ?></li> <?php endif ?> diff --git a/app/Template/project/new.php b/app/Template/project/new.php deleted file mode 100644 index 8e4ccfec..00000000 --- a/app/Template/project/new.php +++ /dev/null @@ -1,24 +0,0 @@ -<section id="main"> - <div class="page-header"> - <ul> - <li><i class="fa fa-folder fa-fw"></i><?= $this->url->link(t('All projects'), 'project', 'index') ?></li> - </ul> - </div> - <form method="post" action="<?= $this->url->href('project', 'save') ?>" autocomplete="off"> - - <?= $this->form->csrf() ?> - <?= $this->form->hidden('is_private', $values) ?> - <?= $this->form->label(t('Name'), 'name') ?> - <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> - - <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> - <?= t('or') ?> <?= $this->url->link(t('cancel'), 'project', 'index') ?> - </div> - </form> - <?php if (isset($is_private) && $is_private): ?> - <div class="alert alert-info"> - <p><?= t('There is no user management for private projects.') ?></p> - </div> - <?php endif ?> -</section>
\ No newline at end of file diff --git a/app/Template/project_creation/create.php b/app/Template/project_creation/create.php new file mode 100644 index 00000000..6caa36af --- /dev/null +++ b/app/Template/project_creation/create.php @@ -0,0 +1,42 @@ +<section id="main"> + <div class="page-header"> + <ul> + <li><i class="fa fa-folder fa-fw"></i><?= $this->url->link(t('All projects'), 'project', 'index') ?></li> + </ul> + </div> + <form class="form-popover" id="project-creation-form" method="post" action="<?= $this->url->href('ProjectCreation', 'save') ?>" autocomplete="off"> + + <?= $this->form->csrf() ?> + <?= $this->form->hidden('is_private', $values) ?> + + <?= $this->form->label(t('Name'), 'name') ?> + <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> + + <?php if (count($projects_list) > 1): ?> + <?= $this->form->label(t('Create from another project'), 'src_project_id') ?> + <?= $this->form->select('src_project_id', $projects_list, $values) ?> + <?php endif ?> + + <div class="project-creation-options" <?= isset($values['src_project_id']) && $values['src_project_id'] > 0 ? '' : 'style="display: none"' ?>> + <p class="alert"><?= t('Which parts of the project do you want to duplicate?') ?></p> + + <?php if (! $is_private): ?> + <?= $this->form->checkbox('projectPermission', t('Permissions'), 1, true) ?> + <?php endif ?> + + <?= $this->form->checkbox('category', t('Categories'), 1, true) ?> + <?= $this->form->checkbox('action', t('Actions'), 1, true) ?> + <?= $this->form->checkbox('swimlane', t('Swimlanes'), 1, true) ?> + <?= $this->form->checkbox('task', t('Tasks'), 1, false) ?> + </div> + + <div class="form-actions"> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"> + </div> + </form> + <?php if ($is_private): ?> + <div class="alert alert-info"> + <p><?= t('There is no user management for private projects.') ?></p> + </div> + <?php endif ?> +</section>
\ No newline at end of file diff --git a/app/Template/project_edit/general.php b/app/Template/project_edit/general.php index 5caefa2d..28cbb66a 100644 --- a/app/Template/project_edit/general.php +++ b/app/Template/project_edit/general.php @@ -24,7 +24,7 @@ <?= $this->form->select('owner_id', $owners, $values, $errors) ?> </div> - <?php if ($this->user->hasProjectAccess('project', 'create', $project['id'])): ?> + <?php if ($this->user->hasProjectAccess('ProjectCreation', 'create', $project['id'])): ?> <hr> <?= $this->form->checkbox('is_private', t('Private project'), 1, $project['is_private'] == 1) ?> <p class="form-help"><?= t('Private projects do not have users and groups management.') ?></p> diff --git a/app/Template/project_user/layout.php b/app/Template/project_user/layout.php index 3a569da4..a87efbff 100644 --- a/app/Template/project_user/layout.php +++ b/app/Template/project_user/layout.php @@ -1,13 +1,6 @@ <section id="main"> <div class="page-header"> <ul> - <?php if ($this->user->hasAccess('project', 'create')): ?> - <li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New project'), 'project', 'create') ?></li> - <?php endif ?> - <li> - <i class="fa fa-lock fa-fw"></i> - <?= $this->url->link(t('New private project'), 'project', 'create', array('private' => 1)) ?> - </li> <li> <i class="fa fa-folder fa-fw"></i> <?= $this->url->link(t('Projects list'), 'project', 'index') ?> |