added controller to render markdown documentation #129
This commit is contained in:
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -6,8 +6,9 @@
|
|||||||
- [ ] New feature (non-breaking change which adds functionality)
|
- [ ] New feature (non-breaking change which adds functionality)
|
||||||
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||||
|
|
||||||
## Checklist:
|
## Checklist
|
||||||
- [ ] My code follows the code style
|
- [ ] My code follows the code style
|
||||||
- [ ] All methods have a docheader with type declarations
|
- [ ] All files have a license header
|
||||||
- [ ] I have updated the documentation accordingly.
|
- [ ] All methods have a doc header with type declarations
|
||||||
- [ ] I have added tests to cover my changes.
|
- [ ] I have updated the documentation accordingly
|
||||||
|
- [ ] I have added tests to cover my changes
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,7 +6,7 @@
|
|||||||
/bin/*
|
/bin/*
|
||||||
!bin/console
|
!bin/console
|
||||||
|
|
||||||
/var/data/*.sqlite
|
/var/data/kimai.sqlite
|
||||||
|
|
||||||
/var/cache/*
|
/var/cache/*
|
||||||
!var/cache/.gitkeep
|
!var/cache/.gitkeep
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"avanzu/admin-theme-bundle": "dev-kevinpapst",
|
"avanzu/admin-theme-bundle": "dev-kevinpapst",
|
||||||
"beberlei/DoctrineExtensions": "^1.0",
|
"beberlei/DoctrineExtensions": "^1.0",
|
||||||
"dama/doctrine-test-bundle": "^4.0",
|
"dama/doctrine-test-bundle": "^4.0",
|
||||||
|
"erusev/parsedown": "^1.6",
|
||||||
"sensio/framework-extra-bundle": "^5.1",
|
"sensio/framework-extra-bundle": "^5.1",
|
||||||
"symfony/asset": "^4.0",
|
"symfony/asset": "^4.0",
|
||||||
"symfony/console": "^4.0",
|
"symfony/console": "^4.0",
|
||||||
@@ -38,6 +39,7 @@
|
|||||||
"phpunit/phpunit": "^6.5",
|
"phpunit/phpunit": "^6.5",
|
||||||
"squizlabs/php_codesniffer": "^3.2",
|
"squizlabs/php_codesniffer": "^3.2",
|
||||||
"symfony/browser-kit": "^4.0",
|
"symfony/browser-kit": "^4.0",
|
||||||
|
"symfony/css-selector": "^4.0",
|
||||||
"symfony/debug-pack": "^1.0",
|
"symfony/debug-pack": "^1.0",
|
||||||
"symfony/dotenv": "^4.0",
|
"symfony/dotenv": "^4.0",
|
||||||
"symfony/maker-bundle": "^1.0",
|
"symfony/maker-bundle": "^1.0",
|
||||||
|
|||||||
100
composer.lock
generated
100
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "53194682429edad5d07d635bbb0cb5e0",
|
"content-hash": "e61ba50d155aed4f2355ddcfa87b6448",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "almasaeed2010/adminlte",
|
"name": "almasaeed2010/adminlte",
|
||||||
@@ -1207,6 +1207,51 @@
|
|||||||
],
|
],
|
||||||
"time": "2017-11-15T23:40:40+00:00"
|
"time": "2017-11-15T23:40:40+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "erusev/parsedown",
|
||||||
|
"version": "1.6.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/erusev/parsedown.git",
|
||||||
|
"reference": "fbe3fe878f4fe69048bb8a52783a09802004f548"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/erusev/parsedown/zipball/fbe3fe878f4fe69048bb8a52783a09802004f548",
|
||||||
|
"reference": "fbe3fe878f4fe69048bb8a52783a09802004f548",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.8.35"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Parsedown": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Emanuil Rusev",
|
||||||
|
"email": "hello@erusev.com",
|
||||||
|
"homepage": "http://erusev.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Parser for Markdown.",
|
||||||
|
"homepage": "http://parsedown.org",
|
||||||
|
"keywords": [
|
||||||
|
"markdown",
|
||||||
|
"parser"
|
||||||
|
],
|
||||||
|
"time": "2017-11-14T20:44:03+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "jdorn/sql-formatter",
|
"name": "jdorn/sql-formatter",
|
||||||
"version": "v1.2.17",
|
"version": "v1.2.17",
|
||||||
@@ -6681,6 +6726,59 @@
|
|||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-01-03T07:38:00+00:00"
|
"time": "2018-01-03T07:38:00+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/css-selector",
|
||||||
|
"version": "v4.0.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/css-selector.git",
|
||||||
|
"reference": "f97600434e3141ef3cbb9ea42cf500fba88022b7"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/css-selector/zipball/f97600434e3141ef3cbb9ea42cf500fba88022b7",
|
||||||
|
"reference": "f97600434e3141ef3cbb9ea42cf500fba88022b7",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.1.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "4.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\CssSelector\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Jean-François Simon",
|
||||||
|
"email": "jeanfrancois.simon@sensiolabs.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony CssSelector Component",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"time": "2018-01-03T07:38:00+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/debug-bundle",
|
"name": "symfony/debug-bundle",
|
||||||
"version": "v4.0.3",
|
"version": "v4.0.3",
|
||||||
|
|||||||
11
config/packages/test/security.yaml
Normal file
11
config/packages/test/security.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# this configuration simplifies testing URLs protected by the security mechanism
|
||||||
|
# See https://symfony.com/doc/current/cookbook/testing/http_authentication.html
|
||||||
|
security:
|
||||||
|
encoders:
|
||||||
|
# to make tests much faster, BCrypt cost is changed to its minimum allowed value (4)
|
||||||
|
# See https://symfony.com/doc/current/reference/configuration/security.html#using-the-bcrypt-password-encoder
|
||||||
|
App\Entity\User: { algorithm: bcrypt, cost: 4 }
|
||||||
|
|
||||||
|
firewalls:
|
||||||
|
secured_area:
|
||||||
|
http_basic: ~
|
||||||
25
src/Constants.php
Normal file
25
src/Constants.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some very global constants for Kimai.
|
||||||
|
*/
|
||||||
|
class Constants
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Currently only used for informational purpose in the footer
|
||||||
|
*/
|
||||||
|
const VERSION = '2.0 dev';
|
||||||
|
/**
|
||||||
|
* Used in multiple views
|
||||||
|
*/
|
||||||
|
const GITHUB = 'https://github.com/kevinpapst/kimai2/';
|
||||||
|
}
|
||||||
83
src/Controller/HelpController.php
Normal file
83
src/Controller/HelpController.php
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Constants;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This controller can render the markdown documentation from /var/docs/
|
||||||
|
*
|
||||||
|
* @Route("/help")
|
||||||
|
* @Security("has_role('ROLE_USER')")
|
||||||
|
*/
|
||||||
|
class HelpController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
const README = 'README';
|
||||||
|
const DOCS_DIR = 'var/docs/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $projectDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HelpController constructor.
|
||||||
|
* @param string $projectDirectory
|
||||||
|
*/
|
||||||
|
public function __construct(string $projectDirectory)
|
||||||
|
{
|
||||||
|
$this->projectDirectory = $projectDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/", defaults={"chapter": "README"}, name="help")
|
||||||
|
* @Route("/{chapter}", requirements={"chapter": "[a-zA-Z]*"}, name="help_chapter")
|
||||||
|
* @Method("GET")
|
||||||
|
*
|
||||||
|
* @param string $chapter
|
||||||
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
public function indexAction(?string $chapter)
|
||||||
|
{
|
||||||
|
$breadcrumb = [self::README];
|
||||||
|
if ($chapter !== self::README) {
|
||||||
|
$breadcrumb[] = $chapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
$chapterFile = $this->getFilenameForChapter($chapter);
|
||||||
|
|
||||||
|
if (!file_exists($chapterFile)) {
|
||||||
|
throw $this->createNotFoundException('Documentation chapter not found: ' . $chapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = file_get_contents($chapterFile);
|
||||||
|
|
||||||
|
return $this->render('help/index.html.twig', [
|
||||||
|
'breadcrumb' => $breadcrumb,
|
||||||
|
'chapter' => $chapter,
|
||||||
|
'documentation' => $content,
|
||||||
|
'github' => Constants::GITHUB
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $chapter
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getFilenameForChapter(string $chapter)
|
||||||
|
{
|
||||||
|
return $this->projectDirectory . DIRECTORY_SEPARATOR . self::DOCS_DIR . $chapter . '.md';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,10 @@ class AppFixtures extends Fixture
|
|||||||
use FixturesTrait;
|
use FixturesTrait;
|
||||||
|
|
||||||
const DEFAULT_PASSWORD = 'kitten';
|
const DEFAULT_PASSWORD = 'kitten';
|
||||||
|
const USERNAME_USER = 'john_user';
|
||||||
|
const USERNAME_TEAMLEAD = 'tony_teamlead';
|
||||||
|
const USERNAME_ADMIN = 'anna_admin';
|
||||||
|
const USERNAME_SUPER_ADMIN = 'susan_super';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var UserPasswordEncoderInterface
|
* @var UserPasswordEncoderInterface
|
||||||
@@ -93,7 +97,7 @@ class AppFixtures extends Fixture
|
|||||||
'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=monsterid&f=y', true
|
'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=monsterid&f=y', true
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'John Doe', 'Developer', 'john_user', 'john_user@example.com', 'ROLE_USER',
|
'John Doe', 'Developer', self::USERNAME_USER, 'john_user@example.com', 'ROLE_USER',
|
||||||
'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=retro&f=y', true
|
'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=retro&f=y', true
|
||||||
],
|
],
|
||||||
// inactive user to test login
|
// inactive user to test login
|
||||||
@@ -102,16 +106,16 @@ class AppFixtures extends Fixture
|
|||||||
'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=retro&f=y', false
|
'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=retro&f=y', false
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'Tony Maier', 'Head of Development', 'tony_teamlead', 'tony_teamlead@example.com', 'ROLE_TEAMLEAD',
|
'Tony Maier', 'Head of Development', self::USERNAME_TEAMLEAD, 'tony_teamlead@example.com', 'ROLE_TEAMLEAD',
|
||||||
'https://en.gravatar.com/userimage/3533186/bf2163b1dd23f3107a028af0195624e9.jpeg', true
|
'https://en.gravatar.com/userimage/3533186/bf2163b1dd23f3107a028af0195624e9.jpeg', true
|
||||||
],
|
],
|
||||||
// no avatar to test default image macro
|
// no avatar to test default image macro
|
||||||
[
|
[
|
||||||
'Anna Smith', 'Administrator', 'anna_admin', 'anna_admin@example.com', 'ROLE_ADMIN', null, true
|
'Anna Smith', 'Administrator', self::USERNAME_ADMIN, 'anna_admin@example.com', 'ROLE_ADMIN', null, true
|
||||||
],
|
],
|
||||||
// no alias to test twig username macro
|
// no alias to test twig username macro
|
||||||
[
|
[
|
||||||
null, 'Super Administrator', 'susan_super', 'susan_super@example.com', 'ROLE_SUPER_ADMIN',
|
null, 'Super Administrator', self::USERNAME_SUPER_ADMIN, 'susan_super@example.com', 'ROLE_SUPER_ADMIN',
|
||||||
'/bundles/avanzuadmintheme/img/avatar.png', true
|
'/bundles/avanzuadmintheme/img/avatar.png', true
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace App\Twig;
|
|||||||
|
|
||||||
use Symfony\Component\Intl\Intl;
|
use Symfony\Component\Intl\Intl;
|
||||||
use App\Entity\Timesheet;
|
use App\Entity\Timesheet;
|
||||||
|
use Twig\TwigFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiple Twig extensions: filters and functions
|
* Multiple Twig extensions: filters and functions
|
||||||
@@ -37,11 +38,11 @@ class Extensions extends \Twig_Extension
|
|||||||
public function getFilters()
|
public function getFilters()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
new \Twig_SimpleFilter('duration', array($this, 'duration')),
|
new TwigFilter('duration', [$this, 'duration']),
|
||||||
new \Twig_SimpleFilter('durationForEntry', array($this, 'durationForEntry')),
|
new TwigFilter('durationForEntry', [$this, 'durationForEntry']),
|
||||||
new \Twig_SimpleFilter('money', array($this, 'money')),
|
new TwigFilter('money', [$this, 'money']),
|
||||||
new \Twig_SimpleFilter('currency', array($this, 'currency')),
|
new TwigFilter('currency', [$this, 'currency']),
|
||||||
new \Twig_SimpleFilter('country', array($this, 'country')),
|
new TwigFilter('country', [$this, 'country']),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,12 +141,4 @@ class Extensions extends \Twig_Extension
|
|||||||
|
|
||||||
return $locales;
|
return $locales;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return 'kimai.extension';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
54
src/Twig/MarkdownExtension.php
Normal file
54
src/Twig/MarkdownExtension.php
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Twig;
|
||||||
|
|
||||||
|
use App\Utils\Markdown;
|
||||||
|
use Twig\TwigFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A twig extension to handle markdown parser.
|
||||||
|
*/
|
||||||
|
class MarkdownExtension extends \Twig_Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Markdown
|
||||||
|
*/
|
||||||
|
private $markdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MarkdownExtension constructor.
|
||||||
|
* @param Markdown $parser
|
||||||
|
*/
|
||||||
|
public function __construct(Markdown $parser)
|
||||||
|
{
|
||||||
|
$this->markdown = $parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TwigFilter[]
|
||||||
|
*/
|
||||||
|
public function getFilters()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new TwigFilter('md2html', [$this, 'markdownToHtml'], ['is_safe' => ['html']]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms the given Markdown content into HTML
|
||||||
|
*
|
||||||
|
* @param string $content
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function markdownToHtml(string $content): string
|
||||||
|
{
|
||||||
|
return $this->markdown->toHtml($content);
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/Utils/Markdown.php
Normal file
41
src/Utils/Markdown.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Utils;
|
||||||
|
|
||||||
|
use Parsedown as MarkdownParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple class to parse markdown syntax and return HTML.
|
||||||
|
*/
|
||||||
|
class Markdown
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MarkdownParser
|
||||||
|
*/
|
||||||
|
private $parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Markdown constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->parser = new MarkdownParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $text
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function toHtml(string $text): string
|
||||||
|
{
|
||||||
|
return $this->parser->text($text);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -101,6 +101,9 @@
|
|||||||
"egulias/email-validator": {
|
"egulias/email-validator": {
|
||||||
"version": "2.1.3"
|
"version": "2.1.3"
|
||||||
},
|
},
|
||||||
|
"erusev/parsedown": {
|
||||||
|
"version": "1.6.4"
|
||||||
|
},
|
||||||
"friendsofphp/php-cs-fixer": {
|
"friendsofphp/php-cs-fixer": {
|
||||||
"version": "2.2",
|
"version": "2.2",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
@@ -260,6 +263,9 @@
|
|||||||
"ref": "9f94d3ea453cd8a3b95db7f82592d7344fe3a76a"
|
"ref": "9f94d3ea453cd8a3b95db7f82592d7344fe3a76a"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"symfony/css-selector": {
|
||||||
|
"version": "v4.0.4"
|
||||||
|
},
|
||||||
"symfony/debug": {
|
"symfony/debug": {
|
||||||
"version": "v4.0.3"
|
"version": "v4.0.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,13 +41,6 @@
|
|||||||
|
|
||||||
{% block avanzu_footer %}
|
{% block avanzu_footer %}
|
||||||
{% block footer %}
|
{% block footer %}
|
||||||
<footer class="main-footer no-print">
|
|
||||||
<div class="pull-right hidden-xs">
|
|
||||||
<b>Version</b> 2.0 dev
|
|
||||||
</div>
|
|
||||||
Made with ♥ by <a href="http://www.kevinpapst.de">Kevin Papst</a>.
|
|
||||||
{{ 'footer.license'|trans }}
|
|
||||||
</footer>
|
|
||||||
<!-- Page rendered on {{ 'now'|localizeddate('long', 'long', null, 'UTC') }} -->
|
<!-- Page rendered on {{ 'now'|localizeddate('long', 'long', null, 'UTC') }} -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
26
templates/help/index.html.twig
Normal file
26
templates/help/index.html.twig
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block page_title %}{{ 'help.title'|trans }}{% endblock %}
|
||||||
|
{% block page_subtitle %}{{ 'help.subtitle'|trans }}{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
{% set replacer = {
|
||||||
|
'.md"': '"',
|
||||||
|
'<table>': '<table class="table">',
|
||||||
|
'href="../../': 'target="_blank" href="'~github~'blob/master/',
|
||||||
|
('href="' ~ github): 'target="_blank" href="'~github
|
||||||
|
} %}
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
{% if chapter != 'README' %}
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<a href="{{ path('help') }}">{{ 'action.back'|trans }}</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="box-body">
|
||||||
|
{{ documentation|md2html|replace(replacer)|raw }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -1,11 +1,24 @@
|
|||||||
<h3 class="control-sidebar-heading">{{ 'home.title'|trans({}, 'sidebar') }}</h3>
|
<h3 class="control-sidebar-heading">{{ 'home.title'|trans({}, 'sidebar') }}</h3>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{ 'home.betainfo'|trans({}, 'sidebar')|raw|nl2br }}
|
{{ 'home.betainfo'|trans({}, 'sidebar')|raw|nl2br }}
|
||||||
<ul class="control-sidebar-menu">
|
</div>
|
||||||
<li>
|
|
||||||
<a href="https://github.com/kevinpapst/kimai2/" target="_blank">{{ 'home.link.issues'|trans({}, 'sidebar') }}</a>
|
<h3 class="control-sidebar-heading">{{ 'help.title'|trans({}, 'sidebar') }}</h3>
|
||||||
</li>
|
<div class="form-group">
|
||||||
</ul>
|
<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>
|
</div>
|
||||||
{#
|
{#
|
||||||
<ul class="control-sidebar-menu">
|
<ul class="control-sidebar-menu">
|
||||||
|
|||||||
74
tests/Controller/ControllerBaseTest.php
Normal file
74
tests/Controller/ControllerBaseTest.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Tests\Controller;
|
||||||
|
|
||||||
|
use App\DataFixtures\AppFixtures;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Client;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ControllerBaseTest adds some useful functions for writing integration tests.
|
||||||
|
*/
|
||||||
|
abstract class ControllerBaseTest extends WebTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
const DEFAULT_LANGUAGE = 'en';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Client
|
||||||
|
*/
|
||||||
|
protected function getClientForAuthenticatedUser()
|
||||||
|
{
|
||||||
|
$client = self::createClient([], [
|
||||||
|
'PHP_AUTH_USER' => AppFixtures::USERNAME_USER,
|
||||||
|
'PHP_AUTH_PW' => AppFixtures::DEFAULT_PASSWORD,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Client $client
|
||||||
|
* @param string $url
|
||||||
|
* @param string $method
|
||||||
|
* @return \Symfony\Component\DomCrawler\Crawler
|
||||||
|
*/
|
||||||
|
protected function request(Client $client, string $url, $method = 'GET')
|
||||||
|
{
|
||||||
|
return $client->request($method, '/' . self::DEFAULT_LANGUAGE . $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $url
|
||||||
|
* @param string $method
|
||||||
|
*/
|
||||||
|
protected function assertUrlIsSecured(string $url, $method = 'GET')
|
||||||
|
{
|
||||||
|
$client = self::createClient();
|
||||||
|
$client->request($method, '/' . self::DEFAULT_LANGUAGE . $url);
|
||||||
|
|
||||||
|
$this->assertTrue($client->getResponse()->isRedirect());
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'http://localhost/' . self::DEFAULT_LANGUAGE . '/login',
|
||||||
|
$client->getResponse()->getTargetUrl(),
|
||||||
|
sprintf('The %s secure URL redirects to the login form.', $url)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Client $client
|
||||||
|
*/
|
||||||
|
protected function assertRouteNotFound(Client $client)
|
||||||
|
{
|
||||||
|
$this->assertFalse($client->getResponse()->isSuccessful());
|
||||||
|
$this->assertEquals(404, $client->getResponse()->getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Tests\Controller;
|
|
||||||
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO adjust to actual app
|
|
||||||
*
|
|
||||||
* Functional test that implements a "smoke test" of all the public and secure
|
|
||||||
* URLs of the application.
|
|
||||||
* See http://symfony.com/doc/current/best_practices/tests.html#functional-tests.
|
|
||||||
*
|
|
||||||
* Execute the application tests using this command (requires PHPUnit to be installed):
|
|
||||||
*
|
|
||||||
* $ cd your-symfony-project/
|
|
||||||
* $ phpunit -c app
|
|
||||||
*
|
|
||||||
* @group integration
|
|
||||||
*/
|
|
||||||
class DefaultControllerTest extends WebTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* PHPUnit's data providers allow to execute the same tests repeated times
|
|
||||||
* using a different set of data each time.
|
|
||||||
* See http://symfony.com/doc/current/cookbook/form/unit_testing.html#testing-against-different-sets-of-data.
|
|
||||||
*
|
|
||||||
* @dataProvider getPublicUrls
|
|
||||||
*/
|
|
||||||
public function testPublicUrls($url)
|
|
||||||
{
|
|
||||||
$this->markTestIncomplete(__METHOD__);
|
|
||||||
$client = self::createClient();
|
|
||||||
$client->request('GET', $url);
|
|
||||||
|
|
||||||
$this->assertTrue(
|
|
||||||
$client->getResponse()->isSuccessful(),
|
|
||||||
sprintf('The %s public URL loads correctly.', $url)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The application contains a lot of secure URLs which shouldn't be
|
|
||||||
* publicly accessible. This tests ensures that whenever a user tries to
|
|
||||||
* access one of those pages, a redirection to the login form is performed.
|
|
||||||
*
|
|
||||||
* @dataProvider getSecureUrls
|
|
||||||
*/
|
|
||||||
public function testSecureUrls($url)
|
|
||||||
{
|
|
||||||
$this->markTestSkipped('No admin URLs for testing');
|
|
||||||
$client = self::createClient();
|
|
||||||
$client->request('GET', $url);
|
|
||||||
|
|
||||||
$this->assertTrue($client->getResponse()->isRedirect());
|
|
||||||
|
|
||||||
$this->assertEquals(
|
|
||||||
'http://localhost/en/login',
|
|
||||||
$client->getResponse()->getTargetUrl(),
|
|
||||||
sprintf('The %s secure URL redirects to the login form.', $url)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPublicUrls()
|
|
||||||
{
|
|
||||||
yield ['/'];
|
|
||||||
yield ['/en/login'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSecureUrls()
|
|
||||||
{
|
|
||||||
yield ['/en/admin/post/'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
46
tests/Controller/HelpControllerTest.php
Normal file
46
tests/Controller/HelpControllerTest.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Tests\Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group integration
|
||||||
|
*/
|
||||||
|
class HelpControllerTest extends ControllerBaseTest
|
||||||
|
{
|
||||||
|
|
||||||
|
public function testIsSecure()
|
||||||
|
{
|
||||||
|
$this->assertUrlIsSecured('/help/');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testReadmePage()
|
||||||
|
{
|
||||||
|
$client = $this->getClientForAuthenticatedUser();
|
||||||
|
$this->request($client, '/help/');
|
||||||
|
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||||
|
$this->assertContains('<h1>Kimai documentation</h1>', $client->getResponse()->getContent());
|
||||||
|
$this->assertNotContains('<a href="/en/help/README">', $client->getResponse()->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUsersPage()
|
||||||
|
{
|
||||||
|
$client = $this->getClientForAuthenticatedUser();
|
||||||
|
$this->request($client, '/help/users');
|
||||||
|
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||||
|
$this->assertContains('<a href="/en/help/README">', $client->getResponse()->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidateRouteDoesNotAllowSpecialChars()
|
||||||
|
{
|
||||||
|
$client = $this->getClientForAuthenticatedUser();
|
||||||
|
$this->request($client, '/help/.users');
|
||||||
|
$this->assertRouteNotFound($client);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
tests/Twig/MarkdownExtensionTest.php
Normal file
36
tests/Twig/MarkdownExtensionTest.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Tests\Twig;
|
||||||
|
|
||||||
|
use App\Twig\MarkdownExtension;
|
||||||
|
use App\Utils\Markdown;
|
||||||
|
use \PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \App\Twig\MarkdownExtension
|
||||||
|
*/
|
||||||
|
class MarkdownExtensionTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function testGetFilters()
|
||||||
|
{
|
||||||
|
$sut = new MarkdownExtension(new Markdown());
|
||||||
|
$filters = $sut->getFilters();
|
||||||
|
$this->assertCount(1, $filters);
|
||||||
|
$this->assertEquals('md2html', $filters[0]->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMarkdownToHtml()
|
||||||
|
{
|
||||||
|
$sut = new MarkdownExtension(new Markdown());
|
||||||
|
$this->assertEquals('<p><em>test</em></p>', $sut->markdownToHtml('*test*'));
|
||||||
|
$this->assertEquals('<h1>foobar</h1>', $sut->markdownToHtml('# foobar'));
|
||||||
|
}
|
||||||
|
}
|
||||||
27
tests/Utils/MarkdownTest.php
Normal file
27
tests/Utils/MarkdownTest.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Tests\Utils;
|
||||||
|
|
||||||
|
use App\Utils\Markdown;
|
||||||
|
use \PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \App\Utils\Markdown
|
||||||
|
*/
|
||||||
|
class MarkdownTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function testMarkdownToHtml()
|
||||||
|
{
|
||||||
|
$sut = new Markdown();
|
||||||
|
$this->assertEquals('<p><em>test</em></p>', $sut->toHtml('*test*'));
|
||||||
|
$this->assertEquals('<h1>foobar</h1>', $sut->toHtml('# foobar'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -116,14 +116,6 @@
|
|||||||
<target>Benutzer</target>
|
<target>Benutzer</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|
||||||
<!--
|
|
||||||
Footer
|
|
||||||
-->
|
|
||||||
<trans-unit id="footer.license">
|
|
||||||
<source>footer.license</source>
|
|
||||||
<target>Alle Rechte vorbehalten.</target>
|
|
||||||
</trans-unit>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Error templates
|
Error templates
|
||||||
-->
|
-->
|
||||||
@@ -368,6 +360,18 @@
|
|||||||
<target>Aktiviert die minimierte Version der linken Navigationsleiste</target>
|
<target>Aktiviert die minimierte Version der linken Navigationsleiste</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Help - Manual
|
||||||
|
-->
|
||||||
|
<trans-unit id="help.title">
|
||||||
|
<source>help.title</source>
|
||||||
|
<target>Hilfe</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="help.subtitle">
|
||||||
|
<source>help.subtitle</source>
|
||||||
|
<target>Anleitung zur Benutzung und Konfiguration von Kimai (nur auf Englisch verfügbar)</target>
|
||||||
|
</trans-unit>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Admin: Timesheet
|
Admin: Timesheet
|
||||||
-->
|
-->
|
||||||
@@ -649,11 +653,11 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="invoice.number">
|
<trans-unit id="invoice.number">
|
||||||
<source>invoice.number</source>
|
<source>invoice.number</source>
|
||||||
<target>Rechnung</target>
|
<target>Rechnungsnummer</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="invoice.subtotal">
|
<trans-unit id="invoice.subtotal">
|
||||||
<source>invoice.subtotal</source>
|
<source>invoice.subtotal</source>
|
||||||
<target>Netto</target>
|
<target>Rechnungsbetrag (netto)</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="invoice.tax">
|
<trans-unit id="invoice.tax">
|
||||||
<source>invoice.tax</source>
|
<source>invoice.tax</source>
|
||||||
@@ -661,7 +665,19 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="invoice.total">
|
<trans-unit id="invoice.total">
|
||||||
<source>invoice.total</source>
|
<source>invoice.total</source>
|
||||||
<target>Rechnungsbetrag</target>
|
<target>Rechnungsendbetrag</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="invoice.service_date">
|
||||||
|
<source>invoice.service_date</source>
|
||||||
|
<target>Leistungsdatum</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="invoice.amount">
|
||||||
|
<source>invoice.amount</source>
|
||||||
|
<target>Anzahl</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="invoice.total_rate">
|
||||||
|
<source>invoice.total_rate</source>
|
||||||
|
<target>Gesamtpreis</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="label.payment_terms">
|
<trans-unit id="label.payment_terms">
|
||||||
<source>label.payment_terms</source>
|
<source>label.payment_terms</source>
|
||||||
|
|||||||
@@ -368,6 +368,18 @@
|
|||||||
<target>Toggle the size of the left sidebar's header (full or collapse)</target>
|
<target>Toggle the size of the left sidebar's header (full or collapse)</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Help - Manual
|
||||||
|
-->
|
||||||
|
<trans-unit id="help.title">
|
||||||
|
<source>help.title</source>
|
||||||
|
<target>Help</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="help.subtitle">
|
||||||
|
<source>help.subtitle</source>
|
||||||
|
<target>Instructions for using and configuring Kimai</target>
|
||||||
|
</trans-unit>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Admin: Timesheet
|
Admin: Timesheet
|
||||||
-->
|
-->
|
||||||
@@ -649,7 +661,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="invoice.number">
|
<trans-unit id="invoice.number">
|
||||||
<source>invoice.number</source>
|
<source>invoice.number</source>
|
||||||
<target>Invoice</target>
|
<target>Invoice number</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="invoice.subtotal">
|
<trans-unit id="invoice.subtotal">
|
||||||
<source>invoice.subtotal</source>
|
<source>invoice.subtotal</source>
|
||||||
@@ -663,6 +675,18 @@
|
|||||||
<source>invoice.total</source>
|
<source>invoice.total</source>
|
||||||
<target>Total</target>
|
<target>Total</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="invoice.service_date">
|
||||||
|
<source>invoice.service_date</source>
|
||||||
|
<target>Service date</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="invoice.amount">
|
||||||
|
<source>invoice.amount</source>
|
||||||
|
<target>Quantity</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="invoice.total_rate">
|
||||||
|
<source>invoice.total_rate</source>
|
||||||
|
<target>Total price</target>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="label.payment_terms">
|
<trans-unit id="label.payment_terms">
|
||||||
<source>label.payment_terms</source>
|
<source>label.payment_terms</source>
|
||||||
<target>Terms of payment</target>
|
<target>Terms of payment</target>
|
||||||
|
|||||||
@@ -13,13 +13,27 @@
|
|||||||
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 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.
|
||||||
|
|
||||||
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!
|
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!
|
||||||
|
|
||||||
Weitere Informationen auf der:
|
|
||||||
]]></target>
|
]]></target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="home.link.issues">
|
<trans-unit id="made.by.license">
|
||||||
<source>home.link.issues</source>
|
<source>made.by.license</source>
|
||||||
<target>GitHub Projekt-Webseite</target>
|
<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>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="help.title">
|
||||||
|
<source>help.title</source>
|
||||||
|
<target>Dokumentation</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>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="preferences.title">
|
<trans-unit id="preferences.title">
|
||||||
<source>preferences.title</source>
|
<source>preferences.title</source>
|
||||||
|
|||||||
@@ -13,13 +13,27 @@
|
|||||||
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 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.
|
||||||
|
|
||||||
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!
|
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!
|
||||||
|
|
||||||
Further information on the:
|
|
||||||
]]></target>
|
]]></target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="home.link.issues">
|
<trans-unit id="made.by.license">
|
||||||
<source>home.link.issues</source>
|
<source>made.by.license</source>
|
||||||
<target>GitHub Project-Website</target>
|
<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>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="help.title">
|
||||||
|
<source>help.title</source>
|
||||||
|
<target>Documentation</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>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="preferences.title">
|
<trans-unit id="preferences.title">
|
||||||
<source>preferences.title</source>
|
<source>preferences.title</source>
|
||||||
|
|||||||
BIN
var/data/kimai_test.sqlite
Normal file
BIN
var/data/kimai_test.sqlite
Normal file
Binary file not shown.
Reference in New Issue
Block a user