Add budget graph

This commit is contained in:
Frederic Guillot 2015-03-22 18:44:45 -04:00
parent 373537efe2
commit 72de621d77
29 changed files with 725 additions and 34 deletions

View File

@ -20,7 +20,7 @@ class Budget extends Base
$project = $this->getProject();
$this->response->html($this->projectLayout('budget/index', array(
'total' => $this->budget->getTotal($project['id']),
'daily_budget' => $this->budget->getDailyBudgetBreakdown($project['id']),
'project' => $project,
'title' => t('Budget')
)));
@ -40,7 +40,7 @@ class Budget extends Base
->setMax(30)
->setOrder('start')
->setDirection('DESC')
->setQuery($this->budget->getBreakdown($project['id']))
->setQuery($this->budget->getSubtaskBreakdown($project['id']))
->calculate();
$this->response->html($this->projectLayout('budget/breakdown', array(

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -778,4 +778,32 @@ return array(
'Files' => 'Fichiers',
'Images' => 'Images',
'Private project' => 'Projet privé',
'Amount' => 'Montant',
'AUD - Australian Dollar' => 'AUD - Dollar australien',
'Budget' => 'Budget',
'Budget line' => 'Ligne budgétaire',
'Budget line removed successfully.' => 'Ligne budgétaire supprimée avec succès.',
'Budget lines' => 'Lignes budgétaire',
'CAD - Canadian Dollar' => 'CAD - Dollar canadien',
'CHF - Swiss Francs' => 'CHF - Franc suisse',
'Cost' => 'Coût',
'Cost breakdown' => 'Détail des coûts',
'Custom Stylesheet' => 'Feuille de style personalisée',
'download' => 'télécharger',
'Do you really want to remove this budget line?' => 'Voulez-vous vraiment supprimer cette ligne budgétaire ?',
'EUR - Euro' => 'EUR - Euro',
'Expenses' => 'Dépenses',
'GBP - British Pound' => 'GBP - Livre sterling',
'INR - Indian Rupee' => 'INR - Roupie indienne',
'JPY - Japanese Yen' => 'JPY - Yen',
'New budget line' => 'Nouvelle ligne budgétaire',
'NZD - New Zealand Dollar' => 'NZD - Dollar néo-zélandais',
'Remove a budget line' => 'Supprimer une ligne budgétaire',
'Remove budget line' => 'Supprimer une ligne budgétaire',
'RSD - Serbian dinar' => 'RSD - Dinar serbe',
'The budget line have been created successfully.' => 'La ligne de budgétaire a été créee avec succès.',
'Unable to create the budget line.' => 'Impossible de créer cette ligne budgétaire.',
'Unable to remove this budget line.' => 'Impossible de supprimer cette ligne budgétaire.',
'USD - US Dollar' => 'USD - Dollar américain',
'Remaining' => 'Restant',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -1,6 +1,8 @@
<?php
return array(
// 'number.decimals_separator' => '',
// 'number.thousands_separator' => '',
'None' => 'Geen',
'edit' => 'bewerken',
'Edit' => 'Bewerken',
@ -375,7 +377,7 @@ return array(
'Unable to unlink your GitHub Account.' => 'Verwijdern van de link met uw Github Account niet gelukt.',
'Login with my GitHub Account' => 'Login met mijn Github Account',
'Link my GitHub Account' => 'Link met mijn Github',
'Unlink my GitHub Account' => 'Link met mijn Github verwijderen',
'Unlink my GitHub Account' => 'Link met mijn Github verwijderen',
'Created by %s' => 'Aangemaakt door %s',
'Last modified on %B %e, %Y at %k:%M %p' => 'Laatst gewijzigd op %d/%m/%Y à %H:%M',
'Tasks Export' => 'Taken exporteren',
@ -410,10 +412,8 @@ return array(
'List of due tasks for the project "%s"' => 'Lijst van taken die binnenkort voltooid moeten worden voor project « %s »',
'New attachment' => 'Nieuwe bijlage',
'New comment' => 'Nieuw commentaar',
'Comment updated' => 'Commentaar aangepast',
'New subtask' => 'Nieuwe subtaak',
'Subtask updated' => 'Subtaak aangepast',
'New task' => 'Nieuwe taak',
'Task updated' => 'Taak aangepast',
'Task closed' => 'Taak gesloten',
'Task opened' => 'Taak geopend',
@ -550,7 +550,7 @@ return array(
'My tasks' => 'Mijn taken',
'Activity stream' => 'Activiteiten',
'Dashboard' => 'Dashboard',
'Bevestiging' => 'Confirmation',
// 'Confirmation' => '',
'Allow everybody to access to this project' => 'Geef iedereen toegang tot dit project',
'Everybody have access to this project.' => 'Iedereen heeft toegang tot dit project.',
'Webhooks' => 'Webhooks',
@ -581,7 +581,7 @@ return array(
'Edit Project' => 'Project aanpassen',
'Github Issue' => 'Github issue',
'Not enough data to show the graph.' => 'Niet genoeg data om de grafiek te laten zien.',
'Vorige' => 'Précédent',
// 'Previous' => '',
'The id must be an integer' => 'Het id moet een integer zijn',
'The project id must be an integer' => 'Het project id moet een integer zijn',
'The status must be an integer' => 'De status moet een integer zijn',
@ -736,4 +736,72 @@ return array(
'Filter recently updated' => 'Filter recent aangepast',
'since %B %e, %Y at %k:%M %p' => 'sinds %d/%m/%Y à %H:%M',
'More filters' => 'Meer filters',
// 'Compact view' => '',
// 'Horizontal scrolling' => '',
// 'Compact/wide view' => '',
// 'No results match:' => '',
// 'Remove hourly rate' => '',
// 'Do you really want to remove this hourly rate?' => '',
// 'Hourly rates' => '',
// 'Hourly rate' => '',
// 'Currency' => '',
// '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' => '',
// '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' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -1,6 +1,8 @@
<?php
return array(
// 'number.decimals_separator' => '',
// 'number.thousands_separator' => '',
'None' => 'None',
'edit' => 'izmeni',
'Edit' => 'Izmeni',
@ -527,9 +529,9 @@ return array(
'Refresh interval for private board' => 'Interval osvežavanja privatnih tabli',
'Refresh interval for public board' => 'Interval osvežavanja javnih tabli',
'Task highlight period' => 'Task highlight period',
// 'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => 'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)',
// 'Frequency in second (60 seconds by default)' => 'Częstotliwosć w sekundach (domyślnie 60 sekund)',
// 'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Częstotliwość w sekundach (0 aby zablokować, domyślnie 10 sekund)',
// 'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => '',
// 'Frequency in second (60 seconds by default)' => '',
// 'Frequency in second (0 to disable this feature, 10 seconds by default)' => '',
'Application URL' => 'Adres URL aplikacji',
'Example: http://example.kanboard.net/ (used by email notifications)' => 'Primer: http://example.kanboard.net/ (koristi se u obaveštenjima putem mail-a)',
'Token regenerated.' => 'Token wygenerowany ponownie.',
@ -556,7 +558,7 @@ return array(
'Integration' => 'Integracja',
// 'Github webhooks' => '',
// 'Help on Github webhooks' => '',
// 'Create a comment from an external provider' => 'Kreiraj komentarz od zewnętrznego dostawcy',
// 'Create a comment from an external provider' => '',
// 'Github issue comment created' => '',
'Configure' => 'Podesi',
'Project management' => 'Uređivanje projekata',
@ -597,7 +599,7 @@ return array(
'Daily project summary export' => 'Izvoz zbirnog pregleda po danima',
'Daily project summary export for "%s"' => 'Izvoz zbirnig pregleda po danima za "%s"',
'Exports' => 'Izvoz',
// 'This export contains the number of tasks per column grouped per day.' => 'Ten eksport zawiera ilość zadań zgrupowanych w kolumnach na dzień',
// 'This export contains the number of tasks per column grouped per day.' => '',
'Nothing to preview...' => 'Ništa za prikazivanje...',
'Preview' => 'Pregled',
'Write' => 'Piši',
@ -617,10 +619,10 @@ return array(
'Swimlane removed successfully.' => 'Razdelnik uspešno uklonjen.',
'Swimlanes' => 'Razdelnici',
'Swimlane updated successfully.' => 'Razdelnik zaktualizowany pomyślnie.',
// 'The default swimlane have been updated successfully.' => 'Domyślny razdelnik zaktualizowany pomyślnie.',
// 'Unable to create your swimlane.' => 'Nie można utworzyć razdelniku.',
// 'Unable to remove this swimlane.' => 'Nie można usunąć razdelniku.',
// 'Unable to update this swimlane.' => 'Nie można zaktualizować razdelniku.',
// 'The default swimlane have been updated successfully.' => '',
// 'Unable to create your swimlane.' => '',
// 'Unable to remove this swimlane.' => '',
// 'Unable to update this swimlane.' => '',
'Your swimlane have been created successfully.' => 'Razdelnik je uspešno kreiran.',
'Example: "Bug, Feature Request, Improvement"' => 'Npr: "Greška, Zahtev za izmenama, Poboljšanje"',
'Default categories for new projects (Comma-separated)' => 'Osnovne kategorije za projekat',
@ -634,7 +636,7 @@ return array(
'Role for this project' => 'Uloga u ovom projektu',
'Project manager' => 'Manadžer projekta',
'Project member' => 'Učesnik projekta',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Menadżer projektu może zmieniać ustawienia projektu i posiada większe uprawnienia od zwykłego użytkownika',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
// 'Gitlab Issue' => '',
'Subtask Id' => 'ID pod-zadania',
'Subtasks' => 'Pod-zadataka',
@ -666,8 +668,8 @@ return array(
// 'Enable time tracking for subtasks' => '',
// 'Select the new status of the subtask: "%s"' => '',
// 'Subtask timesheet' => '',
'There is nothing to show.' => 'Nema podataka',
'Time Tracking' => 'Praćenje vremena',
'There is nothing to show.' => 'Nema podataka',
'Time Tracking' => 'Praćenje vremena',
// 'You already have one subtask in progress' => '',
'Which parts of the project do you want to duplicate?' => 'Koje delove projekta želite da kopirate',
// 'Change dashboard view' => '',
@ -677,7 +679,7 @@ return array(
// 'Show/hide tasks' => '',
// 'Disable login form' => '',
// 'Show/hide calendar' => '',
'Korsički kalendar' => '',
// 'User calendar' => '',
// 'Bitbucket commit received' => '',
// 'Bitbucket webhooks' => '',
// 'Help on Bitbucket webhooks' => '',
@ -686,7 +688,7 @@ return array(
// 'Task age in days' => '',
// 'Days in this column' => '',
// '%dd' => '',
'Add a link' => 'Dodaj link',
'Add a link' => 'Dodaj link',
// 'Add a new link' => '',
// 'Do you really want to remove this link: "%s"?' => '',
// 'Do you really want to remove this link with task #%d?' => '',
@ -734,4 +736,72 @@ return array(
// 'Filter recently updated' => '',
// 'since %B %e, %Y at %k:%M %p' => '',
// 'More filters' => '',
// 'Compact view' => '',
// 'Horizontal scrolling' => '',
// 'Compact/wide view' => '',
// 'No results match:' => '',
// 'Remove hourly rate' => '',
// 'Do you really want to remove this hourly rate?' => '',
// 'Hourly rates' => '',
// 'Hourly rate' => '',
// 'Currency' => '',
// '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' => '',
// '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' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -775,4 +775,33 @@ return array(
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
// 'Files' => '',
// 'Images' => '',
// 'Private project' => '',
// 'Amount' => '',
// 'AUD - Australian Dollar' => '',
// 'Budget' => '',
// 'Budget line' => '',
// 'Budget line removed successfully.' => '',
// 'Budget lines' => '',
// 'CAD - Canadian Dollar' => '',
// 'CHF - Swiss Francs' => '',
// 'Cost' => '',
// 'Cost breakdown' => '',
// 'Custom Stylesheet' => '',
// 'download' => '',
// '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' => '',
);

View File

@ -2,6 +2,8 @@
namespace Model;
use DateInterval;
use DateTime;
use SimpleValidator\Validator;
use SimpleValidator\Validators;
@ -52,7 +54,7 @@ class Budget extends Base
* @param integer $project_id
* @return \PicoDb\Table
*/
public function getBreakdown($project_id)
public function getSubtaskBreakdown($project_id)
{
return $this->db
->table(SubtaskTimeTracking::TABLE)
@ -76,6 +78,53 @@ class Budget extends Base
->filter(array($this, 'applyUserRate'));
}
/**
* Gather necessary information to display the budget graph
*
* @access public
* @param integer $project_id
* @return array
*/
public function getDailyBudgetBreakdown($project_id)
{
$out = array();
$in = $this->db->hashtable(self::TABLE)->eq('project_id', $project_id)->gt('amount', 0)->asc('date')->getAll('date', 'amount');
$time_slots = $this->getSubtaskBreakdown($project_id)->findAll();
foreach ($time_slots as $slot) {
$date = date('Y-m-d', $slot['start']);
if (! isset($out[$date])) {
$out[$date] = 0;
}
$out[$date] += $slot['cost'];
}
$start = key($in) ?: key($out);
$end = new DateTime;
$left = 0;
$serie = array();
for ($today = new DateTime($start); $today <= $end; $today->add(new DateInterval('P1D'))) {
$date = $today->format('Y-m-d');
$today_in = isset($in[$date]) ? (int) $in[$date] : 0;
$today_out = isset($out[$date]) ? (int) $out[$date] : 0;
$left += $today_in;
$left -= $today_out;
$serie[] = array(
'date' => $date,
'in' => $today_in,
'out' => -$today_out,
'left' => $left,
);
}
return $serie;
}
/**
* Filter callback to apply the rate according to the effective date
*

View File

@ -1,5 +1,5 @@
<?= $this->js('assets/js/vendor/d3.v3.4.8.min.js') ?>
<?= $this->js('assets/js/vendor/dimple.v2.1.0.min.js') ?>
<?= $this->js('assets/js/vendor/dimple.v2.1.2.min.js') ?>
<section id="main">
<div class="page-header">

View File

@ -47,6 +47,10 @@
<i class="fa fa-line-chart fa-fw"></i>
<?= $this->a(t('Analytics'), 'analytic', 'tasks', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-pie-chart fa-fw"></i>
<?= $this->a(t('Budget'), 'budget', 'index', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-cog fa-fw"></i>
<?= $this->a(t('Configure'), 'project', 'show', array('project_id' => $project['id'])) ?>

View File

@ -1,3 +1,6 @@
<?= $this->js('assets/js/vendor/d3.v3.4.8.min.js') ?>
<?= $this->js('assets/js/vendor/dimple.v2.1.2.min.js') ?>
<div class="page-header">
<h2><?= t('Budget') ?></h2>
<ul>
@ -6,4 +9,27 @@
</ul>
</div>
<p><?= t('Current budget: ') ?><strong><?= n($total) ?></strong></p>
<?php if (! empty($daily_budget)): ?>
<div id="budget-chart">
<div id="chart"
data-serie='<?= json_encode($daily_budget) ?>'
data-labels='<?= json_encode(array('in' => t('Budget line'), 'out' => t('Expenses'), 'left' => t('Remaining'), 'value' => t('Amount'), 'date' => t('Date'), 'type' => t('Type'))) ?>'></div>
</div>
<hr/>
<table class="table-fixed table-stripped">
<tr>
<th><?= t('Date') ?></td>
<th><?= t('Budget line') ?></td>
<th><?= t('Expenses') ?></td>
<th><?= t('Remaining') ?></td>
</tr>
<?php foreach ($daily_budget as $line): ?>
<tr>
<td><?= $this->e($line['date']) ?></td>
<td><?= n($line['in']) ?></td>
<td><?= n($line['out']) ?></td>
<td><?= n($line['left']) ?></td>
</tr>
<?php endforeach ?>
</table>
<?php endif ?>

File diff suppressed because one or more lines are too long

38
assets/js/src/budget.js Normal file
View File

@ -0,0 +1,38 @@
Kanboard.Budget = (function() {
jQuery(document).ready(function() {
if (Kanboard.Exists("budget-chart")) {
var labels =$("#chart").data("labels");
var serie = $("#chart").data("serie");
var types = ["in", "out", "left"];
var data = [];
for (var i = 0; i < serie.length; i++) {
for (var j = 0; j < types.length; j++) {
var row = {};
row[labels["date"]] = serie[i]["date"];
row[labels["value"]] = serie[i][types[j]];
row[labels["type"]] = labels[types[j]];
data.push(row);
}
}
var svg = dimple.newSvg("#chart", 750, 600);
var myChart = new dimple.chart(svg, data);
var x = myChart.addCategoryAxis("x", [labels["date"], labels["type"]]);
x.addOrderRule(labels["date"]);
myChart.addMeasureAxis("y", labels["value"]);
myChart.addSeries(labels["type"], dimple.plot.bar);
myChart.addLegend(65, 10, 510, 20, "right");
myChart.draw();
}
});
})();

0
assets/js/vendor/chosen.jquery.min.js vendored Executable file → Normal file
View File

File diff suppressed because one or more lines are too long

3
assets/js/vendor/dimple.v2.1.2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

0
assets/js/vendor/jquery-ui.min.js vendored Executable file → Normal file
View File

View File

@ -3,7 +3,7 @@
app_css="base links title table form button alert tooltip header board task comment subtask markdown listing activity dashboard pagination popover confirm sidebar responsive dropdown"
vendor_css="jquery-ui.min chosen.min fullcalendar.min font-awesome.min"
app_js="base board calendar analytic swimlane dashboard"
app_js="base board calendar analytic swimlane dashboard budget"
vendor_js="jquery-1.11.1.min jquery-ui.min jquery.ui.touch-punch.min chosen.jquery.min dropit.min moment.min fullcalendar.min mousetrap.min mousetrap-global-bind.min app.min"
lang_js="da de es fi fr hu it ja pl pt-br ru sv th zh-cn tr"