diff options
author | Frederic Guillot <fred@kanboard.net> | 2015-09-20 18:24:15 -0400 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2015-09-20 18:24:15 -0400 |
commit | e6f547abcfe684658a7498391db72d13b6aa7d9a (patch) | |
tree | 75b709c12fb03e11d7cb85558558f89f19abb284 | |
parent | 2021dccc5a444f60c5ba1673d94b39999912cd26 (diff) |
Move timetable to a plugin
Plugin repository: https://github.com/kanboard/plugin-timetable
59 files changed, 136 insertions, 2467 deletions
@@ -14,6 +14,7 @@ Core functionalities moved to plugins: * Budget planning: https://github.com/kanboard/plugin-budget * SubtaskForecast: https://github.com/kanboard/plugin-subtask-forecast +* Timetable: https://github.com/kanboard/plugin-timetable Improvements: @@ -30,7 +31,7 @@ Improvements: Bug fixes: -* Fix typo in template that prevent the Gitlab oauth link to be displayed +* Fix typo in template that prevent the Gitlab OAuth link to be displayed * Fix Markdown preview links focus * Avoid dropdown menu to be truncated inside a column with scrolling * Deleting subtask doesn't update task time tracking diff --git a/app/Controller/Timetable.php b/app/Controller/Timetable.php deleted file mode 100644 index 65edb44c..00000000 --- a/app/Controller/Timetable.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -namespace Controller; - -use DateTime; - -/** - * Timetable controller - * - * @package controller - * @author Frederic Guillot - */ -class Timetable extends User -{ - /** - * Display timetable for the user - * - * @access public - */ - public function index() - { - $user = $this->getUser(); - $from = $this->request->getStringParam('from', date('Y-m-d')); - $to = $this->request->getStringParam('to', date('Y-m-d', strtotime('next week'))); - $timetable = $this->timetable->calculate($user['id'], new DateTime($from), new DateTime($to)); - - $this->response->html($this->layout('timetable/index', array( - 'user' => $user, - 'timetable' => $timetable, - 'values' => array( - 'from' => $from, - 'to' => $to, - 'controller' => 'timetable', - 'action' => 'index', - 'user_id' => $user['id'], - ), - ))); - } -} diff --git a/app/Controller/Timetableday.php b/app/Controller/Timetableday.php deleted file mode 100644 index c8f7ac8a..00000000 --- a/app/Controller/Timetableday.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -namespace Controller; - -/** - * Day Timetable controller - * - * @package controller - * @author Frederic Guillot - */ -class Timetableday extends User -{ - /** - * Display timetable for the user - * - * @access public - */ - public function index(array $values = array(), array $errors = array()) - { - $user = $this->getUser(); - - $this->response->html($this->layout('timetable_day/index', array( - 'timetable' => $this->timetableDay->getByUser($user['id']), - 'values' => $values + array('user_id' => $user['id']), - 'errors' => $errors, - 'user' => $user, - ))); - } - - /** - * Validate and save - * - * @access public - */ - public function save() - { - $values = $this->request->getValues(); - list($valid, $errors) = $this->timetableDay->validateCreation($values); - - if ($valid) { - - if ($this->timetableDay->create($values['user_id'], $values['start'], $values['end'])) { - $this->session->flash(t('Time slot created successfully.')); - $this->response->redirect($this->helper->url->to('timetableday', 'index', array('user_id' => $values['user_id']))); - } - else { - $this->session->flashError(t('Unable to save this time slot.')); - } - } - - $this->index($values, $errors); - } - - /** - * Confirmation dialag box to remove a row - * - * @access public - */ - public function confirm() - { - $user = $this->getUser(); - - $this->response->html($this->layout('timetable_day/remove', array( - 'slot_id' => $this->request->getIntegerParam('slot_id'), - 'user' => $user, - ))); - } - - /** - * Remove a row - * - * @access public - */ - public function remove() - { - $this->checkCSRFParam(); - $user = $this->getUser(); - - if ($this->timetableDay->remove($this->request->getIntegerParam('slot_id'))) { - $this->session->flash(t('Time slot removed successfully.')); - } - else { - $this->session->flash(t('Unable to remove this time slot.')); - } - - $this->response->redirect($this->helper->url->to('timetableday', 'index', array('user_id' => $user['id']))); - } -} diff --git a/app/Controller/Timetableextra.php b/app/Controller/Timetableextra.php deleted file mode 100644 index 7c6fe265..00000000 --- a/app/Controller/Timetableextra.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Controller; - -/** - * Over-time Timetable controller - * - * @package controller - * @author Frederic Guillot - */ -class Timetableextra extends Timetableoff -{ - protected $model = 'timetableExtra'; - protected $controller_url = 'timetableextra'; - protected $template_dir = 'timetable_extra'; -} diff --git a/app/Controller/Timetableoff.php b/app/Controller/Timetableoff.php deleted file mode 100644 index 585014a3..00000000 --- a/app/Controller/Timetableoff.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -namespace Controller; - -/** - * Time-off Timetable controller - * - * @package controller - * @author Frederic Guillot - */ -class Timetableoff extends User -{ - protected $model = 'timetableOff'; - protected $controller_url = 'timetableoff'; - protected $template_dir = 'timetable_off'; - - /** - * Display timetable for the user - * - * @access public - */ - public function index(array $values = array(), array $errors = array()) - { - $user = $this->getUser(); - - $paginator = $this->paginator - ->setUrl($this->controller_url, 'index', array('user_id' => $user['id'])) - ->setMax(10) - ->setOrder('date') - ->setDirection('desc') - ->setQuery($this->{$this->model}->getUserQuery($user['id'])) - ->calculate(); - - $this->response->html($this->layout($this->template_dir.'/index', array( - 'values' => $values + array('user_id' => $user['id']), - 'errors' => $errors, - 'paginator' => $paginator, - 'user' => $user, - ))); - } - - /** - * Validate and save - * - * @access public - */ - public function save() - { - $values = $this->request->getValues(); - list($valid, $errors) = $this->{$this->model}->validateCreation($values); - - if ($valid) { - - if ($this->{$this->model}->create( - $values['user_id'], - $values['date'], - isset($values['all_day']) && $values['all_day'] == 1, - $values['start'], - $values['end'], - $values['comment'])) { - - $this->session->flash(t('Time slot created successfully.')); - $this->response->redirect($this->helper->url->to($this->controller_url, 'index', array('user_id' => $values['user_id']))); - } - else { - $this->session->flashError(t('Unable to save this time slot.')); - } - } - - $this->index($values, $errors); - } - - /** - * Confirmation dialag box to remove a row - * - * @access public - */ - public function confirm() - { - $user = $this->getUser(); - - $this->response->html($this->layout($this->template_dir.'/remove', array( - 'slot_id' => $this->request->getIntegerParam('slot_id'), - 'user' => $user, - ))); - } - - /** - * Remove a row - * - * @access public - */ - public function remove() - { - $this->checkCSRFParam(); - $user = $this->getUser(); - - if ($this->{$this->model}->remove($this->request->getIntegerParam('slot_id'))) { - $this->session->flash(t('Time slot removed successfully.')); - } - else { - $this->session->flash(t('Unable to remove this time slot.')); - } - - $this->response->redirect($this->helper->url->to($this->controller_url, 'index', array('user_id' => $user['id']))); - } -} diff --git a/app/Controller/Timetableweek.php b/app/Controller/Timetableweek.php deleted file mode 100644 index b8ce00e7..00000000 --- a/app/Controller/Timetableweek.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -namespace Controller; - -/** - * Week Timetable controller - * - * @package controller - * @author Frederic Guillot - */ -class Timetableweek extends User -{ - /** - * Display timetable for the user - * - * @access public - */ - public function index(array $values = array(), array $errors = array()) - { - $user = $this->getUser(); - - if (empty($values)) { - - $day = $this->timetableDay->getByUser($user['id']); - - $values = array( - 'user_id' => $user['id'], - 'start' => isset($day[0]['start']) ? $day[0]['start'] : null, - 'end' => isset($day[0]['end']) ? $day[0]['end'] : null, - ); - } - - $this->response->html($this->layout('timetable_week/index', array( - 'timetable' => $this->timetableWeek->getByUser($user['id']), - 'values' => $values, - 'errors' => $errors, - 'user' => $user, - ))); - } - - /** - * Validate and save - * - * @access public - */ - public function save() - { - $values = $this->request->getValues(); - list($valid, $errors) = $this->timetableWeek->validateCreation($values); - - if ($valid) { - - if ($this->timetableWeek->create($values['user_id'], $values['day'], $values['start'], $values['end'])) { - $this->session->flash(t('Time slot created successfully.')); - $this->response->redirect($this->helper->url->to('timetableweek', 'index', array('user_id' => $values['user_id']))); - } - else { - $this->session->flashError(t('Unable to save this time slot.')); - } - } - - $this->index($values, $errors); - } - - /** - * Confirmation dialag box to remove a row - * - * @access public - */ - public function confirm() - { - $user = $this->getUser(); - - $this->response->html($this->layout('timetable_week/remove', array( - 'slot_id' => $this->request->getIntegerParam('slot_id'), - 'user' => $user, - ))); - } - - /** - * Remove a row - * - * @access public - */ - public function remove() - { - $this->checkCSRFParam(); - $user = $this->getUser(); - - if ($this->timetableWeek->remove($this->request->getIntegerParam('slot_id'))) { - $this->session->flash(t('Time slot removed successfully.')); - } - else { - $this->session->flash(t('Unable to remove this time slot.')); - } - - $this->response->redirect($this->helper->url->to('timetableweek', 'index', array('user_id' => $user['id']))); - } -} diff --git a/app/Core/Base.php b/app/Core/Base.php index 2dec4b29..ba925ebe 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -70,11 +70,6 @@ use Pimple\Container; * @property \Model\TaskPosition $taskPosition * @property \Model\TaskStatus $taskStatus * @property \Model\TaskValidator $taskValidator - * @property \Model\Timetable $timetable - * @property \Model\TimetableDay $timetableDay - * @property \Model\TimetableExtra $timetableExtra - * @property \Model\TimetableOff $timetableOff - * @property \Model\TimetableWeek $timetableWeek * @property \Model\Transition $transition * @property \Model\User $user * @property \Model\UserSession $userSession diff --git a/app/Core/Plugin/Hook.php b/app/Core/Plugin/Hook.php index 4fb55569..fa14af13 100644 --- a/app/Core/Plugin/Hook.php +++ b/app/Core/Plugin/Hook.php @@ -47,6 +47,18 @@ class Hook } /** + * Return true if the hook is used + * + * @access public + * @param string $hook + * @return boolean + */ + public function exists($hook) + { + return isset($this->hooks[$hook]); + } + + /** * Merge listener results with input array * * @access public @@ -67,4 +79,21 @@ class Hook return $values; } + + /** + * Execute only first listener + * + * @access public + * @param string $hook + * @param array $params + * @return mixed + */ + public function first($hook, array $params = array()) + { + foreach ($this->getListeners($hook) as $listener) { + return call_user_func_array($listener, $params); + } + + return null; + } } diff --git a/app/Core/Plugin/Loader.php b/app/Core/Plugin/Loader.php index ffead9f6..45da135b 100644 --- a/app/Core/Plugin/Loader.php +++ b/app/Core/Plugin/Loader.php @@ -67,7 +67,7 @@ class Loader extends \Core\Base $filename = __DIR__.'/../../../plugins/'.$plugin.'/Schema/'.ucfirst(DB_DRIVER).'.php'; if (file_exists($filename)) { - require($filename); + require_once($filename); $this->migrateSchema($plugin); } } diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index 8cea7367..6c5cf0fb 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Kompaktní/plné zobrazení', 'No results match:' => 'Žádná shoda:', 'Currency' => 'Měna', - 'Start time' => 'Počáteční datum', - 'End time' => 'Konečné datum', - 'Comment' => 'Komentář', - 'All day' => 'Všechny dny', - 'Day' => 'Den', - 'Manage timetable' => 'Spravovat pracovní dobu', - 'Overtime timetable' => 'Přesčasy', - 'Time off timetable' => 'Pracovní volno', - 'Timetable' => 'Pracovní doba', - 'Work timetable' => 'Pracovní doba', - 'Week timetable' => 'Týdenní pracovní doba', - 'Day timetable' => 'Denní pracovní doba', - 'From' => 'Od', - 'To' => 'Do', - 'Time slot created successfully.' => 'Časový úsek byl úspěšně vytvořen.', - 'Unable to save this time slot.' => 'Nelze uložit tento časový úsek.', - 'Time slot removed successfully.' => 'Časový úsek byl odstraněn.', - 'Unable to remove this time slot.' => 'Nelze odstranit tento časový úsek', - 'Do you really want to remove this time slot?' => 'Opravdu chcete odstranit tento časový úsek?', - 'Remove time slot' => 'Odstranit časový úsek', - 'Add new time slot' => 'Přidat nový časový úsek', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Tato pracovní doba se použije když je zaškrtnuto políčko "Celý den" pro plánovanou pracovní dobu i přesčas .', 'Files' => 'Soubory', 'Images' => 'Obrázky', 'Private project' => 'Soukromý projekt', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Přesunout úkol do jiného sloupce, když je úkol přiřazen uživateli.', 'Move the task to another column when assignee is cleared' => 'Přesunout úkol do jiného sloupce, když je pověření uživatele vymazáno.', 'Source column' => 'Zdrojový sloupec', - // 'Show subtask estimates (forecast of future work)' => '', 'Transitions' => 'Změny etap', 'Executer' => 'Vykonavatel', 'Time spent in the column' => 'Trvání jednotlivých etap', diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 027b22c5..d0fa1a18 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -666,28 +666,6 @@ return array( // 'Compact/wide view' => '', // 'No results match:' => '', // 'Currency' => '', - // 'Start time' => '', - // 'End time' => '', - // 'Comment' => '', - // 'All day' => '', - // 'Day' => '', - // 'Manage timetable' => '', - // 'Overtime timetable' => '', - // 'Time off timetable' => '', - // 'Timetable' => '', - // 'Work timetable' => '', - // 'Week timetable' => '', - // 'Day timetable' => '', - // 'From' => '', - // 'To' => '', - // 'Time slot created successfully.' => '', - // 'Unable to save this time slot.' => '', - // 'Time slot removed successfully.' => '', - // 'Unable to remove this time slot.' => '', - // 'Do you really want to remove this time slot?' => '', - // 'Remove time slot' => '', - // 'Add new time slot' => '', - // 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '', // 'Files' => '', // 'Images' => '', // 'Private project' => '', @@ -707,7 +685,6 @@ return array( // 'Move the task to another column when assigned to a user' => '', // 'Move the task to another column when assignee is cleared' => '', // 'Source column' => '', - // 'Show subtask estimates (forecast of future work)' => '', // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 0b1df2e7..71a1d7eb 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Kompakt/Breite-Ansicht', 'No results match:' => 'Keine Ergebnisse:', 'Currency' => 'Währung', - 'Start time' => 'Startzeit', - 'End time' => 'Endzeit', - 'Comment' => 'Kommentar', - 'All day' => 'ganztägig', - 'Day' => 'Tag', - 'Manage timetable' => 'Zeitplan verwalten', - 'Overtime timetable' => 'Überstunden Zeitplan', - 'Time off timetable' => 'Freizeit Zeitplan', - 'Timetable' => 'Zeitplan', - 'Work timetable' => 'Arbeitszeitplan', - 'Week timetable' => 'Wochenzeitplan', - 'Day timetable' => 'Tageszeitplan', - 'From' => 'von', - 'To' => 'bis', - 'Time slot created successfully.' => 'Zeitfenster erfolgreich erstellt.', - 'Unable to save this time slot.' => 'Nicht in der Lage, dieses Zeitfenster zu speichern.', - 'Time slot removed successfully.' => 'Zeitfenster erfolgreich entfernt.', - 'Unable to remove this time slot.' => 'Nicht in der Lage, dieses Zeitfenster zu entfernen', - 'Do you really want to remove this time slot?' => 'Soll diese Zeitfenster wirklich gelöscht werden?', - 'Remove time slot' => 'Zeitfenster entfernen', - 'Add new time slot' => 'Neues Zeitfenster hinzufügen', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Dieses Zeitfenster wird verwendet, wenn die Checkbox "ganztägig" für Freizeit und Überstunden angeklickt ist.', 'Files' => 'Dateien', 'Images' => 'Bilder', 'Private project' => 'privates Projekt', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Aufgabe in eine andere Spalte verschieben, wenn ein User zugeordnet wurde.', 'Move the task to another column when assignee is cleared' => 'Aufgabe in eine andere Spalte verschieben, wenn die Zuordnung gelöscht wurde.', 'Source column' => 'Quellspalte', - 'Show subtask estimates (forecast of future work)' => 'Teilaufgaben-Schätzungen anzeigen (Prognose)', 'Transitions' => 'Übergänge', 'Executer' => 'Ausführender', 'Time spent in the column' => 'Zeit in Spalte verbracht', diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index 1e15d8c0..3a80d2fb 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Vista compacta/amplia', 'No results match:' => 'No hay resultados coincidentes:', 'Currency' => 'Moneda', - 'Start time' => 'Tiempo de inicio', - 'End time' => 'Tiempo de fin', - 'Comment' => 'Comentario', - 'All day' => 'Todos los días', - 'Day' => 'Día', - 'Manage timetable' => 'Gestionar horario', - 'Overtime timetable' => 'Horario de tiempo extra', - 'Time off timetable' => 'Horario de tiempo libre', - 'Timetable' => 'Horario', - 'Work timetable' => 'Horario de trabajo', - 'Week timetable' => 'Horario semanal', - 'Day timetable' => 'Horario diario', - 'From' => 'De', - 'To' => 'Para', - 'Time slot created successfully.' => 'Intervalo de tiempo creado correctamente.', - 'Unable to save this time slot.' => 'No pude grabar este intervalo de tiempo.', - 'Time slot removed successfully.' => 'Intervalo de tiempo quitado correctamente.', - 'Unable to remove this time slot.' => 'No pude quitar este intervalo de tiempo.', - 'Do you really want to remove this time slot?' => '¿Realmente quiere quitar este intervalo de tiempo?', - 'Remove time slot' => 'Quitar intervalo de tiempo', - 'Add new time slot' => 'Añadir nuevo intervalo de tiempo', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Este horario se usa cuando se marca la casilla "todos los días" para calendario de tiempo libre y horas extras.', 'Files' => 'Ficheros', 'Images' => 'Imágenes', 'Private project' => 'Proyecto privado', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Mover la tarea a otra columna al asignarse al usuario', 'Move the task to another column when assignee is cleared' => 'Mover la tarea a otra columna al quitar el concesionario', 'Source column' => 'Columna fuente', - 'Show subtask estimates (forecast of future work)' => 'Mostrar estimaciones para la subtarea (pronóstico de trabajo futuro)', 'Transitions' => 'Transiciones', 'Executer' => 'Ejecutor', 'Time spent in the column' => 'Tiempo transcurrido en la columna', diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index da462831..e8940ba9 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -666,28 +666,6 @@ return array( // 'Compact/wide view' => '', // 'No results match:' => '', // 'Currency' => '', - // 'Start time' => '', - // 'End time' => '', - // 'Comment' => '', - // 'All day' => '', - // 'Day' => '', - // 'Manage timetable' => '', - // 'Overtime timetable' => '', - // 'Time off timetable' => '', - // 'Timetable' => '', - // 'Work timetable' => '', - // 'Week timetable' => '', - // 'Day timetable' => '', - // 'From' => '', - // 'To' => '', - // 'Time slot created successfully.' => '', - // 'Unable to save this time slot.' => '', - // 'Time slot removed successfully.' => '', - // 'Unable to remove this time slot.' => '', - // 'Do you really want to remove this time slot?' => '', - // 'Remove time slot' => '', - // 'Add new time slot' => '', - // 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '', // 'Files' => '', // 'Images' => '', // 'Private project' => '', @@ -707,7 +685,6 @@ return array( // 'Move the task to another column when assigned to a user' => '', // 'Move the task to another column when assignee is cleared' => '', // 'Source column' => '', - // 'Show subtask estimates (forecast of future work)' => '', // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index 848b7624..4c149b9a 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -668,28 +668,6 @@ return array( 'Compact/wide view' => 'Basculer entre la vue compacte et étendue', 'No results match:' => 'Aucun résultat :', 'Currency' => 'Devise', - 'Start time' => 'Date de début', - 'End time' => 'Date de fin', - 'Comment' => 'Commentaire', - 'All day' => 'Toute la journée', - 'Day' => 'Jour', - 'Manage timetable' => 'Gérer les horaires', - 'Overtime timetable' => 'Heures supplémentaires', - 'Time off timetable' => 'Heures d\'absences', - 'Timetable' => 'Horaires', - 'Work timetable' => 'Horaires travaillés', - 'Week timetable' => 'Horaires de la semaine', - 'Day timetable' => 'Horaire d\'une journée', - 'From' => 'Depuis', - 'To' => 'À', - 'Time slot created successfully.' => 'Créneau horaire créé avec succès.', - 'Unable to save this time slot.' => 'Impossible de sauvegarder ce créneau horaire.', - 'Time slot removed successfully.' => 'Créneau horaire supprimé avec succès.', - 'Unable to remove this time slot.' => 'Impossible de supprimer ce créneau horaire.', - 'Do you really want to remove this time slot?' => 'Voulez-vous vraiment supprimer ce créneau horaire ?', - 'Remove time slot' => 'Supprimer un créneau horaire', - 'Add new time slot' => 'Ajouter un créneau horaire', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Ces horaires sont utilisés lorsque la case « Toute la journée » est cochée pour les heures d\'absences ou supplémentaires programmées.', 'Files' => 'Fichiers', 'Images' => 'Images', 'Private project' => 'Projet privé', @@ -709,7 +687,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci est assignée à quelqu\'un', 'Move the task to another column when assignee is cleared' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci n\'est plus assignée', 'Source column' => 'Colonne d\'origine', - 'Show subtask estimates (forecast of future work)' => 'Afficher l\'estimation des sous-tâches (prévision du travail à venir)', 'Transitions' => 'Transitions', 'Executer' => 'Exécutant', 'Time spent in the column' => 'Temps passé dans la colonne', diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index a3bbd8f5..0bb99954 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Kompakt/széles nézet', 'No results match:' => 'Nincs találat:', 'Currency' => 'Pénznem', - 'Start time' => 'Kezdés ideje', - 'End time' => 'Végzés ideje', - 'Comment' => 'Megjegyzés', - 'All day' => 'Egész nap', - 'Day' => 'Nap', - 'Manage timetable' => 'Időbeosztás kezelése', - 'Overtime timetable' => 'Túlóra időbeosztás', - 'Time off timetable' => 'Szabadság időbeosztás', - 'Timetable' => 'Időbeosztás', - 'Work timetable' => 'Munka időbeosztás', - 'Week timetable' => 'Heti időbeosztás', - 'Day timetable' => 'Napi időbeosztás', - 'From' => 'Feladó:', - 'To' => 'Címzett:', - 'Time slot created successfully.' => 'Időszelet sikeresen létrehozva.', - 'Unable to save this time slot.' => 'Időszelet mentése sikertelen.', - 'Time slot removed successfully.' => 'Időszelet sikeresen törölve.', - 'Unable to remove this time slot.' => 'Időszelet törlése sikertelen.', - 'Do you really want to remove this time slot?' => 'Biztos törli ezt az időszeletet?', - 'Remove time slot' => 'Időszelet törlése', - 'Add new time slot' => 'Új Időszelet', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Ez az időbeosztás van használatban ha az "egész nap" jelölőnégyzet be van jelölve a tervezett szabadságnál és túlóránál.', 'Files' => 'Fájlok', 'Images' => 'Képek', 'Private project' => 'Privát projekt', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés után', 'Move the task to another column when assignee is cleared' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés törlésekor', 'Source column' => 'Forrás oszlop', - // 'Show subtask estimates (forecast of future work)' => '', // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index a7b52c6f..1945e60b 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -25,7 +25,7 @@ return array( 'Dark Grey' => 'Abu-abu Gelap', 'Pink' => 'Merah Muda', 'Teal' => 'Teal', - 'Cyan'=> 'Sian', + 'Cyan' => 'Sian', 'Lime' => 'Lime', 'Light Green' => 'Hijau Muda', 'Amber' => 'Amber', @@ -338,7 +338,7 @@ return array( 'Display another project' => 'Lihat proyek lain', 'Login with my Github Account' => 'Masuk menggunakan akun Github saya', 'Link my Github Account' => 'Hubungkan akun Github saya ', - 'Unlink my Github Account' => 'Putuskan akun Github saya', + 'Unlink my Github Account' => 'Putuskan akun Github saya', 'Created by %s' => 'Dibuat oleh %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Modifikasi terakhir pada tanggal %d/%m/%Y à %H:%M', 'Tasks Export' => 'Ekspor Tugas', @@ -365,14 +365,12 @@ return array( 'Time tracking:' => 'Pelacakan waktu :', 'New sub-task' => 'Sub-tugas baru', 'New attachment added "%s"' => 'Lampiran baru ditambahkan « %s »', - 'Comment updated' => 'Komentar ditambahkan', + 'Comment updated' => 'Komentar diperbaharui', 'New comment posted by %s' => 'Komentar baru ditambahkan oleh « %s »', 'New attachment' => 'Lampirkan baru', 'New comment' => 'Komentar baru', - 'Comment updated' => 'Komentar diperbaharui', 'New subtask' => 'Sub-tugas baru', 'Subtask updated' => 'Sub-tugas diperbaharui', - 'New task' => 'Tugas baru', 'Task updated' => 'Tugas diperbaharui', 'Task closed' => 'Tugas ditutup', 'Task opened' => 'Tugas dibuka', @@ -397,8 +395,6 @@ return array( 'Remote' => 'Jauh', 'Enabled' => 'Aktif', 'Disabled' => 'Nonaktif', - 'Google account linked' => 'Akun Google yang terhubung', - 'Github account linked' => 'Akun Github yang terhubung', 'Username:' => 'Nama pengguna :', 'Name:' => 'Nama :', 'Email:' => 'Email :', @@ -669,75 +665,26 @@ return array( 'Horizontal scrolling' => 'Horisontal bergulir', 'Compact/wide view' => 'Beralih antara tampilan kompak dan diperluas', 'No results match:' => 'Tidak ada hasil :', - 'Remove hourly rate' => 'Hapus tarif per jam', - 'Do you really want to remove this hourly rate?' => 'Apakah anda yakin akan menghapus tarif per jam ini?', - 'Hourly rates' => 'Tarif per jam', - 'Hourly rate' => 'Tarif per jam', 'Currency' => 'Mata uang', - 'Effective date' => 'Tanggal berlaku', - 'Add new rate' => 'Tambah tarif per jam baru', - 'Rate removed successfully.' => 'Tarif per jam berhasil dihapus.', - 'Unable to remove this rate.' => 'Tidak dapat menghapus tarif per jam ini.', - 'Unable to save the hourly rate.' => 'Tidak dapat menyimpan tarif per jam.', - 'Hourly rate created successfully.' => 'Tarif per jam berhasil dibuat.', - 'Start time' => 'Waktu mulai', - 'End time' => 'Waktu selesai', - 'Comment' => 'Komentar', - 'All day' => 'Semua hari', - 'Day' => 'Hari', - 'Manage timetable' => 'Mengatur jadwal', - 'Overtime timetable' => 'Jadwal lembur', - 'Time off timetable' => 'Jam absensi', - 'Timetable' => 'Jadwal', - 'Work timetable' => 'Jadwal kerja', - 'Week timetable' => 'Jadwal mingguan', - 'Day timetable' => 'Jadwal harian', - 'From' => 'Dari', - 'To' => 'Untuk', - 'Time slot created successfully.' => 'Slot waktu berhasil dibuat.', - 'Unable to save this time slot.' => 'Tidak dapat menyimpan slot waktu ini.', - 'Time slot removed successfully.' => 'Slot waktu berhasil dihapus.', - 'Unable to remove this time slot.' => 'Tidak dapat menghapus slot waktu ini.', - 'Do you really want to remove this time slot?' => 'Apakah anda yakin akan menghapus slot waktu ini?', - 'Remove time slot' => 'Hapus slot waktu', - 'Add new time slot' => 'Tambah slot waktu baru', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Jadwal ini digunakan ketika kotak centang "sepanjang hari" dicentang untuk dijadwalkan cuti dan lembur.', 'Files' => 'Arsip', 'Images' => 'Gambar', 'Private project' => 'Proyek pribadi', - 'Amount' => 'Jumlah', 'AUD - Australian Dollar' => 'AUD - Dollar Australia', - 'Budget' => 'Anggaran', - 'Budget line' => 'Garis anggaran', - 'Budget line removed successfully.' => 'Garis anggaran berhasil dihapus.', - 'Budget lines' => 'Garis anggaran', 'CAD - Canadian Dollar' => 'CAD - Dollar Kanada', 'CHF - Swiss Francs' => 'CHF - Swiss Prancis', - 'Cost' => 'Biaya', - 'Cost breakdown' => 'Rincian biaya', 'Custom Stylesheet' => 'Kustomisasi Stylesheet', 'download' => 'unduh', - 'Do you really want to remove this budget line?' => 'Apakah anda yakin akan menghapus garis anggaran ini?', 'EUR - Euro' => 'EUR - Euro', - 'Expenses' => 'Beban', 'GBP - British Pound' => 'GBP - Poundsterling inggris', 'INR - Indian Rupee' => 'INR - Rupe India', 'JPY - Japanese Yen' => 'JPY - Yen Jepang', - 'New budget line' => 'Garis anggaran baru', 'NZD - New Zealand Dollar' => 'NZD - Dollar Selandia baru', - 'Remove a budget line' => 'Hapus garis anggaran', - 'Remove budget line' => 'Hapus garis anggaran', 'RSD - Serbian dinar' => 'RSD - Dinar Serbia', - 'The budget line have been created successfully.' => 'Garis anggaran berhasil dibuat.', - 'Unable to create the budget line.' => 'Tidak dapat membuat garis anggaran.', - 'Unable to remove this budget line.' => 'Tidak dapat menghapus garis anggaran.', 'USD - US Dollar' => 'USD - Dollar Amerika', - 'Remaining' => 'Sisa', 'Destination column' => 'Kolom tujuan', 'Move the task to another column when assigned to a user' => 'Pindahkan tugas ke kolom lain ketika ditugaskan ke pengguna', 'Move the task to another column when assignee is cleared' => 'Pindahkan tugas ke kolom lain ketika orang yang ditugaskan dibersihkan', 'Source column' => 'Sumber kolom', - 'Show subtask estimates (forecast of future work)' => 'Lihat perkiraan subtugas(perkiraan di masa depan)', 'Transitions' => 'Transisi', 'Executer' => 'Eksekusi', 'Time spent in the column' => 'Waktu yang dihabiskan dalam kolom', @@ -748,7 +695,6 @@ return array( 'Rate' => 'Tarif', 'Change reference currency' => 'Mengubah referensi mata uang', 'Add a new currency rate' => 'Tambahkan nilai tukar mata uang baru', - 'Currency rates are used to calculate project budget.' => 'Nilai tukar mata uang digunakan untuk menghitung anggaran proyek.', 'Reference currency' => 'Referensi mata uang', 'The currency rate have been added successfully.' => 'Nilai tukar mata uang berhasil ditambahkan.', 'Unable to add this currency rate.' => 'Tidak dapat menambahkan nilai tukar mata uang', @@ -880,9 +826,6 @@ return array( '%s moved the task #%d to the first swimlane' => '%s memindahkan tugas n°%d ke swimlane pertama', '%s moved the task #%d to the swimlane "%s"' => '%s memindahkan tugas n°%d ke swimlane « %s »', 'Swimlane' => 'Swimlane', - 'Budget overview' => 'Gambaran anggaran', - 'Type' => 'Tipe', - 'There is not enough data to show something.' => 'Tidak ada data yang cukup untuk menunjukkan sesuatu.', 'Gravatar' => 'Gravatar', 'Hipchat' => 'Hipchat', 'Slack' => 'Slack', diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index e27245f9..5d6d33f6 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Vista compatta/estesa', 'No results match:' => 'Nessun risultato trovato:', 'Currency' => 'Valuta', - 'Start time' => 'Data di inizio', - 'End time' => 'Data di completamento', - 'Comment' => 'Commento', - 'All day' => 'Tutto il giorno', - 'Day' => 'Giorno', - 'Manage timetable' => 'Gestisci orario', - 'Overtime timetable' => 'Straordinari', - 'Time off timetable' => 'Fuori orario', - 'Timetable' => 'Orario', - 'Work timetable' => 'Orario di lavoro', - 'Week timetable' => 'Orario settimanale', - 'Day timetable' => 'Orario giornaliero', - 'From' => 'Da', - 'To' => 'A', - 'Time slot created successfully.' => 'Fascia oraria creata con successo.', - 'Unable to save this time slot.' => 'Impossibile creare questa fascia oraria.', - 'Time slot removed successfully.' => 'Fascia oraria rimossa con successo.', - 'Unable to remove this time slot.' => 'Impossibile rimuovere questa fascia oraria.', - 'Do you really want to remove this time slot?' => 'Vuoi davvero rimuovere questa fascia oraria?', - 'Remove time slot' => 'Rimuovi fascia oraria', - 'Add new time slot' => 'Aggiungi nuova fascia oraria', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Questo orario è utilizzato quando la casella "tutto il giorno" è selezionata per i fuori orari e per gli straordinari', // 'Files' => '', 'Images' => 'Immagini', 'Private project' => 'Progetto privato', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Sposta il compito in un\'altra colonna quando viene assegnato ad un utente', 'Move the task to another column when assignee is cleared' => 'Sposta il compito in un\'altra colonna quando l\'assegnatario cancellato', 'Source column' => 'Colonna sorgente', - // 'Show subtask estimates (forecast of future work)' => '', 'Transitions' => 'Transizioni', 'Executer' => 'Esecutore', 'Time spent in the column' => 'Tempo trascorso nella colonna', diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index 49f92f27..b46ec1c4 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'コンパクト/ワイドビュー', 'No results match:' => '結果が一致しませんでした', 'Currency' => '通貨', - 'Start time' => '開始時間', - 'End time' => '終了時間', - 'Comment' => 'コメント', - 'All day' => '終日', - 'Day' => '日', - 'Manage timetable' => 'タイムテーブルの管理', - 'Overtime timetable' => '残業タイムテーブル', - 'Time off timetable' => '休暇タイムテーブル', - 'Timetable' => 'タイムテーブル', - 'Work timetable' => 'ワークタイムテーブル', - 'Week timetable' => '週次タイムテーブル', - 'Day timetable' => '日時タイムテーブル', - 'From' => 'ここから', - 'To' => 'ここまで', - // 'Time slot created successfully.' => '', - // 'Unable to save this time slot.' => '', - // 'Time slot removed successfully.' => '', - // 'Unable to remove this time slot.' => '', - // 'Do you really want to remove this time slot?' => '', - 'Remove time slot' => 'タイムスロットの削除', - 'Add new time slot' => 'タイムラインの追加', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'このタイムテーブルは、残業や休暇で全日がチェックされた場合に用いられます。', 'Files' => 'ファイル', 'Images' => '画像', 'Private project' => 'プライベートプロジェクト', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'ユーザの割り当てをしたらタスクを他のカラムに移動', 'Move the task to another column when assignee is cleared' => 'ユーザの割り当てがなくなったらタスクを他のカラムに移動', 'Source column' => '移動元のカラム', - // 'Show subtask estimates (forecast of future work)' => '', 'Transitions' => '履歴', 'Executer' => '実行者', 'Time spent in the column' => 'カラムでの時間消費', diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index 9880b921..8ee800e6 100755 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -126,7 +126,6 @@ return array( 'The project name is required' => 'Prosjektnavn er pkrevet', 'This project must be unique' => 'Prosjektnavnet skal vre unikt', 'The title is required' => 'Tittel er prevet', - 'There is no active project, the first step is to create a new project.' => 'Det er ingen aktive prosjekter. Frstesteg er opprette et nytt prosjekt.', 'Settings saved successfully.' => 'Innstillinger lagret.', 'Unable to save your settings.' => 'Innstillinger kunne ikke lagres.', 'Database optimization done.' => 'Databaseoptimering er fullfrt.', @@ -165,8 +164,6 @@ return array( 'Date created' => 'Dato for opprettelse', 'Date completed' => 'Dato for fullfrt', 'Id' => 'ID', - 'Completed tasks' => 'Fullfrte oppgaver', - 'Completed tasks for "%s"' => 'Fullfrte oppgaver for "%s"', '%d closed tasks' => '%d lukkede oppgaver', 'No task for this project' => 'Ingen oppgaver i dette prosjektet', 'Public link' => 'Offentligt lenke', @@ -255,25 +252,21 @@ return array( 'Expiration date' => 'Utlpsdato', 'Remember Me' => 'Husk meg', 'Creation date' => 'Opprettelsesdato', - 'Filter by user' => 'Filtrer efter bruker', - 'Filter by due date' => 'Filtrer etter forfallsdato', 'Everybody' => 'Alle', 'Open' => 'pen', 'Closed' => 'Lukket', 'Search' => 'Sk', 'Nothing found.' => 'Intet funnet.', - 'Search in the project "%s"' => 'Sk i prosjektet "%s"', 'Due date' => 'Forfallsdato', 'Others formats accepted: %s and %s' => 'Andre formater: %s og %s', 'Description' => 'Beskrivelse', '%d comments' => '%d kommentarer', '%d comment' => '%d kommentar', 'Email address invalid' => 'Ugyldig epost', - 'Your Google Account is not linked anymore to your profile.' => 'Din Google-konto er ikke lengre knyttet til din profil.', - 'Unable to unlink your Google Account.' => 'Det var ikke mulig fjerne din Google-konto.', - 'Google authentication failed' => 'Google godjenning mislyktes', - 'Unable to link your Google Account.' => 'Det var ikke mulig knytte opp til din Google-konto.', - 'Your Google Account is linked to your profile successfully.' => 'Din Google-konto er knyttet til din profil.', + // 'Your external account is not linked anymore to your profile.' => '', + // 'Unable to unlink your external account.' => '', + // 'External authentication failed' => '', + // 'Your external account is linked to your profile successfully.' => '', 'Email' => 'Epost', 'Link my Google Account' => 'Knytt til min Google-konto', 'Unlink my Google Account' => 'Fjern knytningen til min Google-konto', @@ -301,7 +294,6 @@ return array( 'Category Name' => 'Kategorinavn', 'Add a new category' => 'Legg til ny kategori', 'Do you really want to remove this category: "%s"?' => 'Vil du fjerne kategorien: "%s"?', - 'Filter by category' => 'Filter etter kategori', 'All categories' => 'Alle kategorier', 'No category' => 'Ingen kategori', 'The name is required' => 'Navnet er pkrevet', @@ -344,14 +336,9 @@ return array( 'Maximum size: ' => 'Maksimum strrelse: ', 'Unable to upload the file.' => 'Filen kunne ikke lastes opp.', 'Display another project' => 'Vis annet prosjekt...', - 'Your GitHub account was successfully linked to your profile.' => 'Din GitHub-konto er knyttet til din profil.', - 'Unable to link your GitHub Account.' => 'Det var ikke mulig knytte din GitHub-konto.', - 'GitHub authentication failed' => 'GitHub godkjenning mislyktes', - 'Your GitHub account is no longer linked to your profile.' => 'Din GitHub-konto er ikke lengere knyttet til din profil.', - 'Unable to unlink your GitHub Account.' => 'Det var ikke muligt at fjerne forbindelsen til din GitHub-konto.', - 'Login with my GitHub Account' => 'Login med min GitHub-konto', - 'Link my GitHub Account' => 'Knytt min GitHub-konto', - 'Unlink my GitHub Account' => 'Fjern knytningen til min GitHub-konto', + // 'Login with my Github Account' => '', + // 'Link my Github Account' => '', + // 'Unlink my Github Account' => '', 'Created by %s' => 'Opprettet av %s', 'Last modified on %B %e, %Y at %k:%M %p' => 'Sist endret %d.%m.%Y - %H:%M', 'Tasks Export' => 'Oppgave eksport', @@ -408,8 +395,6 @@ return array( 'Remote' => 'Fjernstyrt', 'Enabled' => 'Aktiv', 'Disabled' => 'Deaktivert', - 'Google account linked' => 'Google-konto knyttet', - 'Github account linked' => 'GitHub-konto knyttet', 'Username:' => 'Brukernavn', 'Name:' => 'Navn:', 'Email:' => 'Epost:', @@ -445,7 +430,6 @@ return array( '%s updated a comment on the task %s' => '%s oppdaterte en kommentar til oppgaven %s', '%s commented the task %s' => '%s har kommentert oppgaven %s', '%s\'s activity' => '%s\'s aktvitet', - 'No activity.' => 'Ingen aktivitet', 'RSS feed' => 'RSS feed', '%s updated a comment on the task #%d' => '%s oppdaterte en kommentar til oppgaven #%d', '%s commented on the task #%d' => '%s kommenterte oppgaven #%d', @@ -605,14 +589,9 @@ return array( 'Language:' => 'Sprk', 'Timezone:' => 'Tidssone', 'All columns' => 'Alle kolonner', - 'Calendar for "%s"' => 'Kalender for "%s"', - 'Filter by column' => 'Filtrer etter kolonne', - 'Filter by status' => 'Filtrer etter status', 'Calendar' => 'Kalender', 'Next' => 'Neste', // '#%d' => '', - 'Filter by color' => 'Filtrer etter farge', - 'Filter by swimlane' => 'Filtrer etter svmmebane', 'All swimlanes' => 'Alle svmmebaner', 'All colors' => 'Alle farger', 'All status' => 'Alle statuser', @@ -627,14 +606,7 @@ return array( // 'Time Tracking' => '', // 'You already have one subtask in progress' => '', 'Which parts of the project do you want to duplicate?' => 'Hvilke deler av dette prosjektet nsker du kopiere?', - 'Change dashboard view' => 'Endre visning', - 'Show/hide activities' => 'Vis/skjul aktiviteter', - 'Show/hide projects' => 'Vis/skjul prosjekter', - 'Show/hide subtasks' => 'Vis/skjul deloppgaver', - 'Show/hide tasks' => 'Vis/skjul oppgaver', - 'Disable login form' => 'Deaktiver innlogging', - 'Show/hide calendar' => 'Vis/skjul kalender', - 'User calendar' => 'Brukerens kalender', + // 'Disallow login form' => '', // 'Bitbucket commit received' => '', // 'Bitbucket webhooks' => '', // 'Help on Bitbucket webhooks' => '', @@ -688,82 +660,31 @@ return array( 'Keyboard shortcuts' => 'Hurtigtaster', // 'Open board switcher' => '', // 'Application' => '', - 'Filter recently updated' => 'Filter nylig oppdatert', 'since %B %e, %Y at %k:%M %p' => 'siden %B %e, %Y at %k:%M %p', - 'More filters' => 'Flere filtre', 'Compact view' => 'Kompakt visning', 'Horizontal scrolling' => 'Bla horisontalt', 'Compact/wide view' => 'Kompakt/bred visning', 'No results match:' => 'Ingen resultater', - // 'Remove hourly rate' => '', - // 'Do you really want to remove this hourly rate?' => '', - 'Hourly rates' => 'Timepriser', - 'Hourly rate' => 'Timepris', 'Currency' => 'Valuta', - // 'Effective date' => '', - // 'Add new rate' => '', - // 'Rate removed successfully.' => '', - // 'Unable to remove this rate.' => '', - // 'Unable to save the hourly rate.' => '', - // 'Hourly rate created successfully.' => '', - // 'Start time' => '', - // 'End time' => '', - 'Comment' => 'Kommentar', - 'All day' => 'Alle dager', - 'Day' => 'Dag', - 'Manage timetable' => 'Tidstabell', - 'Overtime timetable' => 'Overtidstabell', - 'Time off timetable' => 'Fritidstabell', - 'Timetable' => 'Tidstabell', - 'Work timetable' => 'Arbeidstidstabell', - 'Week timetable' => 'Uketidstabell', - 'Day timetable' => 'Dagtidstabell', - 'From' => 'Fra', - 'To' => 'Til', - // 'Time slot created successfully.' => '', - // 'Unable to save this time slot.' => '', - // 'Time slot removed successfully.' => '', - // 'Unable to remove this time slot.' => '', - // 'Do you really want to remove this time slot?' => '', - // 'Remove time slot' => '', - // 'Add new time slot' => '', - // 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '', 'Files' => 'Filer', 'Images' => 'Bilder', 'Private project' => 'Privat prosjekt', - 'Amount' => 'Belp', // 'AUD - Australian Dollar' => '', - 'Budget' => 'Budsjett', - // 'Budget line' => '', - // 'Budget line removed successfully.' => '', - 'Budget lines' => 'Budsjettlinjer', // 'CAD - Canadian Dollar' => '', // 'CHF - Swiss Francs' => '', - 'Cost' => 'Kostnad', - 'Cost breakdown' => 'Kostnadsnedbryting', // 'Custom Stylesheet' => '', 'download' => 'last ned', - // 'Do you really want to remove this budget line?' => '', // 'EUR - Euro' => '', - // 'Expenses' => '', // 'GBP - British Pound' => '', // 'INR - Indian Rupee' => '', // 'JPY - Japanese Yen' => '', - // 'New budget line' => '', // 'NZD - New Zealand Dollar' => '', - // 'Remove a budget line' => '', - // 'Remove budget line' => '', // 'RSD - Serbian dinar' => '', - // 'The budget line have been created successfully.' => '', - // 'Unable to create the budget line.' => '', - // 'Unable to remove this budget line.' => '', // 'USD - US Dollar' => '', - // 'Remaining' => '', 'Destination column' => 'Ny kolonne', 'Move the task to another column when assigned to a user' => 'Flytt oppgaven til en annen kolonne nr den er tildelt en bruker', 'Move the task to another column when assignee is cleared' => 'Flytt oppgaven til en annen kolonne nr ppgavetildeling fjernes ', 'Source column' => 'Opprinnelig kolonne', - // 'Show subtask estimates (forecast of future work)' => '', 'Transitions' => 'Statusendringer', // 'Executer' => '', // 'Time spent in the column' => '', @@ -774,7 +695,6 @@ return array( // 'Rate' => '', // 'Change reference currency' => '', // 'Add a new currency rate' => '', - // 'Currency rates are used to calculate project budget.' => '', // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // 'Unable to add this currency rate.' => '', @@ -906,9 +826,6 @@ return array( // '%s moved the task #%d to the first swimlane' => '', // '%s moved the task #%d to the swimlane "%s"' => '', 'Swimlane' => 'Svmmebane', - 'Budget overview' => 'Budsjettoversikt', - // 'Type' => '', - // 'There is not enough data to show something.' => '', // 'Gravatar' => '', // 'Hipchat' => '', // 'Slack' => '', @@ -921,7 +838,6 @@ 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"' => '', - 'There is no completed tasks at the moment.' => 'Ingen fullfrte oppgaver funnet.', // 'New title: %s' => '', // 'The task is not assigned anymore' => '', // 'New assignee: %s' => '', @@ -938,7 +854,6 @@ return array( // 'The description have been modified' => '', // 'Do you really want to close the task "%s" as well as all subtasks?' => '', 'Swimlane: %s' => 'Svmmebane: %s', - 'Project calendar' => 'Prosjektkalender', 'I want to receive notifications for:' => 'Jeg vil motta varslinger om:', 'All tasks' => 'Alle oppgaver', 'Only for tasks assigned to me' => 'Kun oppgaver som er tildelt meg', @@ -951,7 +866,7 @@ return array( // '%k:%M %p' => '', // '%%Y-%%m-%%d' => '', 'Total for all columns' => 'Totalt for alle kolonner', - //'You need at least 2 days of data to show the chart.' => '', + // 'You need at least 2 days of data to show the chart.' => '', // '<15m' => '', // '<30m' => '', 'Stop timer' => 'Stopp timer', diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 8be0c61d..7c623914 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -666,28 +666,6 @@ return array( // 'Compact/wide view' => '', // 'No results match:' => '', // 'Currency' => '', - // 'Start time' => '', - // 'End time' => '', - // 'Comment' => '', - // 'All day' => '', - // 'Day' => '', - // 'Manage timetable' => '', - // 'Overtime timetable' => '', - // 'Time off timetable' => '', - // 'Timetable' => '', - // 'Work timetable' => '', - // 'Week timetable' => '', - // 'Day timetable' => '', - // 'From' => '', - // 'To' => '', - // 'Time slot created successfully.' => '', - // 'Unable to save this time slot.' => '', - // 'Time slot removed successfully.' => '', - // 'Unable to remove this time slot.' => '', - // 'Do you really want to remove this time slot?' => '', - // 'Remove time slot' => '', - // 'Add new time slot' => '', - // 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '', // 'Files' => '', // 'Images' => '', // 'Private project' => '', @@ -707,7 +685,6 @@ return array( // 'Move the task to another column when assigned to a user' => '', // 'Move the task to another column when assignee is cleared' => '', // 'Source column' => '', - // 'Show subtask estimates (forecast of future work)' => '', // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index d9cfcdbc..e7683d9a 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Pełny/Kompaktowy widok', 'No results match:' => 'Brak wyników:', 'Currency' => 'Waluta', - 'Start time' => 'Rozpoczęto', - 'End time' => 'Zakończono', - 'Comment' => 'Komentarz', - 'All day' => 'Cały dzień', - 'Day' => 'Dzień', - 'Manage timetable' => 'Zarządzaj rozkładami zajęć', - 'Overtime timetable' => 'Rozkład zajęć - nadgodziny', - 'Time off timetable' => 'Rozkład zajęć - czas wolny', - 'Timetable' => 'Rozkład zajęć', - 'Work timetable' => 'Rozkład zajęć - praca', - 'Week timetable' => 'Tygodniowy rozkład zajęć', - 'Day timetable' => 'Dzienny rozkład zajęć', - 'From' => 'Od', - 'To' => 'Do', - 'Time slot created successfully.' => 'Przydział czasowy utworzony.', - 'Unable to save this time slot.' => 'Nie można zapisać tego przydziału czasowego.', - 'Time slot removed successfully.' => 'Przydział czasowy usunięty.', - 'Unable to remove this time slot.' => 'Nie można usunąć tego przydziału czasowego.', - 'Do you really want to remove this time slot?' => 'Czy na pewno chcesz usunąć ten przedział czasowy?', - 'Remove time slot' => 'Usuń przedział czasowy', - 'Add new time slot' => 'Dodaj przedział czasowy', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Ten rozkład zajęć jest używany przypadku zaznaczenia "cały dzień" dla zaplanowanego czasu wolnego i nadgodzin', 'Files' => 'Pliki', 'Images' => 'Obrazy', 'Private project' => 'Projekt prywatny', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Przenieś zadanie do innej kolumny gdy zostanie przypisane do osoby', 'Move the task to another column when assignee is cleared' => 'Przenieś zadanie do innej kolumny gdy osoba odpowiedzialna zostanie usunięta', 'Source column' => 'Kolumna źródłowa', - 'Show subtask estimates (forecast of future work)' => 'Pokaż planowane czasy wykonania pod-zadań', 'Transitions' => 'Przeniesienia', 'Executer' => 'Wykonał', 'Time spent in the column' => 'Czas spędzony w tej kolumnie', diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index 5f849457..57cfe761 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Alternar entre a vista compacta e ampliada', 'No results match:' => 'Nenhum resultado:', 'Currency' => 'Moeda', - 'Start time' => 'Horário de início', - 'End time' => 'Horário de término', - 'Comment' => 'comentário', - 'All day' => 'Dia inteiro', - 'Day' => 'Dia', - 'Manage timetable' => 'Gestão dos horários', - 'Overtime timetable' => 'Horas extras', - 'Time off timetable' => 'Horas de ausência', - 'Timetable' => 'Horários', - 'Work timetable' => 'Horas trabalhadas', - 'Week timetable' => 'Horário da semana', - 'Day timetable' => 'Horário de un dia', - 'From' => 'Desde', - 'To' => 'A', - 'Time slot created successfully.' => 'Intervalo de tempo criado com sucesso.', - 'Unable to save this time slot.' => 'Impossível de guardar este intervalo de tempo.', - 'Time slot removed successfully.' => 'Intervalo de tempo removido com sucesso.', - 'Unable to remove this time slot.' => 'Impossível de remover esse intervalo de tempo.', - 'Do you really want to remove this time slot?' => 'Você deseja realmente remover este intervalo de tempo?', - 'Remove time slot' => 'Remover um intervalo de tempo', - 'Add new time slot' => 'Adicionar um intervalo de tempo', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Esses horários são usados quando a caixa de seleção "Dia inteiro" está marcada para Horas de ausência ou Extras', 'Files' => 'Arquivos', 'Images' => 'Imagens', 'Private project' => 'Projeto privado', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Mover a tarefa para uma outra coluna quando esta está atribuída a um usuário', 'Move the task to another column when assignee is cleared' => 'Mover a tarefa para uma outra coluna quando esta não está atribuída', 'Source column' => 'Coluna de origem', - 'Show subtask estimates (forecast of future work)' => 'Mostrar a estimativa das subtarefas (previsão para o trabalho futuro)', 'Transitions' => 'Transições', 'Executer' => 'Executor(a)', 'Time spent in the column' => 'Tempo gasto na coluna', diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index 9e20b112..cb2fc53e 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Alternar entre a vista compacta e ampliada', 'No results match:' => 'Nenhum resultado:', 'Currency' => 'Moeda', - 'Start time' => 'Horário de início', - 'End time' => 'Horário de término', - 'Comment' => 'comentário', - 'All day' => 'Dia inteiro', - 'Day' => 'Dia', - 'Manage timetable' => 'Gestão dos horários', - 'Overtime timetable' => 'Horas extras', - 'Time off timetable' => 'Horas de ausência', - 'Timetable' => 'Horários', - 'Work timetable' => 'Horas trabalhadas', - 'Week timetable' => 'Horário da semana', - 'Day timetable' => 'Horário de um dia', - 'From' => 'Desde', - 'To' => 'A', - 'Time slot created successfully.' => 'Intervalo de tempo criado com sucesso.', - 'Unable to save this time slot.' => 'Impossível guardar este intervalo de tempo.', - 'Time slot removed successfully.' => 'Intervalo de tempo removido com sucesso.', - 'Unable to remove this time slot.' => 'Impossível remover esse intervalo de tempo.', - 'Do you really want to remove this time slot?' => 'Tem a certeza que quer remover este intervalo de tempo?', - 'Remove time slot' => 'Remover um intervalo de tempo', - 'Add new time slot' => 'Adicionar um intervalo de tempo', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Esses horários são usados quando a caixa de seleção "Dia inteiro" está marcada para Horas de ausência ou Extras', 'Files' => 'Arquivos', 'Images' => 'Imagens', 'Private project' => 'Projecto privado', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Mover a tarefa para uma outra coluna quando esta está atribuída a um utilizador', 'Move the task to another column when assignee is cleared' => 'Mover a tarefa para uma outra coluna quando esta não está atribuída', 'Source column' => 'Coluna de origem', - 'Show subtask estimates (forecast of future work)' => 'Mostrar a estimativa das subtarefas (previsão para o trabalho futuro)', 'Transitions' => 'Transições', 'Executer' => 'Executor(a)', 'Time spent in the column' => 'Tempo gasto na coluna', diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 054e2ac8..53303506 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Компактный/широкий вид', 'No results match:' => 'Отсутствуют результаты:', 'Currency' => 'Валюта', - 'Start time' => 'Время начала', - 'End time' => 'Время завершения', - 'Comment' => 'Комментарий', - 'All day' => 'Весь день', - 'Day' => 'День', - 'Manage timetable' => 'Управление графиками', - 'Overtime timetable' => 'График сверхурочных', - 'Time off timetable' => 'Время в графике', - 'Timetable' => 'График', - 'Work timetable' => 'Work timetable', - 'Week timetable' => 'График на неделю', - 'Day timetable' => 'График на день', - 'From' => 'От кого', - 'To' => 'Кому', - 'Time slot created successfully.' => 'Временной интервал успешно создан.', - 'Unable to save this time slot.' => 'Невозможно сохранить этот временной интервал.', - 'Time slot removed successfully.' => 'Временной интервал успешно удален.', - 'Unable to remove this time slot.' => 'Не удается удалить этот временной интервал.', - 'Do you really want to remove this time slot?' => 'Вы действительно хотите удалить этот период времени?', - 'Remove time slot' => 'Удалить новый интервал времени', - 'Add new time slot' => 'Добавить новый интервал времени', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Это расписание используется, когда флажок "весь день" проверяется на установленное время выключения и сверхурочное время.', 'Files' => 'Файлы', 'Images' => 'Изображения', 'Private project' => 'Приватный проект', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Переместить задачу в другую колонку, когда она назначена пользователю', 'Move the task to another column when assignee is cleared' => 'Переместить задачу в другую колонку, когда назначение снято ', 'Source column' => 'Исходная колонка', - 'Show subtask estimates (forecast of future work)' => 'Показать оценку подзадач (прогноз будущей работы)', 'Transitions' => 'Перемещения', 'Executer' => 'Исполнитель', 'Time spent in the column' => 'Время проведенное в колонке', @@ -849,9 +826,6 @@ return array( '%s moved the task #%d to the first swimlane' => '%s задач перемещено #%d в первой дорожке', '%s moved the task #%d to the swimlane "%s"' => '%s задач перемещено #%d в дорожке "%s"', 'Swimlane' => 'Дорожки', - 'Budget overview' => 'Обзор бюджета', - 'Type' => 'Тип', - 'There is not enough data to show something.' => 'Недостаточно существующих данных, что бы что-то показать.', 'Gravatar' => 'Граватар', 'Hipchat' => 'Hipchat', 'Slack' => 'Slack', diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index a05d67d3..562b8f22 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -666,28 +666,6 @@ return array( // 'Compact/wide view' => '', // 'No results match:' => '', // 'Currency' => '', - // 'Start time' => '', - // 'End time' => '', - // 'Comment' => '', - // 'All day' => '', - // 'Day' => '', - // 'Manage timetable' => '', - // 'Overtime timetable' => '', - // 'Time off timetable' => '', - // 'Timetable' => '', - // 'Work timetable' => '', - // 'Week timetable' => '', - // 'Day timetable' => '', - // 'From' => '', - // 'To' => '', - // 'Time slot created successfully.' => '', - // 'Unable to save this time slot.' => '', - // 'Time slot removed successfully.' => '', - // 'Unable to remove this time slot.' => '', - // 'Do you really want to remove this time slot?' => '', - // 'Remove time slot' => '', - // 'Add new time slot' => '', - // 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '', // 'Files' => '', // 'Images' => '', // 'Private project' => '', @@ -707,7 +685,6 @@ return array( // 'Move the task to another column when assigned to a user' => '', // 'Move the task to another column when assignee is cleared' => '', // 'Source column' => '', - // 'Show subtask estimates (forecast of future work)' => '', // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index e8bdb9ce..c37759c7 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Kompakt/bred vy', 'No results match:' => 'Inga matchande resultat', 'Currency' => 'Valuta', - 'Start time' => 'Starttid', - 'End time' => 'Sluttid', - 'Comment' => 'Kommentar', - 'All day' => 'Hela dagen', - 'Day' => 'Dag', - 'Manage timetable' => 'Hantera timplan', - 'Overtime timetable' => 'Övertidstimplan', - 'Time off timetable' => 'Ledighetstimplan', - 'Timetable' => 'Timplan', - 'Work timetable' => 'Arbetstimplan', - 'Week timetable' => 'Veckotidplan', - 'Day timetable' => 'Dagstimplan', - 'From' => 'Från', - 'To' => 'Till', - 'Time slot created successfully.' => 'Tidslucka skapad.', - 'Unable to save this time slot.' => 'Kunde inte spara tidsluckan.', - 'Time slot removed successfully.' => 'Tidsluckan tog bort.', - 'Unable to remove this time slot.' => 'Kunde inte ta bort tidsluckan.', - 'Do you really want to remove this time slot?' => 'Vill du verkligen ta bort tidsluckan?', - 'Remove time slot' => 'Ta bort tidslucka', - 'Add new time slot' => 'Lägg till ny tidslucka', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Denna tidslucka används när kryssrutan "hela dagen" är kryssad vid schemalagd ledighet eller övertid.', 'Files' => 'Filer', 'Images' => 'Bilder', 'Private project' => 'Privat projekt', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'Flytta uppgiften till en annan kolumn när den tilldelats en användare', 'Move the task to another column when assignee is cleared' => 'Flytta uppgiften till en annan kolumn när tilldelningen tas bort.', 'Source column' => 'Källkolumn', - 'Show subtask estimates (forecast of future work)' => 'Visa uppskattningar för deluppgifter (prognos för framtida arbete)', 'Transitions' => 'Övergångar', 'Executer' => 'Verkställare', 'Time spent in the column' => 'Tid i kolumnen.', diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index d94107ad..1fdb5d34 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'พอดี/กว้าง มุมมอง', 'No results match:' => 'ไม่มีผลลัพท์ที่ตรง', 'Currency' => 'สกุลเงิน', - 'Start time' => 'เวลาเริ่มต้น', - 'End time' => 'เวลาจบ', - 'Comment' => 'ความคิดเห็น', - 'All day' => 'ทั้งวัน', - 'Day' => 'วัน', - 'Manage timetable' => 'จัดการตารางเวลา', - 'Overtime timetable' => 'ตารางเวลาโอที', - 'Time off timetable' => 'ตารางเวลาวันหยุด', - 'Timetable' => 'ตารางเวลา', - 'Work timetable' => 'ตารางเวลางาน', - 'Week timetable' => 'ตารางเวลาสัปดาห์', - 'Day timetable' => 'ตารางเวลาวัน', - 'From' => 'จาก', - 'To' => 'ถึง', - 'Time slot created successfully.' => 'สร้างช่วงเวลาเรียบร้อยแล้ว', - 'Unable to save this time slot.' => 'ไม่สามารถบันทึกช่วงเวลานี้', - 'Time slot removed successfully.' => 'ลบช่วงเวลาเรียบร้อยแล้ว', - 'Unable to remove this time slot.' => 'ไม่สามารถลบช่วงเวลาได้', - 'Do you really want to remove this time slot?' => 'คุณต้องการลบช่วงเวลานี้?', - 'Remove time slot' => 'ลบช่วงเวลา', - 'Add new time slot' => 'เพิ่มช่วงเวลาใหม่', - // 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '', 'Files' => 'ไฟล์', 'Images' => 'รูปภาพ', 'Private project' => 'โปรเจคส่วนตัว', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => 'ย้ายงานไปคอลัมน์อื่นเมื่อกำหนดบุคคลรับผิดชอบ', 'Move the task to another column when assignee is cleared' => 'ย้ายงานไปคอลัมน์อื่นเมื่อไม่กำหนดบุคคลรับผิดชอบ', 'Source column' => 'คอลัมน์ต้นทาง', - // 'Show subtask estimates (forecast of future work)' => '', 'Transitions' => 'การเปลี่ยนคอลัมน์', 'Executer' => 'ผู้ประมวลผล', 'Time spent in the column' => 'เวลาที่ใช้ในคอลัมน์', diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 87cccac7..44f973d1 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => 'Ekrana sığdır / Geniş görünüm', // 'No results match:' => '', // 'Currency' => '', - // 'Start time' => '', - // 'End time' => '', - // 'Comment' => '', - // 'All day' => '', - // 'Day' => '', - // 'Manage timetable' => '', - // 'Overtime timetable' => '', - // 'Time off timetable' => '', - // 'Timetable' => '', - // 'Work timetable' => '', - // 'Week timetable' => '', - // 'Day timetable' => '', - // 'From' => '', - // 'To' => '', - // 'Time slot created successfully.' => '', - // 'Unable to save this time slot.' => '', - // 'Time slot removed successfully.' => '', - // 'Unable to remove this time slot.' => '', - // 'Do you really want to remove this time slot?' => '', - // 'Remove time slot' => '', - // 'Add new time slot' => '', - // 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '', // 'Files' => '', // 'Images' => '', // 'Private project' => '', @@ -707,7 +685,6 @@ return array( // 'Move the task to another column when assigned to a user' => '', // 'Move the task to another column when assignee is cleared' => '', // 'Source column' => '', - // 'Show subtask estimates (forecast of future work)' => '', // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 102252e5..5ad5e9c8 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -666,28 +666,6 @@ return array( 'Compact/wide view' => '紧凑/宽视图', 'No results match:' => '无匹配结果:', 'Currency' => '货币', - 'Start time' => '开始时间', - 'End time' => '结束时1间', - 'Comment' => '注释', - 'All day' => '全天', - 'Day' => '日期', - 'Manage timetable' => '管理时间表', - // 'Overtime timetable' => '', - 'Time off timetable' => '加班时间表', - 'Timetable' => '时间表', - 'Work timetable' => '工作时间表', - 'Week timetable' => '周时间表', - 'Day timetable' => '日时间表', - 'From' => '从', - 'To' => '到', - 'Time slot created successfully.' => '成功创建时间段。', - 'Unable to save this time slot.' => '无法保存此时间段。', - 'Time slot removed successfully.' => '成功删除时间段。', - 'Unable to remove this time slot.' => '无法删除此时间段。', - 'Do you really want to remove this time slot?' => '确认要删除此时间段吗?', - 'Remove time slot' => '删除时间段', - 'Add new time slot' => '添加新时间段', - 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '如果在放假和加班计划中选择全天,则会使用这里配置的时间段。', 'Files' => '文件', 'Images' => '图片', 'Private project' => '私人项目', @@ -707,7 +685,6 @@ return array( 'Move the task to another column when assigned to a user' => '指定负责人时移动到其它栏目', 'Move the task to another column when assignee is cleared' => '移除负责人时移动到其它栏目', 'Source column' => '原栏目', - // 'Show subtask estimates (forecast of future work)' => '', 'Transitions' => '变更', 'Executer' => '执行者', 'Time spent in the column' => '栏目中的时间消耗', diff --git a/app/Model/SubtaskTimeTracking.php b/app/Model/SubtaskTimeTracking.php index 56998769..d65f2f75 100644 --- a/app/Model/SubtaskTimeTracking.php +++ b/app/Model/SubtaskTimeTracking.php @@ -150,13 +150,14 @@ class SubtaskTimeTracking extends Base * * @access public * @param integer $user_id - * @param integer $start - * @param integer $end + * @param string $start ISO-8601 format + * @param string $end * @return array */ public function getUserCalendarEvents($user_id, $start, $end) { - $result = $this->getUserQuery($user_id) + $hook = 'model:subtask-time-tracking:calendar:events'; + $events = $this->getUserQuery($user_id) ->addCondition($this->getCalendarCondition( $this->dateParser->getTimestampFromIsoFormat($start), $this->dateParser->getTimestampFromIsoFormat($end), @@ -165,9 +166,16 @@ class SubtaskTimeTracking extends Base )) ->findAll(); - $result = $this->timetable->calculateEventsIntersect($user_id, $result, $start, $end); + if ($this->hook->exists($hook)) { + $events = $this->hook->first($hook, array( + 'user_id' => $user_id, + 'events' => $events, + 'start' => $start, + 'end' => $end, + )); + } - return $this->toCalendarEvents($result); + return $this->toCalendarEvents($events); } /** @@ -293,6 +301,7 @@ class SubtaskTimeTracking extends Base */ public function getTimeSpent($subtask_id, $user_id) { + $hook = 'model:subtask-time-tracking:calculate:time-spent'; $start_time = $this->db ->table(self::TABLE) ->eq('subtask_id', $subtask_id) @@ -300,14 +309,23 @@ class SubtaskTimeTracking extends Base ->eq('end', 0) ->findOneColumn('start'); - if ($start_time) { - $start = new DateTime; - $start->setTimestamp($start_time); + if (empty($start_time)) { + return 0; + } + + $end = new DateTime; + $start = new DateTime; + $start->setTimestamp($start_time); - return $this->timetable->calculateEffectiveDuration($user_id, $start, new DateTime); + if ($this->hook->exists($hook)) { + return $this->hook->first($hook, array( + 'user_id' => $user_id, + 'start' => $start, + 'end' => $end, + )); } - return 0; + return $this->dateParser->getHours($start, $end); } /** diff --git a/app/Model/Timetable.php b/app/Model/Timetable.php deleted file mode 100644 index 6ddf826b..00000000 --- a/app/Model/Timetable.php +++ /dev/null @@ -1,356 +0,0 @@ -<?php - -namespace Model; - -use DateTime; -use DateInterval; - -/** - * Timetable - * - * @package model - * @author Frederic Guillot - */ -class Timetable extends Base -{ - /** - * User time slots - * - * @access private - * @var array - */ - private $day; - private $week; - private $overtime; - private $timeoff; - - /** - * Get a set of events by using the intersection between the timetable and the time tracking data - * - * @access public - * @param integer $user_id - * @param array $events Time tracking data - * @param string $start ISO8601 date - * @param string $end ISO8601 date - * @return array - */ - public function calculateEventsIntersect($user_id, array $events, $start, $end) - { - $start_dt = new DateTime($start); - $start_dt->setTime(0, 0); - - $end_dt = new DateTime($end); - $end_dt->setTime(23, 59); - - $timetable = $this->calculate($user_id, $start_dt, $end_dt); - - // The user has no timetable - if (empty($this->week)) { - return $events; - } - - $results = array(); - - foreach ($events as $event) { - $results = array_merge($results, $this->calculateEventIntersect($event, $timetable)); - } - - return $results; - } - - /** - * Get a serie of events based on the timetable and the provided event - * - * @access public - * @param array $event - * @param array $timetable - * @return array - */ - public function calculateEventIntersect(array $event, array $timetable) - { - $events = array(); - - foreach ($timetable as $slot) { - - $start_ts = $slot[0]->getTimestamp(); - $end_ts = $slot[1]->getTimestamp(); - - if ($start_ts > $event['end']) { - break; - } - - if ($event['start'] <= $start_ts) { - $event['start'] = $start_ts; - } - - if ($event['start'] >= $start_ts && $event['start'] <= $end_ts) { - - if ($event['end'] >= $end_ts) { - $events[] = array_merge($event, array('end' => $end_ts)); - } - else { - $events[] = $event; - break; - } - } - } - - return $events; - } - - /** - * Calculate effective worked hours by taking into consideration the timetable - * - * @access public - * @param integer $user_id - * @param \DateTime $start - * @param \DateTime $end - * @return float - */ - public function calculateEffectiveDuration($user_id, DateTime $start, DateTime $end) - { - $end_timetable = clone($end); - $end_timetable->setTime(23, 59); - - $timetable = $this->calculate($user_id, $start, $end_timetable); - $found_start = false; - $hours = 0; - - // The user has no timetable - if (empty($this->week)) { - return $this->dateParser->getHours($start, $end); - } - - foreach ($timetable as $slot) { - - $isStartSlot = $this->dateParser->withinDateRange($start, $slot[0], $slot[1]); - $isEndSlot = $this->dateParser->withinDateRange($end, $slot[0], $slot[1]); - - // Start and end are within the same time slot - if ($isStartSlot && $isEndSlot) { - return $this->dateParser->getHours($start, $end); - } - - // We found the start slot - if (! $found_start && $isStartSlot) { - $found_start = true; - $hours = $this->dateParser->getHours($start, $slot[1]); - } - else if ($found_start) { - - // We found the end slot - if ($isEndSlot) { - $hours += $this->dateParser->getHours($slot[0], $end); - break; - } - else { - - // Sum hours of the intermediate time slots - $hours += $this->dateParser->getHours($slot[0], $slot[1]); - } - } - } - - // The start date was not found in regular hours so we get the nearest time slot - if (! empty($timetable) && ! $found_start) { - $slot = $this->findClosestTimeSlot($start, $timetable); - - if ($start < $slot[0]) { - return $this->calculateEffectiveDuration($user_id, $slot[0], $end); - } - } - - return $hours; - } - - /** - * Find the nearest time slot - * - * @access public - * @param DateTime $date - * @param array $timetable - * @return array - */ - public function findClosestTimeSlot(DateTime $date, array $timetable) - { - $values = array(); - - foreach ($timetable as $slot) { - $t1 = abs($slot[0]->getTimestamp() - $date->getTimestamp()); - $t2 = abs($slot[1]->getTimestamp() - $date->getTimestamp()); - - $values[] = min($t1, $t2); - } - - asort($values); - return $timetable[key($values)]; - } - - /** - * Get the timetable for a user for a given date range - * - * @access public - * @param integer $user_id - * @param \DateTime $start - * @param \DateTime $end - * @return array - */ - public function calculate($user_id, DateTime $start, DateTime $end) - { - $timetable = array(); - - $this->day = $this->timetableDay->getByUser($user_id); - $this->week = $this->timetableWeek->getByUser($user_id); - $this->overtime = $this->timetableExtra->getByUserAndDate($user_id, $start->format('Y-m-d'), $end->format('Y-m-d')); - $this->timeoff = $this->timetableOff->getByUserAndDate($user_id, $start->format('Y-m-d'), $end->format('Y-m-d')); - - for ($today = clone($start); $today <= $end; $today->add(new DateInterval('P1D'))) { - $week_day = $today->format('N'); - $timetable = array_merge($timetable, $this->getWeekSlots($today, $week_day)); - $timetable = array_merge($timetable, $this->getOvertimeSlots($today, $week_day)); - } - - return $timetable; - } - - /** - * Return worked time slots for the given day - * - * @access public - * @param \DateTime $today - * @param string $week_day - * @return array - */ - public function getWeekSlots(DateTime $today, $week_day) - { - $slots = array(); - $dayoff = $this->getDayOff($today); - - if (! empty($dayoff) && $dayoff['all_day'] == 1) { - return array(); - } - - foreach ($this->week as $slot) { - if ($week_day == $slot['day']) { - $slots = array_merge($slots, $this->getDayWorkSlots($slot, $dayoff, $today)); - } - } - - return $slots; - } - - /** - * Get the overtime time slots for the given day - * - * @access public - * @param \DateTime $today - * @param string $week_day - * @return array - */ - public function getOvertimeSlots(DateTime $today, $week_day) - { - $slots = array(); - - foreach ($this->overtime as $slot) { - - $day = new DateTime($slot['date']); - - if ($week_day == $day->format('N')) { - - if ($slot['all_day'] == 1) { - $slots = array_merge($slots, $this->getDaySlots($today)); - } - else { - $slots[] = $this->getTimeSlot($slot, $day); - } - } - } - - return $slots; - } - - /** - * Get worked time slots and remove time off - * - * @access public - * @param array $slot - * @param array $dayoff - * @param \DateTime $today - * @return array - */ - public function getDayWorkSlots(array $slot, array $dayoff, DateTime $today) - { - $slots = array(); - - if (! empty($dayoff) && $dayoff['start'] < $slot['end']) { - - if ($dayoff['start'] > $slot['start']) { - $slots[] = $this->getTimeSlot(array('end' => $dayoff['start']) + $slot, $today); - } - - if ($dayoff['end'] < $slot['end']) { - $slots[] = $this->getTimeSlot(array('start' => $dayoff['end']) + $slot, $today); - } - } - else { - $slots[] = $this->getTimeSlot($slot, $today); - } - - return $slots; - } - - /** - * Get regular day work time slots - * - * @access public - * @param \DateTime $today - * @return array - */ - public function getDaySlots(DateTime $today) - { - $slots = array(); - - foreach ($this->day as $day) { - $slots[] = $this->getTimeSlot($day, $today); - } - - return $slots; - } - - /** - * Get the start and end time slot for a given day - * - * @access public - * @param array $slot - * @param \DateTime $today - * @return array - */ - public function getTimeSlot(array $slot, DateTime $today) - { - $date = $today->format('Y-m-d'); - - return array( - new DateTime($date.' '.$slot['start']), - new DateTime($date.' '.$slot['end']), - ); - } - - /** - * Return day off time slot - * - * @access public - * @param \DateTime $today - * @return array - */ - public function getDayOff(DateTime $today) - { - foreach ($this->timeoff as $day) { - - if ($day['date'] === $today->format('Y-m-d')) { - return $day; - } - } - - return array(); - } -} diff --git a/app/Model/TimetableDay.php b/app/Model/TimetableDay.php deleted file mode 100644 index 0c7bf20b..00000000 --- a/app/Model/TimetableDay.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -namespace Model; - -use SimpleValidator\Validator; -use SimpleValidator\Validators; - -/** - * Timetable Workweek - * - * @package model - * @author Frederic Guillot - */ -class TimetableDay extends Base -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'timetable_day'; - - /** - * Get the timetable for a given user - * - * @access public - * @param integer $user_id User id - * @return array - */ - public function getByUser($user_id) - { - return $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('start')->findAll(); - } - - /** - * Add a new time slot in the database - * - * @access public - * @param integer $user_id User id - * @param string $start Start hour (24h format) - * @param string $end End hour (24h format) - * @return boolean|integer - */ - public function create($user_id, $start, $end) - { - $values = array( - 'user_id' => $user_id, - 'start' => $start, - 'end' => $end, - ); - - return $this->persist(self::TABLE, $values); - } - - /** - * Remove a specific time slot - * - * @access public - * @param integer $slot_id - * @return boolean - */ - public function remove($slot_id) - { - return $this->db->table(self::TABLE)->eq('id', $slot_id)->remove(); - } - - /** - * Validate creation - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $v = new Validator($values, array( - new Validators\Required('user_id', t('Field required')), - new Validators\Required('start', t('Field required')), - new Validators\Required('end', t('Field required')), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } -} diff --git a/app/Model/TimetableExtra.php b/app/Model/TimetableExtra.php deleted file mode 100644 index 48db662d..00000000 --- a/app/Model/TimetableExtra.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -namespace Model; - -use SimpleValidator\Validator; -use SimpleValidator\Validators; - -/** - * Timetable over-time - * - * @package model - * @author Frederic Guillot - */ -class TimetableExtra extends TimetableOff -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'timetable_extra'; -} diff --git a/app/Model/TimetableOff.php b/app/Model/TimetableOff.php deleted file mode 100644 index e4fe32d2..00000000 --- a/app/Model/TimetableOff.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -namespace Model; - -use SimpleValidator\Validator; -use SimpleValidator\Validators; - -/** - * Timetable time off - * - * @package model - * @author Frederic Guillot - */ -class TimetableOff extends Base -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'timetable_off'; - - /** - * Get query to fetch everything (pagination) - * - * @access public - * @param integer $user_id User id - * @return \PicoDb\Table - */ - public function getUserQuery($user_id) - { - return $this->db->table(static::TABLE)->eq('user_id', $user_id); - } - - /** - * Get the timetable for a given user - * - * @access public - * @param integer $user_id User id - * @return array - */ - public function getByUser($user_id) - { - return $this->db->table(static::TABLE)->eq('user_id', $user_id)->desc('date')->asc('start')->findAll(); - } - - /** - * Get the timetable for a given user - * - * @access public - * @param integer $user_id User id - * @param string $start_date - * @param string $end_date - * @return array - */ - public function getByUserAndDate($user_id, $start_date, $end_date) - { - return $this->db->table(static::TABLE) - ->eq('user_id', $user_id) - ->gte('date', $start_date) - ->lte('date', $end_date) - ->desc('date') - ->asc('start') - ->findAll(); - } - - /** - * Add a new time slot in the database - * - * @access public - * @param integer $user_id User id - * @param string $date Day (ISO8601 format) - * @param boolean $all_day All day flag - * @param float $start Start hour (24h format) - * @param float $end End hour (24h format) - * @param string $comment - * @return boolean|integer - */ - public function create($user_id, $date, $all_day, $start = '', $end = '', $comment = '') - { - $values = array( - 'user_id' => $user_id, - 'date' => $date, - 'all_day' => (int) $all_day, // Postgres fix - 'start' => $all_day ? '' : $start, - 'end' => $all_day ? '' : $end, - 'comment' => $comment, - ); - - return $this->persist(static::TABLE, $values); - } - - /** - * Remove a specific time slot - * - * @access public - * @param integer $slot_id - * @return boolean - */ - public function remove($slot_id) - { - return $this->db->table(static::TABLE)->eq('id', $slot_id)->remove(); - } - - /** - * Validate creation - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $v = new Validator($values, array( - new Validators\Required('user_id', t('Field required')), - new Validators\Required('date', t('Field required')), - new Validators\Numeric('all_day', t('This value must be numeric')), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } -} diff --git a/app/Model/TimetableWeek.php b/app/Model/TimetableWeek.php deleted file mode 100644 index b22b3b7e..00000000 --- a/app/Model/TimetableWeek.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -namespace Model; - -use SimpleValidator\Validator; -use SimpleValidator\Validators; - -/** - * Timetable Workweek - * - * @package model - * @author Frederic Guillot - */ -class TimetableWeek extends Base -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'timetable_week'; - - /** - * Get the timetable for a given user - * - * @access public - * @param integer $user_id User id - * @return array - */ - public function getByUser($user_id) - { - return $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('day')->asc('start')->findAll(); - } - - /** - * Add a new time slot in the database - * - * @access public - * @param integer $user_id User id - * @param string $day Day of the week (ISO-8601) - * @param string $start Start hour (24h format) - * @param string $end End hour (24h format) - * @return boolean|integer - */ - public function create($user_id, $day, $start, $end) - { - $values = array( - 'user_id' => $user_id, - 'day' => $day, - 'start' => $start, - 'end' => $end, - ); - - return $this->persist(self::TABLE, $values); - } - - /** - * Remove a specific time slot - * - * @access public - * @param integer $slot_id - * @return boolean - */ - public function remove($slot_id) - { - return $this->db->table(self::TABLE)->eq('id', $slot_id)->remove(); - } - - /** - * Validate creation - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $v = new Validator($values, array( - new Validators\Required('user_id', t('Field required')), - new Validators\Required('day', t('Field required')), - new Validators\Numeric('day', t('This value must be numeric')), - new Validators\Required('start', t('Field required')), - new Validators\Required('end', t('Field required')), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } -} diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index 23a7a90a..c146eb0c 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -321,52 +321,6 @@ function version_53($pdo) $pdo->exec("ALTER TABLE subtask_time_tracking ADD COLUMN time_spent FLOAT DEFAULT 0"); } -function version_51($pdo) -{ - $pdo->exec('CREATE TABLE timetable_day ( - id INT NOT NULL AUTO_INCREMENT, - user_id INT NOT NULL, - start VARCHAR(5) NOT NULL, - end VARCHAR(5) NOT NULL, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE, - PRIMARY KEY(id) - ) ENGINE=InnoDB CHARSET=utf8'); - - $pdo->exec('CREATE TABLE timetable_week ( - id INT NOT NULL AUTO_INCREMENT, - user_id INTEGER NOT NULL, - day INT NOT NULL, - start VARCHAR(5) NOT NULL, - end VARCHAR(5) NOT NULL, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE, - PRIMARY KEY(id) - ) ENGINE=InnoDB CHARSET=utf8'); - - $pdo->exec('CREATE TABLE timetable_off ( - id INT NOT NULL AUTO_INCREMENT, - user_id INT NOT NULL, - date VARCHAR(10) NOT NULL, - all_day TINYINT(1) DEFAULT 0, - start VARCHAR(5) DEFAULT 0, - end VARCHAR(5) DEFAULT 0, - comment TEXT, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE, - PRIMARY KEY(id) - ) ENGINE=InnoDB CHARSET=utf8'); - - $pdo->exec('CREATE TABLE timetable_extra ( - id INT NOT NULL AUTO_INCREMENT, - user_id INT NOT NULL, - date VARCHAR(10) NOT NULL, - all_day TINYINT(1) DEFAULT 0, - start VARCHAR(5) DEFAULT 0, - end VARCHAR(5) DEFAULT 0, - comment TEXT, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE, - PRIMARY KEY(id) - ) ENGINE=InnoDB CHARSET=utf8'); -} - function version_49($pdo) { $pdo->exec('ALTER TABLE subtasks ADD COLUMN position INTEGER DEFAULT 1'); diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index cd4c295e..695d8f1f 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -314,48 +314,6 @@ function version_34($pdo) $pdo->exec("ALTER TABLE subtask_time_tracking ADD COLUMN time_spent REAL DEFAULT 0"); } -function version_32($pdo) -{ - $pdo->exec('CREATE TABLE timetable_day ( - "id" SERIAL PRIMARY KEY, - "user_id" INTEGER NOT NULL, - "start" VARCHAR(5) NOT NULL, - "end" VARCHAR(5) NOT NULL, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE - )'); - - $pdo->exec('CREATE TABLE timetable_week ( - "id" SERIAL PRIMARY KEY, - "user_id" INTEGER NOT NULL, - "day" INTEGER NOT NULL, - "start" VARCHAR(5) NOT NULL, - "end" VARCHAR(5) NOT NULL, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE - )'); - - $pdo->exec('CREATE TABLE timetable_off ( - "id" SERIAL PRIMARY KEY, - "user_id" INTEGER NOT NULL, - "date" VARCHAR(10) NOT NULL, - "all_day" BOOLEAN DEFAULT \'0\', - "start" VARCHAR(5) DEFAULT 0, - "end" VARCHAR(5) DEFAULT 0, - "comment" TEXT, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE - )'); - - $pdo->exec('CREATE TABLE timetable_extra ( - "id" SERIAL PRIMARY KEY, - "user_id" INTEGER NOT NULL, - "date" VARCHAR(10) NOT NULL, - "all_day" BOOLEAN DEFAULT \'0\', - "start" VARCHAR(5) DEFAULT 0, - "end" VARCHAR(5) DEFAULT 0, - "comment" TEXT, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE - )'); -} - function version_30($pdo) { $pdo->exec('ALTER TABLE subtasks ADD COLUMN position INTEGER DEFAULT 1'); diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index 175a583c..26ad96c7 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -291,48 +291,6 @@ function version_52($pdo) $pdo->exec("ALTER TABLE subtask_time_tracking ADD COLUMN time_spent REAL DEFAULT 0"); } -function version_50($pdo) -{ - $pdo->exec('CREATE TABLE timetable_day ( - "id" INTEGER PRIMARY KEY, - "user_id" INTEGER NOT NULL, - "start" TEXT NOT NULL, - "end" TEXT NOT NULL, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE - )'); - - $pdo->exec('CREATE TABLE timetable_week ( - "id" INTEGER PRIMARY KEY, - "user_id" INTEGER NOT NULL, - "day" INTEGER NOT NULL, - "start" TEXT NOT NULL, - "end" TEXT NOT NULL, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE - )'); - - $pdo->exec('CREATE TABLE timetable_off ( - "id" INTEGER PRIMARY KEY, - "user_id" INTEGER NOT NULL, - "date" TEXT NOT NULL, - "all_day" INTEGER DEFAULT 0, - "start" TEXT DEFAULT 0, - "end" TEXT DEFAULT 0, - "comment" TEXT, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE - )'); - - $pdo->exec('CREATE TABLE timetable_extra ( - "id" INTEGER PRIMARY KEY, - "user_id" INTEGER NOT NULL, - "date" TEXT NOT NULL, - "all_day" INTEGER DEFAULT 0, - "start" TEXT DEFAULT 0, - "end" TEXT DEFAULT 0, - "comment" TEXT, - FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE - )'); -} - function version_48($pdo) { $pdo->exec('ALTER TABLE subtasks ADD COLUMN position INTEGER DEFAULT 1'); diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index ee5ddbe4..e72d880a 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -56,11 +56,6 @@ class ClassProvider implements ServiceProviderInterface 'TaskPosition', 'TaskStatus', 'TaskValidator', - 'Timetable', - 'TimetableDay', - 'TimetableExtra', - 'TimetableWeek', - 'TimetableOff', 'Transition', 'User', 'UserSession', diff --git a/app/Template/config/calendar.php b/app/Template/config/calendar.php index 25f4b43d..f5250132 100644 --- a/app/Template/config/calendar.php +++ b/app/Template/config/calendar.php @@ -6,22 +6,24 @@ <?= $this->form->csrf() ?> - <h3><?= t('Project calendar view') ?></h3> <div class="listing"> + <h3><?= t('Project calendar view') ?></h3> <?= $this->form->radios('calendar_project_tasks', array( 'date_creation' => t('Show tasks based on the creation date'), 'date_started' => t('Show tasks based on the start date'), ), $values) ?> </div> - <h3><?= t('User calendar view') ?></h3> <div class="listing"> + <h3><?= t('User calendar view') ?></h3> <?= $this->form->radios('calendar_user_tasks', array( 'date_creation' => t('Show tasks based on the creation date'), 'date_started' => t('Show tasks based on the start date'), ), $values) ?> + </div> - <h4><?= t('Subtasks time tracking') ?></h4> + <div class="listing"> + <h3><?= t('Subtasks time tracking') ?></h3> <?= $this->form->checkbox('calendar_user_subtasks_time_tracking', t('Show subtasks based on the time tracking'), 1, $values['calendar_user_subtasks_time_tracking'] == 1) ?> </div> diff --git a/app/Template/timetable/index.php b/app/Template/timetable/index.php deleted file mode 100644 index 7a63a2ec..00000000 --- a/app/Template/timetable/index.php +++ /dev/null @@ -1,44 +0,0 @@ -<div class="page-header"> - <h2><?= t('Timetable') ?></h2> - <ul> - <li><?= $this->url->link(t('Day timetable'), 'timetableday', 'index', array('user_id' => $user['id'])) ?></li> - <li><?= $this->url->link(t('Week timetable'), 'timetableweek', 'index', array('user_id' => $user['id'])) ?></li> - <li><?= $this->url->link(t('Time off timetable'), 'timetableoff', 'index', array('user_id' => $user['id'])) ?></li> - <li><?= $this->url->link(t('Overtime timetable'), 'timetableextra', 'index', array('user_id' => $user['id'])) ?></li> - </ul> -</div> - -<form method="get" action="?" autocomplete="off" class="form-inline"> - - <?= $this->form->hidden('controller', $values) ?> - <?= $this->form->hidden('action', $values) ?> - <?= $this->form->hidden('user_id', $values) ?> - - <?= $this->form->label(t('From'), 'from') ?> - <?= $this->form->text('from', $values, array(), array(), 'form-date') ?> - - <?= $this->form->label(t('To'), 'to') ?> - <?= $this->form->text('to', $values, array(), array(), 'form-date') ?> - - <input type="submit" value="<?= t('Execute') ?>" class="btn btn-blue"/> -</form> - -<?php if (! empty($timetable)): ?> -<hr/> -<h3><?= t('Work timetable') ?></h3> -<table class="table-fixed table-stripped"> - <tr> - <th><?= t('Day') ?></th> - <th><?= t('Start') ?></th> - <th><?= t('End') ?></th> - </tr> - <?php foreach ($timetable as $slot): ?> - <tr> - <td><?= dt('%B %e, %Y', $slot[0]->getTimestamp()) ?></td> - <td><?= dt('%k:%M %p', $slot[0]->getTimestamp()) ?></td> - <td><?= dt('%k:%M %p', $slot[1]->getTimestamp()) ?></td> - </tr> - <?php endforeach ?> -</table> - -<?php endif ?>
\ No newline at end of file diff --git a/app/Template/timetable_day/index.php b/app/Template/timetable_day/index.php deleted file mode 100644 index 386ceec2..00000000 --- a/app/Template/timetable_day/index.php +++ /dev/null @@ -1,45 +0,0 @@ -<div class="page-header"> - <h2><?= t('Day timetable') ?></h2> -</div> - -<?php if (! empty($timetable)): ?> - -<table class="table-fixed table-stripped"> - <tr> - <th><?= t('Start time') ?></th> - <th><?= t('End time') ?></th> - <th><?= t('Action') ?></th> - </tr> - <?php foreach ($timetable as $slot): ?> - <tr> - <td><?= $slot['start'] ?></td> - <td><?= $slot['end'] ?></td> - <td> - <?= $this->url->link(t('Remove'), 'timetableday', 'confirm', array('user_id' => $user['id'], 'slot_id' => $slot['id'])) ?> - </td> - </tr> - <?php endforeach ?> -</table> - -<h3><?= t('Add new time slot') ?></h3> -<?php endif ?> - -<form method="post" action="<?= $this->url->href('timetableday', 'save', array('user_id' => $user['id'])) ?>" autocomplete="off"> - - <?= $this->form->hidden('user_id', $values) ?> - <?= $this->form->csrf() ?> - - <?= $this->form->label(t('Start time'), 'start') ?> - <?= $this->form->select('start', $this->dt->getDayHours(), $values, $errors) ?> - - <?= $this->form->label(t('End time'), 'end') ?> - <?= $this->form->select('end', $this->dt->getDayHours(), $values, $errors) ?> - - <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> - </div> -</form> - -<p class="alert alert-info"> - <?= t('This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.') ?> -</p>
\ No newline at end of file diff --git a/app/Template/timetable_day/remove.php b/app/Template/timetable_day/remove.php deleted file mode 100644 index 1b33b266..00000000 --- a/app/Template/timetable_day/remove.php +++ /dev/null @@ -1,13 +0,0 @@ -<div class="page-header"> - <h2><?= t('Remove time slot') ?></h2> -</div> - -<div class="confirm"> - <p class="alert alert-info"><?= t('Do you really want to remove this time slot?') ?></p> - - <div class="form-actions"> - <?= $this->url->link(t('Yes'), 'timetableday', 'remove', array('user_id' => $user['id'], 'slot_id' => $slot_id), true, 'btn btn-red') ?> - <?= t('or') ?> - <?= $this->url->link(t('cancel'), 'timetableday', 'index', array('user_id' => $user['id'])) ?> - </div> -</div>
\ No newline at end of file diff --git a/app/Template/timetable_extra/index.php b/app/Template/timetable_extra/index.php deleted file mode 100644 index e9982335..00000000 --- a/app/Template/timetable_extra/index.php +++ /dev/null @@ -1,56 +0,0 @@ -<div class="page-header"> - <h2><?= t('Overtime timetable') ?></h2> -</div> - -<?php if (! $paginator->isEmpty()): ?> - -<table class="table-fixed table-stripped"> - <tr> - <th><?= $paginator->order(t('Day'), 'Day') ?></th> - <th><?= $paginator->order(t('All day'), 'all_day') ?></th> - <th><?= $paginator->order(t('Start time'), 'start') ?></th> - <th><?= $paginator->order(t('End time'), 'end') ?></th> - <th class="column-40"><?= t('Comment') ?></th> - <th><?= t('Action') ?></th> - </tr> - <?php foreach ($paginator->getCollection() as $slot): ?> - <tr> - <td><?= $slot['date'] ?></td> - <td><?= $slot['all_day'] == 1 ? t('Yes') : t('No') ?></td> - <td><?= $slot['start'] ?></td> - <td><?= $slot['end'] ?></td> - <td><?= $this->e($slot['comment']) ?></td> - <td> - <?= $this->url->link(t('Remove'), 'timetableextra', 'confirm', array('user_id' => $user['id'], 'slot_id' => $slot['id'])) ?> - </td> - </tr> - <?php endforeach ?> -</table> - -<?= $paginator ?> - -<?php endif ?> - -<form method="post" action="<?= $this->url->href('timetableextra', 'save', array('user_id' => $user['id'])) ?>" autocomplete="off"> - - <?= $this->form->hidden('user_id', $values) ?> - <?= $this->form->csrf() ?> - - <?= $this->form->label(t('Day'), 'date') ?> - <?= $this->form->text('date', $values, $errors, array('required'), 'form-date') ?> - - <?= $this->form->checkbox('all_day', t('All day'), 1) ?> - - <?= $this->form->label(t('Start time'), 'start') ?> - <?= $this->form->select('start', $this->dt->getDayHours(), $values, $errors) ?> - - <?= $this->form->label(t('End time'), 'end') ?> - <?= $this->form->select('end', $this->dt->getDayHours(), $values, $errors) ?> - - <?= $this->form->label(t('Comment'), 'comment') ?> - <?= $this->form->text('comment', $values, $errors) ?> - - <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> - </div> -</form>
\ No newline at end of file diff --git a/app/Template/timetable_extra/remove.php b/app/Template/timetable_extra/remove.php deleted file mode 100644 index fc907438..00000000 --- a/app/Template/timetable_extra/remove.php +++ /dev/null @@ -1,13 +0,0 @@ -<div class="page-header"> - <h2><?= t('Remove time slot') ?></h2> -</div> - -<div class="confirm"> - <p class="alert alert-info"><?= t('Do you really want to remove this time slot?') ?></p> - - <div class="form-actions"> - <?= $this->url->link(t('Yes'), 'timetableextra', 'remove', array('user_id' => $user['id'], 'slot_id' => $slot_id), true, 'btn btn-red') ?> - <?= t('or') ?> - <?= $this->url->link(t('cancel'), 'timetableextra', 'index', array('user_id' => $user['id'])) ?> - </div> -</div>
\ No newline at end of file diff --git a/app/Template/timetable_off/index.php b/app/Template/timetable_off/index.php deleted file mode 100644 index 615c2b8d..00000000 --- a/app/Template/timetable_off/index.php +++ /dev/null @@ -1,56 +0,0 @@ -<div class="page-header"> - <h2><?= t('Time off timetable') ?></h2> -</div> - -<?php if (! $paginator->isEmpty()): ?> - -<table class="table-fixed table-stripped"> - <tr> - <th><?= $paginator->order(t('Day'), 'Day') ?></th> - <th><?= $paginator->order(t('All day'), 'all_day') ?></th> - <th><?= $paginator->order(t('Start time'), 'start') ?></th> - <th><?= $paginator->order(t('End time'), 'end') ?></th> - <th class="column-40"><?= t('Comment') ?></th> - <th><?= t('Action') ?></th> - </tr> - <?php foreach ($paginator->getCollection() as $slot): ?> - <tr> - <td><?= $slot['date'] ?></td> - <td><?= $slot['all_day'] == 1 ? t('Yes') : t('No') ?></td> - <td><?= $slot['start'] ?></td> - <td><?= $slot['end'] ?></td> - <td><?= $this->e($slot['comment']) ?></td> - <td> - <?= $this->url->link(t('Remove'), 'timetableoff', 'confirm', array('user_id' => $user['id'], 'slot_id' => $slot['id'])) ?> - </td> - </tr> - <?php endforeach ?> -</table> - -<?= $paginator ?> - -<?php endif ?> - -<form method="post" action="<?= $this->url->href('timetableoff', 'save', array('user_id' => $user['id'])) ?>" autocomplete="off"> - - <?= $this->form->hidden('user_id', $values) ?> - <?= $this->form->csrf() ?> - - <?= $this->form->label(t('Day'), 'date') ?> - <?= $this->form->text('date', $values, $errors, array('required'), 'form-date') ?> - - <?= $this->form->checkbox('all_day', t('All day'), 1) ?> - - <?= $this->form->label(t('Start time'), 'start') ?> - <?= $this->form->select('start', $this->dt->getDayHours(), $values, $errors) ?> - - <?= $this->form->label(t('End time'), 'end') ?> - <?= $this->form->select('end', $this->dt->getDayHours(), $values, $errors) ?> - - <?= $this->form->label(t('Comment'), 'comment') ?> - <?= $this->form->text('comment', $values, $errors) ?> - - <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> - </div> -</form>
\ No newline at end of file diff --git a/app/Template/timetable_off/remove.php b/app/Template/timetable_off/remove.php deleted file mode 100644 index 621e191c..00000000 --- a/app/Template/timetable_off/remove.php +++ /dev/null @@ -1,13 +0,0 @@ -<div class="page-header"> - <h2><?= t('Remove time slot') ?></h2> -</div> - -<div class="confirm"> - <p class="alert alert-info"><?= t('Do you really want to remove this time slot?') ?></p> - - <div class="form-actions"> - <?= $this->url->link(t('Yes'), 'timetableoff', 'remove', array('user_id' => $user['id'], 'slot_id' => $slot_id), true, 'btn btn-red') ?> - <?= t('or') ?> - <?= $this->url->link(t('cancel'), 'timetableoff', 'index', array('user_id' => $user['id'])) ?> - </div> -</div>
\ No newline at end of file diff --git a/app/Template/timetable_week/index.php b/app/Template/timetable_week/index.php deleted file mode 100644 index d58c6cfb..00000000 --- a/app/Template/timetable_week/index.php +++ /dev/null @@ -1,46 +0,0 @@ -<div class="page-header"> - <h2><?= t('Week timetable') ?></h2> -</div> - -<?php if (! empty($timetable)): ?> - -<table class="table-fixed table-stripped"> - <tr> - <th><?= t('Day') ?></th> - <th><?= t('Start time') ?></th> - <th><?= t('End time') ?></th> - <th><?= t('Action') ?></th> - </tr> - <?php foreach ($timetable as $slot): ?> - <tr> - <td><?= $this->dt->getWeekDay($slot['day']) ?></td> - <td><?= $slot['start'] ?></td> - <td><?= $slot['end'] ?></td> - <td> - <?= $this->url->link(t('Remove'), 'timetableweek', 'confirm', array('user_id' => $user['id'], 'slot_id' => $slot['id'])) ?> - </td> - </tr> - <?php endforeach ?> -</table> - -<h3><?= t('Add new time slot') ?></h3> -<?php endif ?> - -<form method="post" action="<?= $this->url->href('timetableweek', 'save', array('user_id' => $user['id'])) ?>" autocomplete="off"> - - <?= $this->form->hidden('user_id', $values) ?> - <?= $this->form->csrf() ?> - - <?= $this->form->label(t('Day'), 'day') ?> - <?= $this->form->select('day', $this->dt->getWeekDays(), $values, $errors) ?> - - <?= $this->form->label(t('Start time'), 'start') ?> - <?= $this->form->select('start', $this->dt->getDayHours(), $values, $errors) ?> - - <?= $this->form->label(t('End time'), 'end') ?> - <?= $this->form->select('end', $this->dt->getDayHours(), $values, $errors) ?> - - <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> - </div> -</form>
\ No newline at end of file diff --git a/app/Template/timetable_week/remove.php b/app/Template/timetable_week/remove.php deleted file mode 100644 index f5a10199..00000000 --- a/app/Template/timetable_week/remove.php +++ /dev/null @@ -1,13 +0,0 @@ -<div class="page-header"> - <h2><?= t('Remove time slot') ?></h2> -</div> - -<div class="confirm"> - <p class="alert alert-info"><?= t('Do you really want to remove this time slot?') ?></p> - - <div class="form-actions"> - <?= $this->url->link(t('Yes'), 'timetableweek', 'remove', array('user_id' => $user['id'], 'slot_id' => $slot_id), true, 'btn btn-red') ?> - <?= t('or') ?> - <?= $this->url->link(t('cancel'), 'timetableweek', 'index', array('user_id' => $user['id'])) ?> - </div> -</div>
\ No newline at end of file diff --git a/app/Template/user/sidebar.php b/app/Template/user/sidebar.php index 6a4e9c47..640c8b80 100644 --- a/app/Template/user/sidebar.php +++ b/app/Template/user/sidebar.php @@ -62,9 +62,6 @@ <li <?= $this->app->getRouterController() === 'user' && $this->app->getRouterAction() === 'authentication' ? 'class="active"' : '' ?>> <?= $this->url->link(t('Edit Authentication'), 'user', 'authentication', array('user_id' => $user['id'])) ?> </li> - <li <?= $this->app->getRouterController() === 'timetable' ? 'class="active"' : '' ?>> - <?= $this->url->link(t('Manage timetable'), 'timetable', 'index', array('user_id' => $user['id'])) ?> - </li> <?php endif ?> <?= $this->hook->render('template:user:sidebar:actions', array('user' => $user)) ?> diff --git a/doc/budget.markdown b/doc/budget.markdown deleted file mode 100644 index 63408d46..00000000 --- a/doc/budget.markdown +++ /dev/null @@ -1,34 +0,0 @@ -Budget management -================= - -Budget management is based on the subtask time tracking, the user timetable and the user hourly rate. - -This section is available from project settings page: **Project > Budget**. There is also a shortcut from the dropdown menu on the board. - -Budget lines ------------- - -![Cost Lines](http://kanboard.net/screenshots/documentation/budget-lines.png) - -Budget lines are used to define a budget for the project. -This budget can be adjusted by adding a new entry with an effective date. - -Cost breakdown --------------- - -![Cost Breakdown](http://kanboard.net/screenshots/documentation/budget-cost-breakdown.png) - -Based on the subtask time tracking table and user information you can see the cost of each subtask. - -The time spent is rounded to nearest quarter. - -Budget graph ------------- - -![Budget Graph](http://kanboard.net/screenshots/documentation/budget-graph.png) - -Finally, by combining all information we can generate a graph: - -- Expenses represents user cost -- Budget lines are the provisioned budget -- Remaining is the budget left at the given time diff --git a/doc/fr/budget.markdown b/doc/fr/budget.markdown deleted file mode 100644 index 3eac20d5..00000000 --- a/doc/fr/budget.markdown +++ /dev/null @@ -1,34 +0,0 @@ -Gestion du budget -================= - -La gestion du budget repose sur le suivi du temps d'une sous-tâche, l'emploi du temps de l'utilisateur et le taux horaire de l'utilisateur. - -Cette section est accessible depuis la page de paramètres du projet : **Project > Budget**. Il existe également un raccourci depuis le menu déroulant sur le tableau. - -Lignes budgétaires ------------- - -![Ligne des coûts](http://kanboard.net/screenshots/documentation/budget-lines.png) - -Les lignes budgétaires sont utilisées pour définir le budget du projet. -Celui-ci peut être ajusté en ajoutant une nouvelle entrée avec une date effective. - -Détail des coûts --------------- - -![Détail des coûts](http://kanboard.net/screenshots/documentation/budget-cost-breakdown.png) - -Selon le tableau qui donne le suivi temporel de la sous-tâche et les informations sur l'utilisateur vous pouvez voir le coût de chaque sous-tâche. - -Le temps passé est arrondi au quart d'heure le plus proche. - -Graphique du budget ------------- - -![Graphique du budget](http://kanboard.net/screenshots/documentation/budget-graph.png) - -Finalement, en combinant toutes les informations nous pouvons générer un graphique : - -- Les dépenses représentent le coût utilisateur -- Les lignes budgétaires sont le budget prévisionnel -- Le restant est le budget qui reste après un délai donné diff --git a/doc/hourly-rate.markdown b/doc/hourly-rate.markdown deleted file mode 100644 index 172f2f47..00000000 --- a/doc/hourly-rate.markdown +++ /dev/null @@ -1,11 +0,0 @@ -Hourly Rate -=========== - -Each user can have a predefined hourly rate. -This feature is used for budget calculation. - -To define a new price, go to **User profile > Hourly rates**. - -![Hourly Rate](http://kanboard.net/screenshots/documentation/hourly-rate.png) - -Each hourly rate can have an effective date and and different currency. diff --git a/doc/index.markdown b/doc/index.markdown index 96069250..a66cc720 100644 --- a/doc/index.markdown +++ b/doc/index.markdown @@ -26,7 +26,6 @@ Using Kanboard - [Project permissions](project-permissions.markdown) - [Swimlanes](swimlanes.markdown) - [Calendar](calendar.markdown) -- [Budget](budget.markdown) - [Analytics](analytics.markdown) - [Gantt chart for tasks](gantt-chart-tasks.markdown) - [Gantt chart for projects](gantt-chart-projects.markdown) @@ -49,8 +48,6 @@ Using Kanboard - [User management](user-management.markdown) - [Notifications](notifications.markdown) -- [Hourly rate](hourly-rate.markdown) -- [Timetable](timetable.markdown) - [Two factor authentication](2fa.markdown) ### Settings diff --git a/doc/plugins.markdown b/doc/plugins.markdown index c8222a81..cccda796 100644 --- a/doc/plugins.markdown +++ b/doc/plugins.markdown @@ -94,6 +94,27 @@ $this->hook->on('hook_name', $callable); The first argument is the name of the hook and the second is a PHP callable. +### Hooks executed only one time + +Some hooks can have only one listener: + +#### model:subtask-time-tracking:calculate:time-spent + +- Override time spent calculation when subtask timer is stopped +- Arguments: + - `$user_id` (integer) + - `$start` (DateTime) + - `$end` (DateTime) + +#### model:subtask-time-tracking:calendar:events + +- Override subtask time tracking events to display the calendar +- Arguments: + - `$user_id` (integer) + - `$events` (array) + - `$start` (string, ISO-8601 format) + - `$end` (string, ISO-8601 format) + ### Merge hooks "Merge hooks" act in the same way as the function `array_merge`. The hook callback must return an array. This array will be merged with the default one. @@ -313,5 +334,7 @@ Kanboard will compare the version defined in your schema and the version stored Examples of plugins ------------------- -- Budget planning: https://github.com/kanboard/plugin-budget -- Theme plugin sample: https://github.com/kanboard/plugin-example-theme +- [Budget planning](https://github.com/kanboard/plugin-budget) +- [User timetable](https://github.com/kanboard/plugin-timetable) +- [Subtask Forecast](https://github.com/kanboard/plugin-subtask-forecast) +- [Theme plugin sample](https://github.com/kanboard/plugin-example-theme) diff --git a/doc/timetable.markdown b/doc/timetable.markdown deleted file mode 100644 index 5d2f4c86..00000000 --- a/doc/timetable.markdown +++ /dev/null @@ -1,46 +0,0 @@ -User Timetable -============== - -Each user can have a predefined timetable. -This feature mainly is used for time tracking, project budget calculation and to display subtasks in the calendar. - -Each user have his own timetable. At the moment, that need to be specified manually for each person. -You can also schedule time-off or overtime. - -The timetable section is available from the user profile: **User profile > Timetable**. - -Work timetable --------------- - -This timetable is dynamically calculated according to the regular week timetable, time-off and overtime. - -![Timetable](http://kanboard.net/screenshots/documentation/timetable.png) - -Week timetable --------------- - -![Week Timetable](http://kanboard.net/screenshots/documentation/week-timetable.png) - -The week timetable is used to define regular work hours for the selected user. - -To add a new time slot, just select the day of the week and the time range. - -Time off timetable ------------------- - -The time-off timetable is used to schedule not worked time slot. -This time is deducted from the regular work hours. - -When you check the box "All day", the regular day timetable is used to define the regular work hours. - -Overtime timetable ------------------- - -![Overtime Timetable](http://kanboard.net/screenshots/documentation/overtime-timetable.png) - -The overtime timetable is used to define worked hours outside of regular hours. - -Day timetable -------------- - -This timetable is used when the checkbox "All day" is checked for overtime and time-off entries. diff --git a/tests/units/Core/Plugin/HookTest.php b/tests/units/Core/Plugin/HookTest.php index 95434ce4..f8646cbf 100644 --- a/tests/units/Core/Plugin/HookTest.php +++ b/tests/units/Core/Plugin/HookTest.php @@ -17,6 +17,16 @@ class HookTest extends Base $this->assertEquals(array('A', 'B'), $h->getListeners('myhook')); } + public function testExists() + { + $h = new Hook; + $this->assertFalse($h->exists('myhook')); + + $h->on('myhook', 'A'); + + $this->assertTrue($h->exists('myhook')); + } + public function testMergeWithNoBinding() { $h = new Hook; @@ -59,4 +69,28 @@ class HookTest extends Base $this->assertEquals($expected, $result); $this->assertEquals($expected, $values); } + + public function testFirstWithNoBinding() + { + $h = new Hook; + + $result = $h->first('myhook', array('p' => 2)); + $this->assertEquals(null, $result); + } + + public function testFirstWithMultipleBindings() + { + $h = new Hook; + + $h->on('myhook', function($p) { + return $p + 1; + }); + + $h->on('myhook', function($p) { + return $p; + }); + + $result = $h->first('myhook', array('p' => 3)); + $this->assertEquals(4, $result); + } } diff --git a/tests/units/Model/TimetableTest.php b/tests/units/Model/TimetableTest.php deleted file mode 100644 index 887e1787..00000000 --- a/tests/units/Model/TimetableTest.php +++ /dev/null @@ -1,256 +0,0 @@ -<?php - -require_once __DIR__.'/../Base.php'; - -use Model\User; -use Model\Timetable; -use Model\TimetableDay; -use Model\TimetableWeek; -use Model\TimetableOff; -use Model\TimetableExtra; - -class TimetableTest extends Base -{ - public function testCalculateWorkDays() - { - $w = new TimetableWeek($this->container); - $t = new Timetable($this->container); - - $this->assertNotFalse($w->create(1, 1, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 1, '13:00', '17:00')); - $this->assertNotFalse($w->create(1, 2, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 2, '13:00', '17:00')); - - $monday = new DateTime('next Monday'); - - $timetable = $t->calculate(1, $monday, new DateTime('next Monday + 6 days')); - $this->assertNotEmpty($timetable); - $this->assertCount(4, $timetable); - - $this->assertEquals($monday->format('Y-m-d').' 09:30', $timetable[0][0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 12:00', $timetable[0][1]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 13:00', $timetable[1][0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 17:00', $timetable[1][1]->format('Y-m-d H:i')); - - $this->assertEquals($monday->add(new DateInterval('P1D'))->format('Y-m-d').' 09:30', $timetable[2][0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 12:00', $timetable[2][1]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 13:00', $timetable[3][0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 17:00', $timetable[3][1]->format('Y-m-d H:i')); - } - - public function testCalculateOverTime() - { - $d = new TimetableDay($this->container); - $w = new TimetableWeek($this->container); - $e = new TimetableExtra($this->container); - $t = new Timetable($this->container); - - $monday = new DateTime('next Monday'); - $tuesday = new DateTime('next Monday + 1 day'); - $friday = new DateTime('next Monday + 4 days'); - - $this->assertNotFalse($d->create(1, '08:00', '12:00')); - $this->assertNotFalse($d->create(1, '14:00', '18:00')); - - $this->assertNotFalse($w->create(1, 1, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 1, '13:00', '17:00')); - $this->assertNotFalse($w->create(1, 2, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 2, '13:00', '17:00')); - - $this->assertNotFalse($e->create(1, $tuesday->format('Y-m-d'), 0, '17:00', '22:00')); - $this->assertNotFalse($e->create(1, $friday->format('Y-m-d'), 1)); - - $timetable = $t->calculate(1, $monday, new DateTime('next Monday + 6 days')); - $this->assertNotEmpty($timetable); - $this->assertCount(7, $timetable); - - $this->assertEquals($monday->format('Y-m-d').' 09:30', $timetable[0][0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 12:00', $timetable[0][1]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 13:00', $timetable[1][0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 17:00', $timetable[1][1]->format('Y-m-d H:i')); - - $this->assertEquals($tuesday->format('Y-m-d').' 09:30', $timetable[2][0]->format('Y-m-d H:i')); - $this->assertEquals($tuesday->format('Y-m-d').' 12:00', $timetable[2][1]->format('Y-m-d H:i')); - $this->assertEquals($tuesday->format('Y-m-d').' 13:00', $timetable[3][0]->format('Y-m-d H:i')); - $this->assertEquals($tuesday->format('Y-m-d').' 17:00', $timetable[3][1]->format('Y-m-d H:i')); - - $this->assertEquals($tuesday->format('Y-m-d').' 17:00', $timetable[4][0]->format('Y-m-d H:i')); - $this->assertEquals($tuesday->format('Y-m-d').' 22:00', $timetable[4][1]->format('Y-m-d H:i')); - - $this->assertEquals($friday->format('Y-m-d').' 08:00', $timetable[5][0]->format('Y-m-d H:i')); - $this->assertEquals($friday->format('Y-m-d').' 12:00', $timetable[5][1]->format('Y-m-d H:i')); - - $this->assertEquals($friday->format('Y-m-d').' 14:00', $timetable[6][0]->format('Y-m-d H:i')); - $this->assertEquals($friday->format('Y-m-d').' 18:00', $timetable[6][1]->format('Y-m-d H:i')); - } - - public function testCalculateTimeOff() - { - $d = new TimetableDay($this->container); - $w = new TimetableWeek($this->container); - $o = new TimetableOff($this->container); - $t = new Timetable($this->container); - - $monday = new DateTime('next Monday'); - $tuesday = new DateTime('next Monday + 1 day'); - $friday = new DateTime('next Monday + 4 days'); - - $this->assertNotFalse($d->create(1, '08:00', '12:00')); - $this->assertNotFalse($d->create(1, '14:00', '18:00')); - - $this->assertNotFalse($w->create(1, 1, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 1, '13:00', '17:00')); - $this->assertNotFalse($w->create(1, 2, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 2, '13:00', '17:00')); - $this->assertNotFalse($w->create(1, 5, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 5, '13:00', '17:00')); - - $this->assertNotFalse($o->create(1, $tuesday->format('Y-m-d'), 0, '14:00', '15:00')); - $this->assertNotFalse($o->create(1, $monday->format('Y-m-d'), 1)); - - $timetable = $t->calculate(1, $monday, new DateTime('next Monday + 6 days')); - $this->assertNotEmpty($timetable); - $this->assertCount(5, $timetable); - - $this->assertEquals($tuesday->format('Y-m-d').' 09:30', $timetable[0][0]->format('Y-m-d H:i')); - $this->assertEquals($tuesday->format('Y-m-d').' 12:00', $timetable[0][1]->format('Y-m-d H:i')); - - $this->assertEquals($tuesday->format('Y-m-d').' 13:00', $timetable[1][0]->format('Y-m-d H:i')); - $this->assertEquals($tuesday->format('Y-m-d').' 14:00', $timetable[1][1]->format('Y-m-d H:i')); - - $this->assertEquals($tuesday->format('Y-m-d').' 15:00', $timetable[2][0]->format('Y-m-d H:i')); - $this->assertEquals($tuesday->format('Y-m-d').' 17:00', $timetable[2][1]->format('Y-m-d H:i')); - - $this->assertEquals($friday->format('Y-m-d').' 09:30', $timetable[3][0]->format('Y-m-d H:i')); - $this->assertEquals($friday->format('Y-m-d').' 12:00', $timetable[3][1]->format('Y-m-d H:i')); - - $this->assertEquals($friday->format('Y-m-d').' 13:00', $timetable[4][0]->format('Y-m-d H:i')); - $this->assertEquals($friday->format('Y-m-d').' 17:00', $timetable[4][1]->format('Y-m-d H:i')); - } - - public function testClosestTimeSlot() - { - $w = new TimetableWeek($this->container); - $t = new Timetable($this->container); - - $this->assertNotFalse($w->create(1, 1, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 1, '13:00', '17:00')); - $this->assertNotFalse($w->create(1, 2, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 2, '13:00', '17:00')); - - $monday = new DateTime('next Monday'); - $tuesday = new DateTime('next Monday + 1 day'); - - $timetable = $t->calculate(1, new DateTime('next Monday'), new DateTime('next Monday + 6 days')); - $this->assertNotEmpty($timetable); - $this->assertCount(4, $timetable); - - // Start to work before timetable - $date = clone($monday); - $date->setTime(5, 02); - - $slot = $t->findClosestTimeSlot($date, $timetable); - $this->assertNotEmpty($slot); - $this->assertEquals($monday->format('Y-m-d').' 09:30', $slot[0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 12:00', $slot[1]->format('Y-m-d H:i')); - - // Start to work at the end of the timeslot - $date = clone($monday); - $date->setTime(12, 02); - - $slot = $t->findClosestTimeSlot($date, $timetable); - $this->assertNotEmpty($slot); - $this->assertEquals($monday->format('Y-m-d').' 09:30', $slot[0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 12:00', $slot[1]->format('Y-m-d H:i')); - - // Start to work at lunch time - $date = clone($monday); - $date->setTime(12, 32); - - $slot = $t->findClosestTimeSlot($date, $timetable); - $this->assertNotEmpty($slot); - $this->assertEquals($monday->format('Y-m-d').' 13:00', $slot[0]->format('Y-m-d H:i')); - $this->assertEquals($monday->format('Y-m-d').' 17:00', $slot[1]->format('Y-m-d H:i')); - - // Start to work early in the morning - $date = clone($tuesday); - $date->setTime(8, 02); - - $slot = $t->findClosestTimeSlot($date, $timetable); - $this->assertNotEmpty($slot); - $this->assertEquals($tuesday->format('Y-m-d').' 09:30', $slot[0]->format('Y-m-d H:i')); - $this->assertEquals($tuesday->format('Y-m-d').' 12:00', $slot[1]->format('Y-m-d H:i')); - } - - public function testCalculateDuration() - { - $w = new TimetableWeek($this->container); - $t = new Timetable($this->container); - - $this->assertNotFalse($w->create(1, 1, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 1, '13:00', '17:00')); - $this->assertNotFalse($w->create(1, 2, '09:30', '12:00')); - $this->assertNotFalse($w->create(1, 2, '13:00', '17:00')); - - $monday = new DateTime('next Monday'); - $tuesday = new DateTime('next Monday + 1 day'); - - // Different day - $start = clone($monday); - $start->setTime(16, 02); - - $end = clone($tuesday); - $end->setTime(10, 03); - - $this->assertEquals(1.5, $t->calculateEffectiveDuration(1, $start, $end)); - - // Same time slot - $start = clone($monday); - $start->setTime(16, 02); - - $end = clone($monday); - $end->setTime(17, 03); - - $this->assertEquals(1, $t->calculateEffectiveDuration(1, $start, $end)); - - // Intermediate time slot - $start = clone($monday); - $start->setTime(10, 02); - - $end = clone($tuesday); - $end->setTime(16, 03); - - $this->assertEquals(11.5, $t->calculateEffectiveDuration(1, $start, $end)); - - // Different day - $start = clone($monday); - $start->setTime(9, 02); - - $end = clone($tuesday); - $end->setTime(10, 03); - - $this->assertEquals(7, $t->calculateEffectiveDuration(1, $start, $end)); - - // Start before first time slot - $start = clone($monday); - $start->setTime(5, 32); - - $end = clone($tuesday); - $end->setTime(11, 17); - - $this->assertEquals(8.25, $t->calculateEffectiveDuration(1, $start, $end)); - } - - public function testCalculateDurationWithEmptyTimetable() - { - $t = new Timetable($this->container); - - $start = new DateTime('next Monday'); - $start->setTime(16, 02); - - $end = new DateTime('next Monday'); - $end->setTime(17, 03); - - $this->assertEquals(1, $t->calculateEffectiveDuration(1, $start, $end)); - } -} |