Merge remote-tracking branch 'refs/remotes/origin/master'
This commit is contained in:
commit
16e8241f0f
|
|
@ -21,8 +21,9 @@ Contributors:
|
|||
- [Crash5](https://github.com/crash5)
|
||||
- [Creador30](https://github.com/creador30)
|
||||
- [Cynthia Pereira](https://github.com/cynthiapereira)
|
||||
- [David-Norris](https://github.com/David-Norris)
|
||||
- [Damian](https://github.com/dromek)
|
||||
- [Daniel Raknes](https://github.com/danielraknes)
|
||||
- [David-Norris](https://github.com/David-Norris)
|
||||
- [Draza (bdpsoft)](https://github.com/bdpsoft)
|
||||
- [Eskiso](https://github.com/eSkiSo)
|
||||
- [Esteban Monge](https://github.com/EstebanMonge)
|
||||
|
|
@ -56,6 +57,7 @@ Contributors:
|
|||
- [Maxime](https://github.com/EpocDotFr)
|
||||
- [Max Kamashev](https://github.com/ukko)
|
||||
- [mfoucrier](https://github.com/mfoucrier)
|
||||
- [Matthew Cillo](https://github.com/peripatetic-sojourner)
|
||||
- [Mgro](https://github.com/mgro)
|
||||
- [Michael Lüpkes](https://github.com/mluepkes)
|
||||
- [Mihailov Vasilievic Filho](https://github.com/mihailov-vf)
|
||||
|
|
|
|||
23
ChangeLog
23
ChangeLog
|
|
@ -1,25 +1,38 @@
|
|||
Version 1.0.22 (unreleased)
|
||||
Version 1.0.23 (unreleased)
|
||||
---------------------------
|
||||
|
||||
New features:
|
||||
|
||||
- Add report to compare working hours between open and closed tasks
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Fix wrong constant name that cause a PHP error in project management section
|
||||
- Fix pagination in group members listing
|
||||
|
||||
Version 1.0.22
|
||||
--------------
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* LDAP configuration parameters changes (See documentation)
|
||||
* SQL table changes:
|
||||
- "users" table: added new column "role" and removed columns "is_admin" and "is_project_admin"
|
||||
- "project_has_users" table: replace column "is_owner" by column "role"
|
||||
- "project_has_users" table: replaced column "is_owner" with column "role"
|
||||
- Sqlite does not support alter table, old columns still there but unused
|
||||
* API procedure changes:
|
||||
- createUser
|
||||
- createLdapUser
|
||||
- updateUser
|
||||
* Event removed: "session.bootstrap" use "app.boostrap" instead
|
||||
- updateTask
|
||||
* Event removed: "session.bootstrap", use "app.boostrap" instead
|
||||
|
||||
New features:
|
||||
|
||||
* Add pluggable authentication and authorization system (full rewrite)
|
||||
* Add pluggable authentication and authorization system (complete rewrite)
|
||||
* Add groups (teams/organization)
|
||||
* Add LDAP groups synchronization
|
||||
* Add project groups permissions
|
||||
* Add project group permissions
|
||||
* Add new project role Viewer
|
||||
* Add generic LDAP client library
|
||||
* Add search query attribute for task link
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -4,7 +4,7 @@ CSS_APP = $(addprefix assets/css/src/, $(addsuffix .css, base links title table
|
|||
CSS_PRINT = $(addprefix assets/css/src/, $(addsuffix .css, print links table board task comment subtask markdown))
|
||||
CSS_VENDOR = $(addprefix assets/css/vendor/, $(addsuffix .css, jquery-ui.min jquery-ui-timepicker-addon.min chosen.min fullcalendar.min font-awesome.min c3.min))
|
||||
|
||||
JS_APP = $(addprefix assets/js/src/, $(addsuffix .js, Popover Dropdown Tooltip Markdown Sidebar Search App Screenshot Calendar Board Swimlane Gantt Task Project TaskRepartitionChart UserRepartitionChart CumulativeFlowDiagram BurndownChart AvgTimeColumnChart TaskTimeColumnChart LeadCycleTimeChart Router))
|
||||
JS_APP = $(addprefix assets/js/src/, $(addsuffix .js, Popover Dropdown Tooltip Markdown Sidebar Search App Screenshot Calendar Board Swimlane Gantt Task Project TaskRepartitionChart UserRepartitionChart CumulativeFlowDiagram BurndownChart AvgTimeColumnChart TaskTimeColumnChart LeadCycleTimeChart CompareHoursColumnChart Router))
|
||||
JS_VENDOR = $(addprefix assets/js/vendor/, $(addsuffix .js, jquery-1.11.3.min jquery-ui.min jquery-ui-timepicker-addon.min jquery.ui.touch-punch.min chosen.jquery.min moment.min fullcalendar.min mousetrap.min mousetrap-global-bind.min))
|
||||
JS_LANG = $(addprefix assets/js/vendor/lang/, $(addsuffix .js, cs da de es fi fr hu id it ja nl nb pl pt pt-br ru sv sr th tr zh-cn))
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,14 @@ class Task extends Base
|
|||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
|
||||
if ($owner_id !== 0 && ! $this->projectPermission->isMember($project_id, $owner_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->userSession->isLogged()) {
|
||||
$creator_id = $this->userSession->getId();
|
||||
}
|
||||
|
||||
$values = array(
|
||||
'title' => $title,
|
||||
'project_id' => $project_id,
|
||||
|
|
@ -96,20 +104,28 @@ class Task extends Base
|
|||
return $valid ? $this->taskCreation->create($values) : false;
|
||||
}
|
||||
|
||||
public function updateTask($id, $title = null, $project_id = null, $color_id = null, $owner_id = null,
|
||||
$creator_id = null, $date_due = null, $description = null, $category_id = null, $score = null,
|
||||
public function updateTask($id, $title = null, $color_id = null, $owner_id = null,
|
||||
$date_due = null, $description = null, $category_id = null, $score = null,
|
||||
$recurrence_status = null, $recurrence_trigger = null, $recurrence_factor = null,
|
||||
$recurrence_timeframe = null, $recurrence_basedate = null, $reference = null)
|
||||
{
|
||||
$this->checkTaskPermission($id);
|
||||
|
||||
$project_id = $this->taskFinder->getProjectId($id);
|
||||
|
||||
if ($project_id === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($owner_id !== null && ! $this->projectPermission->isMember($project_id, $owner_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$values = array(
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'project_id' => $project_id,
|
||||
'color_id' => $color_id,
|
||||
'owner_id' => $owner_id,
|
||||
'creator_id' => $creator_id,
|
||||
'date_due' => $date_due,
|
||||
'description' => $description,
|
||||
'category_id' => $category_id,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Controller;
|
||||
use Kanboard\Model\Task as TaskModel;
|
||||
|
||||
/**
|
||||
* Project Analytic controller
|
||||
|
|
@ -166,4 +167,32 @@ class Analytic extends Base
|
|||
'title' => t($title, $project['name']),
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show comparison between actual and estimated hours chart
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function compareHours()
|
||||
{
|
||||
$project = $this->getProject();
|
||||
$params = $this->getProjectFilters('analytic', 'compareHours');
|
||||
$query = $this->taskFilter->search('status:all')->filterByProject($params['project']['id'])->getQuery();
|
||||
|
||||
$paginator = $this->paginator
|
||||
->setUrl('analytic', 'compareHours', array('project_id' => $project['id']))
|
||||
->setMax(30)
|
||||
->setOrder(TaskModel::TABLE.'.id')
|
||||
->setQuery($query)
|
||||
->calculate();
|
||||
|
||||
$stats = $this->projectAnalytic->getHoursByStatus($project['id']);
|
||||
|
||||
$this->response->html($this->layout('analytic/compare_hours', array(
|
||||
'project' => $project,
|
||||
'paginator' => $paginator,
|
||||
'metrics' => $stats,
|
||||
'title' => t('Compare hours for "%s"', $project['name']),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class Group extends Base
|
|||
$group = $this->group->getById($group_id);
|
||||
|
||||
$paginator = $this->paginator
|
||||
->setUrl('group', 'users')
|
||||
->setUrl('group', 'users', array('group_id' => $group_id))
|
||||
->setMax(30)
|
||||
->setOrder('username')
|
||||
->setQuery($this->groupMember->getQuery($group_id))
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class Csv
|
|||
{
|
||||
if (! empty($value)) {
|
||||
$value = trim(strtolower($value));
|
||||
return $value === '1' || $value{0} === 't' ? 1 : 0;
|
||||
return $value === '1' || $value{0} === 't' || $value{0} === 'y' ? 1 : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Subtask extends \Kanboard\Core\Base
|
|||
return trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']);
|
||||
}
|
||||
|
||||
if ($subtask['status'] == 0 && isset($this->sessionStorage->hasSubtaskInProgress) && $this->sessionStorage->hasSubtaskInProgress === true) {
|
||||
if ($subtask['status'] == 0 && isset($this->sessionStorage->hasSubtaskInProgress) && $this->sessionStorage->hasSubtaskInProgress) {
|
||||
return $this->helper->url->link(
|
||||
trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']),
|
||||
'subtask',
|
||||
|
|
|
|||
|
|
@ -20,15 +20,15 @@ return array(
|
|||
'Red' => 'Czerwony',
|
||||
'Orange' => 'Pomarańczowy',
|
||||
'Grey' => 'Szary',
|
||||
// 'Brown' => '',
|
||||
// 'Deep Orange' => '',
|
||||
// 'Dark Grey' => '',
|
||||
// 'Pink' => '',
|
||||
// 'Teal' => '',
|
||||
// 'Cyan' => '',
|
||||
// 'Lime' => '',
|
||||
// 'Light Green' => '',
|
||||
// 'Amber' => '',
|
||||
'Brown' => 'Brąz',
|
||||
'Deep Orange' => 'Ciemnopomarańczowy',
|
||||
'Dark Grey' => 'Ciemnoszary',
|
||||
'Pink' => 'Różowy',
|
||||
'Teal' => 'Turkusowy',
|
||||
'Cyan' => 'Cyjan',
|
||||
'Lime' => 'Limonkowy',
|
||||
'Light Green' => 'Jasnozielony',
|
||||
'Amber' => 'Amber',
|
||||
'Save' => 'Zapisz',
|
||||
'Login' => 'Login',
|
||||
'Official website:' => 'Oficjalna strona:',
|
||||
|
|
@ -148,7 +148,7 @@ return array(
|
|||
'Task created successfully.' => 'Zadanie zostało utworzone.',
|
||||
'User created successfully.' => 'Użytkownik dodany',
|
||||
'Unable to create your user.' => 'Nie udało się dodać użytkownika.',
|
||||
'User updated successfully.' => 'Użytkownik zaktualizowany.',
|
||||
'User updated successfully.' => 'Profil użytkownika został zaaktualizowany.',
|
||||
'Unable to update your user.' => 'Nie udało się zaktualizować użytkownika.',
|
||||
'User removed successfully.' => 'Użytkownik usunięty.',
|
||||
'Unable to remove this user.' => 'Nie udało się usunąć użytkownika.',
|
||||
|
|
@ -364,7 +364,7 @@ return array(
|
|||
'Task updated' => 'Zaktualizowane zadanie',
|
||||
'Task closed' => 'Zadanie zamknięte',
|
||||
'Task opened' => 'Zadanie otwarte',
|
||||
'I want to receive notifications only for those projects:' => 'Chcę otrzymywać powiadiomienia tylko dla tych projektów:',
|
||||
'I want to receive notifications only for those projects:' => 'Chcę otrzymywać powiadomienia tylko dla poniższych projektów:',
|
||||
'view the task on Kanboard' => 'Zobacz zadanie',
|
||||
'Public access' => 'Dostęp publiczny',
|
||||
'User management' => 'Zarządzanie użytkownikami',
|
||||
|
|
@ -494,7 +494,7 @@ return array(
|
|||
'Project management' => 'Menadżer projektu',
|
||||
'My projects' => 'Moje projekty',
|
||||
'Columns' => 'Kolumny',
|
||||
'Task' => 'zadania',
|
||||
'Task' => 'Zadanie',
|
||||
'Your are not member of any project.' => 'Nie bierzesz udziału w żadnym projekcie',
|
||||
'Percentage' => 'Procent',
|
||||
'Number of tasks' => 'Liczba zadań',
|
||||
|
|
@ -688,7 +688,7 @@ return array(
|
|||
'The two factor authentication code is valid.' => 'Kod weryfikujący poprawny',
|
||||
'Code' => 'Kod',
|
||||
'Two factor authentication' => 'Uwierzytelnianie dwustopniowe',
|
||||
'Enable/disable two factor authentication' => 'Włącz/Wyłącz uwierzytelnianie dwustopniowe',
|
||||
'Enable/disable two factor authentication' => 'Włącz/wyłącz uwierzytelnianie dwustopniowe',
|
||||
'This QR code contains the key URI: ' => 'Ten kod QR zawiera URI klucza: ',
|
||||
'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Zapisz sekretny klucz w swoim oprogramowaniu TOTP (na przykład FreeOTP lub Google Authenticator)',
|
||||
'Check my code' => 'Sprawdź kod',
|
||||
|
|
@ -699,8 +699,8 @@ return array(
|
|||
'uploaded by: %s' => 'Dodane przez: %s',
|
||||
'uploaded on: %s' => 'Data dodania: %s',
|
||||
'size: %s' => 'Rozmiar: %s',
|
||||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
'Burndown chart for "%s"' => 'Wykres Burndown dla "%s"',
|
||||
'Burndown chart' => 'Wykres Burndown',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
'Screenshot taken %s' => 'Zrzut ekranu zapisany %s',
|
||||
'Add a screenshot' => 'Dodaj zrzut ekranu',
|
||||
|
|
@ -770,19 +770,19 @@ return array(
|
|||
// 'Commit made by @%s on Gitlab' => '',
|
||||
// 'Add a comment log when moving the task between columns' => '',
|
||||
// 'Move the task to another column when the category is changed' => '',
|
||||
// 'Send a task by email to someone' => '',
|
||||
// 'Reopen a task' => '',
|
||||
'Send a task by email to someone' => 'Wyślij zadanie mailem do kogokolwiek',
|
||||
'Reopen a task' => 'Otwórz ponownie zadanie',
|
||||
// 'Bitbucket issue opened' => '',
|
||||
// 'Bitbucket issue closed' => '',
|
||||
// 'Bitbucket issue reopened' => '',
|
||||
// 'Bitbucket issue assignee change' => '',
|
||||
// 'Bitbucket issue comment created' => '',
|
||||
// 'Column change' => '',
|
||||
// 'Position change' => '',
|
||||
// 'Swimlane change' => '',
|
||||
// 'Assignee change' => '',
|
||||
'Column change' => 'Zmiana kolumny',
|
||||
'Position change' => 'Zmiana pozycji',
|
||||
'Swimlane change' => 'Zmiana Swimlane',
|
||||
'Assignee change' => 'Zmiana przypisanego użytkownika',
|
||||
// '[%s] Overdue tasks' => '',
|
||||
// 'Notification' => '',
|
||||
'Notification' => 'Powiadomienie',
|
||||
// '%s moved the task #%d to the first swimlane' => '',
|
||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||
// 'Swimlane' => '',
|
||||
|
|
@ -796,12 +796,12 @@ return array(
|
|||
// 'The task have been moved to the first swimlane' => '',
|
||||
// 'The task have been moved to another swimlane:' => '',
|
||||
// 'Overdue tasks for the project "%s"' => '',
|
||||
// 'New title: %s' => '',
|
||||
// 'The task is not assigned anymore' => '',
|
||||
// 'New assignee: %s' => '',
|
||||
// 'There is no category now' => '',
|
||||
// 'New category: %s' => '',
|
||||
// 'New color: %s' => '',
|
||||
'New title: %s' => 'Nowy tytuł: %s',
|
||||
'The task is not assigned anymore' => 'Brak osoby odpowiedzialnej za zadanie',
|
||||
'New assignee: %s' => 'Nowy odpowiedzialny: %s',
|
||||
'There is no category now' => 'Aktualnie zadanie nie posiada kategorii',
|
||||
'New category: %s' => 'Nowa kategoria: %s',
|
||||
'New color: %s' => 'Nowy kolor: %s',
|
||||
// 'New complexity: %d' => '',
|
||||
// 'The due date have been removed' => '',
|
||||
// 'There is no description anymore' => '',
|
||||
|
|
@ -811,61 +811,61 @@ return array(
|
|||
// 'The field "%s" have been updated' => '',
|
||||
// 'The description have been modified' => '',
|
||||
// 'Do you really want to close the task "%s" as well as all subtasks?' => '',
|
||||
// 'Swimlane: %s' => '',
|
||||
// 'I want to receive notifications for:' => '',
|
||||
// 'All tasks' => '',
|
||||
// 'Only for tasks assigned to me' => '',
|
||||
// 'Only for tasks created by me' => '',
|
||||
// 'Only for tasks created by me and assigned to me' => '',
|
||||
//'Swimlane: %s' => '',
|
||||
'I want to receive notifications for:' => 'Wysyłaj powiadomienia dla:',
|
||||
'All tasks' => 'Wszystkich zadań',
|
||||
'Only for tasks assigned to me' => 'Tylko zadań przypisanych do mnie',
|
||||
'Only for tasks created by me' => 'Tylko zadań utworzonych przeze mnie',
|
||||
'Only for tasks created by me and assigned to me' => 'Tylko zadań przypisanych lub utworzonych przeze mnie',
|
||||
// '%A' => '',
|
||||
// '%b %e, %Y, %k:%M %p' => '',
|
||||
// 'New due date: %B %e, %Y' => '',
|
||||
// 'Start date changed: %B %e, %Y' => '',
|
||||
'New due date: %B %e, %Y' => 'Nowy termin: %B %e, %Y',
|
||||
'Start date changed: %B %e, %Y' => 'Zmiana daty rozpoczęcia: %B %e, %Y',
|
||||
// '%k:%M %p' => '',
|
||||
// '%%Y-%%m-%%d' => '',
|
||||
// 'Total for all columns' => '',
|
||||
// 'You need at least 2 days of data to show the chart.' => '',
|
||||
// '<15m' => '',
|
||||
// '<30m' => '',
|
||||
// 'Stop timer' => '',
|
||||
// 'Start timer' => '',
|
||||
// 'Add project member' => '',
|
||||
// 'Enable notifications' => '',
|
||||
// 'My activity stream' => '',
|
||||
// 'My calendar' => '',
|
||||
// 'Search tasks' => '',
|
||||
// 'Back to the calendar' => '',
|
||||
// 'Filters' => '',
|
||||
// 'Reset filters' => '',
|
||||
// 'My tasks due tomorrow' => '',
|
||||
// 'Tasks due today' => '',
|
||||
// 'Tasks due tomorrow' => '',
|
||||
// 'Tasks due yesterday' => '',
|
||||
// 'Closed tasks' => '',
|
||||
// 'Open tasks' => '',
|
||||
// 'Not assigned' => '',
|
||||
// 'View advanced search syntax' => '',
|
||||
// 'Overview' => '',
|
||||
'Stop timer' => 'Zatrzymaj pomiar czasu',
|
||||
'Start timer' => 'Uruchom pomiar czasu',
|
||||
'Add project member' => 'Dodaj członka projektu',
|
||||
'Enable notifications' => 'Włącz powiadomienia',
|
||||
'My activity stream' => 'Moja aktywność',
|
||||
'My calendar' => 'Mój kalendarz',
|
||||
'Search tasks' => 'Szukaj zadań',
|
||||
'Back to the calendar' => 'Wróć do kalendarza',
|
||||
'Filters' => 'Filtry',
|
||||
'Reset filters' => 'Resetuj zastosowane filtry',
|
||||
'My tasks due tomorrow' => 'Moje zadania do jutra',
|
||||
'Tasks due today' => 'Zadania do dzisiaj',
|
||||
'Tasks due tomorrow' => 'Zadania do jutra',
|
||||
'Tasks due yesterday' => 'Zadania na wczoraj',
|
||||
'Closed tasks' => 'Zamknięte zadania',
|
||||
'Open tasks' => 'Otwarte zadania',
|
||||
'Not assigned' => 'Nieprzypisane zadania',
|
||||
'View advanced search syntax' => 'Pomoc dotycząca budowania filtrów',
|
||||
'Overview' => 'Przegląd',
|
||||
// '%b %e %Y' => '',
|
||||
// 'Board/Calendar/List view' => '',
|
||||
// 'Switch to the board view' => '',
|
||||
// 'Switch to the calendar view' => '',
|
||||
// 'Switch to the list view' => '',
|
||||
// 'Go to the search/filter box' => '',
|
||||
// 'There is no activity yet.' => '',
|
||||
// 'No tasks found.' => '',
|
||||
// 'Keyboard shortcut: "%s"' => '',
|
||||
// 'List' => '',
|
||||
// 'Filter' => '',
|
||||
// 'Advanced search' => '',
|
||||
// 'Example of query: ' => '',
|
||||
// 'Search by project: ' => '',
|
||||
// 'Search by column: ' => '',
|
||||
// 'Search by assignee: ' => '',
|
||||
// 'Search by color: ' => '',
|
||||
// 'Search by category: ' => '',
|
||||
// 'Search by description: ' => '',
|
||||
// 'Search by due date: ' => '',
|
||||
'Board/Calendar/List view' => 'Widok: Tablica/Kalendarz/Lista',
|
||||
'Switch to the board view' => 'Przełącz na tablicę',
|
||||
'Switch to the calendar view' => 'Przełącz na kalendarz',
|
||||
'Switch to the list view' => 'Przełącz na listę',
|
||||
'Go to the search/filter box' => 'Użyj pola wyszukiwania/filtrów',
|
||||
'There is no activity yet.' => 'Brak powiadomień',
|
||||
'No tasks found.' => 'Nie znaleziono zadań',
|
||||
'Keyboard shortcut: "%s"' => 'Skrót klawiaturowy: "%s"',
|
||||
'List' => 'Lista',
|
||||
'Filter' => 'Filtr',
|
||||
'Advanced search' => 'Zaawansowane wyszukiwanie',
|
||||
'Example of query: ' => 'Przykładowe zapytanie:',
|
||||
'Search by project: ' => 'Szukaj wg projektów:',
|
||||
'Search by column: ' => 'Szukaj wg kolumn:',
|
||||
'Search by assignee: ' => 'Szukaj wg użytkownika:',
|
||||
'Search by color: ' => 'Szukaj wg koloru:',
|
||||
'Search by category: ' => 'Szukaj wg kategorii:',
|
||||
'Search by description: ' => 'Szukaj wg opisu:',
|
||||
'Search by due date: ' => 'Szukaj wg terminu:',
|
||||
// 'Lead and Cycle time for "%s"' => '',
|
||||
// 'Average time spent into each column for "%s"' => '',
|
||||
// 'Average time spent into each column' => '',
|
||||
|
|
@ -890,7 +890,7 @@ return array(
|
|||
// 'The cycle time is the duration between the start date and the completion.' => '',
|
||||
// 'If the task is not closed the current time is used instead of the completion date.' => '',
|
||||
// 'Set automatically the start date' => '',
|
||||
// 'Edit Authentication' => '',
|
||||
'Edit Authentication' => 'Edycja autoryzacji',
|
||||
// 'Google Id' => '',
|
||||
// 'Github Id' => '',
|
||||
// 'Remote user' => '',
|
||||
|
|
@ -898,62 +898,62 @@ return array(
|
|||
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
|
||||
// 'By @%s on Gitlab' => '',
|
||||
// 'Gitlab issue comment created' => '',
|
||||
// 'New remote user' => '',
|
||||
// 'New local user' => '',
|
||||
// 'Default task color' => '',
|
||||
// 'Hide sidebar' => '',
|
||||
// 'Expand sidebar' => '',
|
||||
// 'This feature does not work with all browsers.' => '',
|
||||
'New remote user' => 'Nowy użytkownik zdalny',
|
||||
'New local user' => 'Nowy użytkownik lokalny',
|
||||
'Default task color' => 'Domyślny kolor zadań',
|
||||
'Hide sidebar' => 'Ukryj menu boczne',
|
||||
'Expand sidebar' => 'Pokaż menu boczne',
|
||||
'This feature does not work with all browsers.' => 'Ta funkcja może nie działać z każdą przeglądarką',
|
||||
// 'There is no destination project available.' => '',
|
||||
// 'Trigger automatically subtask time tracking' => '',
|
||||
// 'Include closed tasks in the cumulative flow diagram' => '',
|
||||
// 'Current swimlane: %s' => '',
|
||||
// 'Current column: %s' => '',
|
||||
// 'Current category: %s' => '',
|
||||
// 'no category' => '',
|
||||
// 'Current assignee: %s' => '',
|
||||
// 'not assigned' => '',
|
||||
// 'Author:' => '',
|
||||
// 'contributors' => '',
|
||||
// 'License:' => '',
|
||||
// 'License' => '',
|
||||
// 'Enter the text below' => '',
|
||||
// 'Gantt chart for %s' => '',
|
||||
// 'Sort by position' => '',
|
||||
// 'Sort by date' => '',
|
||||
// 'Add task' => '',
|
||||
// 'Start date:' => '',
|
||||
// 'Due date:' => '',
|
||||
// 'There is no start date or due date for this task.' => '',
|
||||
'Current swimlane: %s' => 'Bieżący swimlane: %s',
|
||||
'Current column: %s' => 'Bieżąca kolumna: %s',
|
||||
'Current category: %s' => 'Bieżąca kategoria: %s',
|
||||
'no category' => 'brak kategorii',
|
||||
//'Current assignee: %s' => '',
|
||||
'not assigned' => 'Brak osoby odpowiedzialnej',
|
||||
'Author:' => 'Autor',
|
||||
'contributors' => 'współautorzy',
|
||||
'License:' => 'Licencja:',
|
||||
'License' => 'Licencja',
|
||||
'Enter the text below' => 'Wpisz tekst poniżej',
|
||||
'Gantt chart for %s' => 'Wykres Gantt dla %s',
|
||||
'Sort by position' => 'Sortuj wg pozycji',
|
||||
'Sort by date' => 'Sortuj wg daty',
|
||||
'Add task' => 'Dodaj zadanie',
|
||||
'Start date:' => 'Data rozpoczęcia:',
|
||||
'Due date:' => 'Termin',
|
||||
'There is no start date or due date for this task.' => 'Brak daty rozpoczęcia lub terminu zadania',
|
||||
// 'Moving or resizing a task will change the start and due date of the task.' => '',
|
||||
// 'There is no task in your project.' => '',
|
||||
// 'Gantt chart' => '',
|
||||
// 'People who are project managers' => '',
|
||||
// 'People who are project members' => '',
|
||||
'Gantt chart' => 'Wykres Gantta',
|
||||
'People who are project managers' => 'Użytkownicy będący menedżerami projektu',
|
||||
'People who are project members' => 'Użytkownicy będący uczestnikami projektu',
|
||||
// 'NOK - Norwegian Krone' => '',
|
||||
// 'Show this column' => '',
|
||||
// 'Hide this column' => '',
|
||||
// 'open file' => '',
|
||||
// 'End date' => '',
|
||||
// 'Users overview' => '',
|
||||
// 'Managers' => '',
|
||||
// 'Members' => '',
|
||||
// 'Shared project' => '',
|
||||
// 'Project managers' => '',
|
||||
// 'Gantt chart for all projects' => '',
|
||||
// 'Projects list' => '',
|
||||
// 'Gantt chart for this project' => '',
|
||||
// 'Project board' => '',
|
||||
// 'End date:' => '',
|
||||
// 'There is no start date or end date for this project.' => '',
|
||||
// 'Projects Gantt chart' => '',
|
||||
// 'Start date: %s' => '',
|
||||
// 'End date: %s' => '',
|
||||
// 'Link type' => '',
|
||||
// 'Change task color when using a specific task link' => '',
|
||||
// 'Task link creation or modification' => '',
|
||||
'Show this column' => 'Pokaż tą kolumnę',
|
||||
'Hide this column' => 'Ukryj tą kolumnę',
|
||||
'open file' => 'otwórz plik',
|
||||
'End date' => 'Data zakończenia',
|
||||
'Users overview' => 'Przegląd użytkowników',
|
||||
'Managers' => 'Menedżerowie',
|
||||
'Members' => 'Uczestnicy',
|
||||
'Shared project' => 'Projekt udostępniony',
|
||||
'Project managers' => 'Menedżerowie projektu',
|
||||
'Gantt chart for all projects' => 'Wykres Gantta dla wszystkich projektów',
|
||||
'Projects list' => 'Lista projektów',
|
||||
'Gantt chart for this project' => 'Wykres Gantta dla bieżacego projektu',
|
||||
'Project board' => 'Talica projektu',
|
||||
'End date:' => 'Data zakończenia:',
|
||||
'There is no start date or end date for this project.' => 'Nie zdefiniowano czasu trwania projektu',
|
||||
'Projects Gantt chart' => 'Wykres Gantta dla projektów',
|
||||
'Start date: %s' => 'Data rozpoczęcia: %s',
|
||||
'End date: %s' => 'Data zakończenia: %s',
|
||||
'Link type' => 'Typ adresu URL',
|
||||
'Change task color when using a specific task link' => 'Zmień kolor zadania używając specjalnego adresu URL',
|
||||
'Task link creation or modification' => 'Adres URL do utworzenia zadania lub modyfikacji',
|
||||
// 'Login with my Gitlab Account' => '',
|
||||
// 'Milestone' => '',
|
||||
'Milestone' => 'Kamień milowy',
|
||||
// 'Gitlab Authentication' => '',
|
||||
// 'Help on Gitlab authentication' => '',
|
||||
// 'Gitlab Id' => '',
|
||||
|
|
@ -963,17 +963,17 @@ return array(
|
|||
// 'Documentation: %s' => '',
|
||||
// 'Switch to the Gantt chart view' => '',
|
||||
// 'Reset the search/filter box' => '',
|
||||
// 'Documentation' => '',
|
||||
'Documentation' => 'Dokumentacja',
|
||||
// 'Table of contents' => '',
|
||||
// 'Gantt' => '',
|
||||
// 'Author' => '',
|
||||
// 'Version' => '',
|
||||
// 'Plugins' => '',
|
||||
// 'There is no plugin loaded.' => '',
|
||||
// 'Set maximum column height' => '',
|
||||
// 'Remove maximum column height' => '',
|
||||
// 'My notifications' => '',
|
||||
// 'Custom filters' => '',
|
||||
'Author' => 'Autor',
|
||||
'Version' => 'Wersja',
|
||||
'Plugins' => 'Wtyczki',
|
||||
'There is no plugin loaded.' => 'Nie wykryto żadnych wtyczek.',
|
||||
'Set maximum column height' => 'Ustaw maksymalną wysokość kolumn',
|
||||
'Remove maximum column height' => 'Usuń maksymalną wysokość kolumn',
|
||||
'My notifications' => 'Moje powiadomienia',
|
||||
'Custom filters' => 'Dostosuj filtry',
|
||||
// 'Your custom filter have been created successfully.' => '',
|
||||
// 'Unable to create your custom filter.' => '',
|
||||
// 'Custom filter removed successfully.' => '',
|
||||
|
|
@ -982,68 +982,68 @@ return array(
|
|||
// 'Your custom filter have been updated successfully.' => '',
|
||||
// 'Unable to update custom filter.' => '',
|
||||
// 'Web' => '',
|
||||
// 'New attachment on task #%d: %s' => '',
|
||||
// 'New comment on task #%d' => '',
|
||||
// 'Comment updated on task #%d' => '',
|
||||
// 'New subtask on task #%d' => '',
|
||||
// 'Subtask updated on task #%d' => '',
|
||||
// 'New task #%d: %s' => '',
|
||||
// 'Task updated #%d' => '',
|
||||
// 'Task #%d closed' => '',
|
||||
// 'Task #%d opened' => '',
|
||||
// 'Column changed for task #%d' => '',
|
||||
// 'New position for task #%d' => '',
|
||||
// 'Swimlane changed for task #%d' => '',
|
||||
// 'Assignee changed on task #%d' => '',
|
||||
'New attachment on task #%d: %s' => 'Nowy załącznik do zadania #%d: %s',
|
||||
'New comment on task #%d' => 'Nowy załącznik #%d',
|
||||
'Comment updated on task #%d' => 'Comment updated on task #%d',
|
||||
'New subtask on task #%d' => 'Nowe pod-zadanie dla zadania #%d',
|
||||
'Subtask updated on task #%d' => 'Aktualizacja pod-zadania w zadaniu #%d',
|
||||
'New task #%d: %s' => 'Nowe zadanie #%d: %s',
|
||||
'Task updated #%d' => 'Aktualizacja zadania #%d',
|
||||
'Task #%d closed' => 'Zamknięto zadanie #%d',
|
||||
'Task #%d opened' => 'Otwarto zadanie #%d',
|
||||
'Column changed for task #%d' => 'Zmieniono kolumnę zadania #%d',
|
||||
'New position for task #%d' => 'Ustalono nową pozycję zadania #%d',
|
||||
'Swimlane changed for task #%d' => 'Zmieniono swimlane dla zadania #%d',
|
||||
'Assignee changed on task #%d' => 'Zmieniono osobę odpowiedzialną dla zadania #%d',
|
||||
// '%d overdue tasks' => '',
|
||||
// 'Task #%d is overdue' => '',
|
||||
// 'No new notifications.' => '',
|
||||
// 'Mark all as read' => '',
|
||||
// 'Mark as read' => '',
|
||||
'No new notifications.' => 'Brak nowych powiadomień.',
|
||||
'Mark all as read' => 'Oznacz wszystkie jako przeczytane',
|
||||
'Mark as read' => 'Oznacz jako przeczytane',
|
||||
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||
// 'Collapse swimlane' => '',
|
||||
// 'Expand swimlane' => '',
|
||||
// 'Add a new filter' => '',
|
||||
// 'Share with all project members' => '',
|
||||
// 'Shared' => '',
|
||||
// 'Owner' => '',
|
||||
// 'Unread notifications' => '',
|
||||
// 'My filters' => '',
|
||||
// 'Notification methods:' => '',
|
||||
'Collapse swimlane' => 'Zwiń swimlane',
|
||||
'Expand swimlane' => 'Rozwiń swimlane',
|
||||
'Add a new filter' => 'Dodaj nowy filtr',
|
||||
'Share with all project members' => 'Udostępnij wszystkim uczestnikom projektu',
|
||||
//'Shared' => '',
|
||||
'Owner' => 'Właściciel',
|
||||
'Unread notifications' => 'Nieprzeczytane powiadomienia',
|
||||
'My filters' => 'Moje filtry',
|
||||
'Notification methods:' => 'Metody powiadomień:',
|
||||
// 'Import tasks from CSV file' => '',
|
||||
// 'Unable to read your file' => '',
|
||||
// '%d task(s) have been imported successfully.' => '',
|
||||
// 'Nothing have been imported!' => '',
|
||||
// 'Import users from CSV file' => '',
|
||||
// '%d user(s) have been imported successfully.' => '',
|
||||
// 'Comma' => '',
|
||||
// 'Semi-colon' => '',
|
||||
// 'Tab' => '',
|
||||
// 'Vertical bar' => '',
|
||||
// 'Double Quote' => '',
|
||||
// 'Single Quote' => '',
|
||||
'Comma' => 'Przecinek',
|
||||
'Semi-colon' => 'Średnik',
|
||||
'Tab' => 'Tabulacja',
|
||||
'Vertical bar' => 'Kreska pionowa',
|
||||
'Double Quote' => 'Cudzysłów',
|
||||
'Single Quote' => 'Apostrof',
|
||||
// '%s attached a file to the task #%d' => '',
|
||||
// 'There is no column or swimlane activated in your project!' => '',
|
||||
// 'Append filter (instead of replacement)' => '',
|
||||
'Append filter (instead of replacement)' => 'Dołączaj filtr do zastosowanego filtru(zamiast przełączać)',
|
||||
// 'Append/Replace' => '',
|
||||
// 'Append' => '',
|
||||
// 'Replace' => '',
|
||||
// 'There is no notification method registered.' => '',
|
||||
'There is no notification method registered.' => 'Tablica nie posiada aktywnych metod powiadomień.',
|
||||
// 'Import' => '',
|
||||
// 'change sorting' => '',
|
||||
// 'Tasks Importation' => '',
|
||||
// 'Delimiter' => '',
|
||||
// 'Enclosure' => '',
|
||||
// 'CSV File' => '',
|
||||
// 'Instructions' => '',
|
||||
// 'Your file must use the predefined CSV format' => '',
|
||||
// 'Your file must be encoded in UTF-8' => '',
|
||||
// 'The first row must be the header' => '',
|
||||
// 'Duplicates are not verified for you' => '',
|
||||
// 'The due date must use the ISO format: YYYY-MM-DD' => '',
|
||||
// 'Download CSV template' => '',
|
||||
'Tasks Importation' => 'Import zadań',
|
||||
'Delimiter' => 'Separator pola',
|
||||
'Enclosure' => 'Separator tekstu',
|
||||
'CSV File' => 'Plik CSV',
|
||||
'Instructions' => 'Instrukcje',
|
||||
'Your file must use the predefined CSV format' => 'Twój plik musi być zgodny z predefiniowanym formatem CSV (pobierz szablon)',
|
||||
'Your file must be encoded in UTF-8' => 'Twój plik musi być kodowany w UTF-8',
|
||||
'The first row must be the header' => 'Pierwszy wiersz pliku musi definiować nagłówki',
|
||||
'Duplicates are not verified for you' => 'Duplikaty nie będą weryfikowane',
|
||||
'The due date must use the ISO format: YYYY-MM-DD' => 'Data musi być w formacie ISO: YYYY-MM-DD',
|
||||
'Download CSV template' => 'Pobierz szablon pliku CSV',
|
||||
// 'No external integration registered.' => '',
|
||||
// 'Duplicates are not imported' => '',
|
||||
'Duplicates are not imported' => 'Duplikaty nie zostaną zaimportowane',
|
||||
// 'Usernames must be lowercase and unique' => '',
|
||||
// 'Passwords will be encrypted if present' => '',
|
||||
// '%s attached a new file to the task %s' => '',
|
||||
|
|
@ -1051,52 +1051,52 @@ return array(
|
|||
// 'BAM - Konvertible Mark' => '',
|
||||
// 'Assignee Username' => '',
|
||||
// 'Assignee Name' => '',
|
||||
// 'Groups' => '',
|
||||
// 'Members of %s' => '',
|
||||
// 'New group' => '',
|
||||
// 'Group created successfully.' => '',
|
||||
// 'Unable to create your group.' => '',
|
||||
// 'Edit group' => '',
|
||||
// 'Group updated successfully.' => '',
|
||||
// 'Unable to update your group.' => '',
|
||||
// 'Add group member to "%s"' => '',
|
||||
// 'Group member added successfully.' => '',
|
||||
// 'Unable to add group member.' => '',
|
||||
// 'Remove user from group "%s"' => '',
|
||||
// 'User removed successfully from this group.' => '',
|
||||
// 'Unable to remove this user from the group.' => '',
|
||||
// 'Remove group' => '',
|
||||
// 'Group removed successfully.' => '',
|
||||
// 'Unable to remove this group.' => '',
|
||||
// 'Project Permissions' => '',
|
||||
// 'Manager' => '',
|
||||
// 'Project Manager' => '',
|
||||
// 'Project Member' => '',
|
||||
// 'Project Viewer' => '',
|
||||
'Groups' => 'Grupy',
|
||||
'Members of %s' => 'Członkowie %s',
|
||||
'New group' => 'Nowa grupa',
|
||||
'Group created successfully.' => 'Grupa została utworzona.',
|
||||
'Unable to create your group.' => 'Nie można utworzyć grupy.',
|
||||
'Edit group' => 'Edytuj grupę',
|
||||
'Group updated successfully.' => 'Grupa została zaaktualizowana.',
|
||||
'Unable to update your group.' => 'Nie można zaaktualizować grupy.',
|
||||
'Add group member to "%s"' => 'Dodaj członka do grupy "%s"',
|
||||
'Group member added successfully.' => 'Użytkownik został dodany do grupy.',
|
||||
'Unable to add group member.' => 'Nie można dodać użytkownika do grupy.',
|
||||
'Remove user from group "%s"' => 'Usuń użytkownika z grupy "%s"',
|
||||
'User removed successfully from this group.' => 'Użytkownik został usunięty z grupy.',
|
||||
'Unable to remove this user from the group.' => 'Nie można usunąć użytkownika z grupy.',
|
||||
'Remove group' => 'Usuń grupę',
|
||||
'Group removed successfully.' => 'Grupa została usunięta.',
|
||||
'Unable to remove this group.' => 'Nie można usunąć grupy.',
|
||||
'Project Permissions' => 'Prawa dostępowe projektu',
|
||||
'Manager' => 'Menedżer',
|
||||
'Project Manager' => 'Menedżer projektu',
|
||||
'Project Member' => 'Uczestnik projektu',
|
||||
'Project Viewer' => 'Obserwator projektu',
|
||||
// 'Gitlab issue reopened' => '',
|
||||
// 'Your account is locked for %d minutes' => '',
|
||||
// 'Invalid captcha' => '',
|
||||
// 'The name must be unique' => '',
|
||||
// 'View all groups' => '',
|
||||
// 'View group members' => '',
|
||||
// 'There is no user available.' => '',
|
||||
// 'Do you really want to remove the user "%s" from the group "%s"?' => '',
|
||||
// 'There is no group.' => '',
|
||||
// 'External Id' => '',
|
||||
// 'Add group member' => '',
|
||||
// 'Do you really want to remove this group: "%s"?' => '',
|
||||
// 'There is no user in this group.' => '',
|
||||
// 'Remove this user' => '',
|
||||
// 'Permissions' => '',
|
||||
// 'Allowed Users' => '',
|
||||
// 'No user have been allowed specifically.' => '',
|
||||
// 'Role' => '',
|
||||
// 'Enter user name...' => '',
|
||||
// 'Allowed Groups' => '',
|
||||
// 'No group have been allowed specifically.' => '',
|
||||
// 'Group' => '',
|
||||
// 'Group Name' => '',
|
||||
// 'Enter group name...' => '',
|
||||
// 'Role:' => '',
|
||||
// 'Project members' => '',
|
||||
'Your account is locked for %d minutes' => 'Twoje konto zostało zablokowane na %d minut',
|
||||
'Invalid captcha' => 'Błędny kod z obrazka (captcha)',
|
||||
'The name must be unique' => 'Nazwa musi być unikatowa',
|
||||
'View all groups' => 'Wyświetl wszystkie grupy',
|
||||
'View group members' => 'Wyświetl wszystkich członków grupy',
|
||||
'There is no user available.' => 'Żaden użytkownik nie jest dostępny.',
|
||||
'Do you really want to remove the user "%s" from the group "%s"?' => 'Czy napewno chcesz usunąć użytkownika "%s" z grupy "%s"?',
|
||||
'There is no group.' => 'Brak grup.',
|
||||
'External Id' => 'Zewnętrzny Id',
|
||||
'Add group member' => 'Dodaj członka grupy',
|
||||
'Do you really want to remove this group: "%s"?' => 'Czy napewno chcesz usunąć grupę "%s"?',
|
||||
'There is no user in this group.' => 'Wybrana grupa nie posiada członków.',
|
||||
'Remove this user' => 'Usuń użytkownika',
|
||||
'Permissions' => 'Prawa dostępu',
|
||||
'Allowed Users' => 'Użytkownicy z dostępem',
|
||||
'No user have been allowed specifically.' => 'Żaden użytkownik nie ma przyznanego dostępu.',
|
||||
'Role' => 'Rola',
|
||||
'Enter user name...' => 'Wprowadź nazwę użytkownika...',
|
||||
'Allowed Groups' => 'Dostępne grupy',
|
||||
'No group have been allowed specifically.' => 'Żadna grupa nie ma przyznanego dostępu.',
|
||||
'Group' => 'Grupa',
|
||||
'Group Name' => 'Nazwa grupy',
|
||||
'Enter group name...' => 'Wprowadź nazwę grupy...',
|
||||
'Role:' => 'Rola:',
|
||||
'Project members' => 'Uczestnicy projektu',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -179,4 +179,49 @@ class ProjectAnalytic extends Base
|
|||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time spent and estimated into each status
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id
|
||||
* @return array
|
||||
*/
|
||||
public function getHoursByStatus($project_id)
|
||||
{
|
||||
$stats = array();
|
||||
|
||||
// Get the times related to each task
|
||||
$tasks = $this->db
|
||||
->table(Task::TABLE)
|
||||
->columns('id', 'time_estimated', 'time_spent', 'is_active')
|
||||
->eq('project_id', $project_id)
|
||||
->desc('id')
|
||||
->limit(1000)
|
||||
->findAll();
|
||||
|
||||
// Init values
|
||||
$stats['closed'] = array(
|
||||
'time_spent' => 0,
|
||||
'time_estimated' => 0,
|
||||
);
|
||||
|
||||
$stats['open'] = array(
|
||||
'time_spent' => 0,
|
||||
'time_estimated' => 0,
|
||||
);
|
||||
|
||||
// Add times spent and estimated to each status
|
||||
foreach ($tasks as &$task) {
|
||||
if ($task['is_active']) {
|
||||
$stats['open']['time_estimated'] += $task['time_estimated'];
|
||||
$stats['open']['time_spent'] += $task['time_spent'];
|
||||
} else {
|
||||
$stats['closed']['time_estimated'] += $task['time_estimated'];
|
||||
$stats['closed']['time_spent'] += $task['time_spent'];
|
||||
}
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ class ProjectPermission extends Base
|
|||
|
||||
return $this
|
||||
->db
|
||||
->table(self::TABLE)
|
||||
->table(ProjectUserRole::TABLE)
|
||||
->join(User::TABLE, 'id', 'user_id')
|
||||
->join(Project::TABLE, 'id', 'project_id')
|
||||
->eq(self::TABLE.'.role', $role)
|
||||
->eq(ProjectUserRole::TABLE.'.role', $role)
|
||||
->eq(Project::TABLE.'.is_private', 0)
|
||||
->in(Project::TABLE.'.id', $project_ids)
|
||||
->columns(
|
||||
|
|
@ -88,7 +88,7 @@ class ProjectPermission extends Base
|
|||
*/
|
||||
public function isMember($project_id, $user_id)
|
||||
{
|
||||
return in_array($this->projectUserRole->getUSerRole($project_id, $user_id), array(Role::PROJECT_MEMBER, Role::PROJECT_MANAGER));
|
||||
return in_array($this->projectUserRole->getUserRole($project_id, $user_id), array(Role::PROJECT_MEMBER, Role::PROJECT_MANAGER));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ class TaskFinder extends Base
|
|||
'tasks.recurrence_parent',
|
||||
'tasks.recurrence_child',
|
||||
'tasks.time_estimated',
|
||||
'tasks.time_spent',
|
||||
User::TABLE.'.username AS assignee_username',
|
||||
User::TABLE.'.name AS assignee_name',
|
||||
Category::TABLE.'.name AS category_name',
|
||||
|
|
|
|||
|
|
@ -57,6 +57,13 @@ class RouteProvider implements ServiceProviderInterface
|
|||
$container['router']->addRoute('project/:project_id/permissions', 'ProjectPermission', 'index', array('project_id'));
|
||||
$container['router']->addRoute('project/:project_id/import', 'taskImport', 'step1', array('project_id'));
|
||||
|
||||
// ProjectUser routes
|
||||
$container['router']->addRoute('projects/managers/:user_id', 'projectuser', 'managers', array('user_id'));
|
||||
$container['router']->addRoute('projects/members/:user_id', 'projectuser', 'members', array('user_id'));
|
||||
$container['router']->addRoute('projects/tasks/:user_id/opens', 'projectuser', 'opens', array('user_id'));
|
||||
$container['router']->addRoute('projects/tasks/:user_id/closed', 'projectuser', 'closed', array('user_id'));
|
||||
$container['router']->addRoute('projects/managers', 'projectuser', 'managers');
|
||||
|
||||
// Action routes
|
||||
$container['router']->addRoute('project/:project_id/actions', 'action', 'index', array('project_id'));
|
||||
$container['router']->addRoute('project/:project_id/action/:action_id/confirm', 'action', 'confirm', array('project_id', 'action_id'));
|
||||
|
|
|
|||
|
|
@ -57,8 +57,6 @@ class AuthSubscriber extends Base implements EventSubscriberInterface
|
|||
$this->userSession->validatePostAuthentication();
|
||||
}
|
||||
|
||||
$this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
||||
|
||||
if (isset($this->sessionStorage->hasRememberMe) && $this->sessionStorage->hasRememberMe) {
|
||||
$session = $this->rememberMeSession->create($this->userSession->getId(), $ipAddress, $userAgent);
|
||||
$this->rememberMeCookie->write($session['token'], $session['sequence'], $session['expiration']);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class BootstrapSubscriber extends \Kanboard\Core\Base implements EventSubscriber
|
|||
{
|
||||
$this->config->setupTranslations();
|
||||
$this->config->setupTimezone();
|
||||
$this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
<div class="page-header">
|
||||
<h2><?= t('Compare Estimated Time vs Actual Time') ?></h2>
|
||||
</div>
|
||||
|
||||
<div class="listing">
|
||||
<ul>
|
||||
<li><?= t('Estimated hours: ').'<strong>'.$this->e($metrics['open']['time_estimated']+$metrics['open']['time_estimated']) ?></strong></li>
|
||||
<li><?= t('Actual hours: ').'<strong>'.$this->e($metrics['open']['time_spent']+$metrics['closed']['time_spent']) ?></strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<?php if (empty($metrics)): ?>
|
||||
<p class="alert"><?= t('Not enough data to show the graph.') ?></p>
|
||||
<?php else: ?>
|
||||
<section id="analytic-compare-hours">
|
||||
<div id="chart" data-metrics='<?= json_encode($metrics, JSON_HEX_APOS)?>' data-label-spent="<?= t('Hours Spent') ?>" data-label-estimated="<?= t('Hours Estimated') ?>"></div>
|
||||
|
||||
<?php if ($paginator->isEmpty()): ?>
|
||||
<p class="alert"><?= t('No tasks found.') ?></p>
|
||||
<?php elseif (! $paginator->isEmpty()): ?>
|
||||
<table class="table-fixed table-small">
|
||||
<tr>
|
||||
<th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th>
|
||||
<th><?= $paginator->order(t('Title'), 'tasks.title') ?></th>
|
||||
<th class="column-5"><?= $paginator->order(t('Status'), 'tasks.is_active') ?></th>
|
||||
<th class="column-10"><?= $paginator->order(t('Estimated Time'), 'tasks.time_estimated') ?></th>
|
||||
<th class="column-10"><?= $paginator->order(t('Actual Time'), 'tasks.time_spent') ?></th>
|
||||
</tr>
|
||||
<?php foreach ($paginator->getCollection() as $task): ?>
|
||||
<tr>
|
||||
<td class="task-table color-<?= $task['color_id'] ?>">
|
||||
<?= $this->url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?>
|
||||
</td>
|
||||
<td>
|
||||
<?= $this->url->link($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($task['is_active'] == \Kanboard\Model\Task::STATUS_OPEN): ?>
|
||||
<?= t('Open') ?>
|
||||
<?php else: ?>
|
||||
<?= t('Closed') ?>
|
||||
<?php endif ?>
|
||||
</td>
|
||||
<td>
|
||||
<?= $this->e($task['time_estimated']) ?>
|
||||
</td>
|
||||
<td>
|
||||
<?= $this->e($task['time_spent']) ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
|
||||
<?= $paginator ?>
|
||||
<?php endif ?>
|
||||
</section>
|
||||
<?php endif ?>
|
||||
|
|
@ -19,7 +19,10 @@
|
|||
<li <?= $this->app->getRouterAction() === 'leadandcycletime' ? 'class="active"' : '' ?>>
|
||||
<?= $this->url->link(t('Lead and cycle time'), 'analytic', 'leadAndCycleTime', array('project_id' => $project['id'])) ?>
|
||||
</li>
|
||||
<li <?= $this->app->getRouterAction() === 'comparehours' ? 'class="active"' : '' ?>>
|
||||
<?= $this->url->link(t('Compare hours'), 'analytic', 'compareHours', array('project_id' => $project['id'])) ?>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="sidebar-collapse"><a href="#" title="<?= t('Hide sidebar') ?>"><i class="fa fa-chevron-left"></i></a></div>
|
||||
<div class="sidebar-expand" style="display: none"><a href="#" title="<?= t('Expand sidebar') ?>"><i class="fa fa-chevron-right"></i></a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,37 @@
|
|||
function CompareHoursColumnChart(app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
CompareHoursColumnChart.prototype.execute = function() {
|
||||
var metrics = $("#chart").data("metrics");
|
||||
var spent = [$("#chart").data("label-spent")];
|
||||
var estimated = [$("#chart").data("label-estimated")];
|
||||
var categories = [];
|
||||
|
||||
for (var status in metrics) {
|
||||
spent.push(parseInt(metrics[status].time_spent));
|
||||
estimated.push(parseInt(metrics[status].time_estimated));
|
||||
categories.push(status);
|
||||
}
|
||||
|
||||
c3.generate({
|
||||
data: {
|
||||
columns: [spent, estimated],
|
||||
type: 'bar'
|
||||
},
|
||||
bar: {
|
||||
width: {
|
||||
ratio: 0.2
|
||||
}
|
||||
},
|
||||
axis: {
|
||||
x: {
|
||||
type: 'category',
|
||||
categories: categories
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: true
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -185,7 +185,7 @@ Gantt.prototype.addBlocks = function(slider, start) {
|
|||
|
||||
var block = jQuery("<div>", {
|
||||
"class": "ganttview-block tooltip" + (this.options.allowMoves ? " ganttview-block-movable" : ""),
|
||||
"title": this.getBarTooltip(this.data[i]),
|
||||
"title": this.getBarTooltip(series),
|
||||
"css": {
|
||||
"width": ((size * this.options.cellWidth) - 9) + "px",
|
||||
"margin-left": (offset * this.options.cellWidth) + "px"
|
||||
|
|
@ -193,23 +193,25 @@ Gantt.prototype.addBlocks = function(slider, start) {
|
|||
}).append(text);
|
||||
|
||||
if (size >= 2) {
|
||||
text.append(this.data[i].progress);
|
||||
text.append(series.progress);
|
||||
}
|
||||
|
||||
block.data("record", this.data[i]);
|
||||
this.setBarColor(block, this.data[i]);
|
||||
block.data("record", series);
|
||||
this.setBarColor(block, series);
|
||||
|
||||
block.append(jQuery("<div>", {
|
||||
"css": {
|
||||
"z-index": 0,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"bottom": 0,
|
||||
"background-color": series.color.border,
|
||||
"width": series.progress,
|
||||
"opacity": 0.4
|
||||
}
|
||||
}));
|
||||
if (series.progress != "0%") {
|
||||
block.append(jQuery("<div>", {
|
||||
"css": {
|
||||
"z-index": 0,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"bottom": 0,
|
||||
"background-color": series.color.border,
|
||||
"width": series.progress,
|
||||
"opacity": 0.4
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
jQuery(rows[rowIdx]).append(block);
|
||||
rowIdx = rowIdx + 1;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ jQuery(document).ready(function() {
|
|||
router.addRoute('analytic-avg-time-column', AvgTimeColumnChart);
|
||||
router.addRoute('analytic-task-time-column', TaskTimeColumnChart);
|
||||
router.addRoute('analytic-lead-cycle-time', LeadCycleTimeChart);
|
||||
router.addRoute('analytic-compare-hours', CompareHoursColumnChart);
|
||||
router.addRoute('gantt-chart', Gantt);
|
||||
router.dispatch(app);
|
||||
app.listen();
|
||||
|
|
|
|||
|
|
@ -392,10 +392,8 @@ Response example:
|
|||
- Parameters:
|
||||
- **id** (integer, required)
|
||||
- **title** (string, optional)
|
||||
- **project_id** (integer, optional)
|
||||
- **color_id** (string, optional)
|
||||
- **owner_id** (integer, optional)
|
||||
- **creator_id** (integer, optional)
|
||||
- **date_due**: ISO8601 format (string, optional)
|
||||
- **description** Markdown content (string, optional)
|
||||
- **category_id** (integer, optional)
|
||||
|
|
|
|||
|
|
@ -366,6 +366,33 @@ class Api extends PHPUnit_Framework_TestCase
|
|||
$this->assertEquals('Swimlane A', $swimlanes[2]['name']);
|
||||
}
|
||||
|
||||
public function testCreateTaskWithWrongMember()
|
||||
{
|
||||
$task = array(
|
||||
'title' => 'Task #1',
|
||||
'color_id' => 'blue',
|
||||
'owner_id' => 1,
|
||||
'project_id' => 1,
|
||||
'column_id' => 2,
|
||||
);
|
||||
|
||||
$task_id = $this->client->createTask($task);
|
||||
|
||||
$this->assertFalse($task_id);
|
||||
}
|
||||
|
||||
public function testGetAllowedUsers()
|
||||
{
|
||||
$users = $this->client->getMembers(1);
|
||||
$this->assertNotFalse($users);
|
||||
$this->assertEquals(array(), $users);
|
||||
}
|
||||
|
||||
public function testAddMember()
|
||||
{
|
||||
$this->assertTrue($this->client->allowUser(1, 1));
|
||||
}
|
||||
|
||||
public function testCreateTask()
|
||||
{
|
||||
$task = array(
|
||||
|
|
@ -573,20 +600,13 @@ class Api extends PHPUnit_Framework_TestCase
|
|||
$this->assertEquals('titi@localhost', $user['email']);
|
||||
}
|
||||
|
||||
public function testGetAllowedUsers()
|
||||
{
|
||||
$users = $this->client->getMembers(1);
|
||||
$this->assertNotFalse($users);
|
||||
$this->assertEquals(array(), $users);
|
||||
}
|
||||
|
||||
public function testAllowedUser()
|
||||
{
|
||||
$this->assertTrue($this->client->allowUser(1, 2));
|
||||
|
||||
$users = $this->client->getMembers(1);
|
||||
$this->assertNotFalse($users);
|
||||
$this->assertEquals(array(2 => 'Titi'), $users);
|
||||
$this->assertEquals(array(1 => 'admin', 2 => 'Titi'), $users);
|
||||
}
|
||||
|
||||
public function testRevokeUser()
|
||||
|
|
@ -595,7 +615,7 @@ class Api extends PHPUnit_Framework_TestCase
|
|||
|
||||
$users = $this->client->getMembers(1);
|
||||
$this->assertNotFalse($users);
|
||||
$this->assertEquals(array(), $users);
|
||||
$this->assertEquals(array(1 => 'admin'), $users);
|
||||
}
|
||||
|
||||
public function testCreateComment()
|
||||
|
|
|
|||
|
|
@ -163,6 +163,12 @@ class UserApi extends PHPUnit_Framework_TestCase
|
|||
$this->assertEquals(2, $this->admin->createTask('my admin title', 1));
|
||||
}
|
||||
|
||||
public function testCreateTaskWithWrongMember()
|
||||
{
|
||||
$this->assertFalse($this->user->createTask(array('title' => 'something', 'project_id' => 2, 'owner_id' => 1)));
|
||||
$this->assertFalse($this->app->createTask(array('title' => 'something', 'project_id' => 1, 'owner_id' => 2)));
|
||||
}
|
||||
|
||||
public function testGetTask()
|
||||
{
|
||||
$task = $this->user->getTask(1);
|
||||
|
|
@ -218,6 +224,11 @@ class UserApi extends PHPUnit_Framework_TestCase
|
|||
$this->assertTrue($this->user->moveTaskPosition(2, 1, 2, 1));
|
||||
}
|
||||
|
||||
public function testUpdateTaskWithWrongMember()
|
||||
{
|
||||
$this->assertFalse($this->user->updateTask(array('id' => 1, 'title' => 'new title', 'reference' => 'test', 'owner_id' => 1)));
|
||||
}
|
||||
|
||||
public function testUpdateTask()
|
||||
{
|
||||
$this->assertTrue($this->user->updateTask(array('id' => 1, 'title' => 'new title', 'reference' => 'test', 'owner_id' => 2)));
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ class CsvTest extends Base
|
|||
$this->assertEquals(1, Csv::getBooleanValue('TRUE'));
|
||||
$this->assertEquals(1, Csv::getBooleanValue('true'));
|
||||
$this->assertEquals(1, Csv::getBooleanValue('T'));
|
||||
$this->assertEquals(1, Csv::getBooleanValue('Y'));
|
||||
$this->assertEquals(1, Csv::getBooleanValue('y'));
|
||||
$this->assertEquals(1, Csv::getBooleanValue('yes'));
|
||||
$this->assertEquals(1, Csv::getBooleanValue('Yes'));
|
||||
|
||||
$this->assertEquals(0, Csv::getBooleanValue('0'));
|
||||
$this->assertEquals(0, Csv::getBooleanValue('123'));
|
||||
|
|
|
|||
|
|
@ -13,6 +13,183 @@ use Kanboard\Core\Security\Role;
|
|||
|
||||
class ProjectPermissionTest extends Base
|
||||
{
|
||||
public function testGetQueryByRole()
|
||||
{
|
||||
$userModel = new User($this->container);
|
||||
$projectModel = new Project($this->container);
|
||||
$groupModel = new Group($this->container);
|
||||
$groupMemberModel = new GroupMember($this->container);
|
||||
$groupRoleModel = new ProjectGroupRole($this->container);
|
||||
$userRoleModel = new ProjectUserRole($this->container);
|
||||
$projectPermission = new ProjectPermission($this->container);
|
||||
|
||||
$this->assertEquals(1, $projectModel->create(array('name' => 'Project 1')));
|
||||
$this->assertEquals(2, $projectModel->create(array('name' => 'Project 2')));
|
||||
$this->assertEquals(3, $projectModel->create(array('name' => 'Project 3')));
|
||||
|
||||
$this->assertEquals(2, $userModel->create(array('username' => 'user 1')));
|
||||
$this->assertEquals(3, $userModel->create(array('username' => 'user 2')));
|
||||
$this->assertEquals(4, $userModel->create(array('username' => 'user 3')));
|
||||
$this->assertEquals(5, $userModel->create(array('username' => 'user 4')));
|
||||
|
||||
$this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MANAGER));
|
||||
$this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MANAGER));
|
||||
$this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MEMBER));
|
||||
$this->assertTrue($userRoleModel->addUser(1, 5, Role::PROJECT_MEMBER));
|
||||
|
||||
$this->assertTrue($userRoleModel->addUser(2, 2, Role::PROJECT_MEMBER));
|
||||
$this->assertTrue($userRoleModel->addUser(2, 3, Role::PROJECT_MEMBER));
|
||||
$this->assertTrue($userRoleModel->addUser(2, 5, Role::PROJECT_MANAGER));
|
||||
|
||||
$this->assertTrue($userRoleModel->addUser(3, 4, Role::PROJECT_MANAGER));
|
||||
$this->assertTrue($userRoleModel->addUser(3, 5, Role::PROJECT_VIEWER));
|
||||
|
||||
$this->assertEmpty($projectPermission->getQueryByRole(array(), Role::PROJECT_MANAGER)->findAll());
|
||||
|
||||
$users = $projectPermission->getQueryByRole(array(1, 2), Role::PROJECT_MANAGER)->findAll();
|
||||
$this->assertCount(3, $users);
|
||||
$this->assertEquals('user 1', $users[0]['username']);
|
||||
$this->assertEquals('Project 1', $users[0]['project_name']);
|
||||
$this->assertEquals('user 2', $users[1]['username']);
|
||||
$this->assertEquals('Project 1', $users[1]['project_name']);
|
||||
$this->assertEquals('user 4', $users[2]['username']);
|
||||
$this->assertEquals('Project 2', $users[2]['project_name']);
|
||||
|
||||
$users = $projectPermission->getQueryByRole(array(1), Role::PROJECT_MANAGER)->findAll();
|
||||
$this->assertCount(2, $users);
|
||||
$this->assertEquals('user 1', $users[0]['username']);
|
||||
$this->assertEquals('Project 1', $users[0]['project_name']);
|
||||
$this->assertEquals('user 2', $users[1]['username']);
|
||||
$this->assertEquals('Project 1', $users[1]['project_name']);
|
||||
|
||||
$users = $projectPermission->getQueryByRole(array(1, 2, 3), Role::PROJECT_MEMBER)->findAll();
|
||||
$this->assertCount(4, $users);
|
||||
$this->assertEquals('user 3', $users[0]['username']);
|
||||
$this->assertEquals('Project 1', $users[0]['project_name']);
|
||||
$this->assertEquals('user 4', $users[1]['username']);
|
||||
$this->assertEquals('Project 1', $users[1]['project_name']);
|
||||
$this->assertEquals('user 1', $users[2]['username']);
|
||||
$this->assertEquals('Project 2', $users[2]['project_name']);
|
||||
$this->assertEquals('user 2', $users[3]['username']);
|
||||
$this->assertEquals('Project 2', $users[3]['project_name']);
|
||||
|
||||
$users = $projectPermission->getQueryByRole(array(1, 2, 3), Role::PROJECT_VIEWER)->findAll();
|
||||
$this->assertCount(1, $users);
|
||||
$this->assertEquals('user 4', $users[0]['username']);
|
||||
$this->assertEquals('Project 3', $users[0]['project_name']);
|
||||
}
|
||||
|
||||
public function testEverybodyAllowed()
|
||||
{
|
||||
$projectModel = new Project($this->container);
|
||||
$projectPermission = new ProjectPermission($this->container);
|
||||
|
||||
$this->assertEquals(1, $projectModel->create(array('name' => 'Project 1')));
|
||||
$this->assertEquals(2, $projectModel->create(array('name' => 'Project 2', 'is_everybody_allowed' => 1)));
|
||||
|
||||
$this->assertFalse($projectPermission->isEverybodyAllowed(1));
|
||||
$this->assertTrue($projectPermission->isEverybodyAllowed(2));
|
||||
}
|
||||
|
||||
public function testIsUserAllowed()
|
||||
{
|
||||
$userModel = new User($this->container);
|
||||
$projectModel = new Project($this->container);
|
||||
$groupModel = new Group($this->container);
|
||||
$groupRoleModel = new ProjectGroupRole($this->container);
|
||||
$groupMemberModel = new GroupMember($this->container);
|
||||
$userRoleModel = new ProjectUserRole($this->container);
|
||||
$projectPermission = new ProjectPermission($this->container);
|
||||
|
||||
$this->assertEquals(2, $userModel->create(array('username' => 'user 1')));
|
||||
$this->assertEquals(3, $userModel->create(array('username' => 'user 2')));
|
||||
$this->assertEquals(4, $userModel->create(array('username' => 'user 3')));
|
||||
$this->assertEquals(5, $userModel->create(array('username' => 'user 4')));
|
||||
|
||||
$this->assertEquals(1, $projectModel->create(array('name' => 'Project 1')));
|
||||
$this->assertEquals(2, $projectModel->create(array('name' => 'Project 2')));
|
||||
|
||||
$this->assertEquals(1, $groupModel->create('Group A'));
|
||||
|
||||
$this->assertTrue($groupMemberModel->addUser(1, 2));
|
||||
$this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER));
|
||||
|
||||
$this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER));
|
||||
$this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MANAGER));
|
||||
|
||||
$this->assertTrue($projectPermission->isUserAllowed(1, 2));
|
||||
$this->assertTrue($projectPermission->isUserAllowed(1, 3));
|
||||
$this->assertTrue($projectPermission->isUserAllowed(1, 4));
|
||||
$this->assertFalse($projectPermission->isUserAllowed(1, 5));
|
||||
|
||||
$this->assertFalse($projectPermission->isUserAllowed(2, 2));
|
||||
$this->assertFalse($projectPermission->isUserAllowed(2, 3));
|
||||
$this->assertFalse($projectPermission->isUserAllowed(2, 4));
|
||||
$this->assertFalse($projectPermission->isUserAllowed(2, 5));
|
||||
}
|
||||
|
||||
public function testIsMember()
|
||||
{
|
||||
$userModel = new User($this->container);
|
||||
$projectModel = new Project($this->container);
|
||||
$groupModel = new Group($this->container);
|
||||
$groupRoleModel = new ProjectGroupRole($this->container);
|
||||
$groupMemberModel = new GroupMember($this->container);
|
||||
$userRoleModel = new ProjectUserRole($this->container);
|
||||
$projectPermission = new ProjectPermission($this->container);
|
||||
|
||||
$this->assertEquals(2, $userModel->create(array('username' => 'user 1')));
|
||||
$this->assertEquals(3, $userModel->create(array('username' => 'user 2')));
|
||||
$this->assertEquals(4, $userModel->create(array('username' => 'user 3')));
|
||||
$this->assertEquals(5, $userModel->create(array('username' => 'user 4')));
|
||||
|
||||
$this->assertEquals(1, $projectModel->create(array('name' => 'Project 1')));
|
||||
$this->assertEquals(2, $projectModel->create(array('name' => 'Project 2')));
|
||||
|
||||
$this->assertEquals(1, $groupModel->create('Group A'));
|
||||
|
||||
$this->assertTrue($groupMemberModel->addUser(1, 2));
|
||||
$this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_VIEWER));
|
||||
|
||||
$this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MEMBER));
|
||||
$this->assertTrue($userRoleModel->addUser(1, 4, Role::PROJECT_MANAGER));
|
||||
|
||||
$this->assertFalse($projectPermission->isMember(1, 2));
|
||||
$this->assertTrue($projectPermission->isMember(1, 3));
|
||||
$this->assertTrue($projectPermission->isMember(1, 4));
|
||||
$this->assertFalse($projectPermission->isMember(1, 5));
|
||||
|
||||
$this->assertFalse($projectPermission->isMember(2, 2));
|
||||
$this->assertFalse($projectPermission->isMember(2, 3));
|
||||
$this->assertFalse($projectPermission->isMember(2, 4));
|
||||
$this->assertFalse($projectPermission->isMember(2, 5));
|
||||
}
|
||||
|
||||
public function testGetActiveProjectIds()
|
||||
{
|
||||
$userModel = new User($this->container);
|
||||
$projectModel = new Project($this->container);
|
||||
$groupModel = new Group($this->container);
|
||||
$groupRoleModel = new ProjectGroupRole($this->container);
|
||||
$groupMemberModel = new GroupMember($this->container);
|
||||
$userRoleModel = new ProjectUserRole($this->container);
|
||||
$projectPermission = new ProjectPermission($this->container);
|
||||
|
||||
$this->assertEquals(2, $userModel->create(array('username' => 'user 1')));
|
||||
$this->assertEquals(3, $userModel->create(array('username' => 'user 2')));
|
||||
|
||||
$this->assertEquals(1, $projectModel->create(array('name' => 'Project 1')));
|
||||
$this->assertEquals(2, $projectModel->create(array('name' => 'Project 2', 'is_active' => 0)));
|
||||
|
||||
$this->assertTrue($userRoleModel->addUser(1, 2, Role::PROJECT_MEMBER));
|
||||
$this->assertTrue($userRoleModel->addUser(2, 2, Role::PROJECT_VIEWER));
|
||||
$this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_VIEWER));
|
||||
|
||||
$this->assertEmpty($projectPermission->getActiveProjectIds(1));
|
||||
$this->assertEquals(array(1), $projectPermission->getActiveProjectIds(2));
|
||||
$this->assertEquals(array(1), $projectPermission->getActiveProjectIds(3));
|
||||
}
|
||||
|
||||
public function testDuplicate()
|
||||
{
|
||||
$userModel = new User($this->container);
|
||||
|
|
|
|||
Loading…
Reference in New Issue