13 Commits
Author SHA1 Message Date
TorstenHettstedt 3dd0f451fc Merge pull request 'Deployment.' (#14) from deployment into master
Reviewed-on: #14
2021-04-19 11:14:28 +02:00
Torstem_JetBrain 46313cc290 Die Installation der PHP-Abhängigkeiten hinzugefügt. 2021-04-19 11:11:06 +02:00
Torstem_JetBrain 65195e702e Für den Anfang wird eine einfache Bash-Datei zum Deployment benutzt. 2021-04-16 21:58:54 +02:00
Torstem_JetBrain ec22f42623 Docker-Composer-Datei wurden um die Oberfläche erweitert. 2021-04-16 21:47:23 +02:00
Torstem_JetBrain b43b6382d7 Font-Dateien wurden nicht mit gesichert. 2021-04-16 21:46:07 +02:00
TorstenHettstedt 12ed91a6da Merge pull request 'womtfix/negative-werte' (#12) from womtfix/negative-werte into master
Reviewed-on: #12
2021-04-15 12:25:33 +02:00
Torstem_JetBrain cc9941d1d3 Negative Werte werden deutlich dargestellt. 2021-04-15 12:23:22 +02:00
Torstem_JetBrain 2b2753e009 Die Darstellung von negativen Werten erfolgt richtig. 2021-04-15 11:34:50 +02:00
Torstem_JetBrain 735b195c06 Die Tests hatten nicht die richtige Darstellung von negativen Werten getestet. 2021-04-15 11:34:04 +02:00
Torstem_JetBrain 0bd8932fa1 Es wurde sich auf Functions-Tests verlassen. 2021-04-15 11:28:47 +02:00
TorstenHettstedt 114e31029c Merge pull request 'feature/css-datei' (#11) from feature/css-datei into master
Reviewed-on: #11
2021-04-15 10:55:54 +02:00
Torstem_JetBrain de0535be32 Bereinigung von Altlasten, da die Texte von woanders übernommen wurden. 2021-04-14 17:23:31 +02:00
Torstem_JetBrain b74e9bbd69 Es wurde an die Darstellung auf einen iPhone bzw. ähnlichen Geräten angepasst. 2021-04-14 17:10:01 +02:00
31 changed files with 78774 additions and 307 deletions
+2 -1
View File
@@ -91,12 +91,13 @@ class WorkingHoursView implements ModelInterface
'overtime' => "string"
])] public function jsonSerialize(): array
{
$formatOvertime = (($this->getOvertime()->invert === 1) ? '-' : '') . '%H:%I:%S';
return [
'period' => $this->getPeriod()->format($this->getPeriodDesignation()->getValue()),
'periodDesignation' => strtolower($this->getPeriodDesignation()->getKey()),
'workingDays' => $this->getWorkingDays(),
'totalHours' => $this->getTotalHours()->format('%H:%I:%S'),
'overtime' => $this->getOvertime()->format('%H:%I:%S')
'overtime' => $this->getOvertime()->format($formatOvertime)
];
}
}
+20 -1
View File
@@ -12,6 +12,9 @@ use Psr\Http\Message\StreamInterface;
use Psr\Log\LoggerInterface;
use Slim\App;
use Slim\Exception\HttpException;
use Slim\Interfaces\RouteParserInterface;
use Slim\Routing\RouteContext;
use Slim\Routing\RoutingResults;
use TorstenHettstedt\TimekeepingApi\Middleware\ErrorHandler;
class ErrorHandlerTest extends Unit
@@ -28,6 +31,7 @@ class ErrorHandlerTest extends Unit
protected function _before(): void
{
parent::_before();
/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
$this->app = $this->makeEmpty(App::class, [
'getResponseFactory' => $this->makeEmpty(ResponseFactoryInterface::class, [
'createResponse' => $this->makeEmpty(ResponseInterface::class, [
@@ -40,7 +44,16 @@ class ErrorHandlerTest extends Unit
]),
]),
]);
$this->request = $this->makeEmpty(ServerRequestInterface::class);
/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
$this->request = $this->makeEmpty(ServerRequestInterface::class, [
'getAttribute' => function($name) {
return match ($name) {
RouteContext::ROUTE_PARSER => $this->makeEmpty(RouteParserInterface::class),
RouteContext::ROUTING_RESULTS => $this->makeEmpty(RoutingResults::class),
default => null,
};
}
]);
}
/**
@@ -48,11 +61,13 @@ class ErrorHandlerTest extends Unit
*/
public function testUseWithLogger(): void
{
/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
$this->exception = $this->make(Exception::class, [
'message' => '',
'code' => 400,
'file' => '/path(to/file',
]);
/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
$this->logger = $this->makeEmpty(LoggerInterface::class, [
'error' => Expected::once(),
]);
@@ -66,12 +81,14 @@ class ErrorHandlerTest extends Unit
*/
public function testUseWithHttpException(): void
{
/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
$this->exception = $this->make(HttpException::class, [
'message' => '',
'code' => 400,
'file' => '/path(to/file',
'getTitle' => Expected::once('The Title'),
]);
/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
$this->logger = $this->makeEmpty(LoggerInterface::class, []);
$middleWare = new ErrorHandler($this->app);
@@ -84,11 +101,13 @@ class ErrorHandlerTest extends Unit
*/
public function testUseWithGeneralException(): void
{
/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
$this->exception = $this->make(Exception::class, [
'message' => '',
'code' => 400,
'file' => '/path(to/file',
]);
/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
$this->logger = $this->makeEmpty(LoggerInterface::class, []);
$middleWare = new ErrorHandler($this->app);
+37 -15
View File
@@ -17,13 +17,15 @@ class WorkingHoursViewTest extends Unit
*/
public function workingHoursProvider(): array
{
$date = new DateTime('2020-11-30');
$work_days = 15;
$total_hours = new DateInterval("PT32H22M");
$overtime = new DateInterval("PT22M");
$absence_time = clone $overtime;
$absence_time->invert = 1;
return [
[
new DateTime('2020-11-30'),
PeriodDesignationEnum::WEEKLY(),
15,
new DateInterval("PT32H22M"),
new DateInterval("PT22M"),
$date, PeriodDesignationEnum::WEEKLY(), $work_days, $total_hours, $overtime,
[
'period' => '2020#49',
'periodDesignation' => 'weekly',
@@ -33,11 +35,17 @@ class WorkingHoursViewTest extends Unit
],
],
[
new DateTime('2020-11-30'),
PeriodDesignationEnum::MONTHLY(),
15,
new DateInterval("PT32H22M"),
new DateInterval("PT22M"),
$date, PeriodDesignationEnum::WEEKLY(), $work_days, $total_hours, $absence_time,
[
'period' => '2020#49',
'periodDesignation' => 'weekly',
'workingDays' => 15,
'totalHours' => '32:22:00',
'overtime' => '-00:22:00'
],
],
[
$date, PeriodDesignationEnum::MONTHLY(), $work_days, $total_hours, $overtime,
[
'period' => '2020-11',
'periodDesignation' => 'monthly',
@@ -47,12 +55,17 @@ class WorkingHoursViewTest extends Unit
],
],
[
new DateTime('2020-11-30'),
PeriodDesignationEnum::YEARLY(),
15,
new DateInterval("PT32H22M"),
new DateInterval("PT22M"),
$date, PeriodDesignationEnum::MONTHLY(), $work_days, $total_hours, $absence_time,
[
'period' => '2020-11',
'periodDesignation' => 'monthly',
'workingDays' => 15,
'totalHours' => '32:22:00',
'overtime' => '-00:22:00'
],
],
[
$date, PeriodDesignationEnum::YEARLY(), $work_days, $total_hours, $overtime, [
'period' => '2020',
'periodDesignation' => 'yearly',
'workingDays' => 15,
@@ -60,6 +73,15 @@ class WorkingHoursViewTest extends Unit
'overtime' => '00:22:00'
],
],
[
$date, PeriodDesignationEnum::YEARLY(), $work_days, $total_hours, $absence_time, [
'period' => '2020',
'periodDesignation' => 'yearly',
'workingDays' => 15,
'totalHours' => '32:22:00',
'overtime' => '-00:22:00'
],
],
];
}
+6
View File
@@ -24,3 +24,9 @@ services:
volumes:
- ./api:/var/www
- logs:/var/www/logs
ui:
build: ./ui/
ports:
- 80:80
depends_on:
- api
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
install_api_dependence() {
cd api/ || exit 2
composer install
cd ..
}
build_ui() {
cd ui/ || exit 2
npm run build
cd ..
}
test_unit() {
pwd
cd api/ || exit 2
./vendor/bin/codecept run unit
cd ..
}
test_api() {
cd api/ || exit 2
./vendor/bin/codecept run api
cd ..
}
composer_run() {
docker-compose up -d
}
install_api_dependence && build_ui && test_unit && composer_run && test_api
+3
View File
@@ -0,0 +1,3 @@
FROM httpd:2.4
COPY ./public/ /usr/local/apache2/htdocs/
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.
Binary file not shown.
-9
View File
@@ -71,15 +71,6 @@ section article {
font-size: 1.30em;
font-weight: bold;
}
div.zelle > label {
}
}
}
&.http-error {
header {
background: hsl(340, 90%, 50%);
color: hsl(0, 0%, 95%);
}
}
}
+1
View File
@@ -6,6 +6,7 @@ Definition der Farben
@hueSub: 215;
@mainColor: hsl(@hueMain, 90%, 29%);
@redColor: hsl(0, 90%, 29%);
@mainColorDark: darken(@mainColor,66%,relativ);
@mainColorLight: lighten(@mainColor,66%,relativ);
@subColor: hsl(@hueSub, 90%, 29%);
+8 -90
View File
@@ -72,18 +72,6 @@ main {
margin: @sectionMargin;
text-indent: @sectionMargin * 2;
}
ul, ol {
margin: initial;
li {
margin: initial;
padding: initial;
}
}
dl {
dd {
margin-left: 2em;
}
}
table {
thead {
tr:last-child {
@@ -91,6 +79,13 @@ main {
border-bottom: @mainColor solid thin;
}
}
};
tbody {
td.absence-time {
color: @redColor;
text-decoration-line: underline;
text-decoration-style: dashed;
}
}
}
form {
@@ -116,7 +111,7 @@ main {
display: inline-block;
margin: 0.5rem;
}
input, textarea {
input {
display: inline-block;
width: @formItemWidth;
padding: 0.25rem;
@@ -124,38 +119,6 @@ main {
border-style: solid;
border-width: thin;
}
div.radio-button {
padding-left: 20%;
label, input {
display: inline;
width: auto;
}
input {
margin-top: inherit;
margin-right: 1rem;
margin-left: 1rem;
margin-bottom: inherit;
}
}
textarea {
height: 10rem;
}
ul.suche {
width: 30rem;
margin-left: @formLabelWidth + 1.5rem;
margin-top: -1rem;
background: white;
position: absolute;
border: solid thin;
li {list-style: none;
text-indent: 0;
cursor: pointer;
&:hover {
background: @mainColorLight;
color: @mainColor;
}
}
}
}
}
}
@@ -188,48 +151,3 @@ main {
}
}
}
aside {
background: @mainColorLight ;
li {
background: @mainColorLight;
color: @mainColor;
font-weight: bold ;
&:not(:first-child) {
margin-top: 1rem;
}
a {
display: block;
padding: 1.25rem .5rem;
text-decoration: none;
color: @mainColor;
&:hover, &:active, &:focus {
color: darken(@mainColor,10%,relative);
}
}
&:hover, &:active, &:focus {
background: lighten(@mainColorLight,10%,relative);
}
}
form {
@paddingForm: 0.5rem;
@paddingInput: @paddingForm/2;
background: @mainColorLight;
color: @mainColor;
padding: 2 * @paddingForm @paddingForm;
input {
display: block;
width: @breiteNavBereich - (@paddingForm + @paddingInput) * 2 ;
border: none;
margin-bottom: @paddingForm;
padding: @paddingInput;
}
}
p {
line-height: 1.5em;
text-align: left;
.hyphens();
margin: 1em;
font-size: 85%;
}
}
+43 -4
View File
@@ -137,6 +137,7 @@
width: @breiteNavBereich;
}
}
@media screen and (max-width: 830px) {
html body {
@boxHeight: 5rem;
@@ -145,16 +146,18 @@
font-size: @boxHeight;
text-align: center;
padding: 1rem;
}
& > footer {
padding: 1rem;
}
& > nav {
background: none;
left:auto;
ul {
li {
display: inline-block;
border: none;
width: auto;
height: 1.5em;
padding-top: 0.25em;
a {
padding: 0.75rem;
}
@@ -184,6 +187,7 @@
@formLabelWidth: 10rem;
@formItemWidth: 40rem;
@sectionMargin: 1rem;
margin: @sectionMargin;
fieldset {
width: auto;
margin: 1rem auto;
@@ -262,6 +266,41 @@
}
}
}
@media screen and (max-width: 720px) {
html body {
@boxHeight: 2.5rem;
& > header {
height: @boxHeight;
font-size: @boxHeight;
text-align: center;
padding: 1rem;
}
& > nav {
.hamburgerMenu();
}
main section header {
h1, h2 {
text-align: center;
margin: 0.5rem auto;
}
}
table {
width: 100%;
margin: 1rem 0;
td, th {
padding: 0.25rem;
}
colgroup:not(:first-child) col:first-child{
border-left: solid thin;
}
thead {
th {
font-size: 100%;
font-weight: bold;
.hyphens();
}
}
}
}
}
+7 -50
View File
@@ -1,14 +1,3 @@
.clearfix() {
&:after {
content: ".";
display: block;
height: 0;
line-height: 0;
clear: both;
visibility: hidden;
}
}
.hyphens() {
-webkit-hyphens: auto;
-moz-hyphens: auto;
@@ -59,27 +48,22 @@
text-overflow: ellipsis;
}
.mywrap() {
white-space: normal;
}
.hamburgerMenu() {
color: white;
width: 3rem;
height: 2rem;
top: 0.5rem;
right: 0.5rem;
left: auto;
top: 0.25rem;
left: 0.25rem;
.border-radius(4px);
border: none;
.vertical-gradient(#555; #000);
.vertical-gradient(@mainColorDark; @mainColor);
> ul {
height: auto;
width: auto;
position: absolute;
right: 0;
left: 0;
top: 100%;
background: fade(black,80%);
background: fade(@mainColorDark,80%);
.border-radius(5px);
display: none;
> li {
@@ -100,7 +84,7 @@
&:hover,
&:focus {
color: white;
.vertical-gradient(#59b4fd; #0560e8);
.vertical-gradient(@mainColorLight; @mainColor);
}
}
&:first-child {
@@ -115,7 +99,7 @@
}
}
}
&:hover, &:focus, &:active {
&:hover, &:focus, &:active, &:checked {
ul {
display: block;
}
@@ -130,19 +114,6 @@
}
}
.transition(@property) {
-moz-transition: ~"@{property}";
-webkit-transition: ~"@{property}";
-o-transition: ~"@{property}";
-ms-transition: ~"@{property}";
transition: ~"@{property}";
-moz-transition-duration: 0.5s;
-webkit-transition-duration: 0.5s;
-o-transition-duration: 0.5s;
-ms-transition-duration: 0.5s;
transition-duration: 0.5s;
}
.flexEltern() {
display:-ms-flexbox;
display: flexbox;
@@ -172,17 +143,3 @@
flex: @num;
flex-grow: @num;
}
.background-size(...) {
-webkit-background-size: @arguments;
-moz-background-size: @arguments;
background-size: @arguments;
}
.transform(...) {
-ms-transform: @arguments;
-webkit-transform: @arguments;
-o-transform: @arguments;
-moz-transform: @arguments;
transform: @arguments;
}
+1 -4
View File
@@ -75,9 +75,6 @@ section article {
}
}
&.http-error {
header {
background: hsl(340, 90%, 50%);
color: hsl(0, 0%, 95%);
}
display: none;
}
}
+6 -125
View File
@@ -21,17 +21,15 @@ html {
margin: 1rem;
}
}
> nav {
display: none;
}
> footer {
color: contrast(@mainColor);
}
}
}
#inhalts-bereich {
background-color: @mainColorLight;
color: @mainColor;
}
main {
* {
border-style: none;
@@ -46,22 +44,10 @@ main {
h1, h2 {
margin: @sectionMargin;
}
p, ul, ol, dl {
p {
margin: @sectionMargin;
text-indent: @sectionMargin * 2;
}
ul, ol {
margin: initial;
li {
margin: initial;
padding: initial;
}
}
dl {
dd {
margin-left: 2em;
}
}
table {
colgroup:not(:first-child) col:first-child{
border-left: solid medium;
@@ -86,70 +72,10 @@ main {
}
}
form {
@formLabelWidth: 10rem;
@formItemWidth: 40rem;
fieldset {
width: @formItemWidth + @formLabelWidth + 2rem;
margin: 1rem auto;
border-style: solid ;
padding: @sectionMargin;
&.tasten {
border: none;
background-color: @mainColorLight;
}
legend {
margin: @sectionMargin;
margin-left: @sectionMargin * 2;
}
}
div.zelle {
& > label {
width: @formLabelWidth;
display: inline-block;
margin: 0.5rem;
}
input, textarea {
display: inline-block;
width: @formItemWidth;
padding: 0.25rem;
margin-bottom: 1.0rem;
border-style: solid;
border-width: thin;
}
div.radio-button {
padding-left: 20%;
label, input {
display: inline;
width: auto;
}
input {
margin-top: inherit;
margin-right: 1rem;
margin-left: 1rem;
margin-bottom: inherit;
}
}
textarea {
height: 10rem;
}
display: none;
}
button {
@farbeHintergrund: @mainColorLight;
@farbeHintergrundHell: lighten(@farbeHintergrund,50%,relativ);
@farbeText: spin(lighten(@farbeHintergrund,66%,relativ),@mainColor);
@farbeSchatten: fade(@farbeHintergrund,50%);
height: 2.5em;
.border-radius(1.25em);
padding: 0.5em 1.25em;
.vertical-gradient(@farbeHintergrundHell,@farbeHintergrund);
.box-shadow(0.1em 0.2em 0.5em @farbeSchatten);
color: @farbeText;
font-weight: bold;
&:hover {
.vertical-gradient(@farbeHintergrund,@farbeHintergrundHell);
}
margin: 0.25rem;
}
display: none;
}
footer {
text-align: right;
@@ -171,48 +97,3 @@ main {
}
}
}
aside {
background: @subColorLight ;
li {
background: @mainColorLight;
color: @mainColor;
font-weight: bold ;
&:not(:first-child) {
margin-top: 1rem;
}
a {
display: block;
padding: 1.25rem .5rem;
text-decoration: none;
color: @mainColor;
&:hover, &:active, &:focus {
color: darken(@mainColor,10%,relative);
}
}
&:hover, &:active, &:focus {
background: lighten(@mainColor,10%,relative);
}
}
form {
@paddingForm: 0.5rem;
@paddingInput: @paddingForm/2;
background: @mainColorLight;
color: @mainColor;
padding: 2 * @paddingForm @paddingForm;
input {
display: block;
width: @mainColor - (@paddingForm + @paddingInput) * 2 ;
border: none;
margin-bottom: @paddingForm;
padding: @paddingInput;
}
}
p {
line-height: 1.5em;
text-align: left;
.hyphens();
margin: 1em;
font-size: 85%;
}
}
+9 -1
View File
@@ -1,6 +1,14 @@
<script>
export let params;
console.log(params)
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.indexOf(searchString, position) === position;
};
}
$: isNegative = time => time.startsWith('-') ? 'absence-time' : '';
$: cutMinusChar = time => time.startsWith('-') ? time.substr(1) : time;
</script>
<svelte:head>
@@ -36,7 +44,7 @@
<td>{record.period}</td>
<td>{record.workingDays}</td>
<td>{record.totalHours}</td>
<td>{record.overtime}</td>
<td class="{ isNegative(record.overtime) }">{cutMinusChar(record.overtime)}</td>
</tr>
{/each}
</tbody>