When creating a new project, have the possibility to select another project to duplicate

This commit is contained in:
Frederic Guillot
2016-01-31 17:46:19 -05:00
parent 1500ff92b2
commit fc21d3873e
30 changed files with 694 additions and 342 deletions

View File

@@ -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
{

View File

@@ -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);
}
}

View File

@@ -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
);
}
}

View File

@@ -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);
}
}

View File

@@ -12,6 +12,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
*
@@ -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'));

View File

@@ -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']]);

View File

@@ -120,8 +120,6 @@ class ExternalLinkManager extends Base
*/
public function find()
{
$provider = null;
if ($this->userInputType === self::TYPE_AUTO) {
$provider = $this->findProvider();
} else {

View File

@@ -2,6 +2,8 @@
namespace Kanboard\Model;
use Kanboard\Core\Security\Role;
/**
* Project Duplication
*
@@ -11,6 +13,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
*
@@ -30,79 +54,107 @@ class ProjectDuplication extends Base
return $name.$suffix;
}
/**
* Clone a project with all settings
*
* @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($src_project_id, $selection = array('projectPermission', 'category', 'action'), $owner_id = 0, $name = null, $private = null)
{
$this->db->startTransaction();
// Get the cloned project Id
$dst_project_id = $this->copy($src_project_id, $owner_id, $name, $private);
if (! $dst_project_id) {
$this->db->cancelTransaction();
return false;
}
// Clone Columns, Categories, Permissions and Actions
foreach ($this->getPossibleSelection() as $model) {
// Skip if optional part has not been selected
if (in_array($model, $this->getOptionalSelection()) && ! in_array($model, $selection)) {
continue;
}
// 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();
return (int) $dst_project_id;
}
/**
* Create a project from another one
*
* @param integer $project_id Project Id
* @return integer Cloned Project Id
* @access private
* @param integer $src_project_id
* @param integer $owner_id
* @param string $name
* @param boolean $private
* @return integer
*/
public function copy($project_id)
private function copy($src_project_id, $owner_id = 0, $name = null, $private = null)
{
$project = $this->project->getById($project_id);
$project = $this->project->getById($src_project_id);
$is_private = empty($project['is_private']) ? 0 : 1;
$values = array(
'name' => $this->getClonedProjectName($project['name']),
'is_active' => true,
'last_modified' => 0,
'name' => $name ?: $this->getClonedProjectName($project['name']),
'is_active' => 1,
'last_modified' => time(),
'token' => '',
'is_public' => 0,
'is_private' => empty($project['is_private']) ? 0 : 1,
'is_private' => $private ? 1 : $is_private,
'owner_id' => $owner_id,
);
if (! $this->db->table(Project::TABLE)->save($values)) {
return 0;
return false;
}
return $this->db->getLastId();
}
/**
* Clone a project with all settings
* Make sure that the creator of the duplicated project is alsp owner
*
* @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
* @access private
* @param integer $dst_project_id
* @param integer $owner_id
* @return boolean
*/
public function duplicate($project_id, $part_selection = array('category', 'action'))
private function makeOwnerManager($dst_project_id, $owner_id)
{
$this->db->startTransaction();
if ($owner_id > 0) {
$this->projectUserRole->removeUser($dst_project_id, $owner_id);
// Get the cloned project Id
$clone_project_id = $this->copy($project_id);
if (! $clone_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) {
// Skip if optional part has not been selected
if (in_array($model, $optional_parts) && ! in_array($model, $part_selection)) {
continue;
}
if (! $this->$model->duplicate($project_id, $clone_project_id)) {
$this->db->cancelTransaction();
if (! $this->projectUserRole->addUser($dst_project_id, $owner_id, Role::PROJECT_MANAGER)) {
return false;
}
}
$this->db->closeTransaction();
// Clone Tasks if in $part_selection
if (in_array('task', $part_selection)) {
$tasks = $this->taskFinder->getAll($project_id);
foreach ($tasks as $task) {
if (! $this->taskDuplication->duplicateToProject($task['id'], $clone_project_id)) {
return false;
}
}
}
return (int) $clone_project_id;
return true;
}
}

View File

@@ -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;
}
}

View File

@@ -179,6 +179,23 @@ class TaskFinder extends Base
->findAll();
}
/**
* 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
*

View File

@@ -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);

View File

@@ -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');

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 ?>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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') ?>