diff options
Diffstat (limited to 'app')
44 files changed, 633 insertions, 16 deletions
diff --git a/app/Controller/PredefinedTaskDescriptionController.php b/app/Controller/PredefinedTaskDescriptionController.php new file mode 100644 index 00000000..1b7eca12 --- /dev/null +++ b/app/Controller/PredefinedTaskDescriptionController.php @@ -0,0 +1,116 @@ +<?php + +namespace Kanboard\Controller; + +use Kanboard\Core\Controller\PageNotFoundException; + +/** + * Predefined Task Description Controller + * + * @package Kanboard\Controller + * @author Frederic Guillot + */ +class PredefinedTaskDescriptionController extends BaseController +{ + public function create(array $values = array(), array $errors = array()) + { + $project = $this->getProject(); + + $this->response->html($this->template->render('predefined_task_description/create', array( + 'values' => $values, + 'errors' => $errors, + 'project' => $project, + ))); + } + + public function save() + { + $project = $this->getProject(); + $values = $this->request->getValues(); + + list($valid, $errors) = $this->predefinedTaskDescriptionValidator->validate($values); + + if ($valid) { + if ($this->predefinedTaskDescriptionModel->create($project['id'], $values['title'], $values['description']) !== false) { + $this->flash->success(t('Template created successfully.')); + } else { + $this->flash->failure(t('Unable to create this template.')); + } + + $this->response->redirect($this->helper->url->to('ProjectPredefinedContentController', 'show', array('project_id' => $project['id'])), true); + } else { + $this->create($values, $errors); + } + } + + public function edit(array $values = array(), array $errors = array()) + { + $project = $this->getProject(); + $template = $this->predefinedTaskDescriptionModel->getById($project['id'], $this->request->getIntegerParam('id')); + + $this->response->html($this->template->render('predefined_task_description/edit', array( + 'values' => empty($values) ? $template : $values, + 'template' => $template, + 'errors' => $errors, + 'project' => $project, + ))); + } + + public function update() + { + $project = $this->getProject(); + $template = $this->getTemplate($project); + $values = $this->request->getValues(); + + list($valid, $errors) = $this->predefinedTaskDescriptionValidator->validate($values); + + if ($valid) { + if ($this->predefinedTaskDescriptionModel->update($project['id'], $template['id'], $values['title'], $values['description']) !== false) { + $this->flash->success(t('Template updated successfully.')); + } else { + $this->flash->failure(t('Unable to update this template.')); + } + + $this->response->redirect($this->helper->url->to('ProjectPredefinedContentController', 'show', array('project_id' => $project['id'])), true); + } else { + $this->edit($values, $errors); + } + } + + public function confirm() + { + $project = $this->getProject(); + $template = $this->getTemplate($project); + + $this->response->html($this->template->render('predefined_task_description/remove', array( + 'template' => $template, + 'project' => $project, + ))); + } + + public function remove() + { + $this->checkCSRFParam(); + $project = $this->getProject(); + $template = $this->getTemplate($project); + + if ($this->predefinedTaskDescriptionModel->remove($project['id'], $template['id'])) { + $this->flash->success(t('Template removed successfully.')); + } else { + $this->flash->failure(t('Unable to remove this template.')); + } + + $this->response->redirect($this->helper->url->to('ProjectPredefinedContentController', 'show', array('project_id' => $project['id'])), true); + } + + protected function getTemplate(array $project) + { + $template = $this->predefinedTaskDescriptionModel->getById($project['id'], $this->request->getIntegerParam('id')); + + if (empty($template)) { + throw new PageNotFoundException(); + } + + return $template; + } +}
\ No newline at end of file diff --git a/app/Controller/ProjectPredefinedContentController.php b/app/Controller/ProjectPredefinedContentController.php index 1195dfa3..709d6b79 100644 --- a/app/Controller/ProjectPredefinedContentController.php +++ b/app/Controller/ProjectPredefinedContentController.php @@ -10,13 +10,6 @@ namespace Kanboard\Controller; */ class ProjectPredefinedContentController extends BaseController { - /** - * Edit project - * - * @access public - * @param array $values - * @param array $errors - */ public function show(array $values = array(), array $errors = array()) { $project = $this->getProject(); @@ -25,15 +18,11 @@ class ProjectPredefinedContentController extends BaseController 'values' => empty($values) ? $project : $values, 'errors' => $errors, 'project' => $project, - 'title' => t('Predefined Contents') + 'predefined_task_descriptions' => $this->predefinedTaskDescriptionModel->getAll($project['id']), + 'title' => t('Predefined Contents'), ))); } - /** - * Validate and update a project - * - * @access public - */ public function update() { $project = $this->getProject(); diff --git a/app/Core/Base.php b/app/Core/Base.php index bf89c00f..4e553746 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -105,6 +105,7 @@ use Pimple\Container; * @property \Kanboard\Model\LinkModel $linkModel * @property \Kanboard\Model\NotificationModel $notificationModel * @property \Kanboard\Model\PasswordResetModel $passwordResetModel + * @property \Kanboard\Model\PredefinedTaskDescriptionModel $predefinedTaskDescriptionModel * @property \Kanboard\Model\ProjectModel $projectModel * @property \Kanboard\Model\ProjectActivityModel $projectActivityModel * @property \Kanboard\Model\ProjectDuplicationModel $projectDuplicationModel @@ -179,6 +180,7 @@ use Pimple\Container; * @property \Kanboard\Validator\TaskLinkValidator $taskLinkValidator * @property \Kanboard\Validator\TaskValidator $taskValidator * @property \Kanboard\Validator\UserValidator $userValidator + * @property \Kanboard\Validator\PredefinedTaskDescriptionValidator $predefinedTaskDescriptionValidator * @property \Kanboard\Import\TaskImport $taskImport * @property \Kanboard\Import\UserImport $userImport * @property \Kanboard\Export\SubtaskExport $subtaskExport diff --git a/app/Helper/TaskHelper.php b/app/Helper/TaskHelper.php index b105eaec..43347a6d 100644 --- a/app/Helper/TaskHelper.php +++ b/app/Helper/TaskHelper.php @@ -61,6 +61,30 @@ class TaskHelper extends Base return $this->helper->form->textEditor('description', $values, $errors, array('tabindex' => 2)); } + public function renderDescriptionTemplateDropdown($projectId) + { + $templates = $this->predefinedTaskDescriptionModel->getAll($projectId); + + if (! empty($templates)) { + $html = '<div class="dropdown">'; + $html .= '<a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-floppy-o fa-fw" aria-hidden="true"></i>'.t('Description Templates').' <i class="fa fa-caret-down" aria-hidden="true"></i></a>'; + $html .= '<ul>'; + + foreach ($templates as $template) { + $html .= '<li>'; + $html .= '<a href="#" data-template-target="textarea[name=description]" data-template="'.$this->helper->text->e($template['description']).'" class="js-template">'; + $html .= $this->helper->text->e($template['title']); + $html .= '</a>'; + $html .= '</li>'; + } + + $html .= '</ul></div>'; + return $html; + } + + return ''; + } + public function renderTagField(array $project, array $tags = array()) { $options = $this->tagModel->getAssignableList($project['id']); diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php index ce0374f2..d53f9291 100644 --- a/app/Locale/bs_BA/translations.php +++ b/app/Locale/bs_BA/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/ca_ES/translations.php b/app/Locale/ca_ES/translations.php index 8e14e2fb..f114484f 100644 --- a/app/Locale/ca_ES/translations.php +++ b/app/Locale/ca_ES/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index 92645582..8b713c8c 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index cfd27c2c..fef985b4 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 81139377..e2d9ba5a 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php index 9bd08132..908c015e 100644 --- a/app/Locale/el_GR/translations.php +++ b/app/Locale/el_GR/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index d0777c00..b97e24eb 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index ad2fa6b1..a508162d 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index 24367389..d281def6 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -1345,4 +1345,15 @@ return array( 'Enter one subtask by line.' => 'Entrez une sous-tâche par ligne.', 'Predefined Contents' => 'Contenus prédéfini', 'Predefined contents' => 'Contenus prédéfini', + 'Predefined Task Description' => 'Modèles de description de tâches', + 'Do you really want to remove this template? "%s"' => 'Voulez-vous vraiment supprimer ce modèle ? « %s »', + 'Add predefined task description' => 'Ajouter un modèle de description de tâche', + 'Predefined Task Descriptions' => 'Modèles de description de tâches', + 'Template created successfully.' => 'Modèle créé avec succès.', + 'Unable to create this template.' => 'Impossible de créer ce modèle.', + 'Template updated successfully.' => 'Modèle mis à jour avec succès.', + 'Unable to update this template.' => 'Impossible de mettre à jour ce modèle.', + 'Template removed successfully.' => 'Modèle supprimé avec succès.', + 'Unable to remove this template.' => 'Impossible de supprimer ce modèle.', + 'Description Templates' => 'Modèles de description', ); diff --git a/app/Locale/hr_HR/translations.php b/app/Locale/hr_HR/translations.php index fa4c87d7..5f2f0a70 100644 --- a/app/Locale/hr_HR/translations.php +++ b/app/Locale/hr_HR/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index c8f9d8ea..740a8e4f 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index aad497ad..2fcbbf76 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index 98647574..13cfd247 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index 86c4800b..1c7c8879 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -1345,4 +1345,15 @@ return array( 'Enter one subtask by line.' => '1行に1件のサブタスクを入力', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/ko_KR/translations.php b/app/Locale/ko_KR/translations.php index 083ddc67..8eafaedb 100644 --- a/app/Locale/ko_KR/translations.php +++ b/app/Locale/ko_KR/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php index 50544f2e..b0bcf90f 100644 --- a/app/Locale/my_MY/translations.php +++ b/app/Locale/my_MY/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index 3fe60424..9f563fd5 100644 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 169654c4..eeb99d5f 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index d0858db9..ec684e98 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index b9384a65..47e7b629 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -1345,4 +1345,15 @@ return array( 'Enter one subtask by line.' => 'Escreva uma subtarefa por linha.', 'Predefined Contents' => 'Conteúdos predefinidos', 'Predefined contents' => 'Conteúdos predefinidos', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index 6fddbfb2..a8abeda3 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 6223f94c..940e58f5 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -1345,4 +1345,15 @@ return array( 'Enter one subtask by line.' => 'Записывайте по одной подзадаче на строку.', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index 7d88e0af..0628ebd5 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index 427f00a1..f20f0501 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index ba4a587e..0d26b352 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index e420eff4..a7ffda9a 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/vi_VN/translations.php b/app/Locale/vi_VN/translations.php index dde397bb..bf9e6ffd 100644 --- a/app/Locale/vi_VN/translations.php +++ b/app/Locale/vi_VN/translations.php @@ -1351,4 +1351,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 9094a7b4..68bbef66 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -1345,4 +1345,15 @@ return array( // 'Enter one subtask by line.' => '', // 'Predefined Contents' => '', // 'Predefined contents' => '', + // 'Predefined Task Description' => '', + // 'Do you really want to remove this template? "%s"' => '', + // 'Add predefined task description' => '', + // 'Predefined Task Descriptions' => '', + // 'Template created successfully.' => '', + // 'Unable to create this template.' => '', + // 'Template updated successfully.' => '', + // 'Unable to update this template.' => '', + // 'Template removed successfully.' => '', + // 'Unable to remove this template.' => '', + // 'Description Templates' => '', ); diff --git a/app/Model/PredefinedTaskDescriptionModel.php b/app/Model/PredefinedTaskDescriptionModel.php new file mode 100644 index 00000000..7b8e6de2 --- /dev/null +++ b/app/Model/PredefinedTaskDescriptionModel.php @@ -0,0 +1,42 @@ +<?php + +namespace Kanboard\Model; + +use Kanboard\Core\Base; + +class PredefinedTaskDescriptionModel extends Base +{ + const TABLE = 'predefined_task_descriptions'; + + public function getAll($projectId) + { + return $this->db->table(self::TABLE)->eq('project_id', $projectId)->findAll(); + } + + public function getById($projectId, $id) + { + return $this->db->table(self::TABLE)->eq('project_id', $projectId)->eq('id', $id)->findOne(); + } + + public function create($projectId, $title, $description) + { + return $this->db->table(self::TABLE)->persist(array( + 'project_id' => $projectId, + 'title' => $title, + 'description' => $description, + )); + } + + public function update($projectId, $id, $title, $description) + { + return $this->db->table(self::TABLE)->eq('project_id', $projectId)->eq('id', $id)->update(array( + 'title' => $title, + 'description' => $description, + )); + } + + public function remove($projectId, $id) + { + return $this->db->table(self::TABLE)->eq('project_id', $projectId)->eq('id', $id)->remove(); + } +} diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index ca284f47..5709b86d 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -8,7 +8,19 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 125; +const VERSION = 126; + +function version_126(PDO $pdo) +{ + $pdo->exec('CREATE TABLE predefined_task_descriptions ( + id INT NOT NULL AUTO_INCREMENT, + project_id INT NOT NULL, + title TEXT NOT NULL, + description TEXT NOT NULL, + FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE, + PRIMARY KEY(id) + ) ENGINE=InnoDB CHARSET=utf8'); +} function version_125(PDO $pdo) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index 312b1dba..bf9acaa7 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -8,7 +8,18 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 104; +const VERSION = 105; + +function version_105(PDO $pdo) +{ + $pdo->exec('CREATE TABLE predefined_task_descriptions ( + id SERIAL PRIMARY KEY, + project_id INTEGER NOT NULL, + title TEXT NOT NULL, + description TEXT NOT NULL, + FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE + )'); +} function version_104(PDO $pdo) { diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index 3966d373..70d13b98 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -8,7 +8,18 @@ use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; use PDO; -const VERSION = 115; +const VERSION = 116; + +function version_116(PDO $pdo) +{ + $pdo->exec('CREATE TABLE predefined_task_descriptions ( + id INTEGER PRIMARY KEY, + project_id INTEGER NOT NULL, + title TEXT NOT NULL, + description TEXT NOT NULL, + FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE + )'); +} function version_115(PDO $pdo) { diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index 98212d45..797e70d0 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -93,6 +93,7 @@ class AuthenticationProvider implements ServiceProviderInterface $acl->add('ProjectPermissionController', '*', Role::PROJECT_MANAGER); $acl->add('ProjectEditController', '*', Role::PROJECT_MANAGER); $acl->add('ProjectPredefinedContentController', '*', Role::PROJECT_MANAGER); + $acl->add('PredefinedTaskDescriptionController', '*', Role::PROJECT_MANAGER); $acl->add('ProjectFileController', '*', Role::PROJECT_MEMBER); $acl->add('ProjectUserOverviewController', '*', Role::PROJECT_MANAGER); $acl->add('ProjectStatusController', '*', Role::PROJECT_MANAGER); diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index f8bb3ae4..aaafafdf 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -47,6 +47,7 @@ class ClassProvider implements ServiceProviderInterface 'LinkModel', 'NotificationModel', 'PasswordResetModel', + 'PredefinedTaskDescriptionModel', 'ProjectModel', 'ProjectFileModel', 'ProjectActivityModel', @@ -118,6 +119,7 @@ class ClassProvider implements ServiceProviderInterface 'TaskLinkValidator', 'TaskValidator', 'UserValidator', + 'PredefinedTaskDescriptionValidator', ), 'Import' => array( 'TaskImport', diff --git a/app/Template/predefined_task_description/create.php b/app/Template/predefined_task_description/create.php new file mode 100644 index 00000000..5a7a8d9f --- /dev/null +++ b/app/Template/predefined_task_description/create.php @@ -0,0 +1,14 @@ +<div class="page-header"> + <h2><?= t('Predefined Task Description') ?></h2> +</div> +<form method="post" action="<?= $this->url->href('PredefinedTaskDescriptionController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off"> + <?= $this->form->csrf() ?> + + <?= $this->form->label(t('Title'), 'title') ?> + <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'tabindex="1"')) ?> + + <?= $this->form->label(t('Description'), 'description') ?> + <?= $this->form->textEditor('description', $values, $errors, array('tabindex' => 2)) ?> + + <?= $this->modal->submitButtons() ?> +</form> diff --git a/app/Template/predefined_task_description/edit.php b/app/Template/predefined_task_description/edit.php new file mode 100644 index 00000000..039d650b --- /dev/null +++ b/app/Template/predefined_task_description/edit.php @@ -0,0 +1,14 @@ +<div class="page-header"> + <h2><?= t('Predefined Task Description') ?></h2> +</div> +<form method="post" action="<?= $this->url->href('PredefinedTaskDescriptionController', 'update', array('project_id' => $project['id'], 'id' => $template['id'])) ?>" autocomplete="off"> + <?= $this->form->csrf() ?> + + <?= $this->form->label(t('Title'), 'title') ?> + <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'tabindex="1"')) ?> + + <?= $this->form->label(t('Description'), 'description') ?> + <?= $this->form->textEditor('description', $values, $errors, array('tabindex' => 2)) ?> + + <?= $this->modal->submitButtons() ?> +</form> diff --git a/app/Template/predefined_task_description/remove.php b/app/Template/predefined_task_description/remove.php new file mode 100644 index 00000000..f60a8e75 --- /dev/null +++ b/app/Template/predefined_task_description/remove.php @@ -0,0 +1,15 @@ +<div class="page-header"> + <h2><?= t('Predefined Task Description') ?></h2> +</div> + +<div class="confirm"> + <p class="alert alert-info"> + <?= t('Do you really want to remove this template? "%s"', $template['title']) ?> + </p> + + <?= $this->modal->confirmButtons( + 'PredefinedTaskDescriptionController', + 'remove', + array('project_id' => $project['id'], 'id' => $template['id']) + ) ?> +</div> diff --git a/app/Template/project_predefined_content/show.php b/app/Template/project_predefined_content/show.php index 8e5ca3dc..b2785ada 100644 --- a/app/Template/project_predefined_content/show.php +++ b/app/Template/project_predefined_content/show.php @@ -1,6 +1,39 @@ <div class="page-header"> <h2><?= t('Predefined Contents') ?></h2> + <ul> + <li> + <?= $this->modal->medium('plus', t('Add predefined task description'), 'PredefinedTaskDescriptionController', 'create', array('project_id' => $project['id'])) ?> + </li> + </ul> </div> + +<?php if (! empty($predefined_task_descriptions)): ?> + <h3><?= t('Predefined Task Descriptions') ?></h3> + <table> + <?php foreach ($predefined_task_descriptions as $template): ?> + <tr> + <td> + <div class="dropdown"> + <a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-cog"></i><i class="fa fa-caret-down"></i></a> + <ul> + <li> + <?= $this->modal->medium('edit', t('Edit'), 'PredefinedTaskDescriptionController', 'edit', array('project_id' => $project['id'], 'id' => $template['id'])) ?> + </li> + <li> + <?= $this->modal->confirm('trash-o', t('Remove'), 'PredefinedTaskDescriptionController', 'confirm', array('project_id' => $project['id'], 'id' => $template['id'])) ?> + </li> + </ul> + </div> + <?= $this->text->e($template['title']) ?> + <span class="tooltip" title="<?= $this->text->markdownAttribute($template['description']) ?>"> + <i class="fa fa-info-circle"></i> + </span> + </td> + </tr> + <?php endforeach ?> + </table> +<?php endif ?> + <form method="post" action="<?= $this->url->href('ProjectPredefinedContentController', 'update', array('project_id' => $project['id'], 'redirect' => 'edit')) ?>" autocomplete="off"> <?= $this->form->csrf() ?> diff --git a/app/Template/task_creation/show.php b/app/Template/task_creation/show.php index e21ea8be..935e0823 100644 --- a/app/Template/task_creation/show.php +++ b/app/Template/task_creation/show.php @@ -8,6 +8,7 @@ <div class="task-form-main-column"> <?= $this->task->renderTitleField($values, $errors) ?> <?= $this->task->renderDescriptionField($values, $errors) ?> + <?= $this->task->renderDescriptionTemplateDropdown($project['id']) ?> <?= $this->task->renderTagField($project) ?> <?= $this->hook->render('template:task:form:first-column', array('values' => $values, 'errors' => $errors)) ?> diff --git a/app/Validator/PredefinedTaskDescriptionValidator.php b/app/Validator/PredefinedTaskDescriptionValidator.php new file mode 100644 index 00000000..3ff4e3cb --- /dev/null +++ b/app/Validator/PredefinedTaskDescriptionValidator.php @@ -0,0 +1,22 @@ +<?php + +namespace Kanboard\Validator; + +use SimpleValidator\Validator; +use SimpleValidator\Validators; + +class PredefinedTaskDescriptionValidator extends BaseValidator +{ + public function validate(array $values) + { + $v = new Validator($values, array( + new Validators\Required('title', t('This value is required')), + new Validators\Required('description', t('This value is required')), + )); + + return array( + $v->execute(), + $v->getErrors() + ); + } +}
\ No newline at end of file |