Move timetable to a plugin

Plugin repository: https://github.com/kanboard/plugin-timetable
This commit is contained in:
Frederic Guillot
2015-09-20 18:24:15 -04:00
parent 2021dccc5a
commit e6f547abcf
59 changed files with 137 additions and 2468 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -46,6 +46,18 @@ class Hook
return isset($this->hooks[$hook]) ? $this->hooks[$hook] : array();
}
/**
* 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
*
@@ -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;
}
}

View File

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

View File

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

View File

@@ -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' => '',

View File

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

View File

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

View File

@@ -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' => '',

View File

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

View File

@@ -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' => '',

View File

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

View File

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

View File

@@ -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' => 'カラムでの時間消費',

View File

@@ -126,7 +126,6 @@ return array(
'The project name is required' => 'Prosjektnavn er påkrevet',
'This project must be unique' => 'Prosjektnavnet skal være unikt',
'The title is required' => 'Tittel er pårevet',
'There is no active project, the first step is to create a new project.' => 'Det er ingen aktive prosjekter. Førstesteg er åopprette et nytt prosjekt.',
'Settings saved successfully.' => 'Innstillinger lagret.',
'Unable to save your settings.' => 'Innstillinger kunne ikke lagres.',
'Database optimization done.' => 'Databaseoptimering er fullført.',
@@ -165,8 +164,6 @@ return array(
'Date created' => 'Dato for opprettelse',
'Date completed' => 'Dato for fullført',
'Id' => 'ID',
'Completed tasks' => 'Fullførte oppgaver',
'Completed tasks for "%s"' => 'Fullførte 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' => 'Utløpsdato',
'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' => 'Søk',
'Nothing found.' => 'Intet funnet.',
'Search in the project "%s"' => 'Søk 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 påkrevet',
@@ -344,14 +336,9 @@ return array(
'Maximum size: ' => 'Maksimum størrelse: ',
'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:' => 'Språk',
'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 svømmebane',
'All swimlanes' => 'Alle svømmebaner',
'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' => 'Beløp',
// '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 når den er tildelt en bruker',
'Move the task to another column when assignee is cleared' => 'Flytt oppgaven til en annen kolonne når 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' => 'Svømmebane',
'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 fullførte 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' => 'Svømmebane: %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',

View File

@@ -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' => '',

View File

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

View File

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

View File

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

View File

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

View File

@@ -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' => '',

View File

@@ -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.',

View File

@@ -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' => 'เวลาที่ใช้ในคอลัมน์',

View File

@@ -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' => '',

View File

@@ -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' => '栏目中的时间消耗',

View File

@@ -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);
return $this->timetable->calculateEffectiveDuration($user_id, $start, new DateTime);
if (empty($start_time)) {
return 0;
}
return 0;
$end = new DateTime;
$start = new DateTime;
$start->setTimestamp($start_time);
if ($this->hook->exists($hook)) {
return $this->hook->first($hook, array(
'user_id' => $user_id,
'start' => $start,
'end' => $end,
));
}
return $this->dateParser->getHours($start, $end);
}
/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -56,11 +56,6 @@ class ClassProvider implements ServiceProviderInterface
'TaskPosition',
'TaskStatus',
'TaskValidator',
'Timetable',
'TimetableDay',
'TimetableExtra',
'TimetableWeek',
'TimetableOff',
'Transition',
'User',
'UserSession',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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