- fixed group by for mysql mode - only user can edit own prefs - updated installation README - pagerfanta shows less links - improved manual tab - moved user profile link to pref tabs - added menu links to top navbar - moved page actions to breadcrumb position - integrated daterangepicker and improved toolbar forms - bugfix for time rounding
This commit is contained in:
32
README.md
32
README.md
@@ -36,6 +36,10 @@ Lets prepare the environment by installing all dependencies:
|
||||
composer install
|
||||
```
|
||||
|
||||
The next steps depend on where you want to use Kimai, you can choose between development or production mdoe.
|
||||
|
||||
### Installation (development)
|
||||
|
||||
The default installation uses a SQLite database, so there is no need to create a database for your first tests.
|
||||
The default settings will work out-of-the-box, but you might want to adjust the `.env` values to your needs.
|
||||
You can configure your database through your environment (e.g. Webserver, Cloud-Provider) or in your `.env` file:
|
||||
@@ -52,15 +56,7 @@ bin/console doctrine:database:create
|
||||
bin/console doctrine:schema:create
|
||||
```
|
||||
|
||||
To generate the frontend assets ([more information here](var/docs/developers.md)), execute:
|
||||
```bash
|
||||
yarn install
|
||||
npm run prod
|
||||
```
|
||||
|
||||
### Installation (development / demo)
|
||||
|
||||
Lets boostrap your environment by executing this commands (which is only available in dev environment):
|
||||
Lets bootstrap your environment by executing this commands (which is only available in dev environment):
|
||||
```bash
|
||||
bin/console kimai:reset-dev
|
||||
```
|
||||
@@ -98,8 +94,19 @@ bin/console server:run
|
||||
This command will start a web server for Kimai. Now you can access the application in your browser at <http://127.0.0.1:8000/>.
|
||||
You can stop the built-in web server by pressing `Ctrl + C` while you're in the terminal.
|
||||
|
||||
To re-generate the frontend assets ([more information here](var/docs/developers.md)), execute:
|
||||
```bash
|
||||
yarn install
|
||||
npm run prod
|
||||
```
|
||||
|
||||
### Installation (live)
|
||||
### Installation (production)
|
||||
|
||||
Make sure the [directories are read and writable by your webserver](https://symfony.com/doc/current/setup/file_permissions.html):
|
||||
```bash
|
||||
chown -R www-data var/
|
||||
chmod -R 777 var/
|
||||
```
|
||||
|
||||
The database to use is up to you, but we would not recommend using the default SQLite database for production usage.
|
||||
Please create your database and configure the connection string in your environment, e.g. with the `.env` file:
|
||||
@@ -109,10 +116,10 @@ DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
|
||||
APP_SECRET=insert_a_random_secret_string_for_production
|
||||
```
|
||||
|
||||
Create the database schemas and warm up the cache:
|
||||
Create the database schemas and warm up the cache (as webserver user):
|
||||
```bash
|
||||
bin/console doctrine:schema:create
|
||||
bin/console cache:warmup --env=prod
|
||||
sudo -u www-data bin/console cache:warmup --env=prod
|
||||
```
|
||||
|
||||
Create your first user with the following command. You will be asked to enter a password afterwards.
|
||||
@@ -120,6 +127,7 @@ Create your first user with the following command. You will be asked to enter a
|
||||
```bash
|
||||
bin/console kimai:create-user username admin@example.com ROLE_SUPER_ADMIN
|
||||
```
|
||||
_Tip: You can skip the "create user" step, if you are going to import data from Kimai v1._
|
||||
|
||||
For available roles, please refer to the [user documentation](var/docs/users.md).
|
||||
|
||||
|
||||
@@ -5,10 +5,38 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@import "~bootstrap-sass/assets/stylesheets/bootstrap/variables";
|
||||
|
||||
.error-page {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
/* ================================ CONTENT ================================ */
|
||||
|
||||
.content {
|
||||
padding: 15px 0;
|
||||
}
|
||||
.content-header {
|
||||
h1 {
|
||||
small {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
.content-header {
|
||||
h1 {
|
||||
small {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================ NAVBAR ================================ */
|
||||
|
||||
.navbar-nav>li>a.ddt-large {
|
||||
@@ -16,7 +44,7 @@
|
||||
padding-bottom: 9px;
|
||||
}
|
||||
|
||||
li.messages-menu ul.menu li:hover .pull-left i {
|
||||
li.messages-menu ul.menu li .pull-left i {
|
||||
color: #dd4b39;
|
||||
}
|
||||
|
||||
@@ -53,8 +81,23 @@ li.open .ticktac i.running{
|
||||
|
||||
/* ================================ TOOLBAR ================================ */
|
||||
|
||||
.control-sidebar select {
|
||||
color: #000;
|
||||
@media (max-width: $screen-md-min) {
|
||||
.content-header > .breadcrumb {
|
||||
position: absolute;
|
||||
float: right;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.control-sidebar {
|
||||
select {
|
||||
color: #000;
|
||||
}
|
||||
div.image {
|
||||
img.img-circle {
|
||||
max-width: 34px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.data_table .box-header>.box-tools {
|
||||
@@ -64,10 +107,12 @@ li.open .ticktac i.running{
|
||||
.box-header .box-title.toolbar form {
|
||||
font-size: 13px;
|
||||
}
|
||||
.toolbar form input,
|
||||
.toolbar form select {
|
||||
display: inline-block;
|
||||
width: inherit;
|
||||
@media (min-width: $screen-sm-min) {
|
||||
.toolbar form input,
|
||||
.toolbar form select {
|
||||
display: inline-block;
|
||||
width: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar form .form-group {
|
||||
@@ -105,6 +150,16 @@ footer.main-footer {
|
||||
|
||||
/* ================================ INVOICES ================================ */
|
||||
|
||||
.invoice {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
.invoice {
|
||||
margin: 10px 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.page-header-small{
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -127,13 +182,6 @@ table.invoice-sum th, table.invoice-sum td {
|
||||
|
||||
/* ================================ DATA-TABLES ================================ */
|
||||
|
||||
/*
|
||||
TODO "display:hidden" regel für dataTable - spalten - mobile ansicht
|
||||
TODO "display:hidden" regel für dataTable - header icon - mobile ansicht
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
dataTables.bootstrap.css
|
||||
*/
|
||||
@@ -194,7 +242,6 @@ div.dataTables_paginate ul.pagination {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
table.dataTable td,
|
||||
table.dataTable th {
|
||||
-webkit-box-sizing: content-box;
|
||||
@@ -202,7 +249,6 @@ table.dataTable th {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
|
||||
table.dataTable {
|
||||
clear: both;
|
||||
/*margin-top: 6px !important;
|
||||
@@ -331,9 +377,6 @@ div.dataTables_scrollHead table.table-bordered {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* TableTools styles
|
||||
*/
|
||||
|
||||
@@ -4,3 +4,4 @@ $fa-font-path: "~font-awesome/fonts";
|
||||
|
||||
@import '~bootstrap-sass/assets/stylesheets/bootstrap';
|
||||
@import '~font-awesome/scss/font-awesome';
|
||||
@import '~daterangepicker/daterangepicker.css';
|
||||
|
||||
@@ -7,6 +7,10 @@ require('jquery-ui');
|
||||
require('bootstrap-sass');
|
||||
require('jquery-slimscroll');
|
||||
|
||||
const Moment = require('moment');
|
||||
global.moment = Moment;
|
||||
require('daterangepicker');
|
||||
|
||||
// ------ for charts ------
|
||||
const Chart = require('../../vendor/almasaeed2010/adminlte/plugins/chartjs/Chart.min.js');
|
||||
global.Chart = Chart;
|
||||
|
||||
@@ -36,6 +36,31 @@ $(function() {
|
||||
|
||||
$('.dropdown-toggle').dropdown();
|
||||
|
||||
$('input[data-datepicker="on"]').daterangepicker({
|
||||
singleDatePicker: true,
|
||||
showDropdowns: true,
|
||||
locale: {
|
||||
format: "YYYY-MM-DD",
|
||||
firstDay: 1
|
||||
}
|
||||
});
|
||||
|
||||
$('input[data-datetimepicker="on"]').daterangepicker({
|
||||
singleDatePicker: true,
|
||||
timePicker: true,
|
||||
timePicker24Hour: true,
|
||||
showDropdowns: true,
|
||||
autoUpdateInput: false,
|
||||
locale: {
|
||||
cancelLabel: 'Clear',
|
||||
format: "YYYY-MM-DD HH:mm",
|
||||
firstDay: 1
|
||||
}
|
||||
});
|
||||
$('input[data-datetimepicker="on"]').on('apply.daterangepicker', function(ev, picker) {
|
||||
$(this).val(picker.startDate.format('YYYY-MM-DD HH:mm'));
|
||||
});
|
||||
|
||||
/*
|
||||
$('input').iCheck({
|
||||
checkboxClass: 'icheckbox_square-blue',
|
||||
|
||||
@@ -7,15 +7,16 @@
|
||||
"prod": "node_modules/.bin/encore production"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@symfony/webpack-encore": "git://github.com/symfony/webpack-encore.git#0.17.2",
|
||||
"@symfony/webpack-encore": "^0.20.1",
|
||||
"bootstrap-sass": "^3.3.7",
|
||||
"daterangepicker": "^3.0.3",
|
||||
"font-awesome": "^4.7.0",
|
||||
"icheck": "^1.0.2",
|
||||
"jquery": "^3.3.1",
|
||||
"jquery-slimscroll": "^1.3.8",
|
||||
"jquery-ui": "^1.12.1",
|
||||
"node-sass": "^4.7.2",
|
||||
"sass-loader": "^6.0.6",
|
||||
"node-sass": "^4.9.0",
|
||||
"sass-loader": "^7.0.2",
|
||||
"webpack-notifier": "^1.5.1"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"build/app.css": "/build/app.css?693b17f722072629aa711aa269697f8d",
|
||||
"build/app.js": "/build/app.js?a780ad21736af2959a4d",
|
||||
"build/app.js": "/build/app.js?ce4b9c776d5d7f2b3282",
|
||||
"build/app.css": "/build/app.css?37c3ca7efa95dd916f5e63b1e0efdee8",
|
||||
"build/fonts/fontawesome-webfont.eot": "/build/fonts/fontawesome-webfont.eot?674f50d2",
|
||||
"build/fonts/fontawesome-webfont.ttf?v=4.7.0": "/build/fonts/fontawesome-webfont.ttf?b06871f2",
|
||||
"build/fonts/fontawesome-webfont.woff2?v=4.7.0": "/build/fonts/fontawesome-webfont.woff2?af7ae505",
|
||||
"build/fonts/fontawesome-webfont.woff?v=4.7.0": "/build/fonts/fontawesome-webfont.woff?fee66e71",
|
||||
"build/fonts/glyphicons-halflings-regular.eot": "/build/fonts/glyphicons-halflings-regular.eot?f4769f9b",
|
||||
"build/fonts/glyphicons-halflings-regular.ttf": "/build/fonts/glyphicons-halflings-regular.ttf?e18bbf61",
|
||||
"build/fonts/glyphicons-halflings-regular.woff": "/build/fonts/glyphicons-halflings-regular.woff?fa277232",
|
||||
"build/fonts/glyphicons-halflings-regular.woff2": "/build/fonts/glyphicons-halflings-regular.woff2?448c34a5",
|
||||
"build/images/blue.png": "/build/images/blue.png?96f8a905",
|
||||
"build/images/blue@2x.png": "/build/images/blue@2x.png?2694acfd",
|
||||
"build/images/boxed-bg.jpg": "/build/images/boxed-bg.jpg?7799dece",
|
||||
"build/images/default_avatar.png": "/build/images/default_avatar.png?fc197350",
|
||||
"build/images/blue.png": "/build/images/blue.png?96f8a905",
|
||||
"build/images/glyphicons-halflings-regular.svg": "/build/images/glyphicons-halflings-regular.svg?89889688",
|
||||
"build/fonts/glyphicons-halflings-regular.eot": "/build/fonts/glyphicons-halflings-regular.eot?f4769f9b",
|
||||
"build/images/fontawesome-webfont.svg?v=4.7.0": "/build/images/fontawesome-webfont.svg?912ec66d",
|
||||
"build/images/glyphicons-halflings-regular.svg": "/build/images/glyphicons-halflings-regular.svg?89889688"
|
||||
"build/fonts/fontawesome-webfont.ttf?v=4.7.0": "/build/fonts/fontawesome-webfont.ttf?b06871f2",
|
||||
"build/fonts/glyphicons-halflings-regular.woff2": "/build/fonts/glyphicons-halflings-regular.woff2?448c34a5",
|
||||
"build/images/blue@2x.png": "/build/images/blue@2x.png?2694acfd",
|
||||
"build/fonts/fontawesome-webfont.woff?v=4.7.0": "/build/fonts/fontawesome-webfont.woff?fee66e71",
|
||||
"build/fonts/fontawesome-webfont.woff2?v=4.7.0": "/build/fonts/fontawesome-webfont.woff2?af7ae505",
|
||||
"build/fonts/glyphicons-halflings-regular.woff": "/build/fonts/glyphicons-halflings-regular.woff?fa277232",
|
||||
"build/fonts/glyphicons-halflings-regular.ttf": "/build/fonts/glyphicons-halflings-regular.ttf?e18bbf61",
|
||||
"build/images/default_avatar.png": "/build/images/default_avatar.png?fc197350"
|
||||
}
|
||||
@@ -32,10 +32,13 @@ class SidebarController extends AbstractController
|
||||
*/
|
||||
public function settingsAction()
|
||||
{
|
||||
return $this->render('sidebar/settings.html.twig', []);
|
||||
$user = $this->getUser();
|
||||
|
||||
return $this->render('sidebar/settings.html.twig', [
|
||||
'user' => $user,
|
||||
]);
|
||||
|
||||
/*
|
||||
$user = $this->getUser();
|
||||
|
||||
$form = $this->createForm(UserPreferencesForm::class, $user, [
|
||||
'action' => $this->generateUrl('user_profile_preferences', ['username' => $user->getUsername()]),
|
||||
|
||||
@@ -90,6 +90,8 @@ trait TimesheetControllerTrait
|
||||
$record->setEnd($end);
|
||||
}
|
||||
|
||||
// TODO validate that end is not before begin
|
||||
|
||||
$entityManager = $this->getDoctrine()->getManager();
|
||||
$entityManager->persist($entry);
|
||||
$entityManager->flush();
|
||||
@@ -132,7 +134,9 @@ trait TimesheetControllerTrait
|
||||
}
|
||||
}
|
||||
|
||||
$entityManager = $this->getDoctrine()->getManager();
|
||||
// TODO validate that end is not before begin
|
||||
|
||||
$entityManager = $this->getDoctrine()->getManager();
|
||||
$entityManager->persist($entry);
|
||||
|
||||
$entityManager->flush();
|
||||
|
||||
@@ -42,7 +42,11 @@ class TimesheetEditForm extends AbstractType
|
||||
if ($entry->getEnd() === null || !$options['duration_only']) {
|
||||
$builder->add('begin', DateTimeType::class, [
|
||||
'label' => 'label.begin',
|
||||
'date_widget' => 'single_text',
|
||||
'widget' => 'single_text',
|
||||
'html5' => false,
|
||||
'format' => 'yyyy-MM-dd H:m',
|
||||
'with_seconds' => false,
|
||||
'attr' => ['data-datetimepicker' => 'on'],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -51,8 +55,12 @@ class TimesheetEditForm extends AbstractType
|
||||
} else {
|
||||
$builder->add('end', DateTimeType::class, [
|
||||
'label' => 'label.end',
|
||||
'date_widget' => 'single_text',
|
||||
'widget' => 'single_text',
|
||||
'required' => false,
|
||||
'html5' => false,
|
||||
'format' => 'yyyy-MM-dd H:m',
|
||||
'with_seconds' => false,
|
||||
'attr' => ['data-datetimepicker' => 'on'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,9 @@ abstract class AbstractToolbarForm extends AbstractType
|
||||
$builder->add('begin', DateType::class, [
|
||||
'label' => 'label.begin',
|
||||
'widget' => 'single_text',
|
||||
'html5' => false,
|
||||
'required' => false,
|
||||
'attr' => ['data-datepicker' => 'on'],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -120,7 +122,9 @@ abstract class AbstractToolbarForm extends AbstractType
|
||||
$builder->add('end', DateType::class, [
|
||||
'label' => 'label.end',
|
||||
'widget' => 'single_text',
|
||||
'html5' => false,
|
||||
'required' => false,
|
||||
'attr' => ['data-datepicker' => 'on'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Repository\Query\CustomerQuery;
|
||||
|
||||
/**
|
||||
* Custom form field type to select a customer.
|
||||
|
||||
@@ -41,6 +41,7 @@ class ActivityRepository extends AbstractRepository
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
|
||||
$qb->select('t', 'a', 'p', 'c')
|
||||
->distinct()
|
||||
->from(Timesheet::class, 't')
|
||||
->join('t.activity', 'a')
|
||||
->join('a.project', 'p')
|
||||
@@ -49,7 +50,7 @@ class ActivityRepository extends AbstractRepository
|
||||
->andWhere('a.visible = 1')
|
||||
->andWhere('p.visible = 1')
|
||||
->andWhere('c.visible = 1')
|
||||
->groupBy('a.id')
|
||||
->groupBy('a.id', 't.id')
|
||||
->orderBy('t.end', 'DESC')
|
||||
->setMaxResults(10)
|
||||
;
|
||||
|
||||
@@ -36,8 +36,9 @@ class TimesheetRepository extends AbstractRepository
|
||||
*/
|
||||
public function stopRecording(Timesheet $entry)
|
||||
{
|
||||
// seems to be necessary so Doctrine will recognize a changed timestamp
|
||||
$entry->setBegin(clone $entry->getBegin());
|
||||
$entry->setEnd(new DateTime());
|
||||
|
||||
$entityManager = $this->getEntityManager();
|
||||
$entityManager->persist($entry);
|
||||
$entityManager->flush();
|
||||
|
||||
@@ -72,18 +72,30 @@ class UserVoter extends AbstractVoter
|
||||
return $this->canView($subject, $user, $token);
|
||||
case self::EDIT:
|
||||
case self::PASSWORD:
|
||||
case self::PREFERENCES:
|
||||
return $this->canEdit($subject, $user, $token);
|
||||
case self::DELETE:
|
||||
return $this->canDelete($subject, $user, $token);
|
||||
case self::CREATE: // create actually passes in the current user as $subject, not the new one
|
||||
case self::ROLES:
|
||||
return $this->canAdminUsers($token);
|
||||
case self::PREFERENCES:
|
||||
return $this->canEditPreferences($subject, $user, $token);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $profile
|
||||
* @param User $user
|
||||
* @param TokenInterface $token
|
||||
* @return bool
|
||||
*/
|
||||
protected function canEditPreferences(User $profile, User $user, TokenInterface $token)
|
||||
{
|
||||
return $profile->getId() == $user->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $profile
|
||||
* @param User $user
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
{% block page_title %}{{ 'admin_activity.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'admin_activity.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
|
||||
{% block page_actions %}{{ widgets.page_actions({'plus-square': path('admin_activity_create')}) }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% if entries.count == 0 %}
|
||||
@@ -12,24 +13,24 @@
|
||||
|
||||
{{ tables.data_table_header({
|
||||
'label.name': '',
|
||||
'label.customer': '',
|
||||
'label.customer': 'hidden-xs',
|
||||
'label.project': '',
|
||||
'label.comment': 'hidden-xs',
|
||||
'label.visible': '',
|
||||
'label.visible': 'hidden-xs',
|
||||
'label.actions': '',
|
||||
}, toolbarForm, {'plus-square': path('admin_activity_create')}) }}
|
||||
}, toolbarForm) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr>
|
||||
<td>{{ entry.name }}</td>
|
||||
<td>
|
||||
<td class="hidden-xs">
|
||||
<a href="{{ path('admin_customer_edit', {'id' : entry.project.customer.id}) }}">{{ widgets.label_customer(entry.project.customer) }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ path('admin_project_edit', {'id' : entry.project.id}) }}">{{ widgets.label_project(entry.project) }}</a>
|
||||
</td>
|
||||
<td class="hidden-xs">{{ entry.comment }}</td>
|
||||
<td>{{ widgets.label_visible(entry.visible) }}</td>
|
||||
<td class="hidden-xs">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
<td>
|
||||
{% set actionButtons = {} %}
|
||||
{% if is_granted('edit', entry) %}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
{% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'admin_customer.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
|
||||
{% block page_actions %}{{ widgets.page_actions({'plus-square': path('admin_customer_create')}) }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% if entries.count == 0 %}
|
||||
@@ -17,9 +18,9 @@
|
||||
'label.country': 'hidden-xs',
|
||||
'label.customer_number': 'hidden-xs',
|
||||
'label.currency': 'hidden-xs',
|
||||
'label.visible': '',
|
||||
'label.visible': 'hidden-xs',
|
||||
'label.actions': '',
|
||||
}, toolbarForm, {'plus-square': path('admin_customer_create')}) }}
|
||||
}, toolbarForm) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr>
|
||||
@@ -27,13 +28,14 @@
|
||||
<td>
|
||||
{% for project in entry.projects %}
|
||||
<a href="{{ path('admin_project_edit', {'id' : project.id}) }}">{{ widgets.label_project(project) }}</a>
|
||||
<br class="visible-xs-block">
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="hidden-xs">{{ entry.comment }}</td>
|
||||
<td class="hidden-xs">{{ entry.country|country }}</td>
|
||||
<td class="hidden-xs">{{ entry.number }}</td>
|
||||
<td class="hidden-xs">{{ entry.currency }} {{ entry.currency|currency }}</td>
|
||||
<td>{{ widgets.label_visible(entry.visible) }}</td>
|
||||
<td class="hidden-xs">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
<td>
|
||||
{% set actionButtons = {} %}
|
||||
{% if is_granted('edit', entry) %}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
{% block page_title %}{{ 'admin_project.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'admin_project.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
|
||||
{% block page_actions %}{{ widgets.page_actions({'plus-square': path('admin_project_create')}) }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% if entries.count == 0 %}
|
||||
@@ -15,9 +16,9 @@
|
||||
'label.customer': '',
|
||||
'label.comment': 'hidden-xs hidden-sm',
|
||||
'label.budget': 'hidden-xs',
|
||||
'label.visible': '',
|
||||
'label.visible': 'hidden-xs',
|
||||
'label.actions': '',
|
||||
}, toolbarForm, {'plus-square': path('admin_project_create')}) }}
|
||||
}, toolbarForm) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr>
|
||||
@@ -27,7 +28,7 @@
|
||||
</td>
|
||||
<td class="hidden-xs hidden-sm">{{ entry.comment }}</td>
|
||||
<td class="hidden-xs">{{ entry.budget|money(entry.customer.currency) }}</td>
|
||||
<td>{{ widgets.label_visible(entry.visible) }}</td>
|
||||
<td class="hidden-xs">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
<td>
|
||||
{% set actionButtons = {} %}
|
||||
{% if is_granted('edit', entry) %}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
{% block page_title %}{{ 'admin_timesheet.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'admin_timesheet.subtitle'|trans }}{% endblock %}
|
||||
{% block page_actions %}{{ widgets.page_actions({'plus-square': path('admin_timesheet_create')}) }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% if entries.count == 0 %}
|
||||
@@ -25,7 +26,7 @@
|
||||
'label.actions': '',
|
||||
}) %}
|
||||
|
||||
{{ tables.data_table_header(columns, toolbarForm, {'plus-square': path('admin_timesheet_create')}) }}
|
||||
{{ tables.data_table_header(columns, toolbarForm) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
{% block page_title %}{{ 'admin_user.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'admin_user.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
|
||||
{% block page_actions %}{{ widgets.page_actions({'plus-square': path('admin_user_create')}) }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% if entries.count == 0 %}
|
||||
@@ -19,7 +20,7 @@
|
||||
'label.active': '',
|
||||
'label.roles': '',
|
||||
'label.actions': '',
|
||||
}, toolbarForm, {'plus-square': path('admin_user_create')}) }}
|
||||
}, toolbarForm) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{% extends '@AvanzuAdminTheme/layout/default-layout.html.twig' %}
|
||||
|
||||
{% block avanzu_page_content_class %}{{ parent() }} {% block main_content_class %}{% endblock %}{% endblock %}
|
||||
|
||||
{% block avanzu_page_content_before %}
|
||||
<div class="pad margin no-print">
|
||||
{% block main_before %}{% endblock %}
|
||||
@@ -47,6 +49,21 @@
|
||||
|
||||
{% block avanzu_navbar_messages %}
|
||||
{% if app.user is not null and is_granted('IS_AUTHENTICATED_REMEMBERED') %}
|
||||
{% if is_granted('ROLE_USER') %}
|
||||
<li class="visible-xs-inline-block">
|
||||
<a href="{{ path('timesheet') }}" class="ddt-large">
|
||||
<i class="fa fa-clock-o fa-2x"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if is_granted('ROLE_TEAMLEAD') %}
|
||||
<li class="visible-xs-inline-block">
|
||||
<a href="{{ path('invoice') }}" class="ddt-large">
|
||||
<i class="fa fa-print fa-2x"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% block navbar_extensions %}{% endblock %}
|
||||
{{ render(controller('App\\Controller\\TimesheetController::activeEntriesAction')) }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -58,15 +75,20 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_navbar_toggle %}{{ parent() }}{% endblock %}
|
||||
{% block avanzu_navbar_tasks %}{{ parent() }}{% endblock %}
|
||||
{% block avanzu_navbar_user %}{{ parent() }}{% endblock %}
|
||||
{% block avanzu_navbar_tasks %}{#{ parent() }#}{% endblock %}
|
||||
{% block avanzu_navbar_user %}{#{ parent() }#}{% endblock %}
|
||||
{% block avanzu_navbar_control_sidebar_toggle %}{{ parent() }}{% endblock %}
|
||||
|
||||
{% block avanzu_sidebar_user %}{# right now we simply deactivate that box #}{% endblock %}
|
||||
{% block avanzu_sidebar_search %}{# right now we simply deactivate that box #}{% endblock %}
|
||||
{% block avanzu_sidebar_nav %}{{ parent() }}{% endblock %}
|
||||
|
||||
{% block avanzu_breadcrumb %}{{ parent() }}{% endblock %}
|
||||
{% block avanzu_breadcrumb %}
|
||||
{{ block('page_actions') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_actions %}{% endblock %}
|
||||
|
||||
{% block avanzu_control_sidebar %}{{ parent() }}{% endblock %}
|
||||
|
||||
{% block avanzu_javascripts %}
|
||||
|
||||
@@ -14,18 +14,6 @@
|
||||
<small>{{user.title}}</small>
|
||||
</p>
|
||||
</li>
|
||||
{#
|
||||
<!-- Menu Body -->
|
||||
<li class="user-body">
|
||||
<div class="col-xs-4 text-center">
|
||||
</div>
|
||||
<div class="col-xs-4 text-center">
|
||||
</div>
|
||||
<div class="col-xs-4 text-center">
|
||||
</div>
|
||||
</li>
|
||||
#}
|
||||
<!-- Menu Footer-->
|
||||
<li class="user-footer">
|
||||
<div class="pull-left">
|
||||
<a href="{{ path('user_profile', {'username' : user.username}) }}" class="btn btn-default btn-flat">{{ 'label.user_profile'|trans }}</a>
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
{% block page_title %}{{ 'dashboard.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'dashboard.subtitle'|trans }}{% endblock %}
|
||||
|
||||
{% block main_content_class %}dashboard{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
{% for settings in dashboard_widgets %}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{% set class = ' timepicker' %}
|
||||
{% endif %}
|
||||
{% set class = class ~ ' datepicker' %}
|
||||
{% set attr = attr|merge({'class' : class, 'data-datepickerenable':'on'}) %}
|
||||
{% set attr = attr|merge({'class' : class}) %}
|
||||
{{ block('form_widget_simple') }}
|
||||
{% else %}
|
||||
{% set date_pattern = '<div class="row">' ~ date_pattern ~ '</div>'|raw %}
|
||||
@@ -21,6 +21,5 @@
|
||||
'{{ month }}': form_widget(form.month),
|
||||
'{{ day }}': form_widget(form.day),
|
||||
})|raw }}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
|
||||
{% block page_title %}{{ 'invoice.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'invoice.subtitle'|trans }}{% endblock %}
|
||||
{% block page_actions %}{{ widgets.page_actions({'plus-square': path('admin_invoice_template_create'), 'list': path('admin_invoice_template')}) }}{% endblock %}
|
||||
|
||||
{% block avanzu_page_content_class %}invoice{% endblock %}
|
||||
{% block main_content_class %}invoice{% endblock %}
|
||||
|
||||
{% block main_before %}
|
||||
{{ macro.toolbar(form, {'plus-square': path('admin_invoice_template_create'), 'list': path('admin_invoice_template')}) }}
|
||||
{{ macro.toolbar(form) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block main_after %}
|
||||
|
||||
@@ -48,6 +48,6 @@
|
||||
</div>
|
||||
|
||||
<div class="navigation text-center no-print">
|
||||
{{ pagerfanta(entries, 'twitter_bootstrap3_translated', { routeName: route }) }}
|
||||
{{ pagerfanta(entries, 'twitter_bootstrap3_translated', { proximity: 1, routeName: route }) }}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
|
||||
{% macro page_actions(tools) %}
|
||||
<div class="breadcrumb">
|
||||
<div class="box-tools">
|
||||
<div class="btn-group">
|
||||
{% for icon,url in tools %}
|
||||
<a class="btn btn-default" href="{{ url }}"><i class="fa fa-{{ icon }}"></i></a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro page_header(title) %}
|
||||
<h2 class="page-header">{{ title|trans }}</h2>
|
||||
{% endmacro %}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
{% if entries is not empty %}
|
||||
<li class="dropdown messages-menu">
|
||||
<a href="#" class="dropdown-toggle ddt-large ticktac" data-toggle="dropdown">
|
||||
<i class="fa fa-play-circle fa-2x"></i>
|
||||
{% if entries is not empty %}<span class="label label-{% if entries|length >= kimai_context.active_warning %}danger{% else %}warning{% endif %}">{{ entries|length }}</span>{% endif %}
|
||||
<span class="label label-{% if entries|length >= kimai_context.active_warning %}danger{% else %}warning{% endif %}">{{ entries|length }}</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="header">
|
||||
@@ -35,3 +35,10 @@
|
||||
<li class="footer"><a href="{{ path('timesheet_create') }}">{{ 'timesheet.start'|trans }}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="messages-menu">
|
||||
<a href="{{ path('timesheet_create') }}" class="ddt-large">
|
||||
<i class="fa fa-play-circle fa-2x"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
@@ -1,53 +1,19 @@
|
||||
<h3 class="control-sidebar-heading">{{ 'home.title'|trans({}, 'sidebar') }}</h3>
|
||||
<div class="form-group">
|
||||
{{ 'home.betainfo'|trans({}, 'sidebar')|raw|nl2br }}
|
||||
</div>
|
||||
|
||||
<h3 class="control-sidebar-heading">{{ 'help.title'|trans({}, 'sidebar') }}</h3>
|
||||
<div class="form-group">
|
||||
<a href="{{ path('help') }}" class="btn btn-success">{{ 'help.link'|trans({}, 'sidebar') }}</a>
|
||||
</div>
|
||||
|
||||
<h3 class="control-sidebar-heading">{{ 'about.title'|trans({}, 'sidebar') }}</h3>
|
||||
<div class="form-group">
|
||||
<p>
|
||||
Kimai {{ constant('App\\Constants::VERSION') }}
|
||||
</p>
|
||||
<p>
|
||||
{{ 'made.by.license'|trans({'%kevin%': '<a href="http://www.kevinpapst.de" target="_blank">Kevin Papst</a>', '%simon%': '<a href="https://github.com/simonschaufi" target="_blank">Simon Schaufelberger</a>'}, 'sidebar')|raw }}
|
||||
</p>
|
||||
<p>
|
||||
{{ 'github.link'|trans({'%url%': constant('App\\Constants::GITHUB')}, 'sidebar')|raw }}
|
||||
</p>
|
||||
</div>
|
||||
{#
|
||||
<ul class="control-sidebar-menu">
|
||||
<li>
|
||||
<a href="javascript:;">
|
||||
<i class="menu-icon fa fa-birthday-cake bg-red"></i>
|
||||
<a href="{{ path('help') }}">
|
||||
<i class="menu-icon fa fa-book bg-yellow"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'Kevin\'s Birthday'|trans({}, 'AvanzuAdminTheme') }}</h4>
|
||||
|
||||
<p>{{ 'Will be 23 on April 24th'|trans({}, 'AvanzuAdminTheme') }}</p>
|
||||
<h4 class="control-sidebar-subheading">{{ 'help.title'|trans({}, 'sidebar') }}</h4>
|
||||
<p>{{ 'help.subtitle'|trans({}, 'sidebar') }}</p>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="control-sidebar-heading">{{ 'Tasks Progress'|trans({}, 'AvanzuAdminTheme') }}</h3>
|
||||
<ul class="control-sidebar-menu">
|
||||
<li>
|
||||
<a href="javascript::;">
|
||||
<h4 class="control-sidebar-subheading">
|
||||
{{ 'Custom Template Design'|trans({}, 'AvanzuAdminTheme') }}
|
||||
<span class="label label-danger pull-right">70%</span>
|
||||
</h4>
|
||||
|
||||
<div class="progress progress-xxs">
|
||||
<div class="progress-bar progress-bar-danger" style="width: 70%"></div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
#}
|
||||
<h3 class="control-sidebar-heading">{{ 'home.title'|trans({}, 'sidebar') }}</h3>
|
||||
<div class="form-group">
|
||||
{{ 'home.betainfo'|trans({'%version%': constant('App\\Constants::VERSION'), '%url%': constant('App\\Constants::GITHUB')}, 'sidebar')|raw|nl2br }}
|
||||
<br>
|
||||
<a href="{{ constant('App\\Constants::GITHUB') }}graphs/contributors">{{ 'made.by.license'|trans({}, 'sidebar')|raw }}</a>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
{% import "@AvanzuAdminTheme/layout/macros.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
|
||||
<ul class="control-sidebar-menu">
|
||||
<li>
|
||||
<a href="{{ path('user_profile', {'username' : user.username}) }}">
|
||||
<div class="pull-left image">
|
||||
{{ macro.avatar(user.avatar, user.username, 'img-circle') }}
|
||||
</div>
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ widgets.username(user) }}</h4>
|
||||
<p>{{ user.title }}</p>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 class="control-sidebar-heading">{{ 'preferences.title'|trans({}, 'sidebar') }}</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-sidebar-subheading">
|
||||
{{ 'preferences.label.language'|trans({}, 'sidebar') }}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
{% block page_title %}{{ 'timesheet.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'timesheet.subtitle'|trans }}{% endblock %}
|
||||
{% block page_actions %}{{ widgets.page_actions({'plus-square': path('timesheet_create')}) }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
@@ -25,7 +26,7 @@
|
||||
'label.actions': '',
|
||||
}) %}
|
||||
|
||||
{{ tables.data_table_header(columns, toolbarForm, {'plus-square': path('timesheet_create')}) }}
|
||||
{{ tables.data_table_header(columns, toolbarForm) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr>
|
||||
|
||||
@@ -569,7 +569,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="stats.durationTotal">
|
||||
<source>stats.durationTotal</source>
|
||||
<target>Working hourstotal</target>
|
||||
<target>Working hours total</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="stats.amountTotal">
|
||||
<source>stats.amountTotal</source>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<body>
|
||||
<trans-unit id="previous">
|
||||
<source>previous</source>
|
||||
<target>Vorherige</target>
|
||||
<target></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="next">
|
||||
<source>next</source>
|
||||
<target>Nächste</target>
|
||||
<target></target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<body>
|
||||
<trans-unit id="previous">
|
||||
<source>previous</source>
|
||||
<target>Previous</target>
|
||||
<target></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="next">
|
||||
<source>next</source>
|
||||
<target>Next</target>
|
||||
<target></target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<body>
|
||||
<trans-unit id="previous">
|
||||
<source>previous</source>
|
||||
<target>Предыдущая</target>
|
||||
<target></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="next">
|
||||
<source>next</source>
|
||||
<target>Следующая</target>
|
||||
<target></target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -8,32 +8,24 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="home.betainfo">
|
||||
<source>home.betainfo</source>
|
||||
<target><![CDATA[Danke für die Nutzung der Open-Source Zeiterfassung <strong>Kimai</strong>.
|
||||
<target><![CDATA[Danke für die Nutzung der Open-Source Zeiterfassung <a href="%url%" target="_blank">Kimai</a>.
|
||||
|
||||
Diese neue Version 2 ist aktuell noch in einer frühen Phase der Entwicklung und wurde vorab veröffentlicht, um frühzeitig Rückmeldungen ihrer Benutzer zu sammeln und deren Ideen in die weitere Planung zu integrieren.
|
||||
Diese neue Version %version% ist aktuell noch in einer frühen Phase der Entwicklung und wurde vorab veröffentlicht, um frühzeitig Rückmeldungen ihrer Benutzer zu sammeln und deren Ideen in die weitere Planung zu integrieren.
|
||||
|
||||
Um bei der Verbesserung von <strong>Kimai</strong> zu helfen, schicken Sie mir bitte eine Nachricht auf der verlinkten Webseite. Egal ob Fragen, Fehlermeldungen oder Ideen für Erweiterungen, Ihr Feedback ist wertvoll!
|
||||
]]></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="made.by.license">
|
||||
<source>made.by.license</source>
|
||||
<target>Mit ♥ entwickelt von %kevin% und %simon%.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="github.link">
|
||||
<source>github.link</source>
|
||||
<target><![CDATA[Weitere Informationen finden Sie auf der <a href="%url%" target="_blank">Kimai Homepage</a>.]]></target>
|
||||
<target>Mit ♥ entwickelt von tollen Mitwirkenden</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="help.title">
|
||||
<source>help.title</source>
|
||||
<target>Dokumentation</target>
|
||||
<target>Bedienungsanleitung</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="help.link">
|
||||
<source>help.link</source>
|
||||
<target>Benutzer Handbuch</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="about.title">
|
||||
<source>about.title</source>
|
||||
<target>Über Kimai</target>
|
||||
<source>help.subtitle</source>
|
||||
<target>Anzeigen (nur englisch)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="preferences.title">
|
||||
<source>preferences.title</source>
|
||||
|
||||
@@ -8,32 +8,24 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="home.betainfo">
|
||||
<source>home.betainfo</source>
|
||||
<target><![CDATA[Thank you for using the open source time-tracker <strong>Kimai</strong>.
|
||||
<target><![CDATA[Thank you for using the open source time-tracker <a href="%url%" target="_blank">Kimai</a>.
|
||||
|
||||
This new version 2 is currently in an early stage of development and has been published in advance to collect feedback from its users and integrate their ideas into further planning.
|
||||
This new version %version% is currently in an early stage of development and has been published in advance to collect feedback from its users and integrate their ideas into further planning.
|
||||
|
||||
To help me improve <strong>Kimai</strong>, please send your message on the linked website. Whether you have questions, error messages or ideas for enhancements, your feedback is valuable!
|
||||
]]></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="made.by.license">
|
||||
<source>made.by.license</source>
|
||||
<target><![CDATA[Made with ♥ by %kevin% and %simon%.]]></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="github.link">
|
||||
<source>github.link</source>
|
||||
<target><![CDATA[Further information can be found on the <a href="%url%" target="_blank">Kimai Homepage</a>.]]></target>
|
||||
<target>Made with ♥ by great contributors</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="help.title">
|
||||
<source>help.title</source>
|
||||
<target>Documentation</target>
|
||||
<target>Manual</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="help.link">
|
||||
<source>help.link</source>
|
||||
<target>User manual</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="about.title">
|
||||
<source>about.title</source>
|
||||
<target>About Kimai</target>
|
||||
<source>help.subtitle</source>
|
||||
<target>Show documentation</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="preferences.title">
|
||||
<source>preferences.title</source>
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="home.betainfo">
|
||||
<source>home.betainfo</source>
|
||||
<target><![CDATA[Спасибо за использование open source Программы для учета времени <strong>Kimai</strong>.
|
||||
<target><![CDATA[Спасибо за использование open source Программы для учета времени <a href="%url%" target="_blank">Kimai</a>.
|
||||
|
||||
Данная "Версия 2" пока еще находится на ранней стадии ее разработки. Она была выпущена с целью получения ранних отзывов от пользователей и их последующего учета при дальнейшем планировании функций.
|
||||
Данная "Версия %version%" пока еще находится на ранней стадии ее разработки. Она была выпущена с целью получения ранних отзывов от пользователей и их последующего учета при дальнейшем планировании функций.
|
||||
|
||||
Для помощи в усовершенствовании <strong>Kimai</strong>, пожалуйства, отправляйте свои сообщения на страницу под ссылкой. Приветствуются любые вопросы, идеи по разработке, в частности на тему развернутых функциий, а также сообщения об ошибках. Нам очень важна любая обратная связь от Вас!
|
||||
|
||||
|
||||
Reference in New Issue
Block a user