Compare commits
185 Commits
8a3c2eaec5
...
197d0d724a
Author | SHA1 | Date |
---|---|---|
![]() |
197d0d724a | |
![]() |
7888dfad78 | |
![]() |
4429516a22 | |
![]() |
4bbeb93d64 | |
![]() |
909f7bba5a | |
![]() |
2baa101a8f | |
![]() |
a3a36de985 | |
![]() |
4244acfb4d | |
![]() |
4fa99b8a04 | |
![]() |
14dbe7f5d9 | |
![]() |
dc7c62ffe5 | |
![]() |
da8178b0bc | |
![]() |
02f998fc38 | |
![]() |
4de882ef85 | |
![]() |
fe836e281e | |
![]() |
8894f183f2 | |
![]() |
5b237febf8 | |
![]() |
497c1772f7 | |
![]() |
2e38b55167 | |
![]() |
1a250dc250 | |
![]() |
ef3bd7c319 | |
![]() |
ea93e27a9d | |
![]() |
a5cebc8535 | |
![]() |
72649c9522 | |
![]() |
b5d94971bc | |
![]() |
ca0a69b17d | |
![]() |
1505d0229d | |
![]() |
e2e18db460 | |
![]() |
8adad075bf | |
![]() |
f826cee63c | |
![]() |
0dbf88ad1c | |
![]() |
8185a74edc | |
![]() |
162116998c | |
![]() |
ac73489aed | |
![]() |
f4c3f7a39e | |
![]() |
23de3579af | |
![]() |
ba4ba8f2f8 | |
![]() |
8b1cd8130e | |
![]() |
48ea35562e | |
![]() |
a35a3580e0 | |
![]() |
15a6ba1c52 | |
![]() |
d89fe01ddd | |
![]() |
f292ce5331 | |
![]() |
269541293c | |
![]() |
545d2a7ccf | |
![]() |
dfd72d2d69 | |
![]() |
f2edb1a45c | |
![]() |
efda1ffc1c | |
![]() |
b8095492ec | |
![]() |
4e6ba3d684 | |
![]() |
1b91d84b5f | |
![]() |
47ad0a6133 | |
![]() |
fec2f17bea | |
![]() |
fd56966435 | |
![]() |
d8310ed6e7 | |
![]() |
3ffb0a38e8 | |
![]() |
e9b8977728 | |
![]() |
9acd06cb04 | |
![]() |
b17dbf46e0 | |
![]() |
7f2f5ab7ed | |
![]() |
58c457be86 | |
![]() |
36c7db40a7 | |
![]() |
0b165bc24c | |
![]() |
bf83e6a300 | |
![]() |
ac74ab489d | |
![]() |
f3347ba140 | |
![]() |
39dbfabea7 | |
![]() |
0a0cf5265c | |
![]() |
176a0b65c5 | |
![]() |
7fda1fc14b | |
![]() |
66738298a9 | |
![]() |
5d14109dbd | |
![]() |
44efd910c6 | |
![]() |
ecc3976c27 | |
![]() |
93270a10fd | |
![]() |
ff179360cc | |
![]() |
1b21bcf769 | |
![]() |
b6bd3eba56 | |
![]() |
6477e5dabd | |
![]() |
24f91ce9b5 | |
![]() |
6022d792dc | |
![]() |
9e3adf6179 | |
![]() |
6564056f16 | |
![]() |
343ce8241c | |
![]() |
7f6e1ff18e | |
![]() |
a31534d9b7 | |
![]() |
24204b1f3c | |
![]() |
27323bfba5 | |
![]() |
1397fe90ce | |
![]() |
89321306bc | |
![]() |
185b7e3fb6 | |
![]() |
9ffe739b24 | |
![]() |
9fb6bd4d10 | |
![]() |
fe37258b35 | |
![]() |
6195692d3d | |
![]() |
fc58d55274 | |
![]() |
9fcee133eb | |
![]() |
fed27210eb | |
![]() |
aeea3067b0 | |
![]() |
38838352e2 | |
![]() |
d251b4c7f7 | |
![]() |
7dbc0481b9 | |
![]() |
0aa4cdd2b0 | |
![]() |
1d5f16a59e | |
![]() |
fddae62669 | |
![]() |
599fff26d4 | |
![]() |
cd8c01c080 | |
![]() |
a70bc6ded8 | |
![]() |
7ce2cca052 | |
![]() |
cf4dc63495 | |
![]() |
dc9441d925 | |
![]() |
8438b8dc51 | |
![]() |
00f4afa2ab | |
![]() |
9f113958ca | |
![]() |
b3dd2b1d47 | |
![]() |
adf00b2739 | |
![]() |
8ebaffd71a | |
![]() |
383f8ebde5 | |
![]() |
4cd7103121 | |
![]() |
4267a76adb | |
![]() |
a2a57ec852 | |
![]() |
29a4b244dc | |
![]() |
4329ee4af9 | |
![]() |
c2dd25fc7c | |
![]() |
3b241529b7 | |
![]() |
40b93e3d8b | |
![]() |
c06cb767da | |
![]() |
dbb089315f | |
![]() |
5c59fec1cf | |
![]() |
102c8428c8 | |
![]() |
67d5950926 | |
![]() |
ee7d30b339 | |
![]() |
87bd4f4fa1 | |
![]() |
9a9ffcfdaf | |
![]() |
f3ec62e121 | |
![]() |
1ca9b99612 | |
![]() |
6b273288bd | |
![]() |
d1d0acf622 | |
![]() |
68dd73e333 | |
![]() |
94ba51bc46 | |
![]() |
24ecea0d65 | |
![]() |
5e702cd177 | |
![]() |
f966b1521f | |
![]() |
2252819800 | |
![]() |
931f3ba10d | |
![]() |
a60c5987ab | |
![]() |
80bec733bd | |
![]() |
c63a671dc4 | |
![]() |
009b0f3f27 | |
![]() |
f4030b86af | |
![]() |
e0b552d18b | |
![]() |
74989df119 | |
![]() |
b5803caf44 | |
![]() |
e03f2936e7 | |
![]() |
6c3bb7521f | |
![]() |
85bc95fea9 | |
![]() |
0a3a3c3b56 | |
![]() |
df4f744f6d | |
![]() |
e11b0db526 | |
![]() |
7f41d5eb1e | |
![]() |
4a907600b7 | |
![]() |
47f0587cd9 | |
![]() |
cffc9854f8 | |
![]() |
af2ac1bc3e | |
![]() |
49300900d6 | |
![]() |
86da8758a4 | |
![]() |
3ae8424aea | |
![]() |
98d2316b08 | |
![]() |
6622680baf | |
![]() |
21423ef305 | |
![]() |
c93c241dc9 | |
![]() |
4378fa2d7d | |
![]() |
8dd4af1bb6 | |
![]() |
f345942e46 | |
![]() |
da2baa75bb | |
![]() |
2c702fc67d | |
![]() |
d9b93e4236 | |
![]() |
1c4c164c39 | |
![]() |
e407a3b780 | |
![]() |
24f958b00d | |
![]() |
db4c5eec1c | |
![]() |
0a1c85d6bd | |
![]() |
c2e6dc5223 | |
![]() |
19a5673231 | |
![]() |
9feed46d4e |
|
@ -155,6 +155,15 @@ yarn lint:
|
||||||
- apk add --no-cache git
|
- apk add --no-cache git
|
||||||
- yarn lint
|
- yarn lint
|
||||||
|
|
||||||
|
translations lint:
|
||||||
|
image: alpine
|
||||||
|
stage: prepare
|
||||||
|
before_script:
|
||||||
|
- apk add gettext
|
||||||
|
script:
|
||||||
|
- find resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
|
||||||
|
- '[[ $(find resources/lang -type f -name "*.po" | wc -l) == $(find resources/lang -type f -name "*.mo" | wc -l) ]]'
|
||||||
|
|
||||||
#
|
#
|
||||||
# Build
|
# Build
|
||||||
#
|
#
|
||||||
|
@ -177,6 +186,7 @@ build-image:
|
||||||
- composer validate
|
- composer validate
|
||||||
- yarn check
|
- yarn check
|
||||||
- yarn lint
|
- yarn lint
|
||||||
|
- translations lint
|
||||||
- generate-version
|
- generate-version
|
||||||
dependencies:
|
dependencies:
|
||||||
- generate-version
|
- generate-version
|
||||||
|
|
|
@ -13,10 +13,14 @@ Please ensure that your pull requests follow the [PSR-12](https://www.php-fig.or
|
||||||
You can check that by running
|
You can check that by running
|
||||||
```bash
|
```bash
|
||||||
composer run phpcs
|
composer run phpcs
|
||||||
|
# with docker
|
||||||
|
docker exec engelsystem_dev-es_workspace-1 composer run phpcs
|
||||||
```
|
```
|
||||||
You may auto fix reported issues by running
|
You may auto fix reported issues by running
|
||||||
```bash
|
```bash
|
||||||
composer run phpcbf
|
composer run phpcbf
|
||||||
|
# with docker
|
||||||
|
docker exec engelsystem_dev-es_workspace-1 composer run phpcbf
|
||||||
```
|
```
|
||||||
|
|
||||||
## Pre-commit hooks
|
## Pre-commit hooks
|
||||||
|
@ -68,7 +72,7 @@ docker compose exec es_workspace yarn build
|
||||||
docker compose exec -e THEMES=0,1 es_workspace yarn build
|
docker compose exec -e THEMES=0,1 es_workspace yarn build
|
||||||
|
|
||||||
# Update the translation files
|
# Update the translation files
|
||||||
docker compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
|
docker compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
|
||||||
|
|
||||||
# Run the migrations
|
# Run the migrations
|
||||||
docker compose exec es_workspace bin/migrate
|
docker compose exec es_workspace bin/migrate
|
||||||
|
@ -114,7 +118,7 @@ The following instructions explain how to get, build and run the latest Engelsys
|
||||||
```
|
```
|
||||||
* Generate translation files
|
* Generate translation files
|
||||||
```bash
|
```bash
|
||||||
find resources/lang/ -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
|
find resources/lang/ -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
|
@ -40,7 +40,7 @@ The Engelsystem may be installed manually or by using the provided [docker setup
|
||||||
* Recommended: Directory Listing should be disabled.
|
* Recommended: Directory Listing should be disabled.
|
||||||
* There must be a MySQL database set up with a user who has full rights to that database.
|
* There must be a MySQL database set up with a user who has full rights to that database.
|
||||||
* If necessary, create a `config/config.php` to override values from `config/config.default.php`.
|
* If necessary, create a `config/config.php` to override values from `config/config.default.php`.
|
||||||
* To edit values from the `footer_items`, `themes`, `locales`, `tshirt_sizes` or `headers` lists, directly modify the `config/config.default.php` file or rename it to `config/config.php`.
|
* To disable/remove values from the `themes`, `tshirt_sizes`, `headers`, `header_items`, `footer_items`, or `locales` lists, set the value of the entry to `null`.
|
||||||
* To import the database, the `bin/migrate` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
|
* To import the database, the `bin/migrate` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
|
||||||
* In the browser, login with credentials `admin` : `asdfasdf` and change the password.
|
* In the browser, login with credentials `admin` : `asdfasdf` and change the password.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you want to contact us directly regarding a security concern, please write an e-mail to contact@engelsystem.de and explain your findings.
|
||||||
|
Thank you!
|
||||||
|
|
||||||
|
## Use of external reporting / bug bounty services
|
||||||
|
|
||||||
|
We kindly ask you to not use any external reporting / bug bounty service. We do not collaborate with any external service and experiences in the past showed that these services usually add a lot of unnecessary overhead.
|
||||||
|
|
||||||
|
Please send security critical bug reports to contact@engelsystem.de.
|
||||||
|
|
||||||
|
If you feel like we are not reacting fast enough (generally no more than 14 days should go by until an initial response; This is a volunteer project mostly used internally after all), please feel free to go for full disclosure via our github issue tracker, and tag the issue there by creating a title prefixed with [SECURITY].
|
||||||
|
|
||||||
|
If you find a critical vulnerability that warrants a CVE, we will also take care of issuing a CVE without any bug bounty platform having to be involved.
|
|
@ -3,10 +3,24 @@
|
||||||
# immediate exit after an error
|
# immediate exit after an error
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
testing() {
|
||||||
|
echo
|
||||||
|
echo "🔎 Checking ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
testing 'JS & CSS 🎨'
|
||||||
yarn check
|
yarn check
|
||||||
yarn lint
|
yarn lint
|
||||||
|
|
||||||
|
testing 'PHP ⚙️'
|
||||||
composer validate
|
composer validate
|
||||||
composer phpcs
|
composer phpcs
|
||||||
composer phpstan
|
composer phpstan
|
||||||
./vendor/bin/phpunit
|
./vendor/bin/phpunit
|
||||||
|
|
||||||
|
testing 'translations 🗺️'
|
||||||
|
find resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
|
||||||
|
[ "$(find resources/lang -type f -name '*.po' | wc -l)" -eq "$(find resources/lang -type f -name '*.mo' | wc -l)" ]
|
||||||
|
find resources/lang -type f -name '*.mo' -exec rm {} \;
|
||||||
|
|
||||||
|
echo '✅ Done 🎉'
|
||||||
|
|
|
@ -35,38 +35,40 @@
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ext-simplexml": "*",
|
"ext-simplexml": "*",
|
||||||
"ext-xml": "*",
|
"ext-xml": "*",
|
||||||
"doctrine/dbal": "^3.5",
|
"doctrine/dbal": "^3.6",
|
||||||
"erusev/parsedown": "^1.7",
|
"erusev/parsedown": "^1.7",
|
||||||
"gettext/gettext": "^5.7",
|
"gettext/gettext": "^5.7",
|
||||||
"gettext/translator": "^1.1",
|
"gettext/translator": "^1.1",
|
||||||
"guzzlehttp/guzzle": "^7.5",
|
"guzzlehttp/guzzle": "^7.8",
|
||||||
"illuminate/container": "^9.43",
|
"illuminate/container": "^10.23",
|
||||||
"illuminate/database": "^9.43",
|
"illuminate/database": "^10.23",
|
||||||
"illuminate/support": "^9.43",
|
"illuminate/support": "^10.23",
|
||||||
"league/oauth2-client": "^2.6",
|
"league/oauth2-client": "^2.7",
|
||||||
|
"league/openapi-psr7-validator": "^0.21",
|
||||||
"nikic/fast-route": "^1.3",
|
"nikic/fast-route": "^1.3",
|
||||||
"nyholm/psr7": "^1.5",
|
"nyholm/psr7": "^1.8",
|
||||||
"psr/container": "^2.0",
|
"psr/container": "^2.0",
|
||||||
|
"psr/http-message": "^1.1",
|
||||||
"psr/http-server-middleware": "^1.0",
|
"psr/http-server-middleware": "^1.0",
|
||||||
"psr/log": "^3.0",
|
"psr/log": "^3.0",
|
||||||
"rcrowe/twigbridge": "^0.14.0",
|
"rcrowe/twigbridge": "^0.14.0",
|
||||||
"respect/validation": "^1.1",
|
"respect/validation": "^1.1",
|
||||||
"symfony/http-foundation": "^6.2",
|
"symfony/http-foundation": "^6.3",
|
||||||
"symfony/mailer": "^6.2",
|
"symfony/mailer": "^6.3",
|
||||||
"symfony/psr-http-message-bridge": "^2.1",
|
"symfony/psr-http-message-bridge": "^2.3",
|
||||||
"twig/twig": "^3.4",
|
"twig/twig": "^3.7",
|
||||||
"vlucas/phpdotenv": "^5.5"
|
"vlucas/phpdotenv": "^5.5"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"dms/phpunit-arraysubset-asserts": "^0.4",
|
"dms/phpunit-arraysubset-asserts": "^0.5",
|
||||||
"fakerphp/faker": "^1.20",
|
"fakerphp/faker": "^1.23",
|
||||||
"fig/log-test": "^1.1",
|
"fig/log-test": "^1.1",
|
||||||
"filp/whoops": "^2.14",
|
"filp/whoops": "^2.15",
|
||||||
"phpstan/phpstan": "^1.9",
|
"phpstan/phpstan": "^1.10",
|
||||||
"phpunit/phpunit": "^9.5",
|
"phpunit/phpunit": "^9.6",
|
||||||
"slevomat/coding-standard": "^8.6",
|
"slevomat/coding-standard": "^8.13",
|
||||||
"squizlabs/php_codesniffer": "^3.7",
|
"squizlabs/php_codesniffer": "^3.7",
|
||||||
"symfony/var-dumper": "^6.2"
|
"symfony/var-dumper": "^6.3"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,7 +28,6 @@ return [
|
||||||
\Engelsystem\Renderer\TwigServiceProvider::class,
|
\Engelsystem\Renderer\TwigServiceProvider::class,
|
||||||
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
|
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
|
||||||
\Engelsystem\Middleware\RequestHandlerServiceProvider::class,
|
\Engelsystem\Middleware\RequestHandlerServiceProvider::class,
|
||||||
\Engelsystem\Middleware\SessionHandlerServiceProvider::class,
|
|
||||||
\Engelsystem\Http\Validation\ValidationServiceProvider::class,
|
\Engelsystem\Http\Validation\ValidationServiceProvider::class,
|
||||||
\Engelsystem\Http\RedirectServiceProvider::class,
|
\Engelsystem\Http\RedirectServiceProvider::class,
|
||||||
|
|
||||||
|
@ -38,6 +37,7 @@ return [
|
||||||
\Engelsystem\Http\HttpClientServiceProvider::class,
|
\Engelsystem\Http\HttpClientServiceProvider::class,
|
||||||
\Engelsystem\Helpers\DumpServerServiceProvider::class,
|
\Engelsystem\Helpers\DumpServerServiceProvider::class,
|
||||||
\Engelsystem\Helpers\UuidServiceProvider::class,
|
\Engelsystem\Helpers\UuidServiceProvider::class,
|
||||||
|
\Engelsystem\Controllers\Api\UsesAuthServiceProvider::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
// Application middleware
|
// Application middleware
|
||||||
|
@ -50,9 +50,11 @@ return [
|
||||||
\Engelsystem\Middleware\SetLocale::class,
|
\Engelsystem\Middleware\SetLocale::class,
|
||||||
\Engelsystem\Middleware\ETagHandler::class,
|
\Engelsystem\Middleware\ETagHandler::class,
|
||||||
\Engelsystem\Middleware\AddHeaders::class,
|
\Engelsystem\Middleware\AddHeaders::class,
|
||||||
|
\Engelsystem\Middleware\TrimInput::class,
|
||||||
|
|
||||||
// The application code
|
// The application code
|
||||||
\Engelsystem\Middleware\ErrorHandler::class,
|
\Engelsystem\Middleware\ErrorHandler::class,
|
||||||
|
\Engelsystem\Middleware\ApiRouteHandler::class,
|
||||||
\Engelsystem\Middleware\VerifyCsrfToken::class,
|
\Engelsystem\Middleware\VerifyCsrfToken::class,
|
||||||
\Engelsystem\Middleware\RouteDispatcher::class,
|
\Engelsystem\Middleware\RouteDispatcher::class,
|
||||||
\Engelsystem\Middleware\SessionHandler::class,
|
\Engelsystem\Middleware\SessionHandler::class,
|
||||||
|
@ -74,6 +76,7 @@ return [
|
||||||
'message.created' => \Engelsystem\Events\Listener\Messages::class . '@created',
|
'message.created' => \Engelsystem\Events\Listener\Messages::class . '@created',
|
||||||
|
|
||||||
'news.created' => \Engelsystem\Events\Listener\News::class . '@created',
|
'news.created' => \Engelsystem\Events\Listener\News::class . '@created',
|
||||||
|
'news.updated' => \Engelsystem\Events\Listener\News::class . '@updated',
|
||||||
|
|
||||||
'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login',
|
'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login',
|
||||||
|
|
||||||
|
@ -81,5 +84,7 @@ return [
|
||||||
\Engelsystem\Events\Listener\Shift::class . '@deletedEntryCreateWorklog',
|
\Engelsystem\Events\Listener\Shift::class . '@deletedEntryCreateWorklog',
|
||||||
\Engelsystem\Events\Listener\Shift::class . '@deletedEntrySendEmail',
|
\Engelsystem\Events\Listener\Shift::class . '@deletedEntrySendEmail',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'shift.updating' => \Engelsystem\Events\Listener\Shift::class . '@updatedShiftSendEmail',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -30,14 +30,24 @@ return [
|
||||||
|
|
||||||
// Header links
|
// Header links
|
||||||
// Available link placeholders: %lang%
|
// Available link placeholders: %lang%
|
||||||
|
// To disable a header_item in the config.php, you can set its value to null
|
||||||
'header_items' => [
|
'header_items' => [
|
||||||
//'Foo' => 'https://foo.bar/batz-%lang%.html',
|
// Name can be a translation string, permission is a engelsystem privilege
|
||||||
|
// 'Name' => 'URL',
|
||||||
|
// 'Name' => ['URL', 'permission'],
|
||||||
|
|
||||||
|
//'Foo' => ['https://foo.bar/batz-%lang%.html', 'logout'], // Permission: for logged-in users
|
||||||
],
|
],
|
||||||
|
|
||||||
// Footer links
|
// Footer links
|
||||||
|
// To disable a footer item in the config.php, you can set its value to null
|
||||||
'footer_items' => [
|
'footer_items' => [
|
||||||
|
// Name can be a translation string, permission is a engelsystem privilege
|
||||||
|
// 'Name' => 'URL',
|
||||||
|
// 'Name' => ['URL', 'permission'],
|
||||||
|
|
||||||
// URL to the angel faq and job description
|
// URL to the angel faq and job description
|
||||||
'FAQ' => env('FAQ_URL', '/faq'),
|
'faq.faq' => [env('FAQ_URL', '/faq'), 'faq.view'],
|
||||||
|
|
||||||
// Contact email address, linked on every page
|
// Contact email address, linked on every page
|
||||||
'Contact' => env('CONTACT_EMAIL', 'mailto:ticket@c3heaven.de'),
|
'Contact' => env('CONTACT_EMAIL', 'mailto:ticket@c3heaven.de'),
|
||||||
|
@ -131,7 +141,14 @@ return [
|
||||||
// Default theme, 1=style1.css
|
// Default theme, 1=style1.css
|
||||||
'theme' => env('THEME', 1),
|
'theme' => env('THEME', 1),
|
||||||
|
|
||||||
|
// Supported themes
|
||||||
|
// To disable a theme in the config.php, you can set its value to null
|
||||||
'themes' => [
|
'themes' => [
|
||||||
|
16 => [
|
||||||
|
'name' => 'Engelsystem cccamp23 (2023)',
|
||||||
|
'type' => 'dark',
|
||||||
|
'navbar_classes' => 'navbar-dark',
|
||||||
|
],
|
||||||
15 => [
|
15 => [
|
||||||
'name' => 'Engelsystem rC3 (2021)',
|
'name' => 'Engelsystem rC3 (2021)',
|
||||||
'type' => 'dark',
|
'type' => 'dark',
|
||||||
|
@ -224,6 +241,16 @@ return [
|
||||||
// Users are able to sign up
|
// Users are able to sign up
|
||||||
'registration_enabled' => (bool) env('REGISTRATION_ENABLED', true),
|
'registration_enabled' => (bool) env('REGISTRATION_ENABLED', true),
|
||||||
|
|
||||||
|
// Required user fields
|
||||||
|
'required_user_fields' => [
|
||||||
|
'pronoun' => (bool) env('PRONOUN_REQUIRED', false),
|
||||||
|
'firstname' => (bool) env('FIRSTNAME_REQUIRED', false),
|
||||||
|
'lastname' => (bool) env('LASTNAME_REQUIRED', false),
|
||||||
|
'tshirt_size' => (bool) env('TSHIRT_SIZE_REQUIRED', true),
|
||||||
|
'mobile' => (bool) env('MOBILE_REQUIRED', false),
|
||||||
|
'dect' => (bool) env('DECT_REQUIRED', false),
|
||||||
|
],
|
||||||
|
|
||||||
// Only arrived angels can sign up for shifts
|
// Only arrived angels can sign up for shifts
|
||||||
'signup_requires_arrival' => (bool) env('SIGNUP_REQUIRES_ARRIVAL', false),
|
'signup_requires_arrival' => (bool) env('SIGNUP_REQUIRES_ARRIVAL', false),
|
||||||
|
|
||||||
|
@ -268,7 +295,7 @@ return [
|
||||||
|
|
||||||
// Regular expression describing a FALSE username.
|
// Regular expression describing a FALSE username.
|
||||||
// Per default usernames must only contain alphanumeric chars, "-", "_" or ".".
|
// Per default usernames must only contain alphanumeric chars, "-", "_" or ".".
|
||||||
'username_regex' => (string) env('USERNAME_REGEX', '/([^\p{L}\p{N}\-_.]+)/ui'),
|
'username_regex' => (string) env('USERNAME_REGEX', '/([^\p{L}\p{N}_.-]+)/ui'),
|
||||||
|
|
||||||
// Enables first name and last name
|
// Enables first name and last name
|
||||||
'enable_user_name' => (bool) env('ENABLE_USER_NAME', false),
|
'enable_user_name' => (bool) env('ENABLE_USER_NAME', false),
|
||||||
|
@ -318,7 +345,15 @@ return [
|
||||||
'voucher_start' => env('VOUCHER_START', null) ?: null,
|
'voucher_start' => env('VOUCHER_START', null) ?: null,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
# Instruction in accordance with § 43 Para. 1 of the German Infection Protection Act (IfSG)
|
||||||
|
'ifsg_enabled' => (bool) env('IFSG_ENABLED', false),
|
||||||
|
|
||||||
|
# Instruction only onsite in accordance with § 43 Para. 1 of the German Infection Protection Act (IfSG)
|
||||||
|
'ifsg_light_enabled' => (bool) env('IFSG_LIGHT_ENABLED', false)
|
||||||
|
&& env('IFSG_ENABLED', false),
|
||||||
|
|
||||||
// Available locales in /resources/lang/
|
// Available locales in /resources/lang/
|
||||||
|
// To disable a locale in the config.php, you can set its value to null
|
||||||
'locales' => [
|
'locales' => [
|
||||||
'de_DE' => 'Deutsch',
|
'de_DE' => 'Deutsch',
|
||||||
'en_US' => 'English',
|
'en_US' => 'English',
|
||||||
|
@ -327,21 +362,28 @@ return [
|
||||||
// The default locale to use
|
// The default locale to use
|
||||||
'default_locale' => env('DEFAULT_LOCALE', 'en_US'),
|
'default_locale' => env('DEFAULT_LOCALE', 'en_US'),
|
||||||
|
|
||||||
// Available T-Shirt sizes, set value to null if not available
|
// Available T-Shirt sizes
|
||||||
|
// To disable a t-shirt size in the config.php, you can set its value to null
|
||||||
'tshirt_sizes' => [
|
'tshirt_sizes' => [
|
||||||
'S' => 'Small Straight-Cut',
|
'S' => 'Small Straight-Cut',
|
||||||
'S-G' => 'Small Fitted-Cut',
|
'S-F' => 'Small Fitted-Cut',
|
||||||
'M' => 'Medium Straight-Cut',
|
'M' => 'Medium Straight-Cut',
|
||||||
'M-G' => 'Medium Fitted-Cut',
|
'M-F' => 'Medium Fitted-Cut',
|
||||||
'L' => 'Large Straight-Cut',
|
'L' => 'Large Straight-Cut',
|
||||||
'L-G' => 'Large Fitted-Cut',
|
'L-F' => 'Large Fitted-Cut',
|
||||||
'XL' => 'XLarge Straight-Cut',
|
'XL' => 'XLarge Straight-Cut',
|
||||||
'XL-G' => 'XLarge Fitted-Cut',
|
'XL-F' => 'XLarge Fitted-Cut',
|
||||||
'2XL' => '2XLarge Straight-Cut',
|
'2XL' => '2XLarge Straight-Cut',
|
||||||
'3XL' => '3XLarge Straight-Cut',
|
'3XL' => '3XLarge Straight-Cut',
|
||||||
'4XL' => '4XLarge Straight-Cut',
|
'4XL' => '4XLarge Straight-Cut',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// Whether to show the current day of the event (-2, -1, 0, 1, 2…) in footer and on the dashboard.
|
||||||
|
// The event start date has to be set for it to appear.
|
||||||
|
'enable_show_day_of_event' => false,
|
||||||
|
// If true there will be a day 0 (-1, 0, 1…). If false there won't (-1, 1…)
|
||||||
|
'event_has_day0' => true,
|
||||||
|
|
||||||
'metrics' => [
|
'metrics' => [
|
||||||
// User work buckets in seconds
|
// User work buckets in seconds
|
||||||
'work' => [1 * 60 * 60, 1.5 * 60 * 60, 2 * 60 * 60, 3 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 20 * 60 * 60],
|
'work' => [1 * 60 * 60, 1.5 * 60 * 60, 2 * 60 * 60, 3 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 20 * 60 * 60],
|
||||||
|
@ -370,6 +412,8 @@ return [
|
||||||
|
|
||||||
// Add additional headers
|
// Add additional headers
|
||||||
'add_headers' => (bool) env('ADD_HEADERS', true),
|
'add_headers' => (bool) env('ADD_HEADERS', true),
|
||||||
|
// Predefined headers
|
||||||
|
// To disable a header in the config.php, you can set its value to null
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'X-Content-Type-Options' => 'nosniff',
|
'X-Content-Type-Options' => 'nosniff',
|
||||||
'X-Frame-Options' => 'sameorigin',
|
'X-Frame-Options' => 'sameorigin',
|
||||||
|
|
|
@ -8,6 +8,8 @@ use FastRoute\RouteCollector;
|
||||||
|
|
||||||
// Pages
|
// Pages
|
||||||
$route->get('/', 'HomeController@index');
|
$route->get('/', 'HomeController@index');
|
||||||
|
$route->get('/register', 'RegistrationController@view');
|
||||||
|
$route->post('/register', 'RegistrationController@save');
|
||||||
$route->get('/credits', 'CreditsController@index');
|
$route->get('/credits', 'CreditsController@index');
|
||||||
$route->get('/health', 'HealthController@index');
|
$route->get('/health', 'HealthController@index');
|
||||||
|
|
||||||
|
@ -38,7 +40,14 @@ $route->addGroup(
|
||||||
$route->post('/theme', 'SettingsController@saveTheme');
|
$route->post('/theme', 'SettingsController@saveTheme');
|
||||||
$route->get('/language', 'SettingsController@language');
|
$route->get('/language', 'SettingsController@language');
|
||||||
$route->post('/language', 'SettingsController@saveLanguage');
|
$route->post('/language', 'SettingsController@saveLanguage');
|
||||||
|
$route->get('/certificates', 'SettingsController@certificate');
|
||||||
|
$route->post('/certificates/ifsg', 'SettingsController@saveIfsgCertificate');
|
||||||
|
$route->post('/certificates/driving', 'SettingsController@saveDrivingLicense');
|
||||||
|
$route->get('/api', 'SettingsController@api');
|
||||||
|
$route->post('/api', 'SettingsController@apiKeyReset');
|
||||||
$route->get('/oauth', 'SettingsController@oauth');
|
$route->get('/oauth', 'SettingsController@oauth');
|
||||||
|
$route->get('/sessions', 'SettingsController@sessions');
|
||||||
|
$route->post('/sessions', 'SettingsController@sessionsDelete');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -62,6 +71,11 @@ $route->addGroup('/angeltypes', function (RouteCollector $route): void {
|
||||||
$route->get('/about', 'AngelTypesController@about');
|
$route->get('/about', 'AngelTypesController@about');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Shifts
|
||||||
|
$route->addGroup('/shifts', function (RouteCollector $route): void {
|
||||||
|
$route->get('/random', 'ShiftsController@random');
|
||||||
|
});
|
||||||
|
|
||||||
// News
|
// News
|
||||||
$route->get('/meetings', 'NewsController@meetings');
|
$route->get('/meetings', 'NewsController@meetings');
|
||||||
$route->addGroup(
|
$route->addGroup(
|
||||||
|
@ -101,7 +115,42 @@ $route->addGroup(
|
||||||
);
|
);
|
||||||
|
|
||||||
// API
|
// API
|
||||||
$route->get('/api[/{resource:.+}]', 'ApiController@index');
|
$route->addGroup(
|
||||||
|
'/api',
|
||||||
|
function (RouteCollector $route): void {
|
||||||
|
$route->get('', 'Api\IndexController@index');
|
||||||
|
|
||||||
|
$route->addGroup(
|
||||||
|
'/v0-beta',
|
||||||
|
function (RouteCollector $route): void {
|
||||||
|
$route->addRoute(['OPTIONS'], '[/{resource:.+}]', 'Api\IndexController@options');
|
||||||
|
$route->get('', 'Api\IndexController@indexV0');
|
||||||
|
$route->get('/openapi', 'Api\IndexController@openApiV0');
|
||||||
|
$route->get('/info', 'Api\IndexController@info');
|
||||||
|
|
||||||
|
$route->get('/angeltypes', 'Api\AngelTypeController@index');
|
||||||
|
$route->get('/angeltypes/{angeltype_id:\d+}/shifts', 'Api\ShiftsController@entriesByAngeltype');
|
||||||
|
|
||||||
|
$route->get('/locations', 'Api\LocationsController@index');
|
||||||
|
$route->get('/locations/{location_id:\d+}/shifts', 'Api\ShiftsController@entriesByLocation');
|
||||||
|
|
||||||
|
$route->get('/news', 'Api\NewsController@index');
|
||||||
|
|
||||||
|
$route->get('/users/{user_id:(?:\d+|self)}', 'Api\UsersController@user');
|
||||||
|
$route->get('/users/{user_id:(?:\d+|self)}/angeltypes', 'Api\AngelTypeController@ofUser');
|
||||||
|
$route->get('/users/{user_id:(?:\d+|self)}/shifts', 'Api\ShiftsController@entriesByUser');
|
||||||
|
|
||||||
|
$route->addRoute(
|
||||||
|
['POST', 'PUT', 'DELETE', 'PATCH'],
|
||||||
|
'/[{resource:.+}]',
|
||||||
|
'Api\IndexController@notImplemented'
|
||||||
|
);
|
||||||
|
$route->get('/[{resource:.+}]', 'Api\IndexController@notFound');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$route->get('/[{resource:.+}]', 'Api\IndexController@notFound');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Feeds
|
// Feeds
|
||||||
$route->get('/atom', 'FeedController@atom');
|
$route->get('/atom', 'FeedController@atom');
|
||||||
|
@ -146,6 +195,27 @@ $route->addGroup(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Shifts
|
||||||
|
$route->addGroup(
|
||||||
|
'/shifts',
|
||||||
|
function (RouteCollector $route): void {
|
||||||
|
$route->get('/history', 'Admin\\ShiftsController@history');
|
||||||
|
$route->post('/history', 'Admin\\ShiftsController@deleteTransaction');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Shift types
|
||||||
|
$route->addGroup(
|
||||||
|
'/shifttypes',
|
||||||
|
function (RouteCollector $route): void {
|
||||||
|
$route->get('', 'Admin\\ShiftTypesController@index');
|
||||||
|
$route->post('', 'Admin\\ShiftTypesController@delete');
|
||||||
|
$route->get('/{shift_type_id:\d+}', 'Admin\\ShiftTypesController@view');
|
||||||
|
$route->get('/edit[/{shift_type_id:\d+}]', 'Admin\\ShiftTypesController@edit');
|
||||||
|
$route->post('/edit[/{shift_type_id:\d+}]', 'Admin\\ShiftTypesController@save');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Questions
|
// Questions
|
||||||
$route->addGroup(
|
$route->addGroup(
|
||||||
'/questions',
|
'/questions',
|
||||||
|
@ -157,14 +227,14 @@ $route->addGroup(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Rooms
|
// Locations
|
||||||
$route->addGroup(
|
$route->addGroup(
|
||||||
'/rooms',
|
'/locations',
|
||||||
function (RouteCollector $route): void {
|
function (RouteCollector $route): void {
|
||||||
$route->get('', 'Admin\\RoomsController@index');
|
$route->get('', 'Admin\\LocationsController@index');
|
||||||
$route->post('', 'Admin\\RoomsController@delete');
|
$route->post('', 'Admin\\LocationsController@delete');
|
||||||
$route->get('/edit[/{room_id:\d+}]', 'Admin\\RoomsController@edit');
|
$route->get('/edit[/{location_id:\d+}]', 'Admin\\LocationsController@edit');
|
||||||
$route->post('/edit[/{room_id:\d+}]', 'Admin\\RoomsController@save');
|
$route->post('/edit[/{location_id:\d+}]', 'Admin\\LocationsController@save');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,11 @@ class AngelTypeFactory extends Factory
|
||||||
|
|
||||||
'restricted' => $this->faker->boolean(),
|
'restricted' => $this->faker->boolean(),
|
||||||
'requires_driver_license' => $this->faker->boolean(),
|
'requires_driver_license' => $this->faker->boolean(),
|
||||||
'no_self_signup' => $this->faker->boolean(),
|
'requires_ifsg_certificate' => $this->faker->boolean(),
|
||||||
|
'shift_self_signup' => $this->faker->boolean(),
|
||||||
'show_on_dashboard' => $this->faker->boolean(),
|
'show_on_dashboard' => $this->faker->boolean(),
|
||||||
'hide_register' => $this->faker->boolean(),
|
'hide_register' => $this->faker->boolean(),
|
||||||
|
'hide_on_shift_view' => $this->faker->boolean(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Database\Factories\Engelsystem\Models;
|
namespace Database\Factories\Engelsystem\Models;
|
||||||
|
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class RoomFactory extends Factory
|
class LocationFactory extends Factory
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $model = Room::class; // phpcs:ignore
|
protected $model = Location::class; // phpcs:ignore
|
||||||
|
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,7 @@ class RoomFactory extends Factory
|
||||||
'name' => $this->faker->unique()->firstName(),
|
'name' => $this->faker->unique()->firstName(),
|
||||||
'map_url' => $this->faker->url(),
|
'map_url' => $this->faker->url(),
|
||||||
'description' => $this->faker->text(),
|
'description' => $this->faker->text(),
|
||||||
|
'dect' => $this->faker->optional()->numberBetween(1000, 9999),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,12 +16,12 @@ class NewsFactory extends Factory
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'title' => $this->faker->text(50),
|
'title' => $this->faker->text(50),
|
||||||
'text' => $this->faker->realText(),
|
'text' => $this->faker->realText(),
|
||||||
'is_meeting' => $this->faker->boolean(),
|
'is_meeting' => $this->faker->boolean(),
|
||||||
'is_pinned' => $this->faker->boolean(.1),
|
'is_pinned' => $this->faker->boolean(.1),
|
||||||
'is_important' => $this->faker->boolean(.1),
|
'is_highlighted' => $this->faker->boolean(.1),
|
||||||
'user_id' => User::factory(),
|
'user_id' => User::factory(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Database\Factories\Engelsystem\Models;
|
||||||
|
|
||||||
|
use Engelsystem\Models\OAuth;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
class OAuthFactory extends Factory
|
||||||
|
{
|
||||||
|
/** @var class-string */
|
||||||
|
protected $model = OAuth::class; // phpcs:ignore
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'user_id' => User::factory(),
|
||||||
|
'provider' => $this->faker->unique()->word(),
|
||||||
|
'identifier' => $this->faker->unique()->word(),
|
||||||
|
'access_token' => $this->faker->unique()->word(),
|
||||||
|
'refresh_token' => $this->faker->unique()->word(),
|
||||||
|
'expires_at' => $this->faker->dateTimeInInterval('+5 days', '+3 months')->format('Y-m-d'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Database\Factories\Engelsystem\Models;
|
||||||
|
|
||||||
|
use Engelsystem\Models\Session;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
class SessionFactory extends Factory
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
protected $model = Session::class; // phpcs:ignore
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->faker->lexify('????????????????????????????????'),
|
||||||
|
'payload' => $this->faker->text(100),
|
||||||
|
'user_id' => $this->faker->optional()->passthrough(User::factory()),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||||
namespace Database\Factories\Engelsystem\Models\Shifts;
|
namespace Database\Factories\Engelsystem\Models\Shifts;
|
||||||
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
@ -17,11 +17,12 @@ class NeededAngelTypeFactory extends Factory
|
||||||
|
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
$forRoom = $this->faker->boolean();
|
$type = $this->faker->numberBetween(0, 2);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'room_id' => $forRoom ? Room::factory() : null,
|
'location_id' => $type == 0 ? Location::factory() : null,
|
||||||
'shift_id' => $forRoom ? null : Shift::factory(),
|
'shift_id' => $type == 1 ? null : Shift::factory(),
|
||||||
|
'shift_type_id' => $type == 2 ? null : Shift::factory(),
|
||||||
'angel_type_id' => AngelType::factory(),
|
'angel_type_id' => AngelType::factory(),
|
||||||
'count' => $this->faker->numberBetween(1, 5),
|
'count' => $this->faker->numberBetween(1, 5),
|
||||||
];
|
];
|
||||||
|
|
|
@ -18,6 +18,7 @@ class ScheduleFactory extends Factory
|
||||||
'name' => $this->faker->unique()->words(4, true),
|
'name' => $this->faker->unique()->words(4, true),
|
||||||
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
|
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
|
||||||
'shift_type' => $this->faker->numberBetween(1, 5),
|
'shift_type' => $this->faker->numberBetween(1, 5),
|
||||||
|
'needed_from_shift_type' => $this->faker->boolean(.2),
|
||||||
'minutes_before' => 15,
|
'minutes_before' => 15,
|
||||||
'minutes_after' => 15,
|
'minutes_after' => 15,
|
||||||
];
|
];
|
||||||
|
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Database\Factories\Engelsystem\Models\Shifts;
|
namespace Database\Factories\Engelsystem\Models\Shifts;
|
||||||
|
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
|
@ -25,7 +25,7 @@ class ShiftFactory extends Factory
|
||||||
'start' => $start,
|
'start' => $start,
|
||||||
'end' => $this->faker->dateTimeInInterval($start, '+3 hours'),
|
'end' => $this->faker->dateTimeInInterval($start, '+3 hours'),
|
||||||
'shift_type_id' => ShiftType::factory(),
|
'shift_type_id' => ShiftType::factory(),
|
||||||
'room_id' => Room::factory(),
|
'location_id' => Location::factory(),
|
||||||
'transaction_id' => $this->faker->optional()->uuid(),
|
'transaction_id' => $this->faker->optional()->uuid(),
|
||||||
'created_by' => User::factory(),
|
'created_by' => User::factory(),
|
||||||
'updated_by' => $this->faker->optional(.3)->boolean() ? User::factory() : null,
|
'updated_by' => $this->faker->optional(.3)->boolean() ? User::factory() : null,
|
||||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||||
namespace Database\Factories\Engelsystem\Models\User;
|
namespace Database\Factories\Engelsystem\Models\User;
|
||||||
|
|
||||||
use Engelsystem\Models\User\Contact;
|
use Engelsystem\Models\User\Contact;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class ContactFactory extends Factory
|
class ContactFactory extends Factory
|
||||||
|
@ -15,6 +16,7 @@ class ContactFactory extends Factory
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'user_id' => User::factory(),
|
||||||
'dect' => $this->faker->optional()->numberBetween(1000, 9999),
|
'dect' => $this->faker->optional()->numberBetween(1000, 9999),
|
||||||
'email' => $this->faker->unique()->optional()->safeEmail(),
|
'email' => $this->faker->unique()->optional()->safeEmail(),
|
||||||
'mobile' => $this->faker->optional(.2)->phoneNumber(),
|
'mobile' => $this->faker->optional(.2)->phoneNumber(),
|
||||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||||
namespace Database\Factories\Engelsystem\Models\User;
|
namespace Database\Factories\Engelsystem\Models\User;
|
||||||
|
|
||||||
use Engelsystem\Models\User\License;
|
use Engelsystem\Models\User\License;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class LicenseFactory extends Factory
|
class LicenseFactory extends Factory
|
||||||
|
@ -21,13 +22,19 @@ class LicenseFactory extends Factory
|
||||||
$drive_forklift = ($drive_car && $this->faker->boolean(.1))
|
$drive_forklift = ($drive_car && $this->faker->boolean(.1))
|
||||||
|| ($drive_12t && $this->faker->boolean(.7));
|
|| ($drive_12t && $this->faker->boolean(.7));
|
||||||
|
|
||||||
|
$ifsg_certificate = $this->faker->boolean(0.1);
|
||||||
|
$ifsg_certificate_light = $this->faker->boolean(0.5) && !$ifsg_certificate;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'has_car' => $drive_car && $this->faker->boolean(.7),
|
'user_id' => User::factory(),
|
||||||
'drive_forklift' => $drive_forklift,
|
'has_car' => $drive_car && $this->faker->boolean(.7),
|
||||||
'drive_car' => $drive_car,
|
'drive_forklift' => $drive_forklift,
|
||||||
'drive_3_5t' => $drive_3_5t,
|
'drive_car' => $drive_car,
|
||||||
'drive_7_5t' => $drive_7_5t,
|
'drive_3_5t' => $drive_3_5t,
|
||||||
'drive_12t' => $drive_12t,
|
'drive_7_5t' => $drive_7_5t,
|
||||||
|
'drive_12t' => $drive_12t,
|
||||||
|
'ifsg_certificate' => $ifsg_certificate,
|
||||||
|
'ifsg_certificate_light' => $ifsg_certificate_light,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||||
namespace Database\Factories\Engelsystem\Models\User;
|
namespace Database\Factories\Engelsystem\Models\User;
|
||||||
|
|
||||||
use Engelsystem\Models\User\PasswordReset;
|
use Engelsystem\Models\User\PasswordReset;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class PasswordResetFactory extends Factory
|
class PasswordResetFactory extends Factory
|
||||||
|
@ -15,6 +16,7 @@ class PasswordResetFactory extends Factory
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'user_id' => User::factory(),
|
||||||
'token' => bin2hex(random_bytes(16)),
|
'token' => bin2hex(random_bytes(16)),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace Database\Factories\Engelsystem\Models\User;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Engelsystem\Models\User\PersonalData;
|
use Engelsystem\Models\User\PersonalData;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class PersonalDataFactory extends Factory
|
class PersonalDataFactory extends Factory
|
||||||
|
@ -19,6 +20,7 @@ class PersonalDataFactory extends Factory
|
||||||
$departure = $this->faker->optional()->dateTimeThisMonth('2 weeks');
|
$departure = $this->faker->optional()->dateTimeThisMonth('2 weeks');
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'user_id' => User::factory(),
|
||||||
'first_name' => $this->faker->optional(.7)->firstName(),
|
'first_name' => $this->faker->optional(.7)->firstName(),
|
||||||
'last_name' => $this->faker->optional()->lastName(),
|
'last_name' => $this->faker->optional()->lastName(),
|
||||||
'pronoun' => $this->faker->optional(.3)->pronoun(),
|
'pronoun' => $this->faker->optional(.3)->pronoun(),
|
||||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||||
namespace Database\Factories\Engelsystem\Models\User;
|
namespace Database\Factories\Engelsystem\Models\User;
|
||||||
|
|
||||||
use Engelsystem\Models\User\Settings;
|
use Engelsystem\Models\User\Settings;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class SettingsFactory extends Factory
|
class SettingsFactory extends Factory
|
||||||
|
@ -15,6 +16,7 @@ class SettingsFactory extends Factory
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'user_id' => User::factory(),
|
||||||
'language' => $this->faker->locale(),
|
'language' => $this->faker->locale(),
|
||||||
'theme' => $this->faker->numberBetween(1, 20),
|
'theme' => $this->faker->numberBetween(1, 20),
|
||||||
'email_human' => $this->faker->boolean(),
|
'email_human' => $this->faker->boolean(),
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace Database\Factories\Engelsystem\Models\User;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Engelsystem\Models\User\State;
|
use Engelsystem\Models\User\State;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class StateFactory extends Factory
|
class StateFactory extends Factory
|
||||||
|
@ -18,8 +19,10 @@ class StateFactory extends Factory
|
||||||
$arrival = $this->faker->optional()->dateTimeThisMonth();
|
$arrival = $this->faker->optional()->dateTimeThisMonth();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'user_id' => User::factory(),
|
||||||
'arrived' => (bool) $arrival,
|
'arrived' => (bool) $arrival,
|
||||||
'arrival_date' => $arrival ? Carbon::instance($arrival) : null,
|
'arrival_date' => $arrival ? Carbon::instance($arrival) : null,
|
||||||
|
'user_info' => $this->faker->optional(.1)->text(),
|
||||||
'active' => $this->faker->boolean(.3),
|
'active' => $this->faker->boolean(.3),
|
||||||
'force_active' => $this->faker->boolean(.1),
|
'force_active' => $this->faker->boolean(.1),
|
||||||
'got_shirt' => $this->faker->boolean(),
|
'got_shirt' => $this->faker->boolean(),
|
||||||
|
|
|
@ -19,6 +19,7 @@ class UserFactory extends Factory
|
||||||
'password' => crypt(random_bytes(16), '$1$salt$'),
|
'password' => crypt(random_bytes(16), '$1$salt$'),
|
||||||
'email' => $this->faker->unique()->safeEmail(),
|
'email' => $this->faker->unique()->safeEmail(),
|
||||||
'api_key' => bin2hex(random_bytes(32)),
|
'api_key' => bin2hex(random_bytes(32)),
|
||||||
|
'updated_at' => $this->faker->dateTimeInInterval('-3 months', 'now'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
802
db/install.sql
802
db/install.sql
|
@ -1,802 +0,0 @@
|
||||||
-- phpMyAdmin SQL Dump
|
|
||||||
-- version 4.5.2
|
|
||||||
-- http://www.phpmyadmin.net
|
|
||||||
--
|
|
||||||
-- Host: localhost
|
|
||||||
-- Erstellungszeit: 27. Sep 2016 um 17:48
|
|
||||||
-- Server-Version: 10.1.10-MariaDB
|
|
||||||
-- PHP-Version: 7.0.4
|
|
||||||
|
|
||||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
|
||||||
SET time_zone = "+00:00";
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Datenbank: `engelsystem`
|
|
||||||
--
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `AngelTypes`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `AngelTypes`;
|
|
||||||
CREATE TABLE `AngelTypes` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`name` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`restricted` int(1) NOT NULL,
|
|
||||||
`description` text NOT NULL,
|
|
||||||
`requires_driver_license` tinyint(1) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `EventConfig`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `EventConfig`;
|
|
||||||
CREATE TABLE `EventConfig` (
|
|
||||||
`event_name` varchar(255) DEFAULT NULL,
|
|
||||||
`buildup_start_date` int(11) DEFAULT NULL,
|
|
||||||
`event_start_date` int(11) DEFAULT NULL,
|
|
||||||
`event_end_date` int(11) DEFAULT NULL,
|
|
||||||
`teardown_end_date` int(11) DEFAULT NULL,
|
|
||||||
`event_welcome_msg` varchar(255) DEFAULT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `GroupPrivileges`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `GroupPrivileges`;
|
|
||||||
CREATE TABLE `GroupPrivileges` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`group_id` int(11) NOT NULL,
|
|
||||||
`privilege_id` int(11) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Daten für Tabelle `GroupPrivileges`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `GroupPrivileges` (`id`, `group_id`, `privilege_id`) VALUES
|
|
||||||
(85, -7, 10),
|
|
||||||
(87, -7, 18),
|
|
||||||
(86, -7, 21),
|
|
||||||
(216, -6, 5),
|
|
||||||
(212, -6, 6),
|
|
||||||
(207, -6, 7),
|
|
||||||
(211, -6, 12),
|
|
||||||
(208, -6, 13),
|
|
||||||
(210, -6, 14),
|
|
||||||
(214, -6, 16),
|
|
||||||
(209, -6, 21),
|
|
||||||
(213, -6, 28),
|
|
||||||
(206, -6, 31),
|
|
||||||
(215, -6, 33),
|
|
||||||
(257, -6, 38),
|
|
||||||
(219, -5, 14),
|
|
||||||
(221, -5, 25),
|
|
||||||
(220, -5, 33),
|
|
||||||
(241, -4, 5),
|
|
||||||
(238, -4, 14),
|
|
||||||
(240, -4, 16),
|
|
||||||
(237, -4, 19),
|
|
||||||
(242, -4, 25),
|
|
||||||
(235, -4, 27),
|
|
||||||
(239, -4, 28),
|
|
||||||
(236, -4, 32),
|
|
||||||
(218, -4, 39),
|
|
||||||
(258, -3, 31),
|
|
||||||
(247, -2, 3),
|
|
||||||
(246, -2, 4),
|
|
||||||
(255, -2, 8),
|
|
||||||
(252, -2, 9),
|
|
||||||
(254, -2, 11),
|
|
||||||
(248, -2, 15),
|
|
||||||
(251, -2, 17),
|
|
||||||
(256, -2, 24),
|
|
||||||
(253, -2, 26),
|
|
||||||
(245, -2, 30),
|
|
||||||
(244, -2, 34),
|
|
||||||
(249, -2, 35),
|
|
||||||
(243, -2, 36),
|
|
||||||
(250, -2, 37),
|
|
||||||
(88, -1, 1),
|
|
||||||
(23, -1, 2),
|
|
||||||
(24, -1, 5);
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `Groups`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `Groups`;
|
|
||||||
CREATE TABLE `Groups` (
|
|
||||||
`Name` varchar(35) NOT NULL,
|
|
||||||
`UID` int(11) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Daten für Tabelle `Groups`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `Groups` (`Name`, `UID`) VALUES
|
|
||||||
('6-Developer', -7),
|
|
||||||
('5-Bürokrat', -6),
|
|
||||||
('4-Team Coordinator', -5),
|
|
||||||
('3-Shift Coordinator', -4),
|
|
||||||
('Shirt-Manager', -3),
|
|
||||||
('2-Engel', -2),
|
|
||||||
('1-Gast', -1);
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `LogEntries`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `LogEntries`;
|
|
||||||
CREATE TABLE `LogEntries` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`timestamp` int(11) NOT NULL,
|
|
||||||
`nick` text NOT NULL,
|
|
||||||
`message` text NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `Messages`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `Messages`;
|
|
||||||
CREATE TABLE `Messages` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`Datum` int(11) NOT NULL,
|
|
||||||
`SUID` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`RUID` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`isRead` char(1) NOT NULL DEFAULT 'N',
|
|
||||||
`Text` text NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Fuers interen Communikationssystem';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `NeededAngelTypes`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `NeededAngelTypes`;
|
|
||||||
CREATE TABLE `NeededAngelTypes` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`room_id` int(11) DEFAULT NULL,
|
|
||||||
`shift_id` int(11) DEFAULT NULL,
|
|
||||||
`angel_type_id` int(11) NOT NULL,
|
|
||||||
`count` int(11) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `News`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `News`;
|
|
||||||
CREATE TABLE `News` (
|
|
||||||
`ID` int(11) NOT NULL,
|
|
||||||
`Datum` int(11) NOT NULL,
|
|
||||||
`Betreff` varchar(150) NOT NULL DEFAULT '',
|
|
||||||
`Text` text NOT NULL,
|
|
||||||
`UID` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`Treffen` tinyint(4) NOT NULL DEFAULT '0'
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `NewsComments`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `NewsComments`;
|
|
||||||
CREATE TABLE `NewsComments` (
|
|
||||||
`ID` bigint(11) NOT NULL,
|
|
||||||
`Refid` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`Datum` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
|
|
||||||
`Text` text NOT NULL,
|
|
||||||
`UID` int(11) NOT NULL DEFAULT '0'
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `Privileges`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `Privileges`;
|
|
||||||
CREATE TABLE `Privileges` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`name` varchar(128) NOT NULL,
|
|
||||||
`desc` varchar(1024) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Daten für Tabelle `Privileges`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES
|
|
||||||
(1, 'start', 'Startseite für Gäste/Nicht eingeloggte User'),
|
|
||||||
(2, 'login', 'Logindialog'),
|
|
||||||
(3, 'news', 'Anzeigen der News-Seite'),
|
|
||||||
(4, 'logout', 'User darf sich ausloggen'),
|
|
||||||
(5, 'register', 'Einen neuen Engel registerieren'),
|
|
||||||
(6, 'admin_rooms', 'Räume administrieren'),
|
|
||||||
(7, 'admin_angel_types', 'Engel Typen administrieren'),
|
|
||||||
(8, 'user_settings', 'User profile settings'),
|
|
||||||
(9, 'user_messages', 'Writing and reading messages from user to user'),
|
|
||||||
(10, 'admin_groups', 'Manage usergroups and their rights'),
|
|
||||||
(11, 'user_questions', 'Let users ask questions'),
|
|
||||||
(12, 'admin_questions', 'Answer user''s questions'),
|
|
||||||
(13, 'admin_faq', 'Edit FAQs'),
|
|
||||||
(14, 'admin_news', 'Administrate the news section'),
|
|
||||||
(15, 'news_comments', 'User can comment news'),
|
|
||||||
(16, 'admin_user', 'Administrate the angels'),
|
|
||||||
(17, 'user_meetings', 'Lists meetings (news)'),
|
|
||||||
(18, 'admin_language', 'Translate the system'),
|
|
||||||
(19, 'admin_log', 'Display recent changes'),
|
|
||||||
(20, 'user_wakeup', 'User wakeup-service organization'),
|
|
||||||
(21, 'admin_import', 'Import rooms and shifts from pentabarf'),
|
|
||||||
(22, 'credits', 'View credits'),
|
|
||||||
(23, 'faq', 'View FAQ'),
|
|
||||||
(24, 'user_shifts', 'Signup for shifts'),
|
|
||||||
(25, 'user_shifts_admin', 'Signup other angels for shifts.'),
|
|
||||||
(26, 'user_myshifts', 'Allow angels to view their own shifts and cancel them.'),
|
|
||||||
(27, 'admin_arrive', 'Mark angels when they arrive.'),
|
|
||||||
(28, 'admin_shifts', 'Create shifts'),
|
|
||||||
(30, 'ical', 'iCal shift export'),
|
|
||||||
(31, 'admin_active', 'Mark angels as active and if they got a t-shirt.'),
|
|
||||||
(32, 'admin_free', 'Show a list of free/unemployed angels.'),
|
|
||||||
(33, 'admin_user_angeltypes', 'Confirm restricted angel types'),
|
|
||||||
(34, 'atom', ' Atom news export'),
|
|
||||||
(35, 'shifts_json_export', 'Export shifts in JSON format'),
|
|
||||||
(36, 'angeltypes', 'View angeltypes'),
|
|
||||||
(37, 'user_angeltypes', 'Join angeltypes.'),
|
|
||||||
(38, 'shifttypes', 'Administrate shift types'),
|
|
||||||
(39, 'admin_event_config', 'Allow editing event config');
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `Questions`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `Questions`;
|
|
||||||
CREATE TABLE `Questions` (
|
|
||||||
`QID` bigint(20) NOT NULL,
|
|
||||||
`UID` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`Question` text NOT NULL,
|
|
||||||
`AID` int(11) DEFAULT NULL,
|
|
||||||
`Answer` text
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Fragen und Antworten';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `Room`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `Room`;
|
|
||||||
CREATE TABLE `Room` (
|
|
||||||
`RID` int(11) NOT NULL,
|
|
||||||
`Name` varchar(35) NOT NULL DEFAULT '',
|
|
||||||
`Man` text,
|
|
||||||
`FromPentabarf` char(1) NOT NULL DEFAULT 'N',
|
|
||||||
`show` char(1) NOT NULL DEFAULT 'Y',
|
|
||||||
`Number` int(11) DEFAULT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Daten für Tabelle `Room`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `Room` (`RID`, `Name`, `Man`, `FromPentabarf`, `show`, `Number`) VALUES
|
|
||||||
(1, 'Testraum', NULL, '', 'Y', 0);
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `ShiftEntry`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `ShiftEntry`;
|
|
||||||
CREATE TABLE `ShiftEntry` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`SID` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`TID` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`UID` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`Comment` text,
|
|
||||||
`freeload_comment` text,
|
|
||||||
`freeloaded` tinyint(1) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `Shifts`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `Shifts`;
|
|
||||||
CREATE TABLE `Shifts` (
|
|
||||||
`SID` int(11) NOT NULL,
|
|
||||||
`title` text,
|
|
||||||
`shifttype_id` int(11) NOT NULL,
|
|
||||||
`start` int(11) NOT NULL,
|
|
||||||
`end` int(11) NOT NULL,
|
|
||||||
`RID` int(11) NOT NULL DEFAULT '0',
|
|
||||||
`URL` text,
|
|
||||||
`PSID` int(11) DEFAULT NULL,
|
|
||||||
`created_by_user_id` int(11) DEFAULT NULL,
|
|
||||||
`created_at_timestamp` int(11) NOT NULL,
|
|
||||||
`edited_by_user_id` int(11) DEFAULT NULL,
|
|
||||||
`edited_at_timestamp` int(11) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `ShiftTypes`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `ShiftTypes`;
|
|
||||||
CREATE TABLE `ShiftTypes` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`name` varchar(255) NOT NULL,
|
|
||||||
`angeltype_id` int(11) DEFAULT NULL,
|
|
||||||
`description` text NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Daten für Tabelle `ShiftTypes`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `ShiftTypes` (`id`, `name`, `angeltype_id`, `description`) VALUES
|
|
||||||
(4, 'Schichttyp1', NULL, '');
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `User`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `User`;
|
|
||||||
CREATE TABLE `User` (
|
|
||||||
`UID` int(11) NOT NULL,
|
|
||||||
`Nick` varchar(23) NOT NULL DEFAULT '',
|
|
||||||
`Name` varchar(23) DEFAULT NULL,
|
|
||||||
`Vorname` varchar(23) DEFAULT NULL,
|
|
||||||
`Alter` int(4) DEFAULT NULL,
|
|
||||||
`Telefon` varchar(40) DEFAULT NULL,
|
|
||||||
`DECT` varchar(5) DEFAULT NULL,
|
|
||||||
`Handy` varchar(40) DEFAULT NULL,
|
|
||||||
`email` varchar(123) DEFAULT NULL,
|
|
||||||
`email_shiftinfo` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'User wants to be informed by mail about changes in his shifts',
|
|
||||||
`jabber` varchar(200) DEFAULT NULL,
|
|
||||||
`Size` varchar(4) DEFAULT NULL,
|
|
||||||
`Passwort` varchar(128) DEFAULT NULL,
|
|
||||||
`password_recovery_token` varchar(32) DEFAULT NULL,
|
|
||||||
`Gekommen` tinyint(4) NOT NULL DEFAULT '0',
|
|
||||||
`Aktiv` tinyint(4) NOT NULL DEFAULT '0',
|
|
||||||
`force_active` tinyint(1) NOT NULL,
|
|
||||||
`Tshirt` tinyint(4) DEFAULT '0',
|
|
||||||
`color` tinyint(4) DEFAULT '10',
|
|
||||||
`Sprache` char(64) NOT NULL,
|
|
||||||
`Menu` char(1) NOT NULL DEFAULT 'L',
|
|
||||||
`lastLogIn` int(11) NOT NULL,
|
|
||||||
`CreateDate` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
|
|
||||||
`Art` varchar(30) DEFAULT NULL,
|
|
||||||
`kommentar` text,
|
|
||||||
`Hometown` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`api_key` varchar(32) NOT NULL,
|
|
||||||
`got_voucher` int(11) NOT NULL,
|
|
||||||
`arrival_date` int(11) DEFAULT NULL,
|
|
||||||
`planned_arrival_date` int(11) NOT NULL,
|
|
||||||
`planned_departure_date` int(11) DEFAULT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Daten für Tabelle `User`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `User` (`UID`, `Nick`, `Name`, `Vorname`, `Alter`, `Telefon`, `DECT`, `Handy`, `email`, `email_shiftinfo`, `jabber`, `Size`, `Passwort`, `password_recovery_token`, `Gekommen`, `Aktiv`, `force_active`, `Tshirt`, `color`, `Sprache`, `Menu`, `lastLogIn`, `CreateDate`, `Art`, `kommentar`, `Hometown`, `api_key`, `got_voucher`, `arrival_date`, `planned_arrival_date`, `planned_departure_date`) VALUES
|
|
||||||
(1, 'admin', 'Gates', 'Bill', 42, '', '-', '', 'admin@example.com', 1, '', 'XL', '$6$rounds=5000$hjXbIhoRTH3vKiRa$Wl2P2iI5T9iRR.HHu/YFHswBW0WVn0yxCfCiX0Keco9OdIoDK6bIAADswP6KvMCJSwTGdV8PgA8g8Xfw5l8BD1', NULL, 1, 1, 0, 1, 0, 'de_DE.UTF-8', 'L', 1474990948, '0001-01-01 00:00:00', '', '', '', '038850abdd1feb264406be3ffa746235', 0, 1439490478, 1436964455, 1440161255);
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `UserAngelTypes`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `UserAngelTypes`;
|
|
||||||
CREATE TABLE `UserAngelTypes` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`user_id` int(11) NOT NULL,
|
|
||||||
`angeltype_id` int(11) NOT NULL,
|
|
||||||
`confirm_user_id` int(11) DEFAULT NULL,
|
|
||||||
`coordinator` tinyint(1) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `UserDriverLicenses`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `UserDriverLicenses`;
|
|
||||||
CREATE TABLE `UserDriverLicenses` (
|
|
||||||
`user_id` int(11) NOT NULL,
|
|
||||||
`has_car` tinyint(1) NOT NULL,
|
|
||||||
`has_license_car` tinyint(1) NOT NULL,
|
|
||||||
`has_license_3_5t_transporter` tinyint(1) NOT NULL,
|
|
||||||
`has_license_7_5t_truck` tinyint(1) NOT NULL,
|
|
||||||
`has_license_12_5t_truck` tinyint(1) NOT NULL,
|
|
||||||
`has_license_forklift` tinyint(1) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Daten für Tabelle `UserDriverLicenses`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `UserDriverLicenses` (`user_id`, `has_car`, `has_license_car`, `has_license_3_5t_transporter`, `has_license_7_5t_truck`, `has_license_12_5t_truck`, `has_license_forklift`) VALUES
|
|
||||||
(1, 1, 1, 1, 1, 1, 1);
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Tabellenstruktur für Tabelle `UserGroups`
|
|
||||||
--
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `UserGroups`;
|
|
||||||
CREATE TABLE `UserGroups` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`uid` int(11) NOT NULL,
|
|
||||||
`group_id` int(11) NOT NULL
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Daten für Tabelle `UserGroups`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `UserGroups` (`id`, `uid`, `group_id`) VALUES
|
|
||||||
(3, 1, -7),
|
|
||||||
(4, 1, -6),
|
|
||||||
(12, 1, -5),
|
|
||||||
(2, 1, -4),
|
|
||||||
(1, 1, -2);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes der exportierten Tabellen
|
|
||||||
--
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `AngelTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `AngelTypes`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD UNIQUE KEY `Name` (`name`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `GroupPrivileges`
|
|
||||||
--
|
|
||||||
ALTER TABLE `GroupPrivileges`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `group_id` (`group_id`,`privilege_id`),
|
|
||||||
ADD KEY `privilege_id` (`privilege_id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `Groups`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Groups`
|
|
||||||
ADD PRIMARY KEY (`UID`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `LogEntries`
|
|
||||||
--
|
|
||||||
ALTER TABLE `LogEntries`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `timestamp` (`timestamp`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `Messages`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Messages`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `Datum` (`Datum`),
|
|
||||||
ADD KEY `SUID` (`SUID`),
|
|
||||||
ADD KEY `RUID` (`RUID`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `NeededAngelTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `NeededAngelTypes`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `room_id` (`room_id`,`angel_type_id`),
|
|
||||||
ADD KEY `shift_id` (`shift_id`),
|
|
||||||
ADD KEY `angel_type_id` (`angel_type_id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `News`
|
|
||||||
--
|
|
||||||
ALTER TABLE `News`
|
|
||||||
ADD PRIMARY KEY (`ID`),
|
|
||||||
ADD KEY `UID` (`UID`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `NewsComments`
|
|
||||||
--
|
|
||||||
ALTER TABLE `NewsComments`
|
|
||||||
ADD PRIMARY KEY (`ID`),
|
|
||||||
ADD KEY `Refid` (`Refid`),
|
|
||||||
ADD KEY `UID` (`UID`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `Privileges`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Privileges`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD UNIQUE KEY `name` (`name`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `Questions`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Questions`
|
|
||||||
ADD PRIMARY KEY (`QID`),
|
|
||||||
ADD KEY `UID` (`UID`),
|
|
||||||
ADD KEY `AID` (`AID`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `Room`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Room`
|
|
||||||
ADD PRIMARY KEY (`RID`),
|
|
||||||
ADD UNIQUE KEY `Name` (`Name`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `ShiftEntry`
|
|
||||||
--
|
|
||||||
ALTER TABLE `ShiftEntry`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `TID` (`TID`),
|
|
||||||
ADD KEY `UID` (`UID`),
|
|
||||||
ADD KEY `SID` (`SID`,`TID`),
|
|
||||||
ADD KEY `freeloaded` (`freeloaded`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `Shifts`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Shifts`
|
|
||||||
ADD PRIMARY KEY (`SID`),
|
|
||||||
ADD UNIQUE KEY `PSID` (`PSID`),
|
|
||||||
ADD KEY `RID` (`RID`),
|
|
||||||
ADD KEY `shifttype_id` (`shifttype_id`),
|
|
||||||
ADD KEY `created_by_user_id` (`created_by_user_id`),
|
|
||||||
ADD KEY `edited_by_user_id` (`edited_by_user_id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `ShiftTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `ShiftTypes`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `angeltype_id` (`angeltype_id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `User`
|
|
||||||
--
|
|
||||||
ALTER TABLE `User`
|
|
||||||
ADD PRIMARY KEY (`UID`),
|
|
||||||
ADD UNIQUE KEY `Nick` (`Nick`),
|
|
||||||
ADD KEY `api_key` (`api_key`),
|
|
||||||
ADD KEY `password_recovery_token` (`password_recovery_token`),
|
|
||||||
ADD KEY `force_active` (`force_active`),
|
|
||||||
ADD KEY `arrival_date` (`arrival_date`,`planned_arrival_date`),
|
|
||||||
ADD KEY `planned_departure_date` (`planned_departure_date`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `UserAngelTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `UserAngelTypes`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `user_id` (`user_id`,`angeltype_id`,`confirm_user_id`),
|
|
||||||
ADD KEY `angeltype_id` (`angeltype_id`),
|
|
||||||
ADD KEY `confirm_user_id` (`confirm_user_id`),
|
|
||||||
ADD KEY `coordinator` (`coordinator`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `UserDriverLicenses`
|
|
||||||
--
|
|
||||||
ALTER TABLE `UserDriverLicenses`
|
|
||||||
ADD PRIMARY KEY (`user_id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Indizes für die Tabelle `UserGroups`
|
|
||||||
--
|
|
||||||
ALTER TABLE `UserGroups`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `uid` (`uid`,`group_id`),
|
|
||||||
ADD KEY `group_id` (`group_id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für exportierte Tabellen
|
|
||||||
--
|
|
||||||
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `AngelTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `AngelTypes`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `GroupPrivileges`
|
|
||||||
--
|
|
||||||
ALTER TABLE `GroupPrivileges`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=259;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `LogEntries`
|
|
||||||
--
|
|
||||||
ALTER TABLE `LogEntries`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `Messages`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Messages`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `NeededAngelTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `NeededAngelTypes`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `News`
|
|
||||||
--
|
|
||||||
ALTER TABLE `News`
|
|
||||||
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `NewsComments`
|
|
||||||
--
|
|
||||||
ALTER TABLE `NewsComments`
|
|
||||||
MODIFY `ID` bigint(11) NOT NULL AUTO_INCREMENT;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `Privileges`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Privileges`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=40;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `Questions`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Questions`
|
|
||||||
MODIFY `QID` bigint(20) NOT NULL AUTO_INCREMENT;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `Room`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Room`
|
|
||||||
MODIFY `RID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `ShiftEntry`
|
|
||||||
--
|
|
||||||
ALTER TABLE `ShiftEntry`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `Shifts`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Shifts`
|
|
||||||
MODIFY `SID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `ShiftTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `ShiftTypes`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `User`
|
|
||||||
--
|
|
||||||
ALTER TABLE `User`
|
|
||||||
MODIFY `UID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `UserAngelTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `UserAngelTypes`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
|
||||||
--
|
|
||||||
-- AUTO_INCREMENT für Tabelle `UserGroups`
|
|
||||||
--
|
|
||||||
ALTER TABLE `UserGroups`
|
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
|
|
||||||
--
|
|
||||||
-- Constraints der exportierten Tabellen
|
|
||||||
--
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `GroupPrivileges`
|
|
||||||
--
|
|
||||||
ALTER TABLE `GroupPrivileges`
|
|
||||||
ADD CONSTRAINT `groupprivileges_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `Groups` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `groupprivileges_ibfk_2` FOREIGN KEY (`privilege_id`) REFERENCES `Privileges` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `Messages`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Messages`
|
|
||||||
ADD CONSTRAINT `messages_ibfk_1` FOREIGN KEY (`SUID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `messages_ibfk_2` FOREIGN KEY (`RUID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `NeededAngelTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `NeededAngelTypes`
|
|
||||||
ADD CONSTRAINT `neededangeltypes_ibfk_1` FOREIGN KEY (`room_id`) REFERENCES `Room` (`RID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `neededangeltypes_ibfk_2` FOREIGN KEY (`shift_id`) REFERENCES `Shifts` (`SID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `neededangeltypes_ibfk_3` FOREIGN KEY (`angel_type_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `News`
|
|
||||||
--
|
|
||||||
ALTER TABLE `News`
|
|
||||||
ADD CONSTRAINT `news_ibfk_1` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `NewsComments`
|
|
||||||
--
|
|
||||||
ALTER TABLE `NewsComments`
|
|
||||||
ADD CONSTRAINT `newscomments_ibfk_1` FOREIGN KEY (`Refid`) REFERENCES `News` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `newscomments_ibfk_2` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `Questions`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Questions`
|
|
||||||
ADD CONSTRAINT `questions_ibfk_1` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `questions_ibfk_2` FOREIGN KEY (`AID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `ShiftEntry`
|
|
||||||
--
|
|
||||||
ALTER TABLE `ShiftEntry`
|
|
||||||
ADD CONSTRAINT `shiftentry_ibfk_1` FOREIGN KEY (`SID`) REFERENCES `Shifts` (`SID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `shiftentry_ibfk_2` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `shiftentry_ibfk_3` FOREIGN KEY (`TID`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `Shifts`
|
|
||||||
--
|
|
||||||
ALTER TABLE `Shifts`
|
|
||||||
ADD CONSTRAINT `shifts_ibfk_1` FOREIGN KEY (`RID`) REFERENCES `Room` (`RID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `shifts_ibfk_2` FOREIGN KEY (`shifttype_id`) REFERENCES `ShiftTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `shifts_ibfk_3` FOREIGN KEY (`created_by_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `shifts_ibfk_4` FOREIGN KEY (`edited_by_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `ShiftTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `ShiftTypes`
|
|
||||||
ADD CONSTRAINT `shifttypes_ibfk_1` FOREIGN KEY (`angeltype_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `UserAngelTypes`
|
|
||||||
--
|
|
||||||
ALTER TABLE `UserAngelTypes`
|
|
||||||
ADD CONSTRAINT `userangeltypes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `userangeltypes_ibfk_2` FOREIGN KEY (`angeltype_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `userangeltypes_ibfk_3` FOREIGN KEY (`confirm_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `UserDriverLicenses`
|
|
||||||
--
|
|
||||||
ALTER TABLE `UserDriverLicenses`
|
|
||||||
ADD CONSTRAINT `userdriverlicenses_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Constraints der Tabelle `UserGroups`
|
|
||||||
--
|
|
||||||
ALTER TABLE `UserGroups`
|
|
||||||
ADD CONSTRAINT `usergroups_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `Groups` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `usergroups_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
@ -29,24 +29,9 @@ class ImportInstallSql extends Migration
|
||||||
'UserAngelTypes',
|
'UserAngelTypes',
|
||||||
'UserDriverLicenses',
|
'UserDriverLicenses',
|
||||||
'UserGroups',
|
'UserGroups',
|
||||||
|
'UserWorkLog',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the migration
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
foreach ($this->oldTables as $table) {
|
|
||||||
if ($this->schema->hasTable($table)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql = file_get_contents(__DIR__ . '/../install.sql');
|
|
||||||
$this->schema->getConnection()->unprepared($sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migration
|
* Reverse the migration
|
||||||
*/
|
*/
|
||||||
|
@ -54,6 +39,7 @@ class ImportInstallSql extends Migration
|
||||||
{
|
{
|
||||||
$this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;');
|
$this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;');
|
||||||
|
|
||||||
|
// Delete all remaining tables
|
||||||
foreach ($this->oldTables as $table) {
|
foreach ($this->oldTables as $table) {
|
||||||
if ($this->schema->hasTable($table)) {
|
if ($this->schema->hasTable($table)) {
|
||||||
$this->schema->dropIfExists($table);
|
$this->schema->dropIfExists($table);
|
||||||
|
|
|
@ -8,24 +8,5 @@ use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
class ImportUpdateSql extends Migration
|
class ImportUpdateSql extends Migration
|
||||||
{
|
{
|
||||||
/**
|
// Do nothing as the tables will be created by later migrations and deleted by ImportInstall
|
||||||
* Run the migration
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
if ($this->schema->hasTable('UserWorkLog')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql = file_get_contents(__DIR__ . '/../update.sql');
|
|
||||||
$this->schema->getConnection()->unprepared($sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migration
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
$this->schema->dropIfExists('UserWorkLog');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ class CreateWorklogsTable extends Migration
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
foreach ($previousRecords as $previousRecord) {
|
foreach ($previousRecords as $previousRecord) {
|
||||||
|
$worked_at = Carbon::createFromTimestamp($previousRecord->work_timestamp);
|
||||||
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
|
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
|
||||||
$this->schema->getConnection()
|
$this->schema->getConnection()
|
||||||
->table('worklogs')
|
->table('worklogs')
|
||||||
|
@ -44,7 +45,7 @@ class CreateWorklogsTable extends Migration
|
||||||
'id' => $previousRecord->id,
|
'id' => $previousRecord->id,
|
||||||
'user_id' => $previousRecord->user_id,
|
'user_id' => $previousRecord->user_id,
|
||||||
'creator_id' => $previousRecord->created_user_id,
|
'creator_id' => $previousRecord->created_user_id,
|
||||||
'worked_at' => $previousRecord->work_timestamp,
|
'worked_at' => $worked_at,
|
||||||
'hours' => $previousRecord->work_hours,
|
'hours' => $previousRecord->work_hours,
|
||||||
'comment' => $previousRecord->comment,
|
'comment' => $previousRecord->comment,
|
||||||
'created_at' => $created_at,
|
'created_at' => $created_at,
|
||||||
|
@ -87,11 +88,11 @@ class CreateWorklogsTable extends Migration
|
||||||
->insert([
|
->insert([
|
||||||
'id' => $record->id,
|
'id' => $record->id,
|
||||||
'user_id' => $record->user_id,
|
'user_id' => $record->user_id,
|
||||||
'work_timestamp' => $record->worked_at->timestamp,
|
'work_timestamp' => Carbon::createFromFormat('Y-m-d', $record->worked_at)->timestamp,
|
||||||
'work_hours' => $record->hours,
|
'work_hours' => $record->hours,
|
||||||
'comment' => $record->comment,
|
'comment' => $record->comment,
|
||||||
'created_user_id' => $record->creator_id,
|
'created_user_id' => $record->creator_id,
|
||||||
'created_timestamp' => $record->created_at->timestamp,
|
'created_timestamp' => Carbon::createFromFormat('Y-m-d H:i:s', $record->created_at)->timestamp,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
|
||||||
|
|
||||||
$this->schema->table('schedules', function (Blueprint $table): void {
|
$this->schema->table('schedules', function (Blueprint $table): void {
|
||||||
$table->string('name')->default('')->after('id');
|
$table->string('name')->default('')->after('id');
|
||||||
$table->integer('shift_type')->default(0)->after('name');
|
$table->unsignedInteger('shift_type')->default(0)->after('name');
|
||||||
$table->integer('minutes_before')->default(0)->after('shift_type');
|
$table->integer('minutes_before')->default(0)->after('shift_type');
|
||||||
$table->integer('minutes_after')->default(0)->after('minutes_before');
|
$table->integer('minutes_after')->default(0)->after('minutes_before');
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
@ -36,7 +36,7 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
|
||||||
|
|
||||||
$this->schema->table('schedules', function (Blueprint $table): void {
|
$this->schema->table('schedules', function (Blueprint $table): void {
|
||||||
$table->string('name')->default(null)->change();
|
$table->string('name')->default(null)->change();
|
||||||
$table->integer('shift_type')->default(null)->change();
|
$table->unsignedInteger('shift_type')->default(null)->change();
|
||||||
$table->integer('minutes_before')->default(null)->change();
|
$table->integer('minutes_before')->default(null)->change();
|
||||||
$table->integer('minutes_after')->default(null)->change();
|
$table->integer('minutes_after')->default(null)->change();
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Config\Config;
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Engelsystem\Helpers\Carbon;
|
||||||
|
use Illuminate\Database\Schema\Builder as SchemaBuilder;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
class CreateFirstUser extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
public function __construct(SchemaBuilder $schemaBuilder, protected Config $config)
|
||||||
|
{
|
||||||
|
parent::__construct($schemaBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
if ($db->table('users')->count() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db->table('users')->insert([
|
||||||
|
'name' => 'admin',
|
||||||
|
'email' => 'admin@localhost',
|
||||||
|
'password' => password_hash('asdfasdf', PASSWORD_DEFAULT),
|
||||||
|
'api_key' => bin2hex(random_bytes(16)),
|
||||||
|
'created_at' => Carbon::now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
/** @var stdClass $admin */
|
||||||
|
$admin = $db->table('users')->where('name', 'admin')->first();
|
||||||
|
foreach (['users_contact', 'users_personal_data', 'users_state'] as $table) {
|
||||||
|
$db->table($table)->insert(['user_id' => $admin->id]);
|
||||||
|
}
|
||||||
|
$db->table('users_settings')->insert(['user_id' => $admin->id, 'language' => 'en_US', 'theme' => 0]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,14 +6,14 @@ namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
use Engelsystem\Config\Config;
|
use Engelsystem\Config\Config;
|
||||||
use Engelsystem\Database\Migration\Migration;
|
use Engelsystem\Database\Migration\Migration;
|
||||||
use Engelsystem\Helpers\Authenticator;
|
|
||||||
use Illuminate\Database\Schema\Builder as SchemaBuilder;
|
use Illuminate\Database\Schema\Builder as SchemaBuilder;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
class SetAdminPassword extends Migration
|
class SetAdminPassword extends Migration
|
||||||
{
|
{
|
||||||
use Reference;
|
use Reference;
|
||||||
|
|
||||||
public function __construct(SchemaBuilder $schemaBuilder, protected Authenticator $auth, protected Config $config)
|
public function __construct(SchemaBuilder $schemaBuilder, protected Config $config)
|
||||||
{
|
{
|
||||||
parent::__construct($schemaBuilder);
|
parent::__construct($schemaBuilder);
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,21 @@ class SetAdminPassword extends Migration
|
||||||
*/
|
*/
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
$admin = $this->auth->authenticate('admin', 'asdfasdf');
|
$db = $this->schema->getConnection();
|
||||||
|
/** @var stdClass $admin */
|
||||||
|
$admin = $db->table('users')->where('name', 'admin')->first();
|
||||||
$setupPassword = $this->config->get('setup_admin_password');
|
$setupPassword = $this->config->get('setup_admin_password');
|
||||||
if (!$admin || !$setupPassword) {
|
|
||||||
|
if (
|
||||||
|
!$admin
|
||||||
|
|| !password_verify('asdfasdf', $admin->password)
|
||||||
|
|| !$setupPassword
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->auth->setPassword($admin, $setupPassword);
|
$db->table('users')
|
||||||
|
->where('id', $admin->id)
|
||||||
|
->update(['password' => password_hash($setupPassword, PASSWORD_DEFAULT)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
class FillPrivilegesAndGroupsRelatedTables extends Migration
|
||||||
|
{
|
||||||
|
use ChangesReferences;
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts missing data into permissions & groups related tables
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
if ($db->table('privileges')->count() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db->table('groups')
|
||||||
|
->insert([
|
||||||
|
['id' => 10, 'name' => 'Guest'],
|
||||||
|
['id' => 20, 'name' => 'Angel'],
|
||||||
|
['id' => 30, 'name' => 'Welcome Angel'],
|
||||||
|
['id' => 35, 'name' => 'Voucher Angel'],
|
||||||
|
['id' => 50, 'name' => 'Shirt Manager'],
|
||||||
|
['id' => 60, 'name' => 'Shift Coordinator'],
|
||||||
|
['id' => 65, 'name' => 'Team Coordinator'],
|
||||||
|
['id' => 80, 'name' => 'Bureaucrat'],
|
||||||
|
['id' => 85, 'name' => 'News Admin'],
|
||||||
|
['id' => 90, 'name' => 'Developer'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$db->table('privileges')
|
||||||
|
->insert([
|
||||||
|
['id' => 1, 'name' => 'start', 'description' => 'Startseite für Gäste/Nicht eingeloggte User'],
|
||||||
|
['id' => 2, 'name' => 'login', 'description' => 'Logindialog'],
|
||||||
|
['id' => 3, 'name' => 'news', 'description' => 'Anzeigen der News-Seite'],
|
||||||
|
['id' => 4, 'name' => 'logout', 'description' => 'User darf sich ausloggen'],
|
||||||
|
['id' => 5, 'name' => 'register', 'description' => 'Einen neuen Engel registerieren'],
|
||||||
|
['id' => 6, 'name' => 'admin_rooms', 'description' => 'Räume administrieren'],
|
||||||
|
['id' => 7, 'name' => 'admin_angel_types', 'description' => 'Engel Typen administrieren'],
|
||||||
|
['id' => 8, 'name' => 'user_settings', 'description' => 'User profile settings'],
|
||||||
|
['id' => 9, 'name' => 'user_messages',
|
||||||
|
'description' => 'Writing and reading messages from user to user'],
|
||||||
|
['id' => 10, 'name' => 'admin_groups', 'description' => 'Manage usergroups and their rights'],
|
||||||
|
['id' => 14, 'name' => 'admin_news', 'description' => 'Administrate the news section'],
|
||||||
|
['id' => 15, 'name' => 'news_comments', 'description' => 'User can comment news'],
|
||||||
|
['id' => 16, 'name' => 'admin_user', 'description' => 'Administrate the angels'],
|
||||||
|
['id' => 17, 'name' => 'user_meetings', 'description' => 'Lists meetings (news)'],
|
||||||
|
['id' => 18, 'name' => 'admin_language', 'description' => 'Translate the system'],
|
||||||
|
['id' => 19, 'name' => 'admin_log', 'description' => 'Display recent changes'],
|
||||||
|
['id' => 21, 'name' => 'schedule.import', 'description' => 'Import rooms and shifts from schedule.xml'],
|
||||||
|
['id' => 24, 'name' => 'user_shifts', 'description' => 'Signup for shifts'],
|
||||||
|
['id' => 25, 'name' => 'user_shifts_admin', 'description' => 'Signup other angels for shifts.'],
|
||||||
|
['id' => 26, 'name' => 'user_myshifts',
|
||||||
|
'description' => 'Allow angels to view their own shifts and cancel them.'],
|
||||||
|
['id' => 27, 'name' => 'admin_arrive', 'description' => 'Mark angels when they arrive.'],
|
||||||
|
['id' => 28, 'name' => 'admin_shifts', 'description' => 'Create shifts'],
|
||||||
|
['id' => 30, 'name' => 'ical', 'description' => 'iCal shift export'],
|
||||||
|
['id' => 31, 'name' => 'admin_active',
|
||||||
|
'description' => 'Mark angels as active and if they got a t-shirt.'],
|
||||||
|
['id' => 32, 'name' => 'admin_free', 'description' => 'Show a list of free/unemployed angels.'],
|
||||||
|
['id' => 33, 'name' => 'admin_user_angeltypes', 'description' => 'Confirm restricted angel types'],
|
||||||
|
['id' => 34, 'name' => 'atom', 'description' => ' Atom news export'],
|
||||||
|
['id' => 35, 'name' => 'shifts_json_export', 'description' => 'Export shifts in JSON format'],
|
||||||
|
['id' => 36, 'name' => 'angeltypes', 'description' => 'View angeltypes'],
|
||||||
|
['id' => 37, 'name' => 'user_angeltypes', 'description' => 'Join angeltypes.'],
|
||||||
|
['id' => 38, 'name' => 'shifttypes', 'description' => 'Administrate shift types'],
|
||||||
|
['id' => 39, 'name' => 'admin_event_config', 'description' => 'Allow editing event config'],
|
||||||
|
['id' => 40, 'name' => 'view_rooms', 'description' => 'User can view rooms'],
|
||||||
|
['id' => 41, 'name' => 'shiftentry_edit_angeltype_supporter',
|
||||||
|
'description' => 'If user with this privilege is angeltype supporter, '
|
||||||
|
. 'he can put users in shifts for their angeltype'],
|
||||||
|
['id' => 43, 'name' => 'admin_user_worklog', 'description' => 'Manage user work log entries.'],
|
||||||
|
['id' => 44, 'name' => 'faq.view', 'description' => 'View FAQ entries'],
|
||||||
|
['id' => 45, 'name' => 'faq.edit', 'description' => 'Edit FAQ entries'],
|
||||||
|
['id' => 46, 'name' => 'question.add', 'description' => 'Ask questions'],
|
||||||
|
['id' => 47, 'name' => 'question.edit', 'description' => 'Answer questions'],
|
||||||
|
['id' => 48, 'name' => 'user.edit.shirt', 'description' => 'Edit user shirts'],
|
||||||
|
['id' => 49, 'name' => 'voucher.edit', 'description' => 'Edit vouchers'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$db->table('group_privileges')->insert([
|
||||||
|
['id' => 23, 'group_id' => 10, 'privilege_id' => 2],
|
||||||
|
['id' => 24, 'group_id' => 10, 'privilege_id' => 5],
|
||||||
|
['id' => 85, 'group_id' => 90, 'privilege_id' => 10],
|
||||||
|
['id' => 86, 'group_id' => 90, 'privilege_id' => 21],
|
||||||
|
['id' => 87, 'group_id' => 90, 'privilege_id' => 18],
|
||||||
|
['id' => 88, 'group_id' => 10, 'privilege_id' => 1],
|
||||||
|
['id' => 206, 'group_id' => 80, 'privilege_id' => 31],
|
||||||
|
['id' => 207, 'group_id' => 80, 'privilege_id' => 7],
|
||||||
|
['id' => 209, 'group_id' => 80, 'privilege_id' => 21],
|
||||||
|
['id' => 210, 'group_id' => 80, 'privilege_id' => 14],
|
||||||
|
['id' => 212, 'group_id' => 80, 'privilege_id' => 6],
|
||||||
|
['id' => 213, 'group_id' => 80, 'privilege_id' => 28],
|
||||||
|
['id' => 214, 'group_id' => 80, 'privilege_id' => 16],
|
||||||
|
['id' => 215, 'group_id' => 80, 'privilege_id' => 33],
|
||||||
|
['id' => 216, 'group_id' => 80, 'privilege_id' => 5],
|
||||||
|
['id' => 218, 'group_id' => 60, 'privilege_id' => 39],
|
||||||
|
['id' => 219, 'group_id' => 65, 'privilege_id' => 14],
|
||||||
|
['id' => 220, 'group_id' => 65, 'privilege_id' => 33],
|
||||||
|
['id' => 221, 'group_id' => 65, 'privilege_id' => 25],
|
||||||
|
['id' => 235, 'group_id' => 60, 'privilege_id' => 27],
|
||||||
|
['id' => 236, 'group_id' => 60, 'privilege_id' => 32],
|
||||||
|
['id' => 237, 'group_id' => 60, 'privilege_id' => 19],
|
||||||
|
['id' => 238, 'group_id' => 60, 'privilege_id' => 14],
|
||||||
|
['id' => 239, 'group_id' => 60, 'privilege_id' => 28],
|
||||||
|
['id' => 240, 'group_id' => 60, 'privilege_id' => 16],
|
||||||
|
['id' => 241, 'group_id' => 60, 'privilege_id' => 5],
|
||||||
|
['id' => 242, 'group_id' => 60, 'privilege_id' => 25],
|
||||||
|
['id' => 243, 'group_id' => 20, 'privilege_id' => 36],
|
||||||
|
['id' => 244, 'group_id' => 20, 'privilege_id' => 34],
|
||||||
|
['id' => 245, 'group_id' => 20, 'privilege_id' => 30],
|
||||||
|
['id' => 246, 'group_id' => 20, 'privilege_id' => 4],
|
||||||
|
['id' => 247, 'group_id' => 20, 'privilege_id' => 3],
|
||||||
|
['id' => 248, 'group_id' => 20, 'privilege_id' => 15],
|
||||||
|
['id' => 249, 'group_id' => 20, 'privilege_id' => 35],
|
||||||
|
['id' => 250, 'group_id' => 20, 'privilege_id' => 37],
|
||||||
|
['id' => 251, 'group_id' => 20, 'privilege_id' => 17],
|
||||||
|
['id' => 252, 'group_id' => 20, 'privilege_id' => 9],
|
||||||
|
['id' => 253, 'group_id' => 20, 'privilege_id' => 26],
|
||||||
|
['id' => 255, 'group_id' => 20, 'privilege_id' => 8],
|
||||||
|
['id' => 256, 'group_id' => 20, 'privilege_id' => 24],
|
||||||
|
['id' => 257, 'group_id' => 80, 'privilege_id' => 38],
|
||||||
|
['id' => 258, 'group_id' => 50, 'privilege_id' => 31],
|
||||||
|
['id' => 259, 'group_id' => 20, 'privilege_id' => 40],
|
||||||
|
['id' => 260, 'group_id' => 85, 'privilege_id' => 14],
|
||||||
|
['id' => 262, 'group_id' => 60, 'privilege_id' => 43],
|
||||||
|
['id' => 263, 'group_id' => 20, 'privilege_id' => 41],
|
||||||
|
['id' => 264, 'group_id' => 30, 'privilege_id' => 27],
|
||||||
|
['id' => 265, 'group_id' => 10, 'privilege_id' => 44],
|
||||||
|
['id' => 266, 'group_id' => 20, 'privilege_id' => 44],
|
||||||
|
['id' => 267, 'group_id' => 60, 'privilege_id' => 45],
|
||||||
|
['id' => 268, 'group_id' => 20, 'privilege_id' => 46],
|
||||||
|
['id' => 269, 'group_id' => 60, 'privilege_id' => 47],
|
||||||
|
['id' => 270, 'group_id' => 60, 'privilege_id' => 48],
|
||||||
|
['id' => 271, 'group_id' => 50, 'privilege_id' => 48],
|
||||||
|
['id' => 272, 'group_id' => 50, 'privilege_id' => 27],
|
||||||
|
['id' => 273, 'group_id' => 60, 'privilege_id' => 49],
|
||||||
|
['id' => 274, 'group_id' => 35, 'privilege_id' => 49],
|
||||||
|
['id' => 275, 'group_id' => 35, 'privilege_id' => 27],
|
||||||
|
]);
|
||||||
|
|
||||||
|
/** @var stdClass $admin */
|
||||||
|
$admin = $db->table('users')->where('name', 'admin')->first();
|
||||||
|
if (!$admin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Angel, ShiCo, Team coordinator, Bureaucrat, Dev
|
||||||
|
foreach ([20, 60, 65, 80, 90] as $group) {
|
||||||
|
$db->table('users_groups')->insert(['user_id' => $admin->id, 'group_id' => $group]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
use Engelsystem\Database\Migration\Migration;
|
use Engelsystem\Database\Migration\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class ChangeApiKeyLength extends Migration
|
class ChangeApiKeyLength extends Migration
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,19 @@ class ChangeApiKeyLength extends Migration
|
||||||
*/
|
*/
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
|
$connection = $this->schema->getConnection();
|
||||||
|
$data = $connection->table('users')->get(['id', 'api_key']);
|
||||||
|
foreach ($data as $user) {
|
||||||
|
if (Str::length($user->api_key) <= 32) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = Str::substr($user->api_key, 0, 32);
|
||||||
|
$connection->table('users')
|
||||||
|
->where('id', $user->id)
|
||||||
|
->update(['api_key' => $key]);
|
||||||
|
}
|
||||||
|
|
||||||
$this->schema->table('users', function (Blueprint $table): void {
|
$this->schema->table('users', function (Blueprint $table): void {
|
||||||
$table->string('api_key', 32)->change();
|
$table->string('api_key', 32)->change();
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
|
class CreateApiPermissions extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')->insert([
|
||||||
|
['name' => 'api', 'description' => 'Use the API'],
|
||||||
|
]);
|
||||||
|
$db->table('groups')->insert([
|
||||||
|
['id' => 40, 'name' => 'API'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$bureaucratGroup = 80;
|
||||||
|
$apiId = $db->table('privileges')->where('name', 'api')->first()->id;
|
||||||
|
$db->table('group_privileges')->insert([
|
||||||
|
['group_id' => $bureaucratGroup, 'privilege_id' => $apiId],
|
||||||
|
['group_id' => 40, 'privilege_id' => $apiId],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->where('name', 'api')
|
||||||
|
->delete();
|
||||||
|
$db->table('groups')
|
||||||
|
->where('id', 40)
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
|
class CleanupShortApiKeys extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('users')
|
||||||
|
->where($db->raw('LENGTH(api_key)'), '<=', 42)
|
||||||
|
->update(['api_key' => '']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AddIfsgCerificatesToUsersLicenses extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('users_licenses', function (Blueprint $table): void {
|
||||||
|
$table->boolean('ifsg_certificate_light')->default(false)->after('drive_12t');
|
||||||
|
$table->boolean('ifsg_certificate')->default(false)->after('ifsg_certificate_light');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('users_licenses', function (Blueprint $table): void {
|
||||||
|
$table->dropColumn('ifsg_certificate_light');
|
||||||
|
$table->dropColumn('ifsg_certificate');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AddRequiresIfsgCerificateToAngeltypes extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('angel_types', function (Blueprint $table): void {
|
||||||
|
$table->boolean('requires_ifsg_certificate')->default(false)->after('requires_driver_license');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('angel_types', function (Blueprint $table): void {
|
||||||
|
$table->dropColumn('requires_ifsg_certificate');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AngeltypesRenameNoSelfSignupToShiftSelfSignup extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('angel_types', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('no_self_signup', 'shift_self_signup')->default(true);
|
||||||
|
$connection = $this->schema->getConnection();
|
||||||
|
$connection->table('angel_types')
|
||||||
|
->update(['no_self_signup' => $connection->raw('NOT no_self_signup'),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('angel_types', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('shift_self_signup', 'no_self_signup');
|
||||||
|
$connection = $this->schema->getConnection();
|
||||||
|
$connection->table('angel_types')
|
||||||
|
->update(['shift_self_signup' => $connection->raw('NOT shift_self_signup'),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AddHideOnShiftViewToAngeltypes extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('angel_types', function (Blueprint $table): void {
|
||||||
|
$table->boolean('hide_on_shift_view')->default(false)->after('hide_register');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('angel_types', function (Blueprint $table): void {
|
||||||
|
$table->dropColumn('hide_on_shift_view');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AddUserToSessionsTable extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('sessions', function (Blueprint $table): void {
|
||||||
|
$this->referencesUser($table)->nullable()->index()->after('payload');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('sessions', function (Blueprint $table): void {
|
||||||
|
$table->dropForeign('sessions_user_id_foreign');
|
||||||
|
$table->dropColumn('user_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class NewsRenameImportantToHighlight extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('news', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('is_important', 'is_highlighted');
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->schema->getConnection()
|
||||||
|
->table('privileges')
|
||||||
|
->where('name', 'news.important')
|
||||||
|
->update(['name' => 'news.highlight', 'description' => 'Highlight News']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('news', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('is_highlighted', 'is_important');
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->schema->getConnection()
|
||||||
|
->table('privileges')
|
||||||
|
->where('name', 'news.highlight')
|
||||||
|
->update(['name' => 'news.important', 'description' => 'Make News Important']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class RenameRoomsToLocations extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->rename('rooms', 'locations');
|
||||||
|
|
||||||
|
$this->schema->table('shifts', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('room_id', 'location_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->schema->table('needed_angel_types', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('room_id', 'location_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')->where('name', 'admin_rooms')->update([
|
||||||
|
'name' => 'admin_locations',
|
||||||
|
'description' => 'Manage locations',
|
||||||
|
]);
|
||||||
|
$db->table('privileges')->where('name', 'view_rooms')->update([
|
||||||
|
'name' => 'view_locations',
|
||||||
|
'description' => 'User can view locations',
|
||||||
|
]);
|
||||||
|
$db->table('privileges')->where('name', 'schedule.import')->update([
|
||||||
|
'description' => 'Import locations and shifts from schedule.xml',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->rename('locations', 'rooms');
|
||||||
|
|
||||||
|
$this->schema->table('shifts', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('location_id', 'room_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->schema->table('needed_angel_types', function (Blueprint $table): void {
|
||||||
|
$table->renameColumn('location_id', 'room_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')->where('name', 'admin_locations')->update([
|
||||||
|
'name' => 'admin_rooms',
|
||||||
|
'description' => 'Räume administrieren',
|
||||||
|
]);
|
||||||
|
$db->table('privileges')->where('name', 'view_locations')->update([
|
||||||
|
'name' => 'view_rooms',
|
||||||
|
'description' => 'User can view rooms',
|
||||||
|
]);
|
||||||
|
$db->table('privileges')->where('name', 'schedule.import')->update([
|
||||||
|
'description' => 'Import rooms and shifts from schedule.xml',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AddMissingScheduleForeignKeys extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$schemaManager = $this->schema->getConnection()->getDoctrineSchemaManager();
|
||||||
|
|
||||||
|
$hasShiftTypeReference = $schemaManager->introspectTable('schedules')
|
||||||
|
->hasIndex('schedules_shift_type_foreign');
|
||||||
|
if (!$hasShiftTypeReference) {
|
||||||
|
$this->schema->table('schedules', function (Blueprint $table): void {
|
||||||
|
$table->unsignedInteger('shift_type')->change();
|
||||||
|
$this->addReference($table, 'shift_type', 'shift_types');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$hasShiftIdReference = $schemaManager->introspectTable('schedule_shift')
|
||||||
|
->hasIndex('schedule_shift_schedule_id_foreign');
|
||||||
|
if (!$hasShiftIdReference) {
|
||||||
|
$this->schema->table('schedule_shift', function (Blueprint $table): void {
|
||||||
|
$table->unsignedInteger('shift_id')->change();
|
||||||
|
$this->addReference($table, 'shift_id', 'shifts');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
|
class DegenderShirtSizes extends Migration
|
||||||
|
{
|
||||||
|
/** @var string[] */
|
||||||
|
protected array $sizes = [
|
||||||
|
'S-G' => 'S-F',
|
||||||
|
'M-G' => 'M-F',
|
||||||
|
'L-G' => 'L-F',
|
||||||
|
'XL-G' => 'XL-F',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->migrate($this->sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->migrate(array_flip($this->sizes));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $sizes
|
||||||
|
*/
|
||||||
|
private function migrate(array $sizes): void
|
||||||
|
{
|
||||||
|
$connection = $this->schema->getConnection();
|
||||||
|
foreach ($sizes as $from => $to) {
|
||||||
|
$connection
|
||||||
|
->table('users_personal_data')
|
||||||
|
->where('shirt_size', $from)
|
||||||
|
->update([
|
||||||
|
'shirt_size' => $to,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AddUserInfoToUsersState extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('users_state', function (Blueprint $table): void {
|
||||||
|
$table->string('user_info')->nullable()->default(null)->after('arrival_date');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('users_state', function (Blueprint $table): void {
|
||||||
|
$table->dropColumn('user_info');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
|
class AddUserInfoPermissions extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->insert([
|
||||||
|
['name' => 'user.info.show', 'description' => 'Show User Info'],
|
||||||
|
['name' => 'user.info.edit', 'description' => 'Edit User Info'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$showUserInfo = $db->table('privileges')
|
||||||
|
->where('name', 'user.info.show')
|
||||||
|
->get(['id'])
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$editUserInfo = $db->table('privileges')
|
||||||
|
->where('name', 'user.info.edit')
|
||||||
|
->get(['id'])
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$buerocrat = 80;
|
||||||
|
$shico = 60;
|
||||||
|
$db->table('group_privileges')
|
||||||
|
->insertOrIgnore([
|
||||||
|
['group_id' => $buerocrat, 'privilege_id' => $editUserInfo->id],
|
||||||
|
['group_id' => $shico, 'privilege_id' => $showUserInfo->id],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->whereIn('name', ['user.info.edit', 'user.info.show'])
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AddUserIdToLogEntries extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('log_entries', function (Blueprint $table): void {
|
||||||
|
$table->unsignedInteger('user_id')->after('id')->nullable()->default(null);
|
||||||
|
$table->foreign('user_id')
|
||||||
|
->references('id')->on('users')
|
||||||
|
->onUpdate('cascade')
|
||||||
|
->nullOnDelete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('log_entries', function (Blueprint $table): void {
|
||||||
|
$table->dropForeign('log_entries_user_id_foreign');
|
||||||
|
$table->dropColumn('user_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Connection;
|
||||||
|
use Illuminate\Database\Schema\Builder as SchemaBuilder;
|
||||||
|
|
||||||
|
class ChangeEditShirtRequireBureaucrat extends Migration
|
||||||
|
{
|
||||||
|
protected int $bureaucrat = 80;
|
||||||
|
|
||||||
|
protected int $shiCo = 60;
|
||||||
|
|
||||||
|
protected int $editShirt;
|
||||||
|
|
||||||
|
protected Connection $db;
|
||||||
|
|
||||||
|
public function __construct(SchemaBuilder $schema)
|
||||||
|
{
|
||||||
|
parent::__construct($schema);
|
||||||
|
$this->db = $this->schema->getConnection();
|
||||||
|
|
||||||
|
$this->editShirt = $this->db->table('privileges')
|
||||||
|
->where('name', 'user.edit.shirt')
|
||||||
|
->get(['id'])
|
||||||
|
->first()->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->movePermission($this->editShirt, $this->shiCo, $this->bureaucrat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->movePermission($this->editShirt, $this->bureaucrat, $this->shiCo);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function movePermission(int $privilege, int $oldGroup, int $newGroup): void
|
||||||
|
{
|
||||||
|
$this->db->table('group_privileges')
|
||||||
|
->insertOrIgnore(['group_id' => $newGroup, 'privilege_id' => $privilege]);
|
||||||
|
|
||||||
|
$this->db->table('group_privileges')
|
||||||
|
->where(['group_id' => $oldGroup, 'privilege_id' => $privilege])
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
|
class AddLogsAllPermission extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->insert([
|
||||||
|
['name' => 'logs.all', 'description' => 'View all logs'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$logsAll = $db->table('privileges')
|
||||||
|
->where('name', 'logs.all')
|
||||||
|
->get(['id'])
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$bureaucrat = 80;
|
||||||
|
$db->table('group_privileges')
|
||||||
|
->insertOrIgnore([
|
||||||
|
['group_id' => $bureaucrat, 'privilege_id' => $logsAll->id],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->where('name', 'logs.all')
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class ScheduleShiftTypeNeededAngelTypes extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('schedules', function (Blueprint $table): void {
|
||||||
|
$table->boolean('needed_from_shift_type')->after('shift_type')->default(false);
|
||||||
|
});
|
||||||
|
$this->schema->table('needed_angel_types', function (Blueprint $table): void {
|
||||||
|
$this->references($table, 'shift_types')->after('shift_id')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('schedules', function (Blueprint $table): void {
|
||||||
|
$table->dropColumn('needed_from_shift_type');
|
||||||
|
});
|
||||||
|
$this->schema->table('needed_angel_types', function (Blueprint $table): void {
|
||||||
|
$table->dropForeign('needed_angel_types_shift_type_id_foreign');
|
||||||
|
$table->dropColumn('shift_type_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
|
||||||
|
class AddUserEditPermission extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->insert([
|
||||||
|
'name' => 'user.edit', 'description' => 'Edit user',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$editUser = $db->table('privileges')
|
||||||
|
->where('name', 'user.edit')
|
||||||
|
->get(['id'])
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$buerocrat = 80;
|
||||||
|
$db->table('group_privileges')
|
||||||
|
->insertOrIgnore([
|
||||||
|
'group_id' => $buerocrat, 'privilege_id' => $editUser->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$db = $this->schema->getConnection();
|
||||||
|
$db->table('privileges')
|
||||||
|
->where('name', 'user.edit')
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,7 @@ trait Reference
|
||||||
$table->primary($fromColumn);
|
$table->primary($fromColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->addReference($table, $fromColumn, $targetTable, $targetColumn ?: 'id');
|
$this->addReference($table, $fromColumn, $targetTable, $targetColumn);
|
||||||
|
|
||||||
return $col;
|
return $col;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES (40, 'view_rooms', 'User can view rooms');
|
|
||||||
INSERT INTO `GroupPrivileges` (`id`, `group_id`, `privilege_id`) VALUES (NULL, '-2', '40');
|
|
||||||
|
|
||||||
ALTER TABLE `UserAngelTypes` CHANGE `coordinator` `supporter` BOOLEAN;
|
|
||||||
|
|
||||||
ALTER TABLE `User` ADD COLUMN `email_by_human_allowed` BOOLEAN NOT NULL;
|
|
||||||
|
|
||||||
-- No Self Sign Up for some Angel Types
|
|
||||||
ALTER TABLE AngelTypes ADD no_self_signup TINYINT(1) NOT NULL;
|
|
||||||
|
|
||||||
ALTER TABLE `AngelTypes`
|
|
||||||
ADD `contact_user_id` INT NULL,
|
|
||||||
ADD `contact_name` VARCHAR(250) NULL,
|
|
||||||
ADD `contact_dect` VARCHAR(5) NULL,
|
|
||||||
ADD `contact_email` VARCHAR(250) NULL,
|
|
||||||
ADD INDEX (`contact_user_id`);
|
|
||||||
ALTER TABLE `AngelTypes`
|
|
||||||
ADD FOREIGN KEY (`contact_user_id`) REFERENCES `User`(`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES (NULL, 'shiftentry_edit_angeltype_supporter', 'If user with this privilege is angeltype supporter, he can put users in shifts for their angeltype');
|
|
||||||
|
|
||||||
-- DB Performance
|
|
||||||
ALTER TABLE `Shifts` ADD INDEX(`start`);
|
|
||||||
ALTER TABLE `NeededAngelTypes` ADD INDEX(`count`);
|
|
||||||
|
|
||||||
-- Security
|
|
||||||
UPDATE `Groups` SET UID = UID * 10;
|
|
||||||
INSERT INTO `Groups` (Name, UID) VALUES ('News Admin', -65);
|
|
||||||
INSERT INTO `Privileges` (id, name, `desc`) VALUES (42, 'admin_news_html', 'Use HTML in news');
|
|
||||||
INSERT INTO `GroupPrivileges` (group_id, privilege_id) VALUES (-65, 14), (-65, 42);
|
|
||||||
|
|
||||||
-- Add log level to LogEntries
|
|
||||||
ALTER TABLE `LogEntries` CHANGE COLUMN `nick` `level` VARCHAR(20) NOT NULL;
|
|
||||||
|
|
||||||
-- Angeltype contact update
|
|
||||||
ALTER TABLE `AngelTypes` DROP FOREIGN KEY angeltypes_ibfk_1;
|
|
||||||
ALTER TABLE `AngelTypes` DROP `contact_user_id`;
|
|
||||||
|
|
||||||
-- Room update
|
|
||||||
ALTER TABLE `Room` DROP `Number`;
|
|
||||||
ALTER TABLE `Room` DROP `show`;
|
|
||||||
ALTER TABLE `Room` DROP `Man`;
|
|
||||||
ALTER TABLE `Room` ADD `from_frab` BOOLEAN NOT NULL AFTER `FromPentabarf`;
|
|
||||||
UPDATE Room SET `from_frab` = (`FromPentabarf` = 'Y');
|
|
||||||
ALTER TABLE `Room` DROP `FromPentabarf`;
|
|
||||||
ALTER TABLE `Room` ADD `map_url` VARCHAR(300) NULL AFTER `from_frab`;
|
|
||||||
ALTER TABLE `Room` ADD `description` TEXT NULL AFTER `map_url`;
|
|
||||||
|
|
||||||
-- Dashboard
|
|
||||||
ALTER TABLE `AngelTypes` ADD `show_on_dashboard` BOOLEAN NOT NULL AFTER `contact_email`;
|
|
||||||
UPDATE `AngelTypes` SET `show_on_dashboard` = TRUE;
|
|
||||||
|
|
||||||
-- Work Log
|
|
||||||
CREATE TABLE `UserWorkLog` ( `id` INT NOT NULL AUTO_INCREMENT , `user_id` INT NOT NULL , `work_hours` DECIMAL NOT NULL , `comment` VARCHAR(200) NOT NULL , `created_user_id` INT NOT NULL , `created_timestamp` INT NOT NULL , PRIMARY KEY (`id`), INDEX (`user_id`), INDEX (`created_user_id`)) ENGINE = InnoDB;
|
|
||||||
ALTER TABLE `UserWorkLog` ADD FOREIGN KEY (`created_user_id`) REFERENCES `User`(`UID`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `UserWorkLog` ADD FOREIGN KEY (`user_id`) REFERENCES `User`(`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
ALTER TABLE `UserWorkLog` ADD INDEX(`created_timestamp`);
|
|
||||||
INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES (NULL, 'admin_user_worklog', 'Manage user work log entries.');
|
|
||||||
ALTER TABLE `UserWorkLog` CHANGE `work_hours` `work_hours` DECIMAL(10,2) NOT NULL;
|
|
||||||
ALTER TABLE `UserWorkLog` ADD `work_timestamp` INT NOT NULL AFTER `user_id`;
|
|
|
@ -8,7 +8,7 @@ RUN composer --no-ansi dump-autoload --optimize
|
||||||
FROM alpine AS translation
|
FROM alpine AS translation
|
||||||
RUN apk add gettext
|
RUN apk add gettext
|
||||||
COPY resources/lang/ /data
|
COPY resources/lang/ /data
|
||||||
RUN find /data -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
|
RUN find /data -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
|
||||||
|
|
||||||
# Build the themes
|
# Build the themes
|
||||||
FROM node:20-alpine AS themes
|
FROM node:20-alpine AS themes
|
||||||
|
@ -26,6 +26,7 @@ COPY config/ /app/config
|
||||||
COPY db/ /app/db
|
COPY db/ /app/db
|
||||||
COPY includes/ /app/includes
|
COPY includes/ /app/includes
|
||||||
COPY public/ /app/public
|
COPY public/ /app/public
|
||||||
|
COPY resources/api /app/resources/api
|
||||||
COPY resources/views /app/resources/views
|
COPY resources/views /app/resources/views
|
||||||
COPY src/ /app/src
|
COPY src/ /app/src
|
||||||
COPY storage/ /app/storage
|
COPY storage/ /app/storage
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use Engelsystem\Helpers\Carbon;
|
use Engelsystem\Helpers\Carbon;
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\UserAngelType;
|
use Engelsystem\Models\UserAngelType;
|
||||||
use Engelsystem\ShiftsFilter;
|
use Engelsystem\ShiftsFilter;
|
||||||
use Engelsystem\ShiftsFilterRenderer;
|
use Engelsystem\ShiftsFilterRenderer;
|
||||||
|
@ -17,7 +17,7 @@ use Illuminate\Support\Collection;
|
||||||
*/
|
*/
|
||||||
function angeltypes_title()
|
function angeltypes_title()
|
||||||
{
|
{
|
||||||
return __('Angeltypes');
|
return __('angeltypes.angeltypes');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +48,7 @@ function angeltypes_controller()
|
||||||
function angeltype_link($angeltype_id, $params = [])
|
function angeltype_link($angeltype_id, $params = [])
|
||||||
{
|
{
|
||||||
$params = array_merge(['action' => 'view', 'angeltype_id' => $angeltype_id], $params);
|
$params = array_merge(['action' => 'view', 'angeltype_id' => $angeltype_id], $params);
|
||||||
return page_link_to('angeltypes', $params);
|
return url('/angeltypes', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,7 +59,7 @@ function angeltype_link($angeltype_id, $params = [])
|
||||||
function angeltype_delete_controller()
|
function angeltype_delete_controller()
|
||||||
{
|
{
|
||||||
if (!auth()->can('admin_angel_types')) {
|
if (!auth()->can('admin_angel_types')) {
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
|
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
|
||||||
|
@ -68,11 +68,11 @@ function angeltype_delete_controller()
|
||||||
$angeltype->delete();
|
$angeltype->delete();
|
||||||
engelsystem_log('Deleted angeltype: ' . AngelType_name_render($angeltype, true));
|
engelsystem_log('Deleted angeltype: ' . AngelType_name_render($angeltype, true));
|
||||||
success(sprintf(__('Angeltype %s deleted.'), $angeltype->name));
|
success(sprintf(__('Angeltype %s deleted.'), $angeltype->name));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
sprintf(__('Delete angeltype %s'), $angeltype->name),
|
sprintf(__('Delete angeltype %s'), htmlspecialchars($angeltype->name)),
|
||||||
AngelType_delete_view($angeltype),
|
AngelType_delete_view($angeltype),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -92,14 +92,14 @@ function angeltype_edit_controller()
|
||||||
// Edit existing angeltype
|
// Edit existing angeltype
|
||||||
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
|
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
|
||||||
|
|
||||||
if (!auth()->user()->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
|
if (!auth()->user()?->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// New angeltype
|
// New angeltype
|
||||||
if ($supporter_mode) {
|
if ($supporter_mode) {
|
||||||
// Supporters aren't allowed to create new angeltypes.
|
// Supporters aren't allowed to create new angeltypes.
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
$angeltype = new AngelType();
|
$angeltype = new AngelType();
|
||||||
}
|
}
|
||||||
|
@ -118,11 +118,13 @@ function angeltype_edit_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltype->restricted = $request->has('restricted');
|
$angeltype->restricted = $request->has('restricted');
|
||||||
$angeltype->no_self_signup = $request->has('no_self_signup');
|
$angeltype->shift_self_signup = $request->has('shift_self_signup');
|
||||||
$angeltype->show_on_dashboard = $request->has('show_on_dashboard');
|
$angeltype->show_on_dashboard = $request->has('show_on_dashboard');
|
||||||
$angeltype->hide_register = $request->has('hide_register');
|
$angeltype->hide_register = $request->has('hide_register');
|
||||||
|
$angeltype->hide_on_shift_view = $request->has('hide_on_shift_view');
|
||||||
|
|
||||||
$angeltype->requires_driver_license = $request->has('requires_driver_license');
|
$angeltype->requires_driver_license = $request->has('requires_driver_license');
|
||||||
|
$angeltype->requires_ifsg_certificate = $request->has('requires_ifsg_certificate');
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltype->description = strip_request_item_nl('description', $angeltype->description);
|
$angeltype->description = strip_request_item_nl('description', $angeltype->description);
|
||||||
|
@ -137,20 +139,22 @@ function angeltype_edit_controller()
|
||||||
success('Angel type saved.');
|
success('Angel type saved.');
|
||||||
engelsystem_log(
|
engelsystem_log(
|
||||||
'Saved angeltype: ' . $angeltype->name . ($angeltype->restricted ? ', restricted' : '')
|
'Saved angeltype: ' . $angeltype->name . ($angeltype->restricted ? ', restricted' : '')
|
||||||
. ($angeltype->no_self_signup ? ', no_self_signup' : '')
|
. ($angeltype->shift_self_signup ? ', shift_self_signup' : '')
|
||||||
. ($angeltype->requires_driver_license ? ', requires driver license' : '') . ', '
|
. ($angeltype->requires_driver_license ? ', requires driver license' : '') . ', '
|
||||||
|
. ($angeltype->requires_ifsg_certificate ? ', requires ifsg certificate' : '') . ', '
|
||||||
. $angeltype->contact_name . ', '
|
. $angeltype->contact_name . ', '
|
||||||
. $angeltype->contact_dect . ', '
|
. $angeltype->contact_dect . ', '
|
||||||
. $angeltype->contact_email . ', '
|
. $angeltype->contact_email . ', '
|
||||||
. $angeltype->show_on_dashboard . ', '
|
. $angeltype->show_on_dashboard . ', '
|
||||||
. $angeltype->hide_register
|
. $angeltype->hide_register . ', '
|
||||||
|
. $angeltype->hide_on_shift_view
|
||||||
);
|
);
|
||||||
throw_redirect(angeltype_link($angeltype->id));
|
throw_redirect(angeltype_link($angeltype->id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
sprintf(__('Edit %s'), $angeltype->name),
|
sprintf(__('Edit %s'), htmlspecialchars((string) $angeltype->name)),
|
||||||
AngelType_edit_view($angeltype, $supporter_mode),
|
AngelType_edit_view($angeltype, $supporter_mode),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -165,7 +169,7 @@ function angeltype_controller()
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
if (!auth()->can('angeltypes')) {
|
if (!auth()->can('angeltypes')) {
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
|
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
|
||||||
|
@ -191,7 +195,7 @@ function angeltype_controller()
|
||||||
|
|
||||||
$isSupporter = !is_null($user_angeltype) && $user_angeltype->supporter;
|
$isSupporter = !is_null($user_angeltype) && $user_angeltype->supporter;
|
||||||
return [
|
return [
|
||||||
sprintf(__('Team %s'), $angeltype->name),
|
sprintf(__('Team %s'), htmlspecialchars($angeltype->name)),
|
||||||
AngelType_view(
|
AngelType_view(
|
||||||
$angeltype,
|
$angeltype,
|
||||||
$members,
|
$members,
|
||||||
|
@ -220,9 +224,8 @@ function angeltype_controller_shiftsFilterDays(AngelType $angeltype)
|
||||||
$days = [];
|
$days = [];
|
||||||
foreach ($all_shifts as $shift) {
|
foreach ($all_shifts as $shift) {
|
||||||
$day = Carbon::make($shift['start'])->format('Y-m-d');
|
$day = Carbon::make($shift['start'])->format('Y-m-d');
|
||||||
$dayFormatted = Carbon::make($shift['start'])->format(__('Y-m-d'));
|
|
||||||
if (!isset($days[$day])) {
|
if (!isset($days[$day])) {
|
||||||
$days[$day] = $dayFormatted;
|
$days[$day] = dateWithEventDay($day);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ksort($days);
|
ksort($days);
|
||||||
|
@ -239,13 +242,13 @@ function angeltype_controller_shiftsFilterDays(AngelType $angeltype)
|
||||||
function angeltype_controller_shiftsFilter(AngelType $angeltype, $days)
|
function angeltype_controller_shiftsFilter(AngelType $angeltype, $days)
|
||||||
{
|
{
|
||||||
$request = request();
|
$request = request();
|
||||||
$roomIds = Room::query()
|
$locationIds = Location::query()
|
||||||
->select('id')
|
->select('id')
|
||||||
->pluck('id')
|
->pluck('id')
|
||||||
->toArray();
|
->toArray();
|
||||||
$shiftsFilter = new ShiftsFilter(
|
$shiftsFilter = new ShiftsFilter(
|
||||||
auth()->can('user_shifts_admin'),
|
auth()->can('user_shifts_admin'),
|
||||||
$roomIds,
|
$locationIds,
|
||||||
[$angeltype->id]
|
[$angeltype->id]
|
||||||
);
|
);
|
||||||
$selected_day = date('Y-m-d');
|
$selected_day = date('Y-m-d');
|
||||||
|
@ -269,59 +272,70 @@ function angeltype_controller_shiftsFilter(AngelType $angeltype, $days)
|
||||||
function angeltypes_list_controller()
|
function angeltypes_list_controller()
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
$admin_angeltypes = auth()->can('admin_angel_types');
|
||||||
|
|
||||||
if (!auth()->can('angeltypes')) {
|
if (!auth()->can('angeltypes')) {
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltypes = AngelTypes_with_user($user->id);
|
$angeltypes = AngelTypes_with_user($user->id);
|
||||||
foreach ($angeltypes as $angeltype) {
|
foreach ($angeltypes as $angeltype) {
|
||||||
$actions = [
|
$actions = [
|
||||||
button(
|
button(
|
||||||
page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
|
url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('eye') . __('view'),
|
icon('eye') . ($admin_angeltypes ? '' : __('View')),
|
||||||
'btn-sm'
|
'btn-sm btn-info',
|
||||||
|
'',
|
||||||
|
($admin_angeltypes ? __('View') : '')
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (auth()->can('admin_angel_types')) {
|
if ($admin_angeltypes) {
|
||||||
$actions[] = button(
|
$actions[] = button(
|
||||||
page_link_to('angeltypes', ['action' => 'edit', 'angeltype_id' => $angeltype->id]),
|
url('/angeltypes', ['action' => 'edit', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('pencil') . __('edit'),
|
icon('pencil'),
|
||||||
'btn-sm'
|
'btn-sm',
|
||||||
|
'',
|
||||||
|
__('form.edit')
|
||||||
);
|
);
|
||||||
$actions[] = button(
|
$actions[] = button(
|
||||||
page_link_to('angeltypes', ['action' => 'delete', 'angeltype_id' => $angeltype->id]),
|
url('/angeltypes', ['action' => 'delete', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('trash') . __('delete'),
|
icon('trash'),
|
||||||
'btn-sm'
|
'btn-sm btn-danger',
|
||||||
|
'',
|
||||||
|
__('form.delete')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltype->membership = AngelType_render_membership($angeltype);
|
$angeltype->membership = AngelType_render_membership($angeltype);
|
||||||
if (!empty($angeltype->user_angel_type_id)) {
|
if (!empty($angeltype->user_angel_type_id)) {
|
||||||
$actions[] = button(
|
$actions[] = button(
|
||||||
page_link_to(
|
url(
|
||||||
'user_angeltypes',
|
'/user-angeltypes',
|
||||||
['action' => 'delete', 'user_angeltype_id' => $angeltype->user_angel_type_id]
|
['action' => 'delete', 'user_angeltype_id' => $angeltype->user_angel_type_id]
|
||||||
),
|
),
|
||||||
icon('box-arrow-right') . __('leave'),
|
icon('box-arrow-right') . ($admin_angeltypes ? '' : __('Leave')),
|
||||||
'btn-sm'
|
'btn-sm',
|
||||||
|
'',
|
||||||
|
($admin_angeltypes ? __('Leave') : '')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$actions[] = button(
|
$actions[] = button(
|
||||||
page_link_to('user_angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
|
url('/user_angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('box-arrow-in-right') . __('join'),
|
icon('box-arrow-in-right') . ($admin_angeltypes ? '' : __('Join')),
|
||||||
'btn-sm'
|
'btn-sm',
|
||||||
|
'',
|
||||||
|
($admin_angeltypes ? __('Join') : '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltype->is_restricted = $angeltype->restricted ? icon('mortarboard-fill') : '';
|
$angeltype->is_restricted = $angeltype->restricted ? icon('mortarboard-fill') : '';
|
||||||
$angeltype->no_self_signup_allowed = $angeltype->no_self_signup ? '' : icon('pencil-square');
|
$angeltype->shift_self_signup_allowed = $angeltype->shift_self_signup ? icon('pencil-square') : '';
|
||||||
|
|
||||||
$angeltype->name = '<a href="'
|
$angeltype->name = '<a href="'
|
||||||
. page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id])
|
. url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id])
|
||||||
. '">'
|
. '">'
|
||||||
. $angeltype->name
|
. htmlspecialchars($angeltype->name)
|
||||||
. '</a>';
|
. '</a>';
|
||||||
|
|
||||||
$angeltype->actions = table_buttons($actions);
|
$angeltype->actions = table_buttons($actions);
|
||||||
|
|
|
@ -17,7 +17,7 @@ function event_config_title()
|
||||||
function event_config_edit_controller()
|
function event_config_edit_controller()
|
||||||
{
|
{
|
||||||
if (!auth()->can('admin_event_config')) {
|
if (!auth()->can('admin_event_config')) {
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = request();
|
$request = request();
|
||||||
|
@ -117,8 +117,8 @@ function event_config_edit_controller()
|
||||||
$teardown_end_date ? $teardown_end_date->format('Y-m-d H:i') : ''
|
$teardown_end_date ? $teardown_end_date->format('Y-m-d H:i') : ''
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
success(__('Settings saved.'));
|
success(__('settings.success'));
|
||||||
throw_redirect(page_link_to('admin_event_config'));
|
throw_redirect(url('/admin_event_config'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,40 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\ShiftsFilter;
|
use Engelsystem\ShiftsFilter;
|
||||||
use Engelsystem\ShiftsFilterRenderer;
|
use Engelsystem\ShiftsFilterRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Room controllers for managing everything room related.
|
* Location controllers for managing everything location related.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View a room with its shifts.
|
* View a location with its shifts.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function room_controller(): array
|
function location_controller(): array
|
||||||
{
|
{
|
||||||
if (!auth()->can('view_rooms')) {
|
if (!auth()->can('view_locations')) {
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = request();
|
$request = request();
|
||||||
$room = load_room();
|
$location = load_location();
|
||||||
|
|
||||||
$all_shifts = $room->shifts->sortBy('start');
|
$all_shifts = $location->shifts->sortBy('start');
|
||||||
$days = [];
|
$days = [];
|
||||||
foreach ($all_shifts as $shift) {
|
foreach ($all_shifts as $shift) {
|
||||||
$day = $shift->start->format('Y-m-d');
|
$day = $shift->start->format('Y-m-d');
|
||||||
if (!isset($days[$day])) {
|
if (!isset($days[$day])) {
|
||||||
$days[$day] = $shift->start->format(__('Y-m-d'));
|
$days[$day] = dateWithEventDay($day);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$shiftsFilter = new ShiftsFilter(
|
$shiftsFilter = new ShiftsFilter(
|
||||||
true,
|
true,
|
||||||
[$room->id],
|
[$location->id],
|
||||||
AngelType::query()->get('id')->pluck('id')->toArray()
|
AngelType::query()->get('id')->pluck('id')->toArray()
|
||||||
);
|
);
|
||||||
$selected_day = date('Y-m-d');
|
$selected_day = date('Y-m-d');
|
||||||
|
@ -53,17 +53,17 @@ function room_controller(): array
|
||||||
$shiftCalendarRenderer = shiftCalendarRendererByShiftFilter($shiftsFilter);
|
$shiftCalendarRenderer = shiftCalendarRendererByShiftFilter($shiftsFilter);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
$room->name,
|
htmlspecialchars($location->name),
|
||||||
Room_view($room, $shiftsFilterRenderer, $shiftCalendarRenderer),
|
location_view($location, $shiftsFilterRenderer, $shiftCalendarRenderer),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch different room actions.
|
* Dispatch different location actions.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function rooms_controller(): array
|
function locations_controller(): array
|
||||||
{
|
{
|
||||||
$request = request();
|
$request = request();
|
||||||
$action = $request->input('action');
|
$action = $request->input('action');
|
||||||
|
@ -72,36 +72,36 @@ function rooms_controller(): array
|
||||||
}
|
}
|
||||||
|
|
||||||
return match ($action) {
|
return match ($action) {
|
||||||
'view' => room_controller(),
|
'view' => location_controller(),
|
||||||
'list' => throw_redirect(page_link_to('admin/rooms')),
|
'list' => throw_redirect(url('/admin/locations')),
|
||||||
default => throw_redirect(page_link_to('admin/rooms')),
|
default => throw_redirect(url('/admin/locations')),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Room $room
|
* @param Location $location
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function room_link(Room $room)
|
function location_link(Location $location)
|
||||||
{
|
{
|
||||||
return page_link_to('rooms', ['action' => 'view', 'room_id' => $room->id]);
|
return url('/locations', ['action' => 'view', 'location_id' => $location->id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads room by request param room_id
|
* Loads location by request param location_id
|
||||||
*
|
*
|
||||||
* @return Room
|
* @return Location
|
||||||
*/
|
*/
|
||||||
function load_room()
|
function load_location()
|
||||||
{
|
{
|
||||||
if (!test_request_int('room_id')) {
|
if (!test_request_int('location_id')) {
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$room = Room::find(request()->input('room_id'));
|
$location = Location::find(request()->input('location_id'));
|
||||||
if (!$room) {
|
if (!$location) {
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $room;
|
return $location;
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\News;
|
use Engelsystem\Models\News;
|
||||||
use Engelsystem\Models\Room;
|
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\ShiftsFilter;
|
use Engelsystem\ShiftsFilter;
|
||||||
|
|
||||||
|
@ -15,22 +15,22 @@ function public_dashboard_controller()
|
||||||
{
|
{
|
||||||
$filter = null;
|
$filter = null;
|
||||||
if (request()->get('filtered')) {
|
if (request()->get('filtered')) {
|
||||||
$requestRooms = check_request_int_array('rooms');
|
$requestLocations = check_request_int_array('locations');
|
||||||
$requestAngelTypes = check_request_int_array('types');
|
$requestAngelTypes = check_request_int_array('types');
|
||||||
|
|
||||||
if (!$requestRooms && !$requestAngelTypes) {
|
if (!$requestLocations && !$requestAngelTypes) {
|
||||||
$sessionFilter = collect(session()->get('shifts-filter', []));
|
$sessionFilter = collect(session()->get('shifts-filter', []));
|
||||||
$requestRooms = $sessionFilter->get('rooms', []);
|
$requestLocations = $sessionFilter->get('locations', []);
|
||||||
$requestAngelTypes = $sessionFilter->get('types', []);
|
$requestAngelTypes = $sessionFilter->get('types', []);
|
||||||
}
|
}
|
||||||
|
|
||||||
$angelTypes = collect(unrestricted_angeltypes());
|
$angelTypes = collect(unrestricted_angeltypes());
|
||||||
$rooms = $requestRooms ?: Room::orderBy('name')->get()->pluck('id')->toArray();
|
$locations = $requestLocations ?: Location::orderBy('name')->get()->pluck('id')->toArray();
|
||||||
$angelTypes = $requestAngelTypes ?: $angelTypes->pluck('id')->toArray();
|
$angelTypes = $requestAngelTypes ?: $angelTypes->pluck('id')->toArray();
|
||||||
$filterValues = [
|
$filterValues = [
|
||||||
'userShiftsAdmin' => false,
|
'userShiftsAdmin' => false,
|
||||||
'filled' => [],
|
'filled' => [],
|
||||||
'rooms' => $rooms,
|
'locations' => $locations,
|
||||||
'types' => $angelTypes,
|
'types' => $angelTypes,
|
||||||
'startTime' => null,
|
'startTime' => null,
|
||||||
'endTime' => null,
|
'endTime' => null,
|
||||||
|
@ -57,14 +57,14 @@ function public_dashboard_controller()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$important_news = News::whereIsImportant(true)
|
$highlighted_news = News::whereIsHighlighted(true)
|
||||||
->orderBy('updated_at')
|
->orderBy('updated_at')
|
||||||
->limit(1)
|
->limit(1)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
__('Public Dashboard'),
|
__('Public Dashboard'),
|
||||||
public_dashboard_view($stats, $free_shifts, $important_news),
|
public_dashboard_view($stats, $free_shifts, $highlighted_news),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ function public_dashboard_controller_free_shift(Shift $shift, ShiftsFilter $filt
|
||||||
'duration' => round(($shift->end->timestamp - $shift->start->timestamp) / 3600),
|
'duration' => round(($shift->end->timestamp - $shift->start->timestamp) / 3600),
|
||||||
'shifttype_name' => $shift->shiftType->name,
|
'shifttype_name' => $shift->shiftType->name,
|
||||||
'title' => $shift->title,
|
'title' => $shift->title,
|
||||||
'room_name' => $shift->room->name,
|
'location_name' => $shift->location->name,
|
||||||
'needed_angels' => public_dashboard_needed_angels($shift->neededAngels, $filter),
|
'needed_angels' => public_dashboard_needed_angels($shift->neededAngels, $filter),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -136,5 +136,5 @@ function public_dashboard_needed_angels($needed_angels, ShiftsFilter $filter = n
|
||||||
*/
|
*/
|
||||||
function public_dashboard_link(array $parameters = []): string
|
function public_dashboard_link(array $parameters = []): string
|
||||||
{
|
{
|
||||||
return page_link_to('public-dashboard', $parameters);
|
return url('/public-dashboard', $parameters);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ function shift_entries_controller(): array
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
throw_redirect(page_link_to('login'));
|
throw_redirect(url('/login'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$action = strip_request_item('action');
|
$action = strip_request_item('action');
|
||||||
|
@ -44,7 +44,7 @@ function shift_entry_create_controller(): array
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if ($user->isFreeloader()) {
|
if ($user->isFreeloader()) {
|
||||||
throw_redirect(page_link_to('user_myshifts'));
|
throw_redirect(url('/user_myshifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$shift = Shift($request->input('shift_id'));
|
$shift = Shift($request->input('shift_id'));
|
||||||
|
@ -113,17 +113,21 @@ function shift_entry_create_controller_admin(Shift $shift, ?AngelType $angeltype
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var User[]|Collection $users */
|
/** @var User[]|Collection $users */
|
||||||
$users = User::query()->orderBy('name')->get();
|
$users = User::with('userAngelTypes')->orderBy('name')->get();
|
||||||
$users_select = [];
|
$users_select = [];
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$users_select[$user->id] = $user->displayName;
|
$name = $user->displayName;
|
||||||
|
if ($user->userAngelTypes->where('id', $angeltype->id)->isEmpty()) {
|
||||||
|
$name = __('%s (not "%s")', [$name, $angeltype->name]);
|
||||||
|
}
|
||||||
|
$users_select[$user->id] = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltypes_select = $angeltypes->pluck('name', 'id')->toArray();
|
$angeltypes_select = $angeltypes->pluck('name', 'id')->toArray();
|
||||||
$room = $shift->room;
|
$location = $shift->location;
|
||||||
return [
|
return [
|
||||||
ShiftEntry_create_title(),
|
ShiftEntry_create_title(),
|
||||||
ShiftEntry_create_view_admin($shift, $room, $angeltype, $angeltypes_select, $signup_user, $users_select),
|
ShiftEntry_create_view_admin($shift, $location, $angeltype, $angeltypes_select, $signup_user, $users_select),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,10 +171,10 @@ function shift_entry_create_controller_supporter(Shift $shift, AngelType $angelt
|
||||||
$users_select[$u->id] = $u->displayName;
|
$users_select[$u->id] = $u->displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
$room = $shift->room;
|
$location = $shift->location;
|
||||||
return [
|
return [
|
||||||
ShiftEntry_create_title(),
|
ShiftEntry_create_title(),
|
||||||
ShiftEntry_create_view_supporter($shift, $room, $angeltype, $signup_user, $users_select),
|
ShiftEntry_create_view_supporter($shift, $location, $angeltype, $signup_user, $users_select),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,10 +254,10 @@ function shift_entry_create_controller_user(Shift $shift, AngelType $angeltype):
|
||||||
throw_redirect(shift_link($shift));
|
throw_redirect(shift_link($shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
$room = $shift->room;
|
$location = $shift->location;
|
||||||
return [
|
return [
|
||||||
ShiftEntry_create_title(),
|
ShiftEntry_create_title(),
|
||||||
ShiftEntry_create_view_user($shift, $room, $angeltype, $comment),
|
ShiftEntry_create_view_user($shift, $location, $angeltype, $comment),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +276,7 @@ function shift_entry_create_link(Shift $shift, AngelType $angeltype, $params = [
|
||||||
'shift_id' => $shift->id,
|
'shift_id' => $shift->id,
|
||||||
'angeltype_id' => $angeltype->id,
|
'angeltype_id' => $angeltype->id,
|
||||||
], $params);
|
], $params);
|
||||||
return page_link_to('shift_entries', $params);
|
return url('/shift-entries', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -288,7 +292,7 @@ function shift_entry_create_link_admin(Shift $shift, $params = [])
|
||||||
'action' => 'create',
|
'action' => 'create',
|
||||||
'shift_id' => $shift->id,
|
'shift_id' => $shift->id,
|
||||||
], $params);
|
], $params);
|
||||||
return page_link_to('shift_entries', $params);
|
return url('/shift-entries', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -301,7 +305,7 @@ function shift_entry_load()
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (!$request->has('shift_entry_id') || !test_request_int('shift_entry_id')) {
|
if (!$request->has('shift_entry_id') || !test_request_int('shift_entry_id')) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
$shiftEntry = ShiftEntry::findOrFail($request->input('shift_entry_id'));
|
$shiftEntry = ShiftEntry::findOrFail($request->input('shift_entry_id'));
|
||||||
|
|
||||||
|
@ -362,5 +366,5 @@ function shift_entry_delete_link($shiftEntry, $params = [])
|
||||||
'action' => 'delete',
|
'action' => 'delete',
|
||||||
'shift_entry_id' => $shiftEntry['shift_entry_id'] ?? $shiftEntry['id'],
|
'shift_entry_id' => $shiftEntry['shift_entry_id'] ?? $shiftEntry['id'],
|
||||||
], $params);
|
], $params);
|
||||||
return page_link_to('shift_entries', $params);
|
return url('/shift-entries', $params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Room;
|
|
||||||
use Engelsystem\Models\Shifts\ScheduleShift;
|
use Engelsystem\Models\Shifts\ScheduleShift;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
|
@ -20,7 +20,7 @@ function shift_link($shift)
|
||||||
$parameters['shift_id'] = $shift['shift_id'] ?? $shift['id'];
|
$parameters['shift_id'] = $shift['shift_id'] ?? $shift['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_link_to('shifts', $parameters);
|
return url('/shifts', $parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +29,7 @@ function shift_link($shift)
|
||||||
*/
|
*/
|
||||||
function shift_delete_link(Shift $shift)
|
function shift_delete_link(Shift $shift)
|
||||||
{
|
{
|
||||||
return page_link_to('user_shifts', ['delete_shift' => $shift->id]);
|
return url('/user-shifts', ['delete_shift' => $shift->id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,7 +38,7 @@ function shift_delete_link(Shift $shift)
|
||||||
*/
|
*/
|
||||||
function shift_edit_link(Shift $shift)
|
function shift_edit_link(Shift $shift)
|
||||||
{
|
{
|
||||||
return page_link_to('user_shifts', ['edit_shift' => $shift->id]);
|
return url('/user-shifts', ['edit_shift' => $shift->id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,11 +52,11 @@ function shift_edit_controller()
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (!auth()->can('admin_shifts')) {
|
if (!auth()->can('admin_shifts')) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$request->has('edit_shift') || !test_request_int('edit_shift')) {
|
if (!$request->has('edit_shift') || !test_request_int('edit_shift')) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
$shift_id = $request->input('edit_shift');
|
$shift_id = $request->input('edit_shift');
|
||||||
|
|
||||||
|
@ -67,14 +67,14 @@ function shift_edit_controller()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$rooms = [];
|
$locations = [];
|
||||||
foreach (Room::orderBy('name')->get() as $room) {
|
foreach (Location::orderBy('name')->get() as $location) {
|
||||||
$rooms[$room->id] = $room->name;
|
$locations[$location->id] = $location->name;
|
||||||
}
|
}
|
||||||
$angeltypes = AngelType::all()->pluck('name', 'id')->toArray();
|
$angeltypes = AngelType::all()->pluck('name', 'id')->toArray();
|
||||||
$shifttypes = ShiftType::all()->pluck('name', 'id')->toArray();
|
$shifttypes = ShiftType::all()->pluck('name', 'id')->toArray();
|
||||||
|
|
||||||
$needed_angel_types = collect(NeededAngelTypes_by_shift($shift_id))->pluck('count', 'angel_type_id')->toArray();
|
$needed_angel_types = collect(NeededAngelTypes_by_shift($shift))->pluck('count', 'angel_type_id')->toArray();
|
||||||
foreach (array_keys($angeltypes) as $angeltype_id) {
|
foreach (array_keys($angeltypes) as $angeltype_id) {
|
||||||
if (!isset($needed_angel_types[$angeltype_id])) {
|
if (!isset($needed_angel_types[$angeltype_id])) {
|
||||||
$needed_angel_types[$angeltype_id] = 0;
|
$needed_angel_types[$angeltype_id] = 0;
|
||||||
|
@ -84,7 +84,7 @@ function shift_edit_controller()
|
||||||
$shifttype_id = $shift->shift_type_id;
|
$shifttype_id = $shift->shift_type_id;
|
||||||
$title = $shift->title;
|
$title = $shift->title;
|
||||||
$description = $shift->description;
|
$description = $shift->description;
|
||||||
$rid = $shift->room_id;
|
$rid = $shift->location_id;
|
||||||
$start = $shift->start;
|
$start = $shift->start;
|
||||||
$end = $shift->end;
|
$end = $shift->end;
|
||||||
|
|
||||||
|
@ -97,12 +97,12 @@ function shift_edit_controller()
|
||||||
if (
|
if (
|
||||||
$request->has('rid')
|
$request->has('rid')
|
||||||
&& preg_match('/^\d+$/', $request->input('rid'))
|
&& preg_match('/^\d+$/', $request->input('rid'))
|
||||||
&& isset($rooms[$request->input('rid')])
|
&& isset($locations[$request->input('rid')])
|
||||||
) {
|
) {
|
||||||
$rid = $request->input('rid');
|
$rid = $request->input('rid');
|
||||||
} else {
|
} else {
|
||||||
$valid = false;
|
$valid = false;
|
||||||
error(__('Please select a room.'));
|
error(__('Please select a location.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('shifttype_id') && isset($shifttypes[$request->input('shifttype_id')])) {
|
if ($request->has('shifttype_id') && isset($shifttypes[$request->input('shifttype_id')])) {
|
||||||
|
@ -154,13 +154,16 @@ function shift_edit_controller()
|
||||||
$shift->shift_type_id = $shifttype_id;
|
$shift->shift_type_id = $shifttype_id;
|
||||||
$shift->title = $title;
|
$shift->title = $title;
|
||||||
$shift->description = $description;
|
$shift->description = $description;
|
||||||
$shift->room_id = $rid;
|
$shift->location_id = $rid;
|
||||||
$shift->start = $start;
|
$shift->start = $start;
|
||||||
$shift->end = $end;
|
$shift->end = $end;
|
||||||
$shift->updatedBy()->associate(auth()->user());
|
$shift->updatedBy()->associate(auth()->user());
|
||||||
$shift->save();
|
$shift->save();
|
||||||
|
|
||||||
mail_shift_change($oldShift, $shift);
|
event('shift.updating', [
|
||||||
|
'shift' => $shift,
|
||||||
|
'oldShift' => $oldShift,
|
||||||
|
]);
|
||||||
|
|
||||||
NeededAngelType::whereShiftId($shift_id)->delete();
|
NeededAngelType::whereShiftId($shift_id)->delete();
|
||||||
$needed_angel_types_info = [];
|
$needed_angel_types_info = [];
|
||||||
|
@ -194,13 +197,16 @@ function shift_edit_controller()
|
||||||
foreach ($angeltypes as $angeltype_id => $angeltype_name) {
|
foreach ($angeltypes as $angeltype_id => $angeltype_name) {
|
||||||
$angel_types_spinner .= form_spinner(
|
$angel_types_spinner .= form_spinner(
|
||||||
'angeltype_count_' . $angeltype_id,
|
'angeltype_count_' . $angeltype_id,
|
||||||
$angeltype_name,
|
htmlspecialchars($angeltype_name),
|
||||||
$needed_angel_types[$angeltype_id]
|
$needed_angel_types[$angeltype_id],
|
||||||
|
[],
|
||||||
|
ScheduleShift::whereShiftId($shift->id)->first() ? true : false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$link = button(url('/shifts', ['action' => 'view', 'shift_id' => $shift_id]), icon('chevron-left'), 'btn-sm', '', __('general.back'));
|
||||||
return page_with_title(
|
return page_with_title(
|
||||||
shifts_title(),
|
$link . ' ' . shifts_title(),
|
||||||
[
|
[
|
||||||
msg(),
|
msg(),
|
||||||
'<noscript>'
|
'<noscript>'
|
||||||
|
@ -208,15 +214,18 @@ function shift_edit_controller()
|
||||||
. '</noscript>',
|
. '</noscript>',
|
||||||
form([
|
form([
|
||||||
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
|
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
|
||||||
form_text('title', __('Title'), $title),
|
form_text('title', __('title.title'), $title),
|
||||||
form_select('rid', __('Room:'), $rooms, $rid),
|
form_select('rid', __('Location:'), $locations, $rid),
|
||||||
form_text('start', __('Start:'), $start->format('Y-m-d H:i')),
|
form_text('start', __('Start:'), $start->format('Y-m-d H:i')),
|
||||||
form_text('end', __('End:'), $end->format('Y-m-d H:i')),
|
form_text('end', __('End:'), $end->format('Y-m-d H:i')),
|
||||||
form_textarea('description', __('Additional description'), $description),
|
form_textarea('description', __('Additional description'), $description),
|
||||||
form_info('', __('This description is for single shifts, otherwise please use the description in shift type.')),
|
form_info(
|
||||||
|
'',
|
||||||
|
__('This description is for single shifts, otherwise please use the description in shift type.')
|
||||||
|
),
|
||||||
'<h2>' . __('Needed angels') . '</h2>',
|
'<h2>' . __('Needed angels') . '</h2>',
|
||||||
$angel_types_spinner,
|
$angel_types_spinner,
|
||||||
form_submit('submit', __('Save')),
|
form_submit('submit', icon('save') . __('form.save')),
|
||||||
]),
|
]),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -230,18 +239,18 @@ function shift_delete_controller()
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (!auth()->can('user_shifts_admin')) {
|
if (!auth()->can('user_shifts_admin')) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schicht komplett löschen (nur für admins/user mit user_shifts_admin privileg)
|
// Schicht komplett löschen (nur für admins/user mit user_shifts_admin privileg)
|
||||||
if (!$request->has('delete_shift') || !preg_match('/^\d+$/', $request->input('delete_shift'))) {
|
if (!$request->has('delete_shift') || !preg_match('/^\d+$/', $request->input('delete_shift'))) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
$shift_id = $request->input('delete_shift');
|
$shift_id = $request->input('delete_shift');
|
||||||
|
|
||||||
$shift = Shift($shift_id);
|
$shift = Shift($shift_id);
|
||||||
if (empty($shift)) {
|
if (empty($shift)) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schicht löschen bestätigt
|
// Schicht löschen bestätigt
|
||||||
|
@ -254,7 +263,7 @@ function shift_delete_controller()
|
||||||
'name' => $shift->shiftType->name,
|
'name' => $shift->shiftType->name,
|
||||||
'title' => $shift->title,
|
'title' => $shift->title,
|
||||||
'type' => $entry->angelType->name,
|
'type' => $entry->angelType->name,
|
||||||
'room' => $shift->room,
|
'location' => $shift->location,
|
||||||
'freeloaded' => $entry->freeloaded,
|
'freeloaded' => $entry->freeloaded,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -267,21 +276,25 @@ function shift_delete_controller()
|
||||||
. ' to ' . $shift->end->format('Y-m-d H:i')
|
. ' to ' . $shift->end->format('Y-m-d H:i')
|
||||||
);
|
);
|
||||||
success(__('Shift deleted.'));
|
success(__('Shift deleted.'));
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_with_title(shifts_title(), [
|
$link = button(url('/shifts', ['action' => 'view', 'shift_id' => $shift_id]), icon('chevron-left'), 'btn-sm', '', __('general.back'));
|
||||||
error(sprintf(
|
return page_with_title(
|
||||||
__('Do you want to delete the shift %s from %s to %s?'),
|
$link . ' ' . shifts_title(),
|
||||||
$shift->shiftType->name,
|
[
|
||||||
$shift->start->format(__('Y-m-d H:i')),
|
error(sprintf(
|
||||||
$shift->end->format(__('H:i'))
|
__('Do you want to delete the shift %s from %s to %s?'),
|
||||||
), true),
|
$shift->shiftType->name,
|
||||||
form([
|
$shift->start->format(__('general.datetime')),
|
||||||
form_hidden('delete_shift', $shift->id),
|
$shift->end->format(__('H:i'))
|
||||||
form_submit('delete', __('delete')),
|
), true),
|
||||||
]),
|
form([
|
||||||
]);
|
form_hidden('delete_shift', $shift->id),
|
||||||
|
form_submit('delete', icon('trash') . __('form.delete'), '', true, 'danger'),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -293,21 +306,21 @@ function shift_controller()
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (!auth()->can('user_shifts')) {
|
if (!auth()->can('user_shifts')) {
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$request->has('shift_id')) {
|
if (!$request->has('shift_id')) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$shift = Shift($request->input('shift_id'));
|
$shift = Shift($request->input('shift_id'));
|
||||||
if (empty($shift)) {
|
if (empty($shift)) {
|
||||||
error(__('Shift could not be found.'));
|
error(__('Shift could not be found.'));
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$shifttype = $shift->shiftType;
|
$shifttype = $shift->shiftType;
|
||||||
$room = $shift->room;
|
$location = $shift->location;
|
||||||
/** @var AngelType[] $angeltypes */
|
/** @var AngelType[] $angeltypes */
|
||||||
$angeltypes = AngelType::all();
|
$angeltypes = AngelType::all();
|
||||||
$user_shifts = Shifts_by_user($user->id);
|
$user_shifts = Shifts_by_user($user->id);
|
||||||
|
@ -338,8 +351,8 @@ function shift_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
$shift->shiftType->name,
|
htmlspecialchars($shift->shiftType->name),
|
||||||
Shift_view($shift, $shifttype, $room, $angeltypes, $shift_signup_state),
|
Shift_view($shift, $shifttype, $location, $angeltypes, $shift_signup_state),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,13 +363,13 @@ function shifts_controller()
|
||||||
{
|
{
|
||||||
$request = request();
|
$request = request();
|
||||||
if (!$request->has('action')) {
|
if (!$request->has('action')) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return match ($request->input('action')) {
|
return match ($request->input('action')) {
|
||||||
'view' => shift_controller(),
|
'view' => shift_controller(),
|
||||||
'next' => shift_next_controller(), // throws redirect
|
'next' => shift_next_controller(), // throws redirect
|
||||||
default => throw_redirect(page_link_to('/')),
|
default => throw_redirect(url('/')),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +379,7 @@ function shifts_controller()
|
||||||
function shift_next_controller()
|
function shift_next_controller()
|
||||||
{
|
{
|
||||||
if (!auth()->can('user_shifts')) {
|
if (!auth()->can('user_shifts')) {
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$upcoming_shifts = ShiftEntries_upcoming_for_user(auth()->user());
|
$upcoming_shifts = ShiftEntries_upcoming_for_user(auth()->user());
|
||||||
|
@ -375,5 +388,5 @@ function shift_next_controller()
|
||||||
throw_redirect(shift_link($upcoming_shifts[0]->shift));
|
throw_redirect(shift_link($upcoming_shifts[0]->shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(url('/user-shifts'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,163 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ShiftType $shifttype
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function shifttype_link(ShiftType $shifttype)
|
|
||||||
{
|
|
||||||
return page_link_to('shifttypes', ['action' => 'view', 'shifttype_id' => $shifttype->id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a shifttype.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function shifttype_delete_controller()
|
|
||||||
{
|
|
||||||
$request = request();
|
|
||||||
if (!$request->has('shifttype_id')) {
|
|
||||||
throw_redirect(page_link_to('shifttypes'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$shifttype = ShiftType::findOrFail($request->input('shifttype_id'));
|
|
||||||
if ($request->hasPostData('delete')) {
|
|
||||||
engelsystem_log('Deleted shifttype ' . $shifttype->name);
|
|
||||||
success(sprintf(__('Shifttype %s deleted.'), $shifttype->name));
|
|
||||||
|
|
||||||
$shifttype->delete();
|
|
||||||
throw_redirect(page_link_to('shifttypes'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
sprintf(__('Delete shifttype %s'), $shifttype->name),
|
|
||||||
ShiftType_delete_view($shifttype),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit or create shift type.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function shifttype_edit_controller()
|
|
||||||
{
|
|
||||||
$shifttype_id = null;
|
|
||||||
$name = '';
|
|
||||||
$description = '';
|
|
||||||
|
|
||||||
$request = request();
|
|
||||||
|
|
||||||
if ($request->has('shifttype_id')) {
|
|
||||||
$shifttype = ShiftType::findOrFail($request->input('shifttype_id'));
|
|
||||||
$shifttype_id = $shifttype->id;
|
|
||||||
$name = $shifttype->name;
|
|
||||||
$description = $shifttype->description;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->hasPostData('submit')) {
|
|
||||||
$valid = true;
|
|
||||||
|
|
||||||
if ($request->has('name') && $request->input('name') != '') {
|
|
||||||
$name = strip_request_item('name');
|
|
||||||
} else {
|
|
||||||
$valid = false;
|
|
||||||
error(__('Please enter a name.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('description')) {
|
|
||||||
$description = strip_request_item_nl('description');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($valid) {
|
|
||||||
$shiftType = ShiftType::findOrNew($shifttype_id);
|
|
||||||
$shiftType->name = $name;
|
|
||||||
$shiftType->description = $description;
|
|
||||||
$shiftType->save();
|
|
||||||
|
|
||||||
if ($shifttype_id) {
|
|
||||||
engelsystem_log('Updated shifttype ' . $name);
|
|
||||||
success(__('Updated shifttype.'));
|
|
||||||
} else {
|
|
||||||
$shifttype_id = $shiftType->id;
|
|
||||||
|
|
||||||
engelsystem_log('Created shifttype ' . $name);
|
|
||||||
success(__('Created shifttype.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw_redirect(page_link_to('shifttypes', ['action' => 'view', 'shifttype_id' => $shifttype_id]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
shifttypes_title(),
|
|
||||||
ShiftType_edit_view($name, $description, $shifttype_id),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function shifttype_controller()
|
|
||||||
{
|
|
||||||
$request = request();
|
|
||||||
if (!$request->has('shifttype_id')) {
|
|
||||||
throw_redirect(page_link_to('shifttypes'));
|
|
||||||
}
|
|
||||||
$shifttype = ShiftType::findOrFail($request->input('shifttype_id'));
|
|
||||||
|
|
||||||
return [
|
|
||||||
$shifttype->name,
|
|
||||||
ShiftType_view($shifttype),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List all shift types.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function shifttypes_list_controller()
|
|
||||||
{
|
|
||||||
$shifttypes = ShiftType::all();
|
|
||||||
|
|
||||||
return [
|
|
||||||
shifttypes_title(),
|
|
||||||
ShiftTypes_list_view($shifttypes),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Text for shift type related links.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function shifttypes_title()
|
|
||||||
{
|
|
||||||
return __('Shifttypes');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Route shift type actions
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function shifttypes_controller()
|
|
||||||
{
|
|
||||||
$request = request();
|
|
||||||
$action = 'list';
|
|
||||||
if ($request->has('action')) {
|
|
||||||
$action = $request->input('action');
|
|
||||||
}
|
|
||||||
|
|
||||||
return match ($action) {
|
|
||||||
'view' => shifttype_controller(),
|
|
||||||
'edit' => shifttype_edit_controller(),
|
|
||||||
'delete' => shifttype_delete_controller(),
|
|
||||||
'list' => shifttypes_list_controller(),
|
|
||||||
default => shifttypes_list_controller(),
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -5,8 +5,6 @@ use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Models\UserAngelType;
|
use Engelsystem\Models\UserAngelType;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
use Symfony\Component\Mailer\Exception\TransportException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a hint for team/angeltype supporters if there are unconfirmed users for his angeltype.
|
* Display a hint for team/angeltype supporters if there are unconfirmed users for his angeltype.
|
||||||
|
@ -37,9 +35,9 @@ function user_angeltypes_unconfirmed_hint()
|
||||||
|
|
||||||
$unconfirmed_links = [];
|
$unconfirmed_links = [];
|
||||||
foreach ($unconfirmed_user_angeltypes as $user_angeltype) {
|
foreach ($unconfirmed_user_angeltypes as $user_angeltype) {
|
||||||
$unconfirmed_links[] = '<a class="text-info" href="'
|
$unconfirmed_links[] = '<a href="'
|
||||||
. page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $user_angeltype->angel_type_id])
|
. url('/angeltypes', ['action' => 'view', 'angeltype_id' => $user_angeltype->angel_type_id])
|
||||||
. '">' . $user_angeltype->angelType->name
|
. '">' . htmlspecialchars($user_angeltype->angelType->name)
|
||||||
. ' (+' . $user_angeltype->count . ')'
|
. ' (+' . $user_angeltype->count . ')'
|
||||||
. '</a>';
|
. '</a>';
|
||||||
}
|
}
|
||||||
|
@ -67,13 +65,13 @@ function user_angeltypes_delete_all_controller(): array
|
||||||
|
|
||||||
if (!$request->has('angeltype_id')) {
|
if (!$request->has('angeltype_id')) {
|
||||||
error(__('Angeltype doesn\'t exist.'));
|
error(__('Angeltype doesn\'t exist.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
|
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
|
||||||
if (!auth()->user()->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
|
if (!auth()->user()->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
|
||||||
error(__('You are not allowed to delete all users for this angeltype.'));
|
error(__('You are not allowed to delete all users for this angeltype.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasPostData('deny_all')) {
|
if ($request->hasPostData('deny_all')) {
|
||||||
|
@ -83,7 +81,7 @@ function user_angeltypes_delete_all_controller(): array
|
||||||
|
|
||||||
engelsystem_log(sprintf('Denied all users for angeltype %s', AngelType_name_render($angeltype, true)));
|
engelsystem_log(sprintf('Denied all users for angeltype %s', AngelType_name_render($angeltype, true)));
|
||||||
success(sprintf(__('Denied all users for angeltype %s.'), $angeltype->name));
|
success(sprintf(__('Denied all users for angeltype %s.'), $angeltype->name));
|
||||||
throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -104,13 +102,13 @@ function user_angeltypes_confirm_all_controller(): array
|
||||||
|
|
||||||
if (!$request->has('angeltype_id')) {
|
if (!$request->has('angeltype_id')) {
|
||||||
error(__('Angeltype doesn\'t exist.'));
|
error(__('Angeltype doesn\'t exist.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
|
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
|
||||||
if (!auth()->can('admin_user_angeltypes') && !$user->isAngelTypeSupporter($angeltype)) {
|
if (!auth()->can('admin_user_angeltypes') && !$user->isAngelTypeSupporter($angeltype)) {
|
||||||
error(__('You are not allowed to confirm all users for this angeltype.'));
|
error(__('You are not allowed to confirm all users for this angeltype.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasPostData('confirm_all')) {
|
if ($request->hasPostData('confirm_all')) {
|
||||||
|
@ -127,7 +125,7 @@ function user_angeltypes_confirm_all_controller(): array
|
||||||
user_angeltype_confirm_email($user, $angeltype);
|
user_angeltype_confirm_email($user, $angeltype);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -148,7 +146,7 @@ function user_angeltype_confirm_controller(): array
|
||||||
|
|
||||||
if (!$request->has('user_angeltype_id')) {
|
if (!$request->has('user_angeltype_id')) {
|
||||||
error(__('User angeltype doesn\'t exist.'));
|
error(__('User angeltype doesn\'t exist.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var UserAngelType $user_angeltype */
|
/** @var UserAngelType $user_angeltype */
|
||||||
|
@ -156,7 +154,7 @@ function user_angeltype_confirm_controller(): array
|
||||||
$angeltype = $user_angeltype->angelType;
|
$angeltype = $user_angeltype->angelType;
|
||||||
if (!$user->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
|
if (!$user->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
|
||||||
error(__('You are not allowed to confirm this users angeltype.'));
|
error(__('You are not allowed to confirm this users angeltype.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_source = $user_angeltype->user;
|
$user_source = $user_angeltype->user;
|
||||||
|
@ -173,7 +171,7 @@ function user_angeltype_confirm_controller(): array
|
||||||
|
|
||||||
user_angeltype_confirm_email($user_source, $angeltype);
|
user_angeltype_confirm_email($user_source, $angeltype);
|
||||||
|
|
||||||
throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -188,23 +186,14 @@ function user_angeltype_confirm_email(User $user, AngelType $angeltype): void
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
/** @var EngelsystemMailer $mailer */
|
||||||
/** @var EngelsystemMailer $mailer */
|
$mailer = app(EngelsystemMailer::class);
|
||||||
$mailer = app(EngelsystemMailer::class);
|
$mailer->sendViewTranslated(
|
||||||
$mailer->sendViewTranslated(
|
$user,
|
||||||
$user,
|
'notification.angeltype.confirmed',
|
||||||
'notification.angeltype.confirmed',
|
'emails/angeltype-confirmed',
|
||||||
'emails/angeltype-confirmed',
|
['name' => $angeltype->name, 'angeltype' => $angeltype, 'username' => $user->displayName]
|
||||||
['name' => $angeltype->name, 'angeltype' => $angeltype, 'username' => $user->displayName]
|
);
|
||||||
);
|
|
||||||
} catch (TransportException $e) {
|
|
||||||
/** @var LoggerInterface $logger */
|
|
||||||
$logger = app('logger');
|
|
||||||
$logger->error(
|
|
||||||
'Unable to send email "{title}" to user {user} with {exception}',
|
|
||||||
['title' => __('notification.angeltype.confirmed'), 'user' => $user->name, 'exception' => $e]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function user_angeltype_add_email(User $user, AngelType $angeltype): void
|
function user_angeltype_add_email(User $user, AngelType $angeltype): void
|
||||||
|
@ -213,23 +202,14 @@ function user_angeltype_add_email(User $user, AngelType $angeltype): void
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
/** @var EngelsystemMailer $mailer */
|
||||||
/** @var EngelsystemMailer $mailer */
|
$mailer = app(EngelsystemMailer::class);
|
||||||
$mailer = app(EngelsystemMailer::class);
|
$mailer->sendViewTranslated(
|
||||||
$mailer->sendViewTranslated(
|
$user,
|
||||||
$user,
|
'notification.angeltype.added',
|
||||||
'notification.angeltype.added',
|
'emails/angeltype-added',
|
||||||
'emails/angeltype-added',
|
['name' => $angeltype->name, 'angeltype' => $angeltype, 'username' => $user->displayName]
|
||||||
['name' => $angeltype->name, 'angeltype' => $angeltype, 'username' => $user->displayName]
|
);
|
||||||
);
|
|
||||||
} catch (TransportException $e) {
|
|
||||||
/** @var LoggerInterface $logger */
|
|
||||||
$logger = app('logger');
|
|
||||||
$logger->error(
|
|
||||||
'Unable to send email "{title}" to user {user} with {exception}',
|
|
||||||
['title' => __('notification.angeltype.added'), 'user' => $user->name, 'exception' => $e]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -244,7 +224,7 @@ function user_angeltype_delete_controller(): array
|
||||||
|
|
||||||
if (!$request->has('user_angeltype_id')) {
|
if (!$request->has('user_angeltype_id')) {
|
||||||
error(__('User angeltype doesn\'t exist.'));
|
error(__('User angeltype doesn\'t exist.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var UserAngelType $user_angeltype */
|
/** @var UserAngelType $user_angeltype */
|
||||||
|
@ -257,7 +237,7 @@ function user_angeltype_delete_controller(): array
|
||||||
&& !auth()->can('admin_user_angeltypes')
|
&& !auth()->can('admin_user_angeltypes')
|
||||||
) {
|
) {
|
||||||
error(__('You are not allowed to delete this users angeltype.'));
|
error(__('You are not allowed to delete this users angeltype.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasPostData('delete')) {
|
if ($request->hasPostData('delete')) {
|
||||||
|
@ -266,7 +246,7 @@ function user_angeltype_delete_controller(): array
|
||||||
engelsystem_log(sprintf('User %s removed from %s.', User_Nick_render($user_source, true), $angeltype->name));
|
engelsystem_log(sprintf('User %s removed from %s.', User_Nick_render($user_source, true), $angeltype->name));
|
||||||
success(sprintf(__('User %s removed from %s.'), $user_source->displayName, $angeltype->name));
|
success(sprintf(__('User %s removed from %s.'), $user_source->displayName, $angeltype->name));
|
||||||
|
|
||||||
throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -287,19 +267,19 @@ function user_angeltype_update_controller(): array
|
||||||
|
|
||||||
if (!auth()->can('admin_angel_types')) {
|
if (!auth()->can('admin_angel_types')) {
|
||||||
error(__('You are not allowed to set supporter rights.'));
|
error(__('You are not allowed to set supporter rights.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$request->has('user_angeltype_id')) {
|
if (!$request->has('user_angeltype_id')) {
|
||||||
error(__('User angeltype doesn\'t exist.'));
|
error(__('User angeltype doesn\'t exist.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('supporter') && preg_match('/^[01]$/', $request->input('supporter'))) {
|
if ($request->has('supporter') && preg_match('/^[01]$/', $request->input('supporter'))) {
|
||||||
$supporter = $request->input('supporter') == '1';
|
$supporter = $request->input('supporter') == '1';
|
||||||
} else {
|
} else {
|
||||||
error(__('No supporter update given.'));
|
error(__('No supporter update given.'));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var UserAngelType $user_angeltype */
|
/** @var UserAngelType $user_angeltype */
|
||||||
|
@ -321,7 +301,7 @@ function user_angeltype_update_controller(): array
|
||||||
));
|
));
|
||||||
success(sprintf($msg, $angeltype->name, $user_source->displayName));
|
success(sprintf($msg, $angeltype->name, $user_source->displayName));
|
||||||
|
|
||||||
throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -382,7 +362,7 @@ function user_angeltype_add_controller(): array
|
||||||
|
|
||||||
user_angeltype_add_email($user_source, $angeltype);
|
user_angeltype_add_email($user_source, $angeltype);
|
||||||
|
|
||||||
throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +386,7 @@ function user_angeltype_join_controller(AngelType $angeltype)
|
||||||
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
|
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
|
||||||
if (!empty($user_angeltype)) {
|
if (!empty($user_angeltype)) {
|
||||||
error(sprintf(__('You are already a %s.'), $angeltype->name));
|
error(sprintf(__('You are already a %s.'), $angeltype->name));
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = request();
|
$request = request();
|
||||||
|
@ -434,11 +414,11 @@ function user_angeltype_join_controller(AngelType $angeltype)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
sprintf(__('Become a %s'), $angeltype->name),
|
sprintf(__('Become a %s'), htmlspecialchars($angeltype->name)),
|
||||||
UserAngelType_join_view($user, $angeltype),
|
UserAngelType_join_view($user, $angeltype),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -452,7 +432,7 @@ function user_angeltypes_controller(): array
|
||||||
{
|
{
|
||||||
$request = request();
|
$request = request();
|
||||||
if (!$request->has('action')) {
|
if (!$request->has('action')) {
|
||||||
throw_redirect(page_link_to('angeltypes'));
|
throw_redirect(url('/angeltypes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return match ($request->input('action')) {
|
return match ($request->input('action')) {
|
||||||
|
@ -462,6 +442,6 @@ function user_angeltypes_controller(): array
|
||||||
'delete' => user_angeltype_delete_controller(),
|
'delete' => user_angeltype_delete_controller(),
|
||||||
'update' => user_angeltype_update_controller(),
|
'update' => user_angeltype_update_controller(),
|
||||||
'add' => user_angeltype_add_controller(),
|
'add' => user_angeltype_add_controller(),
|
||||||
default => throw_redirect(page_link_to('angeltyps')),
|
default => throw_redirect(url('/angeltyps')),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,143 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Engelsystem\Models\User\User;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a hint, if user joined angeltypes that require a driving license and the user has no driver license
|
|
||||||
* information provided.
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
function user_driver_license_required_hint()
|
|
||||||
{
|
|
||||||
$user = auth()->user();
|
|
||||||
|
|
||||||
// User has already entered data, no hint needed.
|
|
||||||
if ($user->license->wantsToDrive()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$angeltypes = $user->userAngelTypes;
|
|
||||||
foreach ($angeltypes as $angeltype) {
|
|
||||||
if ($angeltype->requires_driver_license) {
|
|
||||||
return sprintf(
|
|
||||||
__('You joined an angeltype which requires a driving license. Please edit your driving license information here: %s.'),
|
|
||||||
'<a href="' . user_driver_license_edit_link() . '" class="text-info">' . __('driving license information') . '</a>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Route user driver licenses actions.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function user_driver_licenses_controller()
|
|
||||||
{
|
|
||||||
$user = auth()->user();
|
|
||||||
|
|
||||||
if (!$user) {
|
|
||||||
throw_redirect(page_link_to());
|
|
||||||
}
|
|
||||||
|
|
||||||
$action = strip_request_item('action', 'edit');
|
|
||||||
|
|
||||||
return match ($action) {
|
|
||||||
'edit' => user_driver_license_edit_controller(),
|
|
||||||
default => user_driver_license_edit_controller(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link to user driver license edit page for given user.
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function user_driver_license_edit_link($user = null)
|
|
||||||
{
|
|
||||||
if (!$user) {
|
|
||||||
return page_link_to('user_driver_licenses');
|
|
||||||
}
|
|
||||||
|
|
||||||
return page_link_to('user_driver_licenses', ['user_id' => $user->id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the user for the driver license.
|
|
||||||
*
|
|
||||||
* @return User
|
|
||||||
*/
|
|
||||||
function user_driver_license_load_user()
|
|
||||||
{
|
|
||||||
$request = request();
|
|
||||||
$user_source = auth()->user();
|
|
||||||
|
|
||||||
if ($request->has('user_id')) {
|
|
||||||
$user_source = User::find($request->input('user_id'));
|
|
||||||
if (empty($user_source)) {
|
|
||||||
throw_redirect(user_driver_license_edit_link());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $user_source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit a users driver license information.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function user_driver_license_edit_controller()
|
|
||||||
{
|
|
||||||
$user = auth()->user();
|
|
||||||
$request = request();
|
|
||||||
$user_source = user_driver_license_load_user();
|
|
||||||
|
|
||||||
// only privilege admin_user can edit other users driver license information
|
|
||||||
if ($user->id != $user_source->id && !auth()->can('admin_user')) {
|
|
||||||
throw_redirect(user_driver_license_edit_link());
|
|
||||||
}
|
|
||||||
|
|
||||||
$driverLicense = $user_source->license;
|
|
||||||
if ($request->hasPostData('submit')) {
|
|
||||||
if ($request->has('wants_to_drive')) {
|
|
||||||
$driverLicense->has_car = $request->has('has_car');
|
|
||||||
$driverLicense->drive_car = $request->has('has_license_car');
|
|
||||||
$driverLicense->drive_3_5t = $request->has('has_license_3_5t_transporter');
|
|
||||||
$driverLicense->drive_7_5t = $request->has('has_license_7_5t_truck');
|
|
||||||
$driverLicense->drive_12t = $request->has('has_license_12t_truck');
|
|
||||||
$driverLicense->drive_forklift = $request->has('has_license_forklift');
|
|
||||||
|
|
||||||
if ($driverLicense->wantsToDrive()) {
|
|
||||||
$driverLicense->save();
|
|
||||||
|
|
||||||
engelsystem_log('Driver license information updated.');
|
|
||||||
success(__('Your driver license information has been saved.'));
|
|
||||||
throw_redirect(user_link($user_source->id));
|
|
||||||
} else {
|
|
||||||
error(__('Please select at least one driving license.'));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$driverLicense->has_car = false;
|
|
||||||
$driverLicense->drive_car = false;
|
|
||||||
$driverLicense->drive_3_5t = false;
|
|
||||||
$driverLicense->drive_7_5t = false;
|
|
||||||
$driverLicense->drive_12t = false;
|
|
||||||
$driverLicense->drive_forklift = false;
|
|
||||||
$driverLicense->save();
|
|
||||||
|
|
||||||
engelsystem_log('Driver license information removed.');
|
|
||||||
success(__('Your driver license information has been removed.'));
|
|
||||||
throw_redirect(user_link($user_source->id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
sprintf(__('Edit %s driving license information'), $user_source->displayName),
|
|
||||||
UserDriverLicense_edit_view($user_source, $driverLicense),
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -20,7 +20,7 @@ function users_controller()
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$action = 'list';
|
$action = 'list';
|
||||||
|
@ -55,7 +55,7 @@ function user_delete_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!auth()->can('admin_user')) {
|
if (!auth()->can('admin_user')) {
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// You cannot delete yourself
|
// You cannot delete yourself
|
||||||
|
@ -91,7 +91,7 @@ function user_delete_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
sprintf(__('Delete %s'), $user_source->displayName),
|
sprintf(__('Delete %s'), htmlspecialchars($user_source->displayName)),
|
||||||
User_delete_view($user_source),
|
User_delete_view($user_source),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ function user_delete_controller()
|
||||||
*/
|
*/
|
||||||
function users_link()
|
function users_link()
|
||||||
{
|
{
|
||||||
return page_link_to('users');
|
return url('/users');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,7 +110,7 @@ function users_link()
|
||||||
*/
|
*/
|
||||||
function user_edit_link($userId)
|
function user_edit_link($userId)
|
||||||
{
|
{
|
||||||
return page_link_to('admin_user', ['user_id' => $userId]);
|
return url('/admin-user', ['user_id' => $userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,7 +119,7 @@ function user_edit_link($userId)
|
||||||
*/
|
*/
|
||||||
function user_delete_link($userId)
|
function user_delete_link($userId)
|
||||||
{
|
{
|
||||||
return page_link_to('users', ['action' => 'delete', 'user_id' => $userId]);
|
return url('/users', ['action' => 'delete', 'user_id' => $userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,7 +128,7 @@ function user_delete_link($userId)
|
||||||
*/
|
*/
|
||||||
function user_link($userId)
|
function user_link($userId)
|
||||||
{
|
{
|
||||||
return page_link_to('users', ['action' => 'view', 'user_id' => $userId]);
|
return url('/users', ['action' => 'view', 'user_id' => $userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,7 +149,7 @@ function user_edit_vouchers_controller()
|
||||||
(!auth()->can('admin_user') && !auth()->can('voucher.edit'))
|
(!auth()->can('admin_user') && !auth()->can('voucher.edit'))
|
||||||
|| !config('enable_voucher')
|
|| !config('enable_voucher')
|
||||||
) {
|
) {
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasPostData('submit')) {
|
if ($request->hasPostData('submit')) {
|
||||||
|
@ -182,7 +182,7 @@ function user_edit_vouchers_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
sprintf(__('%s\'s vouchers'), $user_source->displayName),
|
sprintf(__('%s\'s vouchers'), htmlspecialchars($user_source->displayName)),
|
||||||
User_edit_vouchers_view($user_source),
|
User_edit_vouchers_view($user_source),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ function user_controller()
|
||||||
$user_source = User::find($request->input('user_id'));
|
$user_source = User::find($request->input('user_id'));
|
||||||
if (!$user_source) {
|
if (!$user_source) {
|
||||||
error(__('User not found.'));
|
error(__('User not found.'));
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ function user_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($user_source->api_key)) {
|
if (empty($user_source->api_key)) {
|
||||||
User_reset_api_key($user_source, false);
|
auth()->resetApiKey($user_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user_source->state->force_active) {
|
if ($user_source->state->force_active) {
|
||||||
|
@ -244,7 +244,7 @@ function user_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
$user_source->displayName,
|
htmlspecialchars($user_source->displayName),
|
||||||
User_view(
|
User_view(
|
||||||
$user_source,
|
$user_source,
|
||||||
auth()->can('admin_user'),
|
auth()->can('admin_user'),
|
||||||
|
@ -271,7 +271,7 @@ function users_list_controller()
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (!auth()->can('admin_user')) {
|
if (!auth()->can('admin_user')) {
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$order_by = 'name';
|
$order_by = 'name';
|
||||||
|
@ -343,13 +343,13 @@ function load_user()
|
||||||
{
|
{
|
||||||
$request = request();
|
$request = request();
|
||||||
if (!$request->has('user_id')) {
|
if (!$request->has('user_id')) {
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::find($request->input('user_id'));
|
$user = User::find($request->input('user_id'));
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
error(__('User doesn\'t exist.'));
|
error(__('User doesn\'t exist.'));
|
||||||
throw_redirect(page_link_to());
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
|
@ -437,3 +437,57 @@ function shiftCalendarRendererByShiftFilter(ShiftsFilter $shiftsFilter)
|
||||||
|
|
||||||
return new ShiftCalendarRenderer($filtered_shifts, $needed_angeltypes, $shift_entries, $shiftsFilter);
|
return new ShiftCalendarRenderer($filtered_shifts, $needed_angeltypes, $shift_entries, $shiftsFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a hint, if user joined angeltypes that require a driving license and the user has no driver license
|
||||||
|
* information provided.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
function user_driver_license_required_hint()
|
||||||
|
{
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
// User has already entered data, no hint needed.
|
||||||
|
if ($user->license->wantsToDrive()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$angeltypes = $user->userAngelTypes;
|
||||||
|
foreach ($angeltypes as $angeltype) {
|
||||||
|
if ($angeltype->requires_driver_license) {
|
||||||
|
return sprintf(
|
||||||
|
__('angeltype.driving_license.required.info.here'),
|
||||||
|
'<a href="' . url('/settings/certificates') . '">' . __('driving_license.info') . '</a>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function user_ifsg_certificate_required_hint()
|
||||||
|
{
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
// User has already entered data, no hint needed.
|
||||||
|
if (!config('ifsg_enabled') || $user->license->ifsg_light || $user->license->ifsg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$angeltypes = $user->userAngelTypes;
|
||||||
|
foreach ($angeltypes as $angeltype) {
|
||||||
|
if (
|
||||||
|
$angeltype->requires_ifsg_certificate && !(
|
||||||
|
$user->license->ifsg_certificate || $user->license->ifsg_certificate_light
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return sprintf(
|
||||||
|
__('angeltype.ifsg.required.info.here'),
|
||||||
|
'<a href="' . url('/settings/certificates') . '">' . __('ifsg.info') . '</a>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ if ($app->get('config')->get('maintenance')) {
|
||||||
http_response_code(503);
|
http_response_code(503);
|
||||||
$url = $app->get(UrlGeneratorInterface::class);
|
$url = $app->get(UrlGeneratorInterface::class);
|
||||||
$maintenance = file_get_contents(__DIR__ . '/../resources/views/layouts/maintenance.html');
|
$maintenance = file_get_contents(__DIR__ . '/../resources/views/layouts/maintenance.html');
|
||||||
$maintenance = str_replace('%APP_NAME%', $app->get('config')->get('app_name'), $maintenance);
|
$maintenance = str_replace('%APP_NAME%', htmlspecialchars($app->get('config')->get('app_name')), $maintenance);
|
||||||
$maintenance = str_replace('%ASSETS_PATH%', $url->to(''), $maintenance);
|
$maintenance = str_replace('%ASSETS_PATH%', $url->to(''), $maintenance);
|
||||||
echo $maintenance;
|
echo $maintenance;
|
||||||
die();
|
die();
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Helpers\Translation\Translator;
|
|
||||||
use Engelsystem\Mail\EngelsystemMailer;
|
use Engelsystem\Mail\EngelsystemMailer;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Psr\Log\LogLevel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $recipientUser
|
* @param User $recipientUser
|
||||||
|
@ -18,38 +16,18 @@ function engelsystem_email_to_user($recipientUser, $title, $message, $notIfItsMe
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var Translator $translator */
|
/** @var EngelsystemMailer $mailer */
|
||||||
$translator = app()->get('translator');
|
$mailer = app('mailer');
|
||||||
$locale = $translator->getLocale();
|
$status = $mailer->sendViewTranslated(
|
||||||
|
$recipientUser,
|
||||||
$status = true;
|
$title,
|
||||||
try {
|
'emails/mail',
|
||||||
/** @var EngelsystemMailer $mailer */
|
['username' => $recipientUser->displayName, 'message' => $message]
|
||||||
$mailer = app('mailer');
|
);
|
||||||
|
|
||||||
$translator->setLocale($recipientUser->settings->language);
|
|
||||||
$mailer->sendView(
|
|
||||||
$recipientUser->contact->email ?: $recipientUser->email,
|
|
||||||
$title,
|
|
||||||
'emails/mail',
|
|
||||||
['username' => $recipientUser->displayName, 'message' => $message]
|
|
||||||
);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$status = false;
|
|
||||||
engelsystem_log(sprintf(
|
|
||||||
'An exception occurred while sending a mail to %s in %s:%u: %s',
|
|
||||||
$recipientUser->name,
|
|
||||||
$e->getFile(),
|
|
||||||
$e->getLine(),
|
|
||||||
$e->getMessage()
|
|
||||||
), LogLevel::CRITICAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
$translator->setLocale($locale);
|
|
||||||
|
|
||||||
if (!$status) {
|
if (!$status) {
|
||||||
error(sprintf(__('User %s could not be notified by email due to an error.'), $recipientUser->displayName));
|
error(sprintf(__('User %s could not be notified by e-mail due to an error.'), $recipientUser->displayName));
|
||||||
engelsystem_log(sprintf('User %s could not be notified by email due to an error.', $recipientUser->name));
|
engelsystem_log(sprintf('User %s could not be notified by e-mail due to an error.', $recipientUser->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $status;
|
return $status;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Engelsystem\Renderer\Twig\Extensions\Globals;
|
use Engelsystem\Renderer\Twig\Extensions\Globals;
|
||||||
|
use Engelsystem\Helpers\Carbon;
|
||||||
|
use Engelsystem\Helpers\DayOfEvent;
|
||||||
|
|
||||||
function theme_id(): int
|
function theme_id(): int
|
||||||
{
|
{
|
||||||
|
@ -25,3 +27,16 @@ function theme_type(): string
|
||||||
{
|
{
|
||||||
return theme()['type'];
|
return theme()['type'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dateWithEventDay(string $day): string
|
||||||
|
{
|
||||||
|
$date = Carbon::createFromFormat('Y-m-d', $day);
|
||||||
|
$dayOfEvent = DayOfEvent::get($date);
|
||||||
|
$dateFormatted = $date->format(__('general.date'));
|
||||||
|
|
||||||
|
if (!config('enable_show_day_of_event') || is_null($dayOfEvent)) {
|
||||||
|
return $dateFormatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dateFormatted . ' (' . $dayOfEvent . ')';
|
||||||
|
}
|
||||||
|
|
|
@ -17,11 +17,12 @@ function msg()
|
||||||
*
|
*
|
||||||
* @param string $msg
|
* @param string $msg
|
||||||
* @param bool $immediately
|
* @param bool $immediately
|
||||||
|
* @param bool $immediatelyRaw
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function info($msg, $immediately = false)
|
function info($msg, $immediately = false, $immediatelyRaw = false)
|
||||||
{
|
{
|
||||||
return alert(NotificationType::INFORMATION, $msg, $immediately);
|
return alert(NotificationType::INFORMATION, $msg, $immediately, $immediatelyRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,11 +30,12 @@ function info($msg, $immediately = false)
|
||||||
*
|
*
|
||||||
* @param string $msg
|
* @param string $msg
|
||||||
* @param bool $immediately
|
* @param bool $immediately
|
||||||
|
* @param bool $immediatelyRaw
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function warning($msg, $immediately = false)
|
function warning($msg, $immediately = false, $immediatelyRaw = false)
|
||||||
{
|
{
|
||||||
return alert(NotificationType::WARNING, $msg, $immediately);
|
return alert(NotificationType::WARNING, $msg, $immediately, $immediatelyRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,11 +43,12 @@ function warning($msg, $immediately = false)
|
||||||
*
|
*
|
||||||
* @param string $msg
|
* @param string $msg
|
||||||
* @param bool $immediately
|
* @param bool $immediately
|
||||||
|
* @param bool $immediatelyRaw
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function error($msg, $immediately = false)
|
function error($msg, $immediately = false, $immediatelyRaw = false)
|
||||||
{
|
{
|
||||||
return alert(NotificationType::ERROR, $msg, $immediately);
|
return alert(NotificationType::ERROR, $msg, $immediately, $immediatelyRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,24 +56,27 @@ function error($msg, $immediately = false)
|
||||||
*
|
*
|
||||||
* @param string $msg
|
* @param string $msg
|
||||||
* @param bool $immediately
|
* @param bool $immediately
|
||||||
|
* @param bool $immediatelyRaw
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function success($msg, $immediately = false)
|
function success($msg, $immediately = false, $immediatelyRaw = false)
|
||||||
{
|
{
|
||||||
return alert(NotificationType::MESSAGE, $msg, $immediately);
|
return alert(NotificationType::MESSAGE, $msg, $immediately, $immediatelyRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders an alert message with the given alert-* class or sets it in session
|
* Renders an alert message with the given alert-* class or sets it in session
|
||||||
*
|
*
|
||||||
* @see \Engelsystem\Controllers\HasUserNotifications
|
|
||||||
*
|
|
||||||
* @param NotificationType $type
|
* @param NotificationType $type
|
||||||
* @param string $msg
|
* @param string $msg
|
||||||
* @param bool $immediately
|
* @param bool $immediately
|
||||||
|
* @param bool $immediatelyRaw
|
||||||
* @return string
|
* @return string
|
||||||
|
*
|
||||||
|
* @see \Engelsystem\Controllers\HasUserNotifications
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
function alert(NotificationType $type, $msg, $immediately = false)
|
function alert(NotificationType $type, $msg, $immediately = false, $immediatelyRaw = false)
|
||||||
{
|
{
|
||||||
if (empty($msg)) {
|
if (empty($msg)) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -87,6 +93,7 @@ function alert(NotificationType $type, $msg, $immediately = false)
|
||||||
['danger', 'warning', 'info', 'success'],
|
['danger', 'warning', 'info', 'success'],
|
||||||
$type->value
|
$type->value
|
||||||
);
|
);
|
||||||
|
$msg = $immediatelyRaw ? $msg : htmlspecialchars($msg);
|
||||||
return '<div class="alert alert-' . $type . '" role="alert">' . $msg . '</div>';
|
return '<div class="alert alert-' . $type . '" role="alert">' . $msg . '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,13 @@ namespace Engelsystem\Events\Listener;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Engelsystem\Helpers\Shifts;
|
use Engelsystem\Helpers\Shifts;
|
||||||
use Engelsystem\Mail\EngelsystemMailer;
|
use Engelsystem\Mail\EngelsystemMailer;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
|
use Engelsystem\Models\Shifts\Shift as ShiftModel;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Models\Worklog;
|
use Engelsystem\Models\Worklog;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Component\Mailer\Exception\TransportException;
|
|
||||||
|
|
||||||
class Shift
|
class Shift
|
||||||
{
|
{
|
||||||
|
@ -26,7 +28,7 @@ class Shift
|
||||||
string $name,
|
string $name,
|
||||||
string $title,
|
string $title,
|
||||||
string $type,
|
string $type,
|
||||||
Room $room,
|
Location $location,
|
||||||
bool $freeloaded
|
bool $freeloaded
|
||||||
): void {
|
): void {
|
||||||
if ($freeloaded || $start > Carbon::now()) {
|
if ($freeloaded || $start > Carbon::now()) {
|
||||||
|
@ -45,9 +47,9 @@ class Shift
|
||||||
$name,
|
$name,
|
||||||
$title,
|
$title,
|
||||||
$type,
|
$type,
|
||||||
$room->name,
|
$location->name,
|
||||||
$start->format(__('Y-m-d H:i')),
|
$start->format(__('general.datetime')),
|
||||||
$end->format(__('Y-m-d H:i'))
|
$end->format(__('general.datetime'))
|
||||||
);
|
);
|
||||||
$workLog->save();
|
$workLog->save();
|
||||||
|
|
||||||
|
@ -64,34 +66,70 @@ class Shift
|
||||||
string $name,
|
string $name,
|
||||||
string $title,
|
string $title,
|
||||||
string $type,
|
string $type,
|
||||||
Room $room,
|
Location $location,
|
||||||
bool $freeloaded
|
bool $freeloaded
|
||||||
): void {
|
): void {
|
||||||
if (!$user->settings->email_shiftinfo) {
|
if (!$user->settings->email_shiftinfo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$subject = 'notification.shift.deleted';
|
$this->mailer->sendViewTranslated(
|
||||||
try {
|
$user,
|
||||||
|
'notification.shift.deleted',
|
||||||
|
'emails/worklog-from-shift',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'title' => $title,
|
||||||
|
'start' => $start,
|
||||||
|
'end' => $end,
|
||||||
|
'location' => $location,
|
||||||
|
'freeloaded' => $freeloaded,
|
||||||
|
'username' => $user->displayName,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updatedShiftSendEmail(
|
||||||
|
ShiftModel $shift,
|
||||||
|
ShiftModel $oldShift
|
||||||
|
): void {
|
||||||
|
// Only send e-mail on relevant changes
|
||||||
|
if (
|
||||||
|
$oldShift->shift_type_id == $shift->shift_type_id
|
||||||
|
&& $oldShift->title == $shift->title
|
||||||
|
&& $oldShift->start == $shift->start
|
||||||
|
&& $oldShift->end == $shift->end
|
||||||
|
&& $oldShift->location_id == $shift->location_id
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$shift->load(['shiftType', 'location']);
|
||||||
|
$oldShift->load(['shiftType', 'location']);
|
||||||
|
/** @var ShiftEntry[]|Collection $shiftEntries */
|
||||||
|
$shiftEntries = $shift->shiftEntries()
|
||||||
|
->with(['angelType', 'user.settings'])
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($shiftEntries as $shiftEntry) {
|
||||||
|
$user = $shiftEntry->user;
|
||||||
|
$angelType = $shiftEntry->angelType;
|
||||||
|
|
||||||
|
if (!$user->settings->email_shiftinfo || $shift->end < Carbon::now()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$this->mailer->sendViewTranslated(
|
$this->mailer->sendViewTranslated(
|
||||||
$user,
|
$user,
|
||||||
$subject,
|
'notification.shift.updated',
|
||||||
'emails/worklog-from-shift',
|
'emails/updated-shift',
|
||||||
[
|
[
|
||||||
'name' => $name,
|
'shift' => $shift,
|
||||||
'title' => $title,
|
'oldShift' => $oldShift,
|
||||||
'start' => $start,
|
'angelType' => $angelType,
|
||||||
'end' => $end,
|
'username' => $user->displayName,
|
||||||
'room' => $room,
|
|
||||||
'freeloaded' => $freeloaded,
|
|
||||||
'username' => $user->displayName,
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
} catch (TransportException $e) {
|
|
||||||
$this->log->error(
|
|
||||||
'Unable to send email "{title}" to user {user} with {exception}',
|
|
||||||
['title' => $subject, 'user' => $user->name, 'exception' => $e]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,29 +24,25 @@ $includeFiles = [
|
||||||
__DIR__ . '/../includes/view/AngelTypes_view.php',
|
__DIR__ . '/../includes/view/AngelTypes_view.php',
|
||||||
__DIR__ . '/../includes/view/EventConfig_view.php',
|
__DIR__ . '/../includes/view/EventConfig_view.php',
|
||||||
__DIR__ . '/../includes/view/PublicDashboard_view.php',
|
__DIR__ . '/../includes/view/PublicDashboard_view.php',
|
||||||
__DIR__ . '/../includes/view/Rooms_view.php',
|
__DIR__ . '/../includes/view/Locations_view.php',
|
||||||
__DIR__ . '/../includes/view/ShiftCalendarLane.php',
|
__DIR__ . '/../includes/view/ShiftCalendarLane.php',
|
||||||
__DIR__ . '/../includes/view/ShiftCalendarRenderer.php',
|
__DIR__ . '/../includes/view/ShiftCalendarRenderer.php',
|
||||||
__DIR__ . '/../includes/view/ShiftCalendarShiftRenderer.php',
|
__DIR__ . '/../includes/view/ShiftCalendarShiftRenderer.php',
|
||||||
__DIR__ . '/../includes/view/ShiftsFilterRenderer.php',
|
__DIR__ . '/../includes/view/ShiftsFilterRenderer.php',
|
||||||
__DIR__ . '/../includes/view/Shifts_view.php',
|
__DIR__ . '/../includes/view/Shifts_view.php',
|
||||||
__DIR__ . '/../includes/view/ShiftEntry_view.php',
|
__DIR__ . '/../includes/view/ShiftEntry_view.php',
|
||||||
__DIR__ . '/../includes/view/ShiftTypes_view.php',
|
|
||||||
__DIR__ . '/../includes/view/UserAngelTypes_view.php',
|
__DIR__ . '/../includes/view/UserAngelTypes_view.php',
|
||||||
__DIR__ . '/../includes/view/UserDriverLicenses_view.php',
|
|
||||||
__DIR__ . '/../includes/view/UserHintsRenderer.php',
|
__DIR__ . '/../includes/view/UserHintsRenderer.php',
|
||||||
__DIR__ . '/../includes/view/User_view.php',
|
__DIR__ . '/../includes/view/User_view.php',
|
||||||
|
|
||||||
__DIR__ . '/../includes/controller/angeltypes_controller.php',
|
__DIR__ . '/../includes/controller/angeltypes_controller.php',
|
||||||
__DIR__ . '/../includes/controller/event_config_controller.php',
|
__DIR__ . '/../includes/controller/event_config_controller.php',
|
||||||
__DIR__ . '/../includes/controller/public_dashboard_controller.php',
|
__DIR__ . '/../includes/controller/public_dashboard_controller.php',
|
||||||
__DIR__ . '/../includes/controller/rooms_controller.php',
|
__DIR__ . '/../includes/controller/locations_controller.php',
|
||||||
__DIR__ . '/../includes/controller/shift_entries_controller.php',
|
__DIR__ . '/../includes/controller/shift_entries_controller.php',
|
||||||
__DIR__ . '/../includes/controller/shifts_controller.php',
|
__DIR__ . '/../includes/controller/shifts_controller.php',
|
||||||
__DIR__ . '/../includes/controller/shifttypes_controller.php',
|
|
||||||
__DIR__ . '/../includes/controller/users_controller.php',
|
__DIR__ . '/../includes/controller/users_controller.php',
|
||||||
__DIR__ . '/../includes/controller/user_angeltypes_controller.php',
|
__DIR__ . '/../includes/controller/user_angeltypes_controller.php',
|
||||||
__DIR__ . '/../includes/controller/user_driver_licenses_controller.php',
|
|
||||||
|
|
||||||
__DIR__ . '/../includes/helper/legacy_helper.php',
|
__DIR__ . '/../includes/helper/legacy_helper.php',
|
||||||
__DIR__ . '/../includes/helper/message_helper.php',
|
__DIR__ . '/../includes/helper/message_helper.php',
|
||||||
|
@ -62,7 +58,6 @@ $includeFiles = [
|
||||||
__DIR__ . '/../includes/pages/admin_groups.php',
|
__DIR__ . '/../includes/pages/admin_groups.php',
|
||||||
__DIR__ . '/../includes/pages/admin_shifts.php',
|
__DIR__ . '/../includes/pages/admin_shifts.php',
|
||||||
__DIR__ . '/../includes/pages/admin_user.php',
|
__DIR__ . '/../includes/pages/admin_user.php',
|
||||||
__DIR__ . '/../includes/pages/guest_login.php',
|
|
||||||
__DIR__ . '/../includes/pages/user_myshifts.php',
|
__DIR__ . '/../includes/pages/user_myshifts.php',
|
||||||
__DIR__ . '/../includes/pages/user_shifts.php',
|
__DIR__ . '/../includes/pages/user_shifts.php',
|
||||||
|
|
||||||
|
|
|
@ -1,87 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
|
||||||
|
|
||||||
function mail_shift_change(Shift $old_shift, Shift $new_shift)
|
|
||||||
{
|
|
||||||
/** @var ShiftEntry[]|Collection $shiftEntries */
|
|
||||||
$shiftEntries = $old_shift->shiftEntries()
|
|
||||||
->with(['user', 'user.settings'])
|
|
||||||
->get();
|
|
||||||
$old_room = $old_shift->room;
|
|
||||||
$new_room = $new_shift->room;
|
|
||||||
|
|
||||||
$noticeable_changes = false;
|
|
||||||
|
|
||||||
$message = __('A Shift you are registered on has changed:');
|
|
||||||
$message .= "\n";
|
|
||||||
|
|
||||||
if ($old_shift->shift_type_id != $new_shift->shift_type_id) {
|
|
||||||
$message .= sprintf(
|
|
||||||
__('* Shift type changed from %s to %s'),
|
|
||||||
$old_shift->shiftType->name,
|
|
||||||
$new_shift->shiftType->name
|
|
||||||
) . "\n";
|
|
||||||
$noticeable_changes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($old_shift->title != $new_shift->title) {
|
|
||||||
$message .= sprintf(__('* Shift title changed from %s to %s'), $old_shift->title, $new_shift->title) . "\n";
|
|
||||||
$noticeable_changes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($old_shift->start->timestamp != $new_shift->start->timestamp) {
|
|
||||||
$message .= sprintf(
|
|
||||||
__('* Shift Start changed from %s to %s'),
|
|
||||||
$old_shift->start->format(__('Y-m-d H:i')),
|
|
||||||
$new_shift->start->format(__('Y-m-d H:i'))
|
|
||||||
) . "\n";
|
|
||||||
$noticeable_changes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($old_shift->end->timestamp != $new_shift->end->timestamp) {
|
|
||||||
$message .= sprintf(
|
|
||||||
__('* Shift End changed from %s to %s'),
|
|
||||||
$old_shift->end->format(__('Y-m-d H:i')),
|
|
||||||
$new_shift->end->format(__('Y-m-d H:i'))
|
|
||||||
) . "\n";
|
|
||||||
$noticeable_changes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($old_shift->room_id != $new_shift->room_id) {
|
|
||||||
$message .= sprintf(__('* Shift Location changed from %s to %s'), $old_room->name, $new_room->name) . "\n";
|
|
||||||
$noticeable_changes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$noticeable_changes) {
|
|
||||||
// There are no changes worth sending an E-Mail
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$message .= "\n";
|
|
||||||
$message .= __('The updated Shift:') . "\n";
|
|
||||||
|
|
||||||
$message .= $new_shift->shiftType->name . "\n";
|
|
||||||
$message .= $new_shift->title . "\n";
|
|
||||||
$message .= $new_shift->start->format(__('Y-m-d H:i')) . ' - ' . $new_shift->end->format(__('H:i')) . "\n";
|
|
||||||
$message .= $new_room->name . "\n\n";
|
|
||||||
$message .= url('/shifts', ['action' => 'view', 'shift_id' => $new_shift->id]) . "\n";
|
|
||||||
|
|
||||||
foreach ($shiftEntries as $shiftEntry) {
|
|
||||||
$user = $shiftEntry->user;
|
|
||||||
if ($user->settings->email_shiftinfo) {
|
|
||||||
engelsystem_email_to_user(
|
|
||||||
$user,
|
|
||||||
__('Your Shift has changed'),
|
|
||||||
$message,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mail_shift_assign(User $user, Shift $shift)
|
function mail_shift_assign(User $user, Shift $shift)
|
||||||
{
|
{
|
||||||
|
@ -89,13 +9,11 @@ function mail_shift_assign(User $user, Shift $shift)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$room = $shift->room;
|
|
||||||
|
|
||||||
$message = __('You have been assigned to a Shift:') . "\n";
|
$message = __('You have been assigned to a Shift:') . "\n";
|
||||||
$message .= $shift->shiftType->name . "\n";
|
$message .= $shift->shiftType->name . "\n";
|
||||||
$message .= $shift->title . "\n";
|
$message .= $shift->title . "\n";
|
||||||
$message .= $shift->start->format(__('Y-m-d H:i')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
|
$message .= $shift->start->format(__('general.datetime')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
|
||||||
$message .= $room->name . "\n\n";
|
$message .= $shift->location->name . "\n\n";
|
||||||
$message .= url('/shifts', ['action' => 'view', 'shift_id' => $shift->id]) . "\n";
|
$message .= url('/shifts', ['action' => 'view', 'shift_id' => $shift->id]) . "\n";
|
||||||
|
|
||||||
engelsystem_email_to_user($user, __('Assigned to Shift'), $message, true);
|
engelsystem_email_to_user($user, __('Assigned to Shift'), $message, true);
|
||||||
|
@ -107,13 +25,11 @@ function mail_shift_removed(User $user, Shift $shift)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$room = $shift->room;
|
|
||||||
|
|
||||||
$message = __('You have been removed from a Shift:') . "\n";
|
$message = __('You have been removed from a Shift:') . "\n";
|
||||||
$message .= $shift->shiftType->name . "\n";
|
$message .= $shift->shiftType->name . "\n";
|
||||||
$message .= $shift->title . "\n";
|
$message .= $shift->title . "\n";
|
||||||
$message .= $shift->start->format(__('Y-m-d H:i')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
|
$message .= $shift->start->format(__('general.datetime')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
|
||||||
$message .= $room->name . "\n";
|
$message .= $shift->location->name . "\n";
|
||||||
|
|
||||||
engelsystem_email_to_user($user, __('Removed from Shift'), $message, true);
|
engelsystem_email_to_user($user, __('Removed from Shift'), $message, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ function mail_user_delete($user)
|
||||||
{
|
{
|
||||||
return engelsystem_email_to_user(
|
return engelsystem_email_to_user(
|
||||||
$user,
|
$user,
|
||||||
__('Your account has been deleted'),
|
__('Your account has been deleted.'),
|
||||||
__(
|
__(
|
||||||
'Your %s account has been deleted. If you have any questions regarding your account deletion, please contact heaven.',
|
'Your %s account has been deleted. If you have any questions regarding your account deletion, please contact heaven.',
|
||||||
[config('app_name')]
|
[config('app_name')]
|
||||||
|
|
|
@ -1,47 +1,70 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Database\Db;
|
use Engelsystem\Database\Db;
|
||||||
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all needed angeltypes and already taken needs.
|
* Returns all needed angeltypes and already taken needs.
|
||||||
*
|
*
|
||||||
* @param int $shiftId id of shift
|
* @param Shift $shift
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function NeededAngelTypes_by_shift($shiftId)
|
function NeededAngelTypes_by_shift($shift)
|
||||||
{
|
{
|
||||||
$needed_angeltypes_source = Db::select(
|
$needed_angeltypes_source = [];
|
||||||
'
|
// Select from shift
|
||||||
|
if (!$shift->schedule) {
|
||||||
|
$needed_angeltypes_source = Db::select(
|
||||||
|
'
|
||||||
SELECT
|
SELECT
|
||||||
`needed_angel_types`.*,
|
`needed_angel_types`.*,
|
||||||
`angel_types`.`id`,
|
|
||||||
`angel_types`.`name`,
|
`angel_types`.`name`,
|
||||||
`angel_types`.`restricted`,
|
`angel_types`.`restricted`,
|
||||||
`angel_types`.`no_self_signup`
|
`angel_types`.`shift_self_signup`
|
||||||
FROM `needed_angel_types`
|
FROM `needed_angel_types`
|
||||||
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
||||||
WHERE `shift_id` = ?
|
WHERE `needed_angel_types`.`shift_id` = ?
|
||||||
ORDER BY `room_id` DESC',
|
ORDER BY `location_id` DESC
|
||||||
[$shiftId]
|
',
|
||||||
);
|
[$shift->id]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Use settings from room
|
// Get needed by shift type
|
||||||
if (count($needed_angeltypes_source) == 0) {
|
if ($shift->schedule && $shift->schedule->needed_from_shift_type) {
|
||||||
$needed_angeltypes_source = Db::select('
|
$needed_angeltypes_source = Db::select('
|
||||||
SELECT `needed_angel_types`.*, `angel_types`.`name`, `angel_types`.`restricted`
|
SELECT
|
||||||
|
`needed_angel_types`.*,
|
||||||
|
`angel_types`.`name`,
|
||||||
|
`angel_types`.`restricted`,
|
||||||
|
`angel_types`.`shift_self_signup`
|
||||||
FROM `needed_angel_types`
|
FROM `needed_angel_types`
|
||||||
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
||||||
JOIN `shifts` ON `shifts`.`room_id` = `needed_angel_types`.`room_id`
|
WHERE `needed_angel_types`.`shift_type_id` = ?
|
||||||
WHERE `shifts`.`id` = ?
|
ORDER BY `location_id` DESC
|
||||||
ORDER BY `room_id` DESC
|
', [$shift->shift_type_id]);
|
||||||
', [$shiftId]);
|
}
|
||||||
|
|
||||||
|
// Load from room
|
||||||
|
if ($shift->schedule && !$shift->schedule->needed_from_shift_type) {
|
||||||
|
$needed_angeltypes_source = Db::select('
|
||||||
|
SELECT
|
||||||
|
`needed_angel_types`.*,
|
||||||
|
`angel_types`.`name`,
|
||||||
|
`angel_types`.`restricted`,
|
||||||
|
`angel_types`.`shift_self_signup`
|
||||||
|
FROM `needed_angel_types`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
||||||
|
WHERE `needed_angel_types`.`location_id` = ?
|
||||||
|
ORDER BY `location_id` DESC
|
||||||
|
', [$shift->location_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var ShiftEntry[]|Collection $shift_entries */
|
/** @var ShiftEntry[]|Collection $shift_entries */
|
||||||
$shift_entries = ShiftEntry::with('user', 'angelType')
|
$shift_entries = ShiftEntry::with('user', 'angelType')
|
||||||
->where('shift_id', $shiftId)
|
->where('shift_id', $shift->id)
|
||||||
->get();
|
->get();
|
||||||
$needed_angeltypes = [];
|
$needed_angeltypes = [];
|
||||||
foreach ($needed_angeltypes_source as $angeltype) {
|
foreach ($needed_angeltypes_source as $angeltype) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ function ShiftEntry_onCreate(ShiftEntry $shiftEntry): void
|
||||||
'User ' . User_Nick_render($shiftEntry->user, true)
|
'User ' . User_Nick_render($shiftEntry->user, true)
|
||||||
. ' signed up for shift ' . $shiftEntry->shift->title
|
. ' signed up for shift ' . $shiftEntry->shift->title
|
||||||
. ' (' . $shift->shiftType->name . ')'
|
. ' (' . $shift->shiftType->name . ')'
|
||||||
. ' at ' . $shift->room->name
|
. ' at ' . $shift->location->name
|
||||||
. ' from ' . $shift->start->format('Y-m-d H:i')
|
. ' from ' . $shift->start->format('Y-m-d H:i')
|
||||||
. ' to ' . $shift->end->format('Y-m-d H:i')
|
. ' to ' . $shift->end->format('Y-m-d H:i')
|
||||||
. ' as ' . $shiftEntry->angelType->name
|
. ' as ' . $shiftEntry->angelType->name
|
||||||
|
@ -33,14 +33,14 @@ function ShiftEntry_onDelete(ShiftEntry $shiftEntry)
|
||||||
$signout_user = $shiftEntry->user;
|
$signout_user = $shiftEntry->user;
|
||||||
$shift = Shift($shiftEntry->shift);
|
$shift = Shift($shiftEntry->shift);
|
||||||
$shifttype = $shift->shiftType;
|
$shifttype = $shift->shiftType;
|
||||||
$room = $shift->room;
|
$location = $shift->location;
|
||||||
$angeltype = $shiftEntry->angelType;
|
$angeltype = $shiftEntry->angelType;
|
||||||
|
|
||||||
engelsystem_log(
|
engelsystem_log(
|
||||||
'Shift signout: ' . User_Nick_render($signout_user, true)
|
'Shift signout: ' . User_Nick_render($signout_user, true)
|
||||||
. ' from shift ' . $shift->title
|
. ' from shift ' . $shift->title
|
||||||
. ' (' . $shifttype->name . ')'
|
. ' (' . $shifttype->name . ')'
|
||||||
. ' at ' . $room->name
|
. ' at ' . $location->name
|
||||||
. ' from ' . $shift->start->format('Y-m-d H:i')
|
. ' from ' . $shift->start->format('Y-m-d H:i')
|
||||||
. ' to ' . $shift->end->format('Y-m-d H:i')
|
. ' to ' . $shift->end->format('Y-m-d H:i')
|
||||||
. ' as ' . $angeltype->name
|
. ' as ' . $angeltype->name
|
||||||
|
|
|
@ -44,10 +44,10 @@ class ShiftsFilter
|
||||||
* ShiftsFilter constructor.
|
* ShiftsFilter constructor.
|
||||||
*
|
*
|
||||||
* @param bool $user_shifts_admin
|
* @param bool $user_shifts_admin
|
||||||
* @param int[] $rooms
|
* @param int[] $locations
|
||||||
* @param int[] $angelTypes
|
* @param int[] $angelTypes
|
||||||
*/
|
*/
|
||||||
public function __construct($user_shifts_admin = false, private $rooms = [], $angelTypes = [])
|
public function __construct($user_shifts_admin = false, private $locations = [], $angelTypes = [])
|
||||||
{
|
{
|
||||||
$this->types = $angelTypes;
|
$this->types = $angelTypes;
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class ShiftsFilter
|
||||||
return [
|
return [
|
||||||
'userShiftsAdmin' => $this->userShiftsAdmin,
|
'userShiftsAdmin' => $this->userShiftsAdmin,
|
||||||
'filled' => $this->filled,
|
'filled' => $this->filled,
|
||||||
'rooms' => $this->rooms,
|
'locations' => $this->locations,
|
||||||
'types' => $this->types,
|
'types' => $this->types,
|
||||||
'startTime' => $this->startTime,
|
'startTime' => $this->startTime,
|
||||||
'endTime' => $this->endTime,
|
'endTime' => $this->endTime,
|
||||||
|
@ -80,12 +80,12 @@ class ShiftsFilter
|
||||||
*/
|
*/
|
||||||
public function sessionImport($data)
|
public function sessionImport($data)
|
||||||
{
|
{
|
||||||
$this->userShiftsAdmin = $data['userShiftsAdmin'];
|
$this->userShiftsAdmin = $data['userShiftsAdmin'] ?? false;
|
||||||
$this->filled = $data['filled'];
|
$this->filled = $data['filled'] ?? [];
|
||||||
$this->rooms = $data['rooms'];
|
$this->locations = $data['locations'] ?? [];
|
||||||
$this->types = $data['types'];
|
$this->types = $data['types'] ?? [];
|
||||||
$this->startTime = $data['startTime'];
|
$this->startTime = $data['startTime'] ?? null;
|
||||||
$this->endTime = $data['endTime'];
|
$this->endTime = $data['endTime'] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,20 +163,20 @@ class ShiftsFilter
|
||||||
/**
|
/**
|
||||||
* @return int[]
|
* @return int[]
|
||||||
*/
|
*/
|
||||||
public function getRooms()
|
public function getLocations()
|
||||||
{
|
{
|
||||||
if (count($this->rooms) == 0) {
|
if (count($this->locations) == 0) {
|
||||||
return [0];
|
return [0];
|
||||||
}
|
}
|
||||||
return $this->rooms;
|
return $this->locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int[] $rooms
|
* @param int[] $locations
|
||||||
*/
|
*/
|
||||||
public function setRooms($rooms)
|
public function setLocations($locations)
|
||||||
{
|
{
|
||||||
$this->rooms = $rooms;
|
$this->locations = $locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,12 +28,26 @@ function Shifts_by_angeltype(AngelType $angeltype)
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
SELECT DISTINCT `shifts`.* FROM `shifts`
|
SELECT DISTINCT `shifts`.* FROM `shifts`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`room_id` = `shifts`.`room_id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id` = `shifts`.`shift_type_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE `needed_angel_types`.`angel_type_id` = ?
|
WHERE `needed_angel_types`.`angel_type_id` = ?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
', [$angeltype->id, $angeltype->id]);
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT DISTINCT `shifts`.* FROM `shifts`
|
||||||
|
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id` = `shifts`.`location_id`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `needed_angel_types`.`angel_type_id` = ?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
|
', [$angeltype->id, $angeltype->id, $angeltype->id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,25 +67,42 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
|
||||||
$shifts = Db::select('
|
$shifts = Db::select('
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM (
|
FROM (
|
||||||
SELECT id, start
|
SELECT shifts.id, start
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE (`end` > ? AND `start` < ?)
|
WHERE (`end` > ? AND `start` < ?)
|
||||||
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_id`=`shifts`.`id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_id`=`shifts`.`id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
AND s.shift_id IS NULL
|
AND s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
SELECT id, start
|
/* By shift type */
|
||||||
|
SELECT shifts.id, start
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE (`end` > ? AND `start` < ?)
|
WHERE (`end` > ? AND `start` < ?)
|
||||||
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`room_id`=`shifts`.`room_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND `freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT shifts.id, start
|
||||||
|
FROM `shifts`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE (`end` > ? AND `start` < ?)
|
||||||
|
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
|
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
) AS `tmp`
|
) AS `tmp`
|
||||||
ORDER BY `tmp`.`start`
|
ORDER BY `tmp`.`start`
|
||||||
', [
|
', [
|
||||||
|
@ -79,6 +110,8 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
|
||||||
$end,
|
$end,
|
||||||
$start,
|
$start,
|
||||||
$end,
|
$end,
|
||||||
|
$start,
|
||||||
|
$end,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$shifts = collect($shifts);
|
$shifts = collect($shifts);
|
||||||
|
@ -97,32 +130,51 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
{
|
{
|
||||||
$sql = '
|
$sql = '
|
||||||
SELECT * FROM (
|
SELECT * FROM (
|
||||||
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `rooms`.`name` AS `room_name`
|
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
JOIN `rooms` ON `shifts`.`room_id` = `rooms`.`id`
|
JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
|
||||||
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id` = `shifts`.`id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id` = `shifts`.`id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
AND `start` BETWEEN ? AND ?
|
AND `start` BETWEEN ? AND ?
|
||||||
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
|
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
|
||||||
AND s.shift_id IS NULL
|
AND s.shift_id IS NULL
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `rooms`.`name` AS `room_name`
|
/* By shift type */
|
||||||
|
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
JOIN `rooms` ON `shifts`.`room_id` = `rooms`.`id`
|
JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
|
||||||
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
AND `start` BETWEEN ? AND ?
|
AND `start` BETWEEN ? AND ?
|
||||||
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
|
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
|
||||||
|
FROM `shifts`
|
||||||
|
JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
|
||||||
|
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
||||||
|
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
|
AND `start` BETWEEN ? AND ?
|
||||||
|
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
) AS tmp_shifts
|
) AS tmp_shifts
|
||||||
|
|
||||||
ORDER BY `room_name`, `start`
|
ORDER BY `location_name`, `start`
|
||||||
';
|
';
|
||||||
|
|
||||||
$shiftsData = Db::select(
|
$shiftsData = Db::select(
|
||||||
|
@ -132,6 +184,8 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
$shiftsFilter->getEnd(),
|
$shiftsFilter->getEnd(),
|
||||||
$shiftsFilter->getStart(),
|
$shiftsFilter->getStart(),
|
||||||
$shiftsFilter->getEnd(),
|
$shiftsFilter->getEnd(),
|
||||||
|
$shiftsFilter->getStart(),
|
||||||
|
$shiftsFilter->getEnd(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -156,31 +210,54 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
`angel_types`.`id`,
|
`angel_types`.`id`,
|
||||||
`angel_types`.`name`,
|
`angel_types`.`name`,
|
||||||
`angel_types`.`restricted`,
|
`angel_types`.`restricted`,
|
||||||
`angel_types`.`no_self_signup`
|
`angel_types`.`shift_self_signup`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id`=`shifts`.`id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id`=`shifts`.`id`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
AND shifts.`start` BETWEEN ? AND ?
|
AND shifts.`start` BETWEEN ? AND ?
|
||||||
AND s.shift_id IS NULL
|
AND s.shift_id IS NULL
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
SELECT
|
SELECT
|
||||||
`needed_angel_types`.*,
|
`needed_angel_types`.*,
|
||||||
`shifts`.`id` AS shift_id,
|
`shifts`.`id` AS shift_id,
|
||||||
`angel_types`.`id`,
|
`angel_types`.`id`,
|
||||||
`angel_types`.`name`,
|
`angel_types`.`name`,
|
||||||
`angel_types`.`restricted`,
|
`angel_types`.`restricted`,
|
||||||
`angel_types`.`no_self_signup`
|
`angel_types`.`shift_self_signup`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
AND shifts.`start` BETWEEN ? AND ?
|
AND shifts.`start` BETWEEN ? AND ?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT
|
||||||
|
`needed_angel_types`.*,
|
||||||
|
`shifts`.`id` AS shift_id,
|
||||||
|
`angel_types`.`id`,
|
||||||
|
`angel_types`.`name`,
|
||||||
|
`angel_types`.`restricted`,
|
||||||
|
`angel_types`.`shift_self_signup`
|
||||||
|
FROM `shifts`
|
||||||
|
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
|
AND shifts.`start` BETWEEN ? AND ?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
';
|
';
|
||||||
|
|
||||||
return Db::select(
|
return Db::select(
|
||||||
|
@ -190,6 +267,8 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
$shiftsFilter->getEnd(),
|
$shiftsFilter->getEnd(),
|
||||||
$shiftsFilter->getStart(),
|
$shiftsFilter->getStart(),
|
||||||
$shiftsFilter->getEnd(),
|
$shiftsFilter->getEnd(),
|
||||||
|
$shiftsFilter->getStart(),
|
||||||
|
$shiftsFilter->getEnd(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -209,7 +288,7 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
|
||||||
`angel_types`.`id`,
|
`angel_types`.`id`,
|
||||||
`angel_types`.`name`,
|
`angel_types`.`name`,
|
||||||
`angel_types`.`restricted`,
|
`angel_types`.`restricted`,
|
||||||
`angel_types`.`no_self_signup`
|
`angel_types`.`shift_self_signup`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id`=`shifts`.`id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id`=`shifts`.`id`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
|
@ -220,26 +299,51 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
SELECT
|
SELECT
|
||||||
`needed_angel_types`.*,
|
`needed_angel_types`.*,
|
||||||
`shifts`.`id` AS shift_id,
|
`shifts`.`id` AS shift_id,
|
||||||
`angel_types`.`id`,
|
`angel_types`.`id`,
|
||||||
`angel_types`.`name`,
|
`angel_types`.`name`,
|
||||||
`angel_types`.`restricted`,
|
`angel_types`.`restricted`,
|
||||||
`angel_types`.`no_self_signup`
|
`angel_types`.`shift_self_signup`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE `shifts`.`id`=?
|
WHERE `shifts`.`id`=?
|
||||||
AND `angel_types`.`id`=?
|
AND `angel_types`.`id`=?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT
|
||||||
|
`needed_angel_types`.*,
|
||||||
|
`shifts`.`id` AS shift_id,
|
||||||
|
`angel_types`.`id`,
|
||||||
|
`angel_types`.`name`,
|
||||||
|
`angel_types`.`restricted`,
|
||||||
|
`angel_types`.`shift_self_signup`
|
||||||
|
FROM `shifts`
|
||||||
|
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `shifts`.`id`=?
|
||||||
|
AND `angel_types`.`id`=?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
',
|
',
|
||||||
[
|
[
|
||||||
$shift->id,
|
$shift->id,
|
||||||
$angeltype->id,
|
$angeltype->id,
|
||||||
$shift->id,
|
$shift->id,
|
||||||
$angeltype->id,
|
$angeltype->id,
|
||||||
|
$shift->id,
|
||||||
|
$angeltype->id,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -252,7 +356,7 @@ function ShiftEntries_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
{
|
{
|
||||||
return ShiftEntry::with('user')
|
return ShiftEntry::with('user')
|
||||||
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
|
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
|
||||||
->whereIn('shifts.room_id', $shiftsFilter->getRooms())
|
->whereIn('shifts.location_id', $shiftsFilter->getLocations())
|
||||||
->whereBetween('start', [$shiftsFilter->getStart(), $shiftsFilter->getEnd()])
|
->whereBetween('start', [$shiftsFilter->getStart(), $shiftsFilter->getEnd()])
|
||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
@ -368,12 +472,12 @@ function Shift_signup_allowed_angel(
|
||||||
|
|
||||||
if (
|
if (
|
||||||
empty($user_angeltype)
|
empty($user_angeltype)
|
||||||
|| $angeltype->no_self_signup == 1
|
|| !$angeltype->shift_self_signup
|
||||||
|| ($angeltype->restricted == 1 && !isset($user_angeltype['confirm_user_id']))
|
|| ($angeltype->restricted && !isset($user_angeltype['confirm_user_id']))
|
||||||
) {
|
) {
|
||||||
// you cannot join if user is not of this angel type
|
// you cannot join if user is not of this angel type
|
||||||
|
// you cannot join if angeltype has shift self signup disabled
|
||||||
// you cannot join if you are not confirmed
|
// you cannot join if you are not confirmed
|
||||||
// you cannot join if angeltype has no self signup
|
|
||||||
|
|
||||||
return new ShiftSignupState(ShiftSignupStatus::ANGELTYPE, $free_entries);
|
return new ShiftSignupState(ShiftSignupStatus::ANGELTYPE, $free_entries);
|
||||||
}
|
}
|
||||||
|
@ -510,8 +614,8 @@ function Shifts_by_user($userId, $include_freeloaded_comments = false)
|
||||||
$shiftsData = Db::select(
|
$shiftsData = Db::select(
|
||||||
'
|
'
|
||||||
SELECT
|
SELECT
|
||||||
`rooms`.*,
|
`locations`.*,
|
||||||
`rooms`.name AS Name,
|
`locations`.name AS Name,
|
||||||
`shift_types`.`id` AS `shifttype_id`,
|
`shift_types`.`id` AS `shifttype_id`,
|
||||||
`shift_types`.`name`,
|
`shift_types`.`name`,
|
||||||
`shift_entries`.`id` as shift_entry_id,
|
`shift_entries`.`id` as shift_entry_id,
|
||||||
|
@ -525,7 +629,7 @@ function Shifts_by_user($userId, $include_freeloaded_comments = false)
|
||||||
FROM `shift_entries`
|
FROM `shift_entries`
|
||||||
JOIN `shifts` ON (`shift_entries`.`shift_id` = `shifts`.`id`)
|
JOIN `shifts` ON (`shift_entries`.`shift_id` = `shifts`.`id`)
|
||||||
JOIN `shift_types` ON (`shift_types`.`id` = `shifts`.`shift_type_id`)
|
JOIN `shift_types` ON (`shift_types`.`id` = `shifts`.`shift_type_id`)
|
||||||
JOIN `rooms` ON (`shifts`.`room_id` = `rooms`.`id`)
|
JOIN `locations` ON (`shifts`.`location_id` = `locations`.`id`)
|
||||||
WHERE shift_entries.`user_id` = ?
|
WHERE shift_entries.`user_id` = ?
|
||||||
ORDER BY `start`
|
ORDER BY `start`
|
||||||
',
|
',
|
||||||
|
@ -559,7 +663,7 @@ function Shift($shift)
|
||||||
}
|
}
|
||||||
|
|
||||||
$neededAngels = [];
|
$neededAngels = [];
|
||||||
$angelTypes = NeededAngelTypes_by_shift($shift->id);
|
$angelTypes = NeededAngelTypes_by_shift($shift);
|
||||||
foreach ($angelTypes as $type) {
|
foreach ($angelTypes as $type) {
|
||||||
$neededAngels[] = [
|
$neededAngels[] = [
|
||||||
'angel_type_id' => $type['angel_type_id'],
|
'angel_type_id' => $type['angel_type_id'],
|
||||||
|
|
|
@ -24,7 +24,7 @@ function stats_currently_working(ShiftsFilter $filter = null)
|
||||||
)) AS `count`
|
)) AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
WHERE (`end` >= NOW() AND `start` <= NOW())
|
WHERE (`end` >= NOW() AND `start` <= NOW())
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '')
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '')
|
||||||
);
|
);
|
||||||
|
|
||||||
return $result['count'] ?: '-';
|
return $result['count'] ?: '-';
|
||||||
|
@ -47,20 +47,37 @@ function stats_hours_to_work(ShiftsFilter $filter = null)
|
||||||
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE `shifts`.`end` >= NOW()
|
WHERE shifts.`end` >= NOW()
|
||||||
AND s.shift_id IS NULL
|
AND s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
SELECT
|
SELECT
|
||||||
(SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`room_id`=`shifts`.`room_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
(SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE shifts.`end` >= NOW()
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` >= NOW()
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT
|
||||||
|
(SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
|
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
||||||
|
FROM `shifts`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` >= NOW()
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
) AS `tmp`
|
) AS `tmp`
|
||||||
'
|
'
|
||||||
);
|
);
|
||||||
|
@ -90,7 +107,8 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
AND `needed_angel_types`.`shift_id`=`shifts`.`id`
|
AND `needed_angel_types`.`shift_id`=`shifts`.`id`
|
||||||
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
) - (
|
) - (
|
||||||
SELECT COUNT(*) FROM `shift_entries`
|
SELECT COUNT(*)
|
||||||
|
FROM `shift_entries`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
|
@ -103,10 +121,11 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE shifts.`end` > NOW() AND shifts.`start` < ?
|
WHERE shifts.`end` > NOW() AND shifts.`start` < ?
|
||||||
AND s.shift_id IS NULL
|
AND s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
SELECT
|
SELECT
|
||||||
GREATEST(0,
|
GREATEST(0,
|
||||||
(
|
(
|
||||||
|
@ -114,7 +133,7 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
FROM `needed_angel_types`
|
FROM `needed_angel_types`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
|
||||||
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
AND `needed_angel_types`.`room_id`=`shifts`.`room_id`
|
AND `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
) - (
|
) - (
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
|
@ -129,12 +148,46 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
AS `count`
|
AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE `end` > NOW() AND `start` < ?
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` > NOW() AND shifts.`start` < ?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT
|
||||||
|
GREATEST(0,
|
||||||
|
(
|
||||||
|
SELECT SUM(needed_angel_types.`count`)
|
||||||
|
FROM `needed_angel_types`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
|
||||||
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
|
AND `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
||||||
|
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
|
) - (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM `shift_entries`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
|
AND `freeloaded`=0
|
||||||
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
|
)
|
||||||
|
)
|
||||||
|
AS `count`
|
||||||
|
FROM `shifts`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` > NOW() AND shifts.`start` < ?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
) AS `tmp`', [
|
) AS `tmp`', [
|
||||||
$in3hours,
|
$in3hours,
|
||||||
$in3hours,
|
$in3hours,
|
||||||
|
$in3hours,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $result['count'] ?: '-';
|
return $result['count'] ?: '-';
|
||||||
|
@ -185,10 +238,11 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE shifts.`end` > ? AND shifts.`start` < ?
|
WHERE shifts.`end` > ? AND shifts.`start` < ?
|
||||||
AND s.shift_id IS NULL
|
AND s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
SELECT
|
SELECT
|
||||||
GREATEST(0,
|
GREATEST(0,
|
||||||
(
|
(
|
||||||
|
@ -196,28 +250,62 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
|
||||||
FROM `needed_angel_types`
|
FROM `needed_angel_types`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
|
||||||
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
AND `needed_angel_types`.`room_id`=`shifts`.`room_id`
|
AND `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
) - (
|
) - (
|
||||||
SELECT COUNT(*) FROM `shift_entries`
|
SELECT COUNT(*) FROM `shift_entries`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
AND `freeloaded`=0
|
AND shift_entries.`freeloaded`=0
|
||||||
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AS `count`
|
AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE `end` > ? AND `start` < ?
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` > ? AND shifts.`start` < ?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT
|
||||||
|
GREATEST(0,
|
||||||
|
(
|
||||||
|
SELECT SUM(needed_angel_types.`count`)
|
||||||
|
FROM `needed_angel_types`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
|
||||||
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
|
AND `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
||||||
|
' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
|
) - (
|
||||||
|
SELECT COUNT(*) FROM `shift_entries`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
|
AND shift_entries.`freeloaded`=0
|
||||||
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
|
)
|
||||||
|
)
|
||||||
|
AS `count`
|
||||||
|
FROM `shifts`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` > ? AND shifts.`start` < ?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
) AS `tmp`', [
|
) AS `tmp`', [
|
||||||
$night_start,
|
$night_start,
|
||||||
$night_end,
|
$night_end,
|
||||||
$night_start,
|
$night_start,
|
||||||
$night_end,
|
$night_end,
|
||||||
|
$night_start,
|
||||||
|
$night_end,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $result['count'] ?: '-';
|
return $result['count'] ?: '-';
|
||||||
|
|
|
@ -137,22 +137,6 @@ function User_validate_planned_departure_date($planned_arrival_date, $planned_de
|
||||||
return new ValidationResult(true, $planned_departure_date);
|
return new ValidationResult(true, $planned_departure_date);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a new api key for given user.
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
* @param bool $log
|
|
||||||
*/
|
|
||||||
function User_reset_api_key($user, $log = true)
|
|
||||||
{
|
|
||||||
$user->api_key = bin2hex(random_bytes(32));
|
|
||||||
$user->save();
|
|
||||||
|
|
||||||
if ($log) {
|
|
||||||
engelsystem_log(sprintf('API key resetted (%s).', User_Nick_render($user, true)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @return float
|
* @return float
|
||||||
|
|
|
@ -47,11 +47,11 @@ function admin_active()
|
||||||
__('At least %s angels are forced to be active. The number has to be greater.'),
|
__('At least %s angels are forced to be active. The number has to be greater.'),
|
||||||
$forced_count
|
$forced_count
|
||||||
));
|
));
|
||||||
throw_redirect(page_link_to('admin_active'));
|
throw_redirect(url('/admin-active'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$msg .= error(__('Please enter a number of angels to be marked as active.'));
|
$msg .= error(__('Please enter a number of angels to be marked as active.'));
|
||||||
throw_redirect(page_link_to('admin_active'));
|
throw_redirect(url('/admin-active'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasPostData('ack')) {
|
if ($request->hasPostData('ack')) {
|
||||||
|
@ -97,9 +97,9 @@ function admin_active()
|
||||||
$msg = success(__('Marked angels.'), true);
|
$msg = success(__('Marked angels.'), true);
|
||||||
} else {
|
} else {
|
||||||
$set_active = form([
|
$set_active = form([
|
||||||
button(page_link_to('admin_active', ['search' => $search]), '« ' . __('back')),
|
button(url('/admin-active', ['search' => $search]), '« ' . __('general.back')),
|
||||||
form_submit('ack', '» ' . __('apply')),
|
form_submit('ack', '» ' . __('Apply')),
|
||||||
], page_link_to('admin_active', ['search' => $search, 'count' => $count, 'set_active' => 1]));
|
], url('/admin-active', ['search' => $search, 'count' => $count, 'set_active' => 1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ function admin_active()
|
||||||
$user_source->state->got_shirt = true;
|
$user_source->state->got_shirt = true;
|
||||||
$user_source->state->save();
|
$user_source->state->save();
|
||||||
engelsystem_log('User ' . User_Nick_render($user_source, true) . ' has tshirt now.');
|
engelsystem_log('User ' . User_Nick_render($user_source, true) . ' has tshirt now.');
|
||||||
$msg = success(($goodie_tshirt ? __('Angel has got a t-shirt.') : __('Angel has got a goodie.')), true);
|
$msg = success(($goodie_tshirt ? __('Angel has got a T-shirt.') : __('Angel has got a goodie.')), true);
|
||||||
} else {
|
} else {
|
||||||
$msg = error('Angel not found.', true);
|
$msg = error('Angel not found.', true);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ function admin_active()
|
||||||
$user_source->state->got_shirt = false;
|
$user_source->state->got_shirt = false;
|
||||||
$user_source->state->save();
|
$user_source->state->save();
|
||||||
engelsystem_log('User ' . User_Nick_render($user_source, true) . ' has NO tshirt.');
|
engelsystem_log('User ' . User_Nick_render($user_source, true) . ' has NO tshirt.');
|
||||||
$msg = success(($goodie_tshirt ? __('Angel has got no t-shirt.') : __('Angel has got no goodie.')), true);
|
$msg = success(($goodie_tshirt ? __('Angel has got no T-shirt.') : __('Angel has got no goodie.')), true);
|
||||||
} else {
|
} else {
|
||||||
$msg = error(__('Angel not found.'), true);
|
$msg = error(__('Angel not found.'), true);
|
||||||
}
|
}
|
||||||
|
@ -236,8 +236,8 @@ function admin_active()
|
||||||
$parameters['show_all_shifts'] = 1;
|
$parameters['show_all_shifts'] = 1;
|
||||||
}
|
}
|
||||||
$actions[] = form(
|
$actions[] = form(
|
||||||
[form_submit('submit', __('set active'), 'btn-sm', false, 'secondary')],
|
[form_submit('submit', icon('plus-lg') . __('set active'), 'btn-sm', false, 'secondary')],
|
||||||
page_link_to('admin_active', $parameters),
|
url('/admin-active', $parameters),
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -251,8 +251,8 @@ function admin_active()
|
||||||
$parametersRemove['show_all_shifts'] = 1;
|
$parametersRemove['show_all_shifts'] = 1;
|
||||||
}
|
}
|
||||||
$actions[] = form(
|
$actions[] = form(
|
||||||
[form_submit('submit', __('remove active'), 'btn-sm', false, 'secondary')],
|
[form_submit('submit', icon('dash-lg') . __('Remove active'), 'btn-sm', false, 'secondary')],
|
||||||
page_link_to('admin_active', $parametersRemove),
|
url('/admin-active', $parametersRemove),
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -268,8 +268,8 @@ function admin_active()
|
||||||
|
|
||||||
if ($goodie_enabled) {
|
if ($goodie_enabled) {
|
||||||
$actions[] = form(
|
$actions[] = form(
|
||||||
[form_submit('submit', ($goodie_tshirt ? __('got t-shirt') : __('got goodie')), 'btn-sm', false, 'secondary')],
|
[form_submit('submit', icon('person') . ($goodie_tshirt ? __('Got T-shirt') : __('Got goodie')), 'btn-sm', false, 'secondary')],
|
||||||
page_link_to('admin_active', $parametersShirt),
|
url('/admin-active', $parametersShirt),
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -286,8 +286,8 @@ function admin_active()
|
||||||
|
|
||||||
if ($goodie_enabled) {
|
if ($goodie_enabled) {
|
||||||
$actions[] = form(
|
$actions[] = form(
|
||||||
[form_submit('submit', ($goodie_tshirt ? __('remove t-shirt') : __('remove goodie')), 'btn-sm', false, 'secondary')],
|
[form_submit('submit', icon('person') . ($goodie_tshirt ? __('Remove T-shirt') : __('Remove goodie')), 'btn-sm', false, 'secondary')],
|
||||||
page_link_to('admin_active', $parameters),
|
url('/admin-active', $parameters),
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -295,7 +295,7 @@ function admin_active()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($goodie_tshirt) {
|
if ($goodie_tshirt) {
|
||||||
$actions[] = button(url('/admin/user/' . $usr->id . '/goodie'), __('form.edit'), 'btn-secondary btn-sm');
|
$actions[] = button(url('/admin/user/' . $usr->id . '/goodie'), icon('pencil') . __('form.edit'), 'btn-secondary btn-sm');
|
||||||
}
|
}
|
||||||
|
|
||||||
$userData['actions'] = buttons($actions);
|
$userData['actions'] = buttons($actions);
|
||||||
|
@ -328,18 +328,18 @@ function admin_active()
|
||||||
form([
|
form([
|
||||||
form_text('search', __('Search angel:'), $search),
|
form_text('search', __('Search angel:'), $search),
|
||||||
form_checkbox('show_all_shifts', __('Show all shifts'), $show_all_shifts),
|
form_checkbox('show_all_shifts', __('Show all shifts'), $show_all_shifts),
|
||||||
form_submit('submit', __('Search')),
|
form_submit('submit', icon('search') . __('form.search')),
|
||||||
], page_link_to('admin_active')),
|
], url('/admin-active')),
|
||||||
$set_active == '' ? form([
|
$set_active == '' ? form([
|
||||||
form_text('count', __('How much angels should be active?'), $count ?: $forced_count),
|
form_text('count', __('How much angels should be active?'), $count ?: $forced_count),
|
||||||
form_submit('set_active', __('Preview')),
|
form_submit('set_active', icon('eye') . __('form.preview'), 'btn-info'),
|
||||||
]) : $set_active,
|
]) : $set_active,
|
||||||
$msg . msg(),
|
$msg . msg(),
|
||||||
table(
|
table(
|
||||||
array_merge(
|
array_merge(
|
||||||
[
|
[
|
||||||
'no' => __('No.'),
|
'no' => __('No.'),
|
||||||
'nick' => __('Name'),
|
'nick' => __('general.name'),
|
||||||
],
|
],
|
||||||
($goodie_tshirt ? ['shirt_size' => __('Size')] : []),
|
($goodie_tshirt ? ['shirt_size' => __('Size')] : []),
|
||||||
[
|
[
|
||||||
|
@ -350,15 +350,15 @@ function admin_active()
|
||||||
],
|
],
|
||||||
($goodie_enabled ? ['tshirt' => ($goodie_tshirt ? __('T-shirt?') : __('Goodie?'))] : []),
|
($goodie_enabled ? ['tshirt' => ($goodie_tshirt ? __('T-shirt?') : __('Goodie?'))] : []),
|
||||||
[
|
[
|
||||||
'actions' => '',
|
'actions' => __('general.actions'),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
$matched_users
|
$matched_users
|
||||||
),
|
),
|
||||||
$goodie_enabled ? '<h2>' . ($goodie_tshirt ? __('Shirt statistic') : __('Goodie statistic')) . '</h2>' : '',
|
$goodie_enabled ? '<h2>' . ($goodie_tshirt ? __('T-shirt statistic') : __('Goodie statistic')) . '</h2>' : '',
|
||||||
$goodie_enabled ? table(array_merge(
|
$goodie_enabled ? table(array_merge(
|
||||||
($goodie_tshirt ? ['size' => __('Size')] : []),
|
($goodie_tshirt ? ['size' => __('Size')] : []),
|
||||||
['given' => $goodie_tshirt ? __('Given shirts') : __('Given goodies') ]
|
['given' => $goodie_tshirt ? __('Given T-shirts') : __('Given goodies') ]
|
||||||
), $goodie_statistics) : '',
|
), $goodie_statistics) : '',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,13 @@ function admin_arrive()
|
||||||
foreach ($users as $usr) {
|
foreach ($users as $usr) {
|
||||||
if (count($tokens) > 0) {
|
if (count($tokens) > 0) {
|
||||||
$match = false;
|
$match = false;
|
||||||
$index = join(' ', $usr->attributesToArray());
|
$data = collect($usr->toArray())->flatten()->filter(function ($value) {
|
||||||
|
// Remove empty values
|
||||||
|
return !empty($value) &&
|
||||||
|
// Skip datetime
|
||||||
|
!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{6}Z$/', (string) $value);
|
||||||
|
});
|
||||||
|
$index = join(' ', $data->toArray());
|
||||||
foreach ($tokens as $token) {
|
foreach ($tokens as $token) {
|
||||||
$token = trim($token);
|
$token = trim($token);
|
||||||
if (!empty($token) && stristr($index, $token)) {
|
if (!empty($token) && stristr($index, $token)) {
|
||||||
|
@ -92,50 +98,68 @@ function admin_arrive()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$usr->name = User_Nick_render($usr) . User_Pronoun_render($usr);
|
$usr->name = User_Nick_render($usr)
|
||||||
|
. User_Pronoun_render($usr)
|
||||||
|
. ($usr->state->user_info
|
||||||
|
? ' <small><span class="bi bi-info-circle-fill text-info"></span></small>'
|
||||||
|
: '');
|
||||||
$plannedDepartureDate = $usr->personalData->planned_departure_date;
|
$plannedDepartureDate = $usr->personalData->planned_departure_date;
|
||||||
$arrivalDate = $usr->state->arrival_date;
|
$arrivalDate = $usr->state->arrival_date;
|
||||||
$plannedArrivalDate = $usr->personalData->planned_arrival_date;
|
$plannedArrivalDate = $usr->personalData->planned_arrival_date;
|
||||||
$usr['rendered_planned_departure_date'] = $plannedDepartureDate
|
$usr['rendered_planned_departure_date'] = $plannedDepartureDate
|
||||||
? $plannedDepartureDate->format(__('Y-m-d'))
|
? $plannedDepartureDate->format(__('general.date'))
|
||||||
: '-';
|
: '-';
|
||||||
$usr['rendered_planned_arrival_date'] = $plannedArrivalDate ? $plannedArrivalDate->format(__('Y-m-d')) : '-';
|
$usr['rendered_planned_arrival_date'] = $plannedArrivalDate ? $plannedArrivalDate->format(__('general.date')) : '-';
|
||||||
$usr['rendered_arrival_date'] = $arrivalDate ? $arrivalDate->format(__('Y-m-d')) : '-';
|
$usr['rendered_arrival_date'] = $arrivalDate ? $arrivalDate->format(__('general.date')) : '-';
|
||||||
$usr['arrived'] = icon_bool($usr->state->arrived);
|
$usr['arrived'] = icon_bool($usr->state->arrived);
|
||||||
$usr['actions'] = form([
|
$usr['actions'] = form([
|
||||||
form_hidden('action', $usr->state->arrived ? 'reset' : 'arrived'),
|
form_hidden('action', $usr->state->arrived ? 'reset' : 'arrived'),
|
||||||
form_hidden('user', $usr->id),
|
form_hidden('user', $usr->id),
|
||||||
form_submit(
|
form_submit(
|
||||||
'submit',
|
'submit',
|
||||||
$usr->state->arrived ? __('reset') : __('arrived'),
|
$usr->state->arrived
|
||||||
|
? icon('arrow-counterclockwise')
|
||||||
|
: icon('house'),
|
||||||
'btn-sm',
|
'btn-sm',
|
||||||
true,
|
true,
|
||||||
$usr->state->arrived ? 'secondary' : 'primary'
|
$usr->state->arrived ? 'secondary' : 'primary',
|
||||||
|
$usr->state->arrived
|
||||||
|
? __('Reset')
|
||||||
|
: __('user.arrive')
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($usr->state->arrival_date) {
|
if ($usr->state->arrival_date) {
|
||||||
$day = $usr->state->arrival_date->format(__('Y-m-d'));
|
$day = $usr->state->arrival_date->format('Y-m-d');
|
||||||
if (!isset($arrival_count_at_day[$day])) {
|
if (!isset($arrival_count_at_day[$day])) {
|
||||||
$arrival_count_at_day[$day] = 0;
|
$arrival_count_at_day[$day] = [
|
||||||
|
'day' => $usr->state->arrival_date,
|
||||||
|
'count' => 0,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
$arrival_count_at_day[$day]++;
|
$arrival_count_at_day[$day]['count']++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($usr->personalData->planned_arrival_date) {
|
if ($usr->personalData->planned_arrival_date) {
|
||||||
$day = $usr->personalData->planned_arrival_date->format(__('Y-m-d'));
|
$day = $usr->personalData->planned_arrival_date->format('Y-m-d');
|
||||||
if (!isset($planned_arrival_count_at_day[$day])) {
|
if (!isset($planned_arrival_count_at_day[$day])) {
|
||||||
$planned_arrival_count_at_day[$day] = 0;
|
$planned_arrival_count_at_day[$day] = [
|
||||||
|
'day' => $usr->personalData->planned_arrival_date,
|
||||||
|
'count' => 0,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
$planned_arrival_count_at_day[$day]++;
|
$planned_arrival_count_at_day[$day]['count']++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($usr->personalData->planned_departure_date && $usr->state->arrived) {
|
if ($usr->personalData->planned_departure_date && $usr->state->arrived) {
|
||||||
$day = $usr->personalData->planned_departure_date->format(__('Y-m-d'));
|
$day = $usr->personalData->planned_departure_date->format('Y-m-d');
|
||||||
if (!isset($planned_departure_count_at_day[$day])) {
|
if (!isset($planned_departure_count_at_day[$day])) {
|
||||||
$planned_departure_count_at_day[$day] = 0;
|
$planned_departure_count_at_day[$day] = [
|
||||||
|
'day' => $usr->personalData->planned_departure_date,
|
||||||
|
'count' => 0,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
$planned_departure_count_at_day[$day]++;
|
$planned_departure_count_at_day[$day]['count']++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$users_matched[] = $usr;
|
$users_matched[] = $usr;
|
||||||
|
@ -147,33 +171,33 @@ function admin_arrive()
|
||||||
|
|
||||||
$arrival_at_day = [];
|
$arrival_at_day = [];
|
||||||
$arrival_sum = 0;
|
$arrival_sum = 0;
|
||||||
foreach ($arrival_count_at_day as $day => $count) {
|
foreach ($arrival_count_at_day as $day => $entry) {
|
||||||
$arrival_sum += $count;
|
$arrival_sum += $entry['count'];
|
||||||
$arrival_at_day[$day] = [
|
$arrival_at_day[$day] = [
|
||||||
'day' => $day,
|
'day' => $entry['day']->format(__('general.date')),
|
||||||
'count' => $count,
|
'count' => $entry['count'],
|
||||||
'sum' => $arrival_sum,
|
'sum' => $arrival_sum,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$planned_arrival_at_day = [];
|
$planned_arrival_at_day = [];
|
||||||
$planned_arrival_sum = 0;
|
$planned_arrival_sum = 0;
|
||||||
foreach ($planned_arrival_count_at_day as $day => $count) {
|
foreach ($planned_arrival_count_at_day as $day => $entry) {
|
||||||
$planned_arrival_sum += $count;
|
$planned_arrival_sum += $entry['count'];
|
||||||
$planned_arrival_at_day[$day] = [
|
$planned_arrival_at_day[$day] = [
|
||||||
'day' => $day,
|
'day' => $entry['day']->format(__('general.date')),
|
||||||
'count' => $count,
|
'count' => $entry['count'],
|
||||||
'sum' => $planned_arrival_sum,
|
'sum' => $planned_arrival_sum,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$planned_departure_at_day = [];
|
$planned_departure_at_day = [];
|
||||||
$planned_departure_sum = 0;
|
$planned_departure_sum = 0;
|
||||||
foreach ($planned_departure_count_at_day as $day => $count) {
|
foreach ($planned_departure_count_at_day as $day => $entry) {
|
||||||
$planned_departure_sum += $count;
|
$planned_departure_sum += $entry['count'];
|
||||||
$planned_departure_at_day[$day] = [
|
$planned_departure_at_day[$day] = [
|
||||||
'day' => $day,
|
'day' => $entry['day']->format(__('general.date')),
|
||||||
'count' => $count,
|
'count' => $entry['count'],
|
||||||
'sum' => $planned_departure_sum,
|
'sum' => $planned_departure_sum,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -181,60 +205,60 @@ function admin_arrive()
|
||||||
return page_with_title(admin_arrive_title(), [
|
return page_with_title(admin_arrive_title(), [
|
||||||
$msg . msg(),
|
$msg . msg(),
|
||||||
form([
|
form([
|
||||||
form_text('search', __('Search'), $search),
|
form_text('search', __('form.search'), $search),
|
||||||
form_submit('submit', __('Search')),
|
form_submit('submit', icon('search') . __('form.search')),
|
||||||
], page_link_to('admin_arrive')),
|
], url('/admin-arrive')),
|
||||||
table([
|
table([
|
||||||
'name' => __('Name'),
|
'name' => __('general.name'),
|
||||||
'rendered_planned_arrival_date' => __('Planned arrival'),
|
'rendered_planned_arrival_date' => __('Planned arrival'),
|
||||||
'arrived' => __('Arrived?'),
|
'arrived' => __('Arrived?'),
|
||||||
'rendered_arrival_date' => __('Arrival date'),
|
'rendered_arrival_date' => __('Arrival date'),
|
||||||
'rendered_planned_departure_date' => __('Planned departure'),
|
'rendered_planned_departure_date' => __('Planned departure'),
|
||||||
'actions' => '',
|
'actions' => __('general.actions'),
|
||||||
], $users_matched),
|
], $users_matched),
|
||||||
div('row', [
|
div('row', [
|
||||||
div('col-md-4', [
|
div('col-md-4', [
|
||||||
heading(__('Planned arrival statistics'), 3),
|
heading(__('Planned arrival statistics'), 3),
|
||||||
BarChart::render([
|
BarChart::render([
|
||||||
'count' => __('arrived'),
|
'count' => __('user.arrived'),
|
||||||
'sum' => __('arrived sum'),
|
'sum' => __('arrived sum'),
|
||||||
], [
|
], [
|
||||||
'count' => '#090',
|
'count' => '#090',
|
||||||
'sum' => '#888',
|
'sum' => '#888',
|
||||||
], $planned_arrival_at_day),
|
], $planned_arrival_at_day),
|
||||||
table([
|
table([
|
||||||
'day' => __('Date'),
|
'day' => __('title.date'),
|
||||||
'count' => __('Count'),
|
'count' => __('general.count'),
|
||||||
'sum' => __('Sum'),
|
'sum' => __('Sum'),
|
||||||
], $planned_arrival_at_day),
|
], $planned_arrival_at_day),
|
||||||
]),
|
]),
|
||||||
div('col-md-4', [
|
div('col-md-4', [
|
||||||
heading(__('Arrival statistics'), 3),
|
heading(__('Arrival statistics'), 3),
|
||||||
BarChart::render([
|
BarChart::render([
|
||||||
'count' => __('arrived'),
|
'count' => __('user.arrived'),
|
||||||
'sum' => __('arrived sum'),
|
'sum' => __('arrived sum'),
|
||||||
], [
|
], [
|
||||||
'count' => '#090',
|
'count' => '#090',
|
||||||
'sum' => '#888',
|
'sum' => '#888',
|
||||||
], $arrival_at_day),
|
], $arrival_at_day),
|
||||||
table([
|
table([
|
||||||
'day' => __('Date'),
|
'day' => __('title.date'),
|
||||||
'count' => __('Count'),
|
'count' => __('general.count'),
|
||||||
'sum' => __('Sum'),
|
'sum' => __('Sum'),
|
||||||
], $arrival_at_day),
|
], $arrival_at_day),
|
||||||
]),
|
]),
|
||||||
div('col-md-4', [
|
div('col-md-4', [
|
||||||
heading(__('Planned departure statistics'), 3),
|
heading(__('Planned departure statistics'), 3),
|
||||||
BarChart::render([
|
BarChart::render([
|
||||||
'count' => __('arrived'),
|
'count' => __('user.arrived'),
|
||||||
'sum' => __('arrived sum'),
|
'sum' => __('arrived sum'),
|
||||||
], [
|
], [
|
||||||
'count' => '#090',
|
'count' => '#090',
|
||||||
'sum' => '#888',
|
'sum' => '#888',
|
||||||
], $planned_departure_at_day),
|
], $planned_departure_at_day),
|
||||||
table([
|
table([
|
||||||
'day' => __('Date'),
|
'day' => __('title.date'),
|
||||||
'count' => __('Count'),
|
'count' => __('general.count'),
|
||||||
'sum' => __('Sum'),
|
'sum' => __('Sum'),
|
||||||
], $planned_departure_at_day),
|
], $planned_departure_at_day),
|
||||||
]),
|
]),
|
||||||
|
|
|
@ -97,16 +97,20 @@ function admin_free()
|
||||||
|
|
||||||
$email = $usr->contact->email ?: $usr->email;
|
$email = $usr->contact->email ?: $usr->email;
|
||||||
$free_users_table[] = [
|
$free_users_table[] = [
|
||||||
'name' => User_Nick_render($usr) . User_Pronoun_render($usr),
|
'name' => User_Nick_render($usr)
|
||||||
|
. User_Pronoun_render($usr)
|
||||||
|
. ($usr->state->user_info
|
||||||
|
? ' <small><span class="bi bi-info-circle-fill text-info"></span></small>'
|
||||||
|
: ''),
|
||||||
'shift_state' => User_shift_state_render($usr),
|
'shift_state' => User_shift_state_render($usr),
|
||||||
'last_shift' => User_last_shift_render($usr),
|
'last_shift' => User_last_shift_render($usr),
|
||||||
'dect' => sprintf('<a href="tel:%s">%1$s</a>', $usr->contact->dect),
|
'dect' => sprintf('<a href="tel:%s">%1$s</a>', htmlspecialchars((string) $usr->contact->dect)),
|
||||||
'email' => $usr->settings->email_human
|
'email' => $usr->settings->email_human
|
||||||
? sprintf('<a href="mailto:%s">%1$s</a>', $email)
|
? sprintf('<a href="mailto:%s">%1$s</a>', htmlspecialchars((string) $email))
|
||||||
: icon('eye-slash'),
|
: icon('eye-slash'),
|
||||||
'actions' =>
|
'actions' =>
|
||||||
auth()->can('admin_user')
|
auth()->can('admin_user')
|
||||||
? button(page_link_to('admin_user', ['id' => $usr->id]), icon('pencil') . __('edit'), 'btn-sm')
|
? button(url('/admin-user', ['id' => $usr->id]), icon('pencil'), 'btn-sm', '', __('form.edit'))
|
||||||
: '',
|
: '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -115,19 +119,19 @@ function admin_free()
|
||||||
div('row', [
|
div('row', [
|
||||||
div('col-md-12 form-inline', [
|
div('col-md-12 form-inline', [
|
||||||
div('row', [
|
div('row', [
|
||||||
form_text('search', __('Search'), $search, null, null, null, 'col'),
|
form_text('search', __('form.search'), $search, null, null, null, 'col'),
|
||||||
form_select('angeltype', __('Angeltype'), $angel_types, $angelType, '', 'col'),
|
form_select('angeltype', __('Angeltype'), $angel_types, $angelType, '', 'col'),
|
||||||
form_submit('submit', __('Search')),
|
form_submit('submit', icon('search') . __('form.search')),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
table([
|
table([
|
||||||
'name' => __('Name'),
|
'name' => __('general.name'),
|
||||||
'shift_state' => __('Next shift'),
|
'shift_state' => __('shift.next'),
|
||||||
'last_shift' => __('Last shift'),
|
'last_shift' => __('Last shift'),
|
||||||
'dect' => __('DECT'),
|
'dect' => __('general.dect'),
|
||||||
'email' => __('E-Mail'),
|
'email' => __('general.email'),
|
||||||
'actions' => '',
|
'actions' => '',
|
||||||
], $free_users_table),
|
], $free_users_table),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -31,18 +31,21 @@ function admin_groups()
|
||||||
$privileges_html = [];
|
$privileges_html = [];
|
||||||
|
|
||||||
foreach ($privileges as $privilege) {
|
foreach ($privileges as $privilege) {
|
||||||
$privileges_html[] = $privilege['name'];
|
$privileges_html[] = htmlspecialchars($privilege['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$groups_table[] = [
|
$groups_table[] = [
|
||||||
'name' => $group->name,
|
'name' => htmlspecialchars($group->name),
|
||||||
'privileges' => join(', ', $privileges_html),
|
'privileges' => join(', ', $privileges_html),
|
||||||
'actions' => button(
|
'actions' => button(
|
||||||
page_link_to(
|
url(
|
||||||
'admin_groups',
|
'/admin-groups',
|
||||||
['action' => 'edit', 'id' => $group->id]
|
['action' => 'edit', 'id' => $group->id]
|
||||||
),
|
),
|
||||||
icon('pencil') . __('edit'),
|
icon('pencil'),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
__('form.edit'),
|
||||||
'btn-sm'
|
'btn-sm'
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
@ -50,7 +53,7 @@ function admin_groups()
|
||||||
|
|
||||||
return page_with_title(admin_groups_title(), [
|
return page_with_title(admin_groups_title(), [
|
||||||
table([
|
table([
|
||||||
'name' => __('Name'),
|
'name' => __('general.name'),
|
||||||
'privileges' => __('Privileges'),
|
'privileges' => __('Privileges'),
|
||||||
'actions' => '',
|
'actions' => '',
|
||||||
], $groups_table),
|
], $groups_table),
|
||||||
|
@ -72,18 +75,18 @@ function admin_groups()
|
||||||
foreach ($privileges as $privilege) {
|
foreach ($privileges as $privilege) {
|
||||||
$privileges_form[] = form_checkbox(
|
$privileges_form[] = form_checkbox(
|
||||||
'privileges[]',
|
'privileges[]',
|
||||||
$privilege->description . ' (' . $privilege->name . ')',
|
htmlspecialchars($privilege->description . ' (' . $privilege->name . ')'),
|
||||||
$privilege->selected != '',
|
$privilege->selected != '',
|
||||||
$privilege->id,
|
$privilege->id,
|
||||||
'privilege-' . $privilege->name
|
'privilege-' . htmlspecialchars($privilege->name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$privileges_form[] = form_submit('submit', __('Save'));
|
$privileges_form[] = form_submit('submit', icon('save') . __('form.save'));
|
||||||
$html .= page_with_title(__('Edit group') . ' ' . $group->name, [
|
$html .= page_with_title(__('Edit group') . ' ' . htmlspecialchars($group->name), [
|
||||||
form(
|
form(
|
||||||
$privileges_form,
|
$privileges_form,
|
||||||
page_link_to('admin_groups', ['action' => 'save', 'id' => $group->id])
|
url('/admin-groups', ['action' => 'save', 'id' => $group->id])
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -118,7 +121,7 @@ function admin_groups()
|
||||||
'Group privileges of group ' . $group->name
|
'Group privileges of group ' . $group->name
|
||||||
. ' edited: ' . join(', ', $privilege_names)
|
. ' edited: ' . join(', ', $privilege_names)
|
||||||
);
|
);
|
||||||
throw_redirect(page_link_to('admin_groups'));
|
throw_redirect(url('/admin-groups'));
|
||||||
} else {
|
} else {
|
||||||
return error('No Group found.', true);
|
return error('No Group found.', true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Database\Db;
|
|
||||||
use Engelsystem\Helpers\Carbon;
|
use Engelsystem\Helpers\Carbon;
|
||||||
use Engelsystem\Http\Exceptions\HttpForbidden;
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\Schedule;
|
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
use Engelsystem\Models\User\User;
|
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
@ -44,8 +40,8 @@ function admin_shifts()
|
||||||
$shift_over_midnight = true;
|
$shift_over_midnight = true;
|
||||||
|
|
||||||
// Locations laden
|
// Locations laden
|
||||||
$rooms = Room::orderBy('name')->get();
|
$locations = Location::orderBy('name')->get();
|
||||||
$room_array = $rooms->pluck('name', 'id')->toArray();
|
$location_array = $locations->pluck('name', 'id')->toArray();
|
||||||
|
|
||||||
// Load angeltypes
|
// Load angeltypes
|
||||||
/** @var AngelType[] $types */
|
/** @var AngelType[] $types */
|
||||||
|
@ -85,14 +81,14 @@ function admin_shifts()
|
||||||
|
|
||||||
// Auswahl der sichtbaren Locations für die Schichten
|
// Auswahl der sichtbaren Locations für die Schichten
|
||||||
if (
|
if (
|
||||||
$request->has('rid')
|
$request->has('lid')
|
||||||
&& preg_match('/^\d+$/', $request->input('rid'))
|
&& preg_match('/^\d+$/', $request->input('lid'))
|
||||||
&& isset($room_array[$request->input('rid')])
|
&& isset($location_array[$request->input('lid')])
|
||||||
) {
|
) {
|
||||||
$rid = $request->input('rid');
|
$lid = $request->input('lid');
|
||||||
} else {
|
} else {
|
||||||
$valid = false;
|
$valid = false;
|
||||||
$rid = $rooms->first()->id;
|
$lid = $locations->first()?->id ?? 0;
|
||||||
error(__('Please select a location.'));
|
error(__('Please select a location.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +135,29 @@ function admin_shifts()
|
||||||
'trim',
|
'trim',
|
||||||
explode(',', $request->input('change_hours'))
|
explode(',', $request->input('change_hours'))
|
||||||
);
|
);
|
||||||
|
// Fehlende Minutenangaben ergänzen, 24 Uhr -> 00 Uhr
|
||||||
|
array_walk($change_hours, function (&$value) use ($valid) {
|
||||||
|
// Add minutes
|
||||||
|
if (!preg_match('/^(\d{1,2}):\d{2}$/', $value)) {
|
||||||
|
$value .= ':00';
|
||||||
|
}
|
||||||
|
// Add 0 before low hours
|
||||||
|
if (preg_match('/^\d:\d{2}$/', $value)) {
|
||||||
|
$value = '0' . $value;
|
||||||
|
}
|
||||||
|
// Fix 24:00
|
||||||
|
if ($value == '24:00') {
|
||||||
|
$value = '00:00';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Ensure valid time in change hours
|
||||||
|
foreach ($change_hours as $change_hour) {
|
||||||
|
if (!preg_match('/^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/', $change_hour)) {
|
||||||
|
$valid = false;
|
||||||
|
error(sprintf(__('Please validate the change hour %s. It should be between 00:00 and 24:00.'), $change_hour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$change_hours = array_unique($change_hours);
|
||||||
} else {
|
} else {
|
||||||
$valid = false;
|
$valid = false;
|
||||||
error(__('Please split the shift-change hours by colons.'));
|
error(__('Please split the shift-change hours by colons.'));
|
||||||
|
@ -152,7 +171,9 @@ function admin_shifts()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('angelmode')) {
|
if ($request->has('angelmode')) {
|
||||||
if ($request->input('angelmode') == 'location') {
|
if ($request->input('angelmode') == 'shift_type') {
|
||||||
|
$angelmode = 'shift_type';
|
||||||
|
} elseif ($request->input('angelmode') == 'location') {
|
||||||
$angelmode = 'location';
|
$angelmode = 'location';
|
||||||
} elseif ($request->input('angelmode') == 'manually') {
|
} elseif ($request->input('angelmode') == 'manually') {
|
||||||
foreach ($types as $type) {
|
foreach ($types as $type) {
|
||||||
|
@ -184,8 +205,12 @@ function admin_shifts()
|
||||||
|
|
||||||
// Alle Eingaben in Ordnung
|
// Alle Eingaben in Ordnung
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($angelmode == 'location') {
|
if ($angelmode == 'shift_type') {
|
||||||
$needed_angel_types = NeededAngelType::whereRoomId($rid)
|
$needed_angel_types = NeededAngelType::whereShiftTypeId($shifttype_id)
|
||||||
|
->pluck('count', 'angel_type_id')
|
||||||
|
->toArray() + $needed_angel_types;
|
||||||
|
} elseif ($angelmode == 'location') {
|
||||||
|
$needed_angel_types = NeededAngelType::whereLocationId($lid)
|
||||||
->pluck('count', 'angel_type_id')
|
->pluck('count', 'angel_type_id')
|
||||||
->toArray() + $needed_angel_types;
|
->toArray() + $needed_angel_types;
|
||||||
}
|
}
|
||||||
|
@ -195,7 +220,7 @@ function admin_shifts()
|
||||||
$shifts[] = [
|
$shifts[] = [
|
||||||
'start' => $start,
|
'start' => $start,
|
||||||
'end' => $end,
|
'end' => $end,
|
||||||
'room_id' => $rid,
|
'location_id' => $lid,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'shift_type_id' => $shifttype_id,
|
'shift_type_id' => $shifttype_id,
|
||||||
'description' => $description,
|
'description' => $description,
|
||||||
|
@ -215,7 +240,7 @@ function admin_shifts()
|
||||||
$shifts[] = [
|
$shifts[] = [
|
||||||
'start' => $shift_start,
|
'start' => $shift_start,
|
||||||
'end' => $shift_end,
|
'end' => $shift_end,
|
||||||
'room_id' => $rid,
|
'location_id' => $lid,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'shift_type_id' => $shifttype_id,
|
'shift_type_id' => $shifttype_id,
|
||||||
'description' => $description,
|
'description' => $description,
|
||||||
|
@ -224,13 +249,6 @@ function admin_shifts()
|
||||||
$shift_start = $shift_end;
|
$shift_start = $shift_end;
|
||||||
} while ($shift_end < $end);
|
} while ($shift_end < $end);
|
||||||
} elseif ($mode == 'variable') {
|
} elseif ($mode == 'variable') {
|
||||||
// Fehlende Minutenangaben ergänzen
|
|
||||||
array_walk($change_hours, function (&$value) {
|
|
||||||
if (!preg_match('/^\d{1,2}:\d{2}$/', $value)) {
|
|
||||||
$value .= ':00';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Alle Tage durchgehen
|
// Alle Tage durchgehen
|
||||||
$end_day = Carbon::createFromDatetime($end->format('Y-m-d') . ' 00:00');
|
$end_day = Carbon::createFromDatetime($end->format('Y-m-d') . ' 00:00');
|
||||||
$day = Carbon::createFromDatetime($start->format('Y-m-d') . ' 00:00');
|
$day = Carbon::createFromDatetime($start->format('Y-m-d') . ' 00:00');
|
||||||
|
@ -238,10 +256,10 @@ function admin_shifts()
|
||||||
// Alle Schichtwechselstunden durchgehen
|
// Alle Schichtwechselstunden durchgehen
|
||||||
for ($i = 0; $i < count($change_hours); $i++) {
|
for ($i = 0; $i < count($change_hours); $i++) {
|
||||||
$start_hour = $change_hours[$i];
|
$start_hour = $change_hours[$i];
|
||||||
if ($i < count($change_hours) - 1) {
|
if (isset($change_hours[$i + 1])) {
|
||||||
// Normales Intervall zwischen zwei Schichtwechselstunden
|
// Normales Intervall zwischen zwei Schichtwechselstunden
|
||||||
$end_hour = $change_hours[$i + 1];
|
$end_hour = $change_hours[$i + 1];
|
||||||
} elseif ($shift_over_midnight) {
|
} elseif ($shift_over_midnight && $day != $end_day) {
|
||||||
// Letzte Schichtwechselstunde: Wenn eine 24h Abdeckung gewünscht ist,
|
// Letzte Schichtwechselstunde: Wenn eine 24h Abdeckung gewünscht ist,
|
||||||
// hier die erste Schichtwechselstunde als Ende einsetzen
|
// hier die erste Schichtwechselstunde als Ende einsetzen
|
||||||
$end_hour = $change_hours[0];
|
$end_hour = $change_hours[0];
|
||||||
|
@ -283,7 +301,7 @@ function admin_shifts()
|
||||||
$shifts[] = [
|
$shifts[] = [
|
||||||
'start' => $interval_start,
|
'start' => $interval_start,
|
||||||
'end' => $interval_end,
|
'end' => $interval_end,
|
||||||
'room_id' => $rid,
|
'location_id' => $lid,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'shift_type_id' => $shifttype_id,
|
'shift_type_id' => $shifttype_id,
|
||||||
'description' => $description,
|
'description' => $description,
|
||||||
|
@ -300,17 +318,24 @@ function admin_shifts()
|
||||||
|
|
||||||
$shifts_table = [];
|
$shifts_table = [];
|
||||||
foreach ($shifts as $shift) {
|
foreach ($shifts as $shift) {
|
||||||
|
/** @var Carbon $start */
|
||||||
|
$start = $shift['start'];
|
||||||
|
/** @var Carbon $end */
|
||||||
|
$end = $shift['end'];
|
||||||
$shifts_table_entry = [
|
$shifts_table_entry = [
|
||||||
'timeslot' =>
|
'timeslot' =>
|
||||||
icon('clock-history') . ' '
|
icon('clock-history') . ' '
|
||||||
. $shift['start']->format(__('Y-m-d H:i'))
|
. $start->format(__('general.datetime'))
|
||||||
. ' - '
|
. ' - '
|
||||||
. $shift['end']->format(__('H:i'))
|
. '<span title="' . $end->format(__('general.date')) . '">'
|
||||||
. '<br />'
|
. $end->format(__('H:i'))
|
||||||
. Room_name_render(Room::find($shift['room_id'])),
|
. '</span>'
|
||||||
|
. ', ' . round($end->copy()->diffInMinutes($start) / 60, 2) . 'h'
|
||||||
|
. '<br>'
|
||||||
|
. location_name_render(Location::find($shift['location_id'])),
|
||||||
'title' =>
|
'title' =>
|
||||||
ShiftType_name_render(ShiftType::find($shifttype_id))
|
htmlspecialchars(ShiftType::find($shifttype_id)->name)
|
||||||
. ($shift['title'] ? '<br />' . $shift['title'] : ''),
|
. ($shift['title'] ? '<br />' . htmlspecialchars($shift['title']) : ''),
|
||||||
'needed_angels' => '',
|
'needed_angels' => '',
|
||||||
];
|
];
|
||||||
foreach ($types as $type) {
|
foreach ($types as $type) {
|
||||||
|
@ -326,9 +351,9 @@ function admin_shifts()
|
||||||
$session->set('admin_shifts_shifts', $shifts);
|
$session->set('admin_shifts_shifts', $shifts);
|
||||||
$session->set('admin_shifts_types', $needed_angel_types);
|
$session->set('admin_shifts_types', $needed_angel_types);
|
||||||
|
|
||||||
$hidden_types = '';
|
$previousEntries = [];
|
||||||
foreach ($needed_angel_types as $type_id => $count) {
|
foreach ($needed_angel_types as $type_id => $count) {
|
||||||
$hidden_types .= form_hidden('angeltype_count_' . $type_id, $count);
|
$previousEntries['angeltype_count_' . $type_id] = $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of Shifts that will be created (if over 100 its danger-red)
|
// Number of Shifts that will be created (if over 100 its danger-red)
|
||||||
|
@ -338,28 +363,38 @@ function admin_shifts()
|
||||||
$shiftsCreationHint = '<span class="text-danger">' . $shiftsCreationHint . '</span>';
|
$shiftsCreationHint = '<span class="text-danger">' . $shiftsCreationHint . '</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_with_title(__('Preview'), [
|
// Save as previous state to be able to reuse it
|
||||||
|
$previousEntries += [
|
||||||
|
'shifttype_id' => $shifttype_id,
|
||||||
|
'description' => $description,
|
||||||
|
'title' => $title,
|
||||||
|
'lid' => $lid,
|
||||||
|
'start' => $request->input('start'),
|
||||||
|
'end' => $request->input('end'),
|
||||||
|
'mode' => $mode,
|
||||||
|
'length' => $length,
|
||||||
|
'change_hours' => implode(', ', $change_hours),
|
||||||
|
'angelmode' => $angelmode,
|
||||||
|
'shift_over_midnight' => $shift_over_midnight ? 'true' : 'false',
|
||||||
|
];
|
||||||
|
$session->set('admin_shifts_previous', $previousEntries);
|
||||||
|
|
||||||
|
$hidden_types = '';
|
||||||
|
foreach ($previousEntries as $name => $value) {
|
||||||
|
$hidden_types .= form_hidden($name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return page_with_title(__('form.preview'), [
|
||||||
form([
|
form([
|
||||||
$hidden_types,
|
$hidden_types,
|
||||||
form_hidden('shifttype_id', $shifttype_id),
|
form_submit('back', icon('chevron-left') . __('general.back')),
|
||||||
form_hidden('description', $description),
|
|
||||||
form_hidden('title', $title),
|
|
||||||
form_hidden('rid', $rid),
|
|
||||||
form_hidden('start', $start->format('Y-m-d H:i')),
|
|
||||||
form_hidden('end', $end->format('Y-m-d H:i')),
|
|
||||||
form_hidden('mode', $mode),
|
|
||||||
form_hidden('length', $length),
|
|
||||||
form_hidden('change_hours', implode(', ', $change_hours)),
|
|
||||||
form_hidden('angelmode', $angelmode),
|
|
||||||
form_hidden('shift_over_midnight', $shift_over_midnight ? 'true' : 'false'),
|
|
||||||
form_submit('back', icon('chevron-left') . __('back')),
|
|
||||||
$shiftsCreationHint,
|
$shiftsCreationHint,
|
||||||
table([
|
table([
|
||||||
'timeslot' => __('Time and location'),
|
'timeslot' => __('Time and location'),
|
||||||
'title' => __('Type and title'),
|
'title' => __('Type and title'),
|
||||||
'needed_angels' => __('Needed angels'),
|
'needed_angels' => __('Needed angels'),
|
||||||
], $shifts_table),
|
], $shifts_table),
|
||||||
form_submit('submit', icon('save') . __('Save')),
|
form_submit('submit', icon('save') . __('form.save')),
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -368,7 +403,7 @@ function admin_shifts()
|
||||||
!is_array($session->get('admin_shifts_shifts'))
|
!is_array($session->get('admin_shifts_shifts'))
|
||||||
|| !is_array($session->get('admin_shifts_types'))
|
|| !is_array($session->get('admin_shifts_types'))
|
||||||
) {
|
) {
|
||||||
throw_redirect(page_link_to('admin_shifts'));
|
throw_redirect(url('/admin-shifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$transactionId = Str::uuid();
|
$transactionId = Str::uuid();
|
||||||
|
@ -405,22 +440,22 @@ function admin_shifts()
|
||||||
}
|
}
|
||||||
|
|
||||||
success('Shifts created.');
|
success('Shifts created.');
|
||||||
throw_redirect(page_link_to('admin_shifts'));
|
throw_redirect(url('/admin-shifts'));
|
||||||
} else {
|
} else {
|
||||||
$session->remove('admin_shifts_shifts');
|
$session->remove('admin_shifts_shifts');
|
||||||
$session->remove('admin_shifts_types');
|
$session->remove('admin_shifts_types');
|
||||||
}
|
}
|
||||||
|
|
||||||
$rid = null;
|
$lid = null;
|
||||||
if ($request->has('rid')) {
|
if ($request->has('lid')) {
|
||||||
$rid = $request->input('rid');
|
$lid = $request->input('lid');
|
||||||
}
|
}
|
||||||
$angel_types = '';
|
$angel_types = '';
|
||||||
foreach ($types as $type) {
|
foreach ($types as $type) {
|
||||||
$angel_types .= '<div class="col-sm-6 col-md-8 col-lg-6 col-xl-4 col-xxl-3">'
|
$angel_types .= '<div class="col-sm-6 col-md-8 col-lg-6 col-xl-4 col-xxl-3">'
|
||||||
. form_spinner(
|
. form_spinner(
|
||||||
'angeltype_count_' . $type->id,
|
'angeltype_count_' . $type->id,
|
||||||
$type->name,
|
htmlspecialchars($type->name),
|
||||||
$needed_angel_types[$type->id],
|
$needed_angel_types[$type->id],
|
||||||
[
|
[
|
||||||
'radio-name' => 'angelmode',
|
'radio-name' => 'angelmode',
|
||||||
|
@ -430,20 +465,36 @@ function admin_shifts()
|
||||||
. '</div>';
|
. '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$link = button(url('/user-shifts'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
|
||||||
|
$reset = '';
|
||||||
|
if ($session->has('admin_shifts_previous')) {
|
||||||
|
$reset = form_submit(
|
||||||
|
'back',
|
||||||
|
icon('arrow-counterclockwise'),
|
||||||
|
'',
|
||||||
|
false,
|
||||||
|
'link',
|
||||||
|
__('Reset to previous state')
|
||||||
|
);
|
||||||
|
foreach ($session->get('admin_shifts_previous', []) as $name => $value) {
|
||||||
|
$reset .= form_hidden($name, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return page_with_title(
|
return page_with_title(
|
||||||
admin_shifts_title() . ' ' . sprintf(
|
$link . ' ' . admin_shifts_title() . ' ' . sprintf(
|
||||||
'<a href="%s">%s</a>',
|
'<a href="%s">%s</a>',
|
||||||
page_link_to('admin_shifts_history'),
|
url('/admin/shifts/history'),
|
||||||
icon('clock-history')
|
icon('clock-history')
|
||||||
),
|
) . form([$reset], '', 'display:inline'),
|
||||||
[
|
[
|
||||||
msg(),
|
msg(),
|
||||||
form([
|
form([
|
||||||
div('row', [
|
div('row', [
|
||||||
div('col-md-6 col-xl-5', [
|
div('col-md-6 col-xl-5', [
|
||||||
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
|
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
|
||||||
form_text('title', __('Title'), $title),
|
form_text('title', __('title.title'), $title),
|
||||||
form_select('rid', __('Room'), $room_array, $rid),
|
form_select('lid', __('Location'), $location_array, $lid),
|
||||||
]),
|
]),
|
||||||
div('col-md-6 col-xl-7', [
|
div('col-md-6 col-xl-7', [
|
||||||
form_textarea('description', __('Additional description'), $description),
|
form_textarea('description', __('Additional description'), $description),
|
||||||
|
@ -454,10 +505,22 @@ function admin_shifts()
|
||||||
div('col-md-6 col-xl-5', [
|
div('col-md-6 col-xl-5', [
|
||||||
div('row', [
|
div('row', [
|
||||||
div('col-lg-6', [
|
div('col-lg-6', [
|
||||||
form_datetime('start', __('Start'), $start),
|
form_datetime(
|
||||||
|
'start',
|
||||||
|
__('shifts.start'),
|
||||||
|
$request->has('start')
|
||||||
|
? Carbon::createFromDatetime($request->input('start'))
|
||||||
|
: $start
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
div('col-lg-6', [
|
div('col-lg-6', [
|
||||||
form_datetime('end', __('End'), $end),
|
form_datetime(
|
||||||
|
'end',
|
||||||
|
__('shifts.end'),
|
||||||
|
$request->has('end')
|
||||||
|
? Carbon::createFromDatetime($request->input('end'))
|
||||||
|
: $end
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
form_info(__('Mode')),
|
form_info(__('Mode')),
|
||||||
|
@ -488,7 +551,7 @@ function admin_shifts()
|
||||||
'change_hours',
|
'change_hours',
|
||||||
__('Shift change hours'),
|
__('Shift change hours'),
|
||||||
$request->has('change_hours')
|
$request->has('change_hours')
|
||||||
? $request->input('change_hours')
|
? ($change_hours ? implode(', ', $change_hours) : $request->input('change_hours'))
|
||||||
: '00, 04, 08, 10, 12, 14, 16, 18, 20, 22',
|
: '00, 04, 08, 10, 12, 14, 16, 18, 20, 22',
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
|
@ -509,7 +572,13 @@ function admin_shifts()
|
||||||
form_info(__('Needed angels')),
|
form_info(__('Needed angels')),
|
||||||
form_radio(
|
form_radio(
|
||||||
'angelmode',
|
'angelmode',
|
||||||
__('Take needed angels from room settings'),
|
__('Copy needed angels from shift type settings'),
|
||||||
|
$angelmode == 'shift_type',
|
||||||
|
'shift_type'
|
||||||
|
),
|
||||||
|
form_radio(
|
||||||
|
'angelmode',
|
||||||
|
__('Copy needed angels from location settings'),
|
||||||
$angelmode == 'location',
|
$angelmode == 'location',
|
||||||
'location'
|
'location'
|
||||||
),
|
),
|
||||||
|
@ -524,104 +593,8 @@ function admin_shifts()
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
form_submit('preview', icon('search') . __('Preview')),
|
form_submit('preview', icon('eye') . __('form.preview'), 'btn-info'),
|
||||||
]),
|
]),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function admin_shifts_history_title(): string
|
|
||||||
{
|
|
||||||
return __('Shifts history');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display shifts transaction history
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function admin_shifts_history(): string
|
|
||||||
{
|
|
||||||
if (!auth()->can('admin_shifts')) {
|
|
||||||
throw new HttpForbidden();
|
|
||||||
}
|
|
||||||
|
|
||||||
$request = request();
|
|
||||||
$transactionId = $request->postData('transaction_id');
|
|
||||||
if ($request->hasPostData('delete') && $transactionId) {
|
|
||||||
$shifts = Shift::whereTransactionId($transactionId)->get();
|
|
||||||
|
|
||||||
engelsystem_log('Deleting ' . count($shifts) . ' shifts (transaction id ' . $transactionId . ')');
|
|
||||||
|
|
||||||
foreach ($shifts as $shift) {
|
|
||||||
$shift = Shift($shift);
|
|
||||||
foreach ($shift->shiftEntries as $entry) {
|
|
||||||
event('shift.entry.deleting', [
|
|
||||||
'user' => $entry->user,
|
|
||||||
'start' => $shift->start,
|
|
||||||
'end' => $shift->end,
|
|
||||||
'name' => $shift->shiftType->name,
|
|
||||||
'title' => $shift->title,
|
|
||||||
'type' => $entry->angelType->name,
|
|
||||||
'room' => $shift->room,
|
|
||||||
'freeloaded' => $entry->freeloaded,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$shift->delete();
|
|
||||||
|
|
||||||
engelsystem_log(
|
|
||||||
'Deleted shift ' . $shift->title . ' / ' . $shift->shiftType->name
|
|
||||||
. ' from ' . $shift->start->format('Y-m-d H:i')
|
|
||||||
. ' to ' . $shift->end->format('Y-m-d H:i')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
success(sprintf(__('%s shifts deleted.'), count($shifts)));
|
|
||||||
throw_redirect(page_link_to('admin_shifts_history'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$schedules = Schedule::all()->pluck('name', 'id')->toArray();
|
|
||||||
$shiftsData = Db::select('
|
|
||||||
SELECT
|
|
||||||
s.transaction_id,
|
|
||||||
s.title,
|
|
||||||
schedule_shift.schedule_id,
|
|
||||||
COUNT(s.id) AS count,
|
|
||||||
MIN(s.start) AS start,
|
|
||||||
MAX(s.end) AS end,
|
|
||||||
s.created_by AS user_id,
|
|
||||||
MAX(s.created_at) AS created_at
|
|
||||||
FROM shifts AS s
|
|
||||||
LEFT JOIN schedule_shift on schedule_shift.shift_id = s.id
|
|
||||||
WHERE s.transaction_id IS NOT NULL
|
|
||||||
GROUP BY s.transaction_id
|
|
||||||
ORDER BY created_at DESC
|
|
||||||
');
|
|
||||||
|
|
||||||
foreach ($shiftsData as &$shiftData) {
|
|
||||||
$shiftData['title'] = $shiftData['schedule_id'] ? __('shifts_history.schedule', [$schedules[$shiftData['schedule_id']]]) : $shiftData['title'];
|
|
||||||
$shiftData['user'] = User_Nick_render(User::find($shiftData['user_id']));
|
|
||||||
$shiftData['start'] = Carbon::make($shiftData['start'])->format(__('Y-m-d H:i'));
|
|
||||||
$shiftData['end'] = Carbon::make($shiftData['end'])->format(__('Y-m-d H:i'));
|
|
||||||
$shiftData['created_at'] = Carbon::make($shiftData['created_at'])->format(__('Y-m-d H:i'));
|
|
||||||
$shiftData['actions'] = form([
|
|
||||||
form_hidden('transaction_id', $shiftData['transaction_id']),
|
|
||||||
form_submit('delete', icon('trash') . __('delete all'), 'btn-sm', true, 'danger'),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return page_with_title(admin_shifts_history_title(), [
|
|
||||||
msg(),
|
|
||||||
table([
|
|
||||||
'transaction_id' => __('ID'),
|
|
||||||
'title' => __('Title'),
|
|
||||||
'count' => __('Count'),
|
|
||||||
'start' => __('Start'),
|
|
||||||
'end' => __('End'),
|
|
||||||
'user' => __('User'),
|
|
||||||
'created_at' => __('Created'),
|
|
||||||
'actions' => '',
|
|
||||||
], $shiftsData),
|
|
||||||
], true);
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,6 +27,9 @@ function admin_user()
|
||||||
$goodie = GoodieType::from(config('goodie_type'));
|
$goodie = GoodieType::from(config('goodie_type'));
|
||||||
$goodie_enabled = $goodie !== GoodieType::None;
|
$goodie_enabled = $goodie !== GoodieType::None;
|
||||||
$goodie_tshirt = $goodie === GoodieType::Tshirt;
|
$goodie_tshirt = $goodie === GoodieType::Tshirt;
|
||||||
|
$user_info_edit = auth()->can('user.info.edit');
|
||||||
|
$user_edit_shirt = auth()->can('user.edit.shirt');
|
||||||
|
$user_edit = auth()->can('user.edit');
|
||||||
|
|
||||||
if (!$request->has('id')) {
|
if (!$request->has('id')) {
|
||||||
throw_redirect(users_link());
|
throw_redirect(users_link());
|
||||||
|
@ -41,38 +44,51 @@ function admin_user()
|
||||||
}
|
}
|
||||||
|
|
||||||
$html .= __('Here you can change the user entry. Under the item \'Arrived\' the angel is marked as present, a yes at Active means that the angel was active.');
|
$html .= __('Here you can change the user entry. Under the item \'Arrived\' the angel is marked as present, a yes at Active means that the angel was active.');
|
||||||
if ($goodie_enabled) {
|
if ($goodie_enabled && $user_edit_shirt) {
|
||||||
if ($goodie_tshirt) {
|
if ($goodie_tshirt) {
|
||||||
$html .= ' ' . __('If the angel is active, it can claim a T-shirt. If T-shirt is set to \'Yes\', the angel already got their T-shirt.');
|
$html .= ' ' . __('If the angel is active, it can claim a T-shirt. If T-shirt is set to \'Yes\', the angel already got their T-shirt.');
|
||||||
} else {
|
} else {
|
||||||
$html .= ' ' . __('If the angel is active, it can claim a goodie. If goodie is set to \'Yes\', the angel already got their goodie.');
|
$html .= ' ' . __('If the angel is active, it can claim a goodie. If goodie is set to \'Yes\', the angel already got their goodie.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$html .= '<br /><br />';
|
$html .= '<br><br>';
|
||||||
$html .= '<form action="'
|
$html .= '<form action="'
|
||||||
. page_link_to('admin_user', ['action' => 'save', 'id' => $user_id])
|
. url('/admin-user', ['action' => 'save', 'id' => $user_id])
|
||||||
. '" method="post">' . "\n";
|
. '" method="post">' . "\n";
|
||||||
$html .= form_csrf();
|
$html .= form_csrf();
|
||||||
$html .= '<table>' . "\n";
|
$html .= '<table>' . "\n";
|
||||||
$html .= '<input type="hidden" name="Type" value="Normal">' . "\n";
|
$html .= '<input type="hidden" name="Type" value="Normal">' . "\n";
|
||||||
$html .= '<tr><td>' . "\n";
|
$html .= '<tr><td>' . "\n";
|
||||||
$html .= '<table>' . "\n";
|
$html .= '<table>' . "\n";
|
||||||
$html .= ' <tr><td>' . __('Nickname') . '</td><td>' . '<input size="40" name="eNick" value="' . $user_source->name . '" class="form-control" maxlength="24"></td></tr>' . "\n";
|
$html .= ' <tr><td>' . __('general.nick') . '</td><td>'
|
||||||
|
. '<input size="40" name="eNick" value="' . htmlspecialchars($user_source->name)
|
||||||
|
. '" class="form-control" maxlength="24" ' . ($user_edit ? '' : 'disabled') . '>'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
$html .= ' <tr><td>' . __('Last login') . '</td><td><p class="help-block">'
|
$html .= ' <tr><td>' . __('Last login') . '</td><td><p class="help-block">'
|
||||||
. ($user_source->last_login_at ? $user_source->last_login_at->format(__('Y-m-d H:i')) : '-')
|
. ($user_source->last_login_at ? $user_source->last_login_at->format(__('general.datetime')) : '-')
|
||||||
. '</p></td></tr>' . "\n";
|
. '</p></td></tr>' . "\n";
|
||||||
if (config('enable_user_name')) {
|
if (config('enable_user_name')) {
|
||||||
$html .= ' <tr><td>' . __('Prename') . '</td><td>' . '<input size="40" name="eName" value="' . $user_source->personalData->last_name . '" class="form-control" maxlength="64"></td></tr>' . "\n";
|
$html .= ' <tr><td>' . __('settings.profile.firstname') . '</td><td>'
|
||||||
$html .= ' <tr><td>' . __('Last name') . '</td><td>' . '<input size="40" name="eVorname" value="' . $user_source->personalData->first_name . '" class="form-control" maxlength="64"></td></tr>' . "\n";
|
. '<input size="40" name="eName" value="' . htmlspecialchars((string) $user_source->personalData->last_name) . '" class="form-control" maxlength="64">'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
|
$html .= ' <tr><td>' . __('settings.profile.lastname') . '</td><td>'
|
||||||
|
. '<input size="40" name="eVorname" value="' . htmlspecialchars((string) $user_source->personalData->first_name) . '" class="form-control" maxlength="64">'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
}
|
}
|
||||||
$html .= ' <tr><td>' . __('Mobile') . '</td><td>' . '<input type= "tel" size="40" name="eHandy" value="' . $user_source->contact->mobile . '" class="form-control" maxlength="40"></td></tr>' . "\n";
|
$html .= ' <tr><td>' . __('settings.profile.mobile') . '</td><td>'
|
||||||
|
. '<input type= "tel" size="40" name="eHandy" value="' . htmlspecialchars((string) $user_source->contact->mobile) . '" class="form-control" maxlength="40">'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
if (config('enable_dect')) {
|
if (config('enable_dect')) {
|
||||||
$html .= ' <tr><td>' . __('DECT') . '</td><td>' . '<input size="40" name="eDECT" value="' . $user_source->contact->dect . '" class="form-control" maxlength="40"></td></tr>' . "\n";
|
$html .= ' <tr><td>' . __('general.dect') . '</td><td>'
|
||||||
|
. '<input size="40" name="eDECT" value="' . htmlspecialchars((string) $user_source->contact->dect) . '" class="form-control" maxlength="40">'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
}
|
}
|
||||||
if ($user_source->settings->email_human) {
|
if ($user_source->settings->email_human) {
|
||||||
$html .= ' <tr><td>' . __('settings.profile.email') . '</td><td>' . '<input type="email" size="40" name="eemail" value="' . $user_source->email . '" class="form-control" maxlength="254"></td></tr>' . "\n";
|
$html .= ' <tr><td>' . __('general.email') . '</td><td>'
|
||||||
|
. '<input type="email" size="40" name="eemail" value="' . htmlspecialchars($user_source->email) . '" class="form-control" maxlength="254">'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
}
|
}
|
||||||
if ($goodie_tshirt) {
|
if ($goodie_tshirt && $user_edit_shirt) {
|
||||||
$html .= ' <tr><td>' . __('user.shirt_size') . '</td><td>'
|
$html .= ' <tr><td>' . __('user.shirt_size') . '</td><td>'
|
||||||
. html_select_key(
|
. html_select_key(
|
||||||
'size',
|
'size',
|
||||||
|
@ -84,34 +100,50 @@ function admin_user()
|
||||||
. '</td></tr>' . "\n";
|
. '</td></tr>' . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User info
|
||||||
|
if ($user_info_edit) {
|
||||||
|
$html .= ' <tr><td>'
|
||||||
|
. __('user.info')
|
||||||
|
. ' <span class="bi bi-info-circle-fill text-info" data-bs-toggle="tooltip" title="'
|
||||||
|
. __('user.info.hint')
|
||||||
|
. '"></span>'
|
||||||
|
. '</td><td>'
|
||||||
|
. '<textarea cols="40" rows="" name="userInfo" class="form-control">'
|
||||||
|
. htmlspecialchars((string) $user_source->state->user_info)
|
||||||
|
. '</textarea>'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
$options = [
|
$options = [
|
||||||
'1' => __('Yes'),
|
'1' => __('Yes'),
|
||||||
'0' => __('No'),
|
'0' => __('No'),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Gekommen?
|
// Arrived?
|
||||||
$html .= ' <tr><td>' . __('Arrived') . '</td><td>' . "\n";
|
$html .= ' <tr><td>' . __('user.arrived') . '</td><td>' . "\n";
|
||||||
if ($user_source->state->arrived) {
|
$html .= ($user_source->state->arrived ? __('Yes') : __('No'));
|
||||||
$html .= __('Yes');
|
|
||||||
} else {
|
|
||||||
$html .= __('No');
|
|
||||||
}
|
|
||||||
$html .= '</td></tr>' . "\n";
|
$html .= '</td></tr>' . "\n";
|
||||||
|
|
||||||
// Aktiv?
|
// Active?
|
||||||
$html .= ' <tr><td>' . __('user.active') . '</td><td>' . "\n";
|
if ($user_edit_shirt) {
|
||||||
$html .= html_options('eAktiv', $options, $user_source->state->active) . '</td></tr>' . "\n";
|
$html .= ' <tr><td>' . __('user.active') . '</td><td>' . "\n";
|
||||||
|
$html .= html_options('eAktiv', $options, $user_source->state->active) . '</td></tr>' . "\n";
|
||||||
|
} else {
|
||||||
|
$html .= ' <tr><td>' . __('user.active') . '</td><td>' . "\n";
|
||||||
|
$html .= ($user_source->state->active ? __('Yes') : __('No'));
|
||||||
|
$html .= '</td></tr>' . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
// Aktiv erzwingen
|
// Forced active?
|
||||||
if (auth()->can('admin_active')) {
|
if (auth()->can('admin_active')) {
|
||||||
$html .= ' <tr><td>' . __('Force active') . '</td><td>' . "\n";
|
$html .= ' <tr><td>' . __('Force active') . '</td><td>' . "\n";
|
||||||
$html .= html_options('force_active', $options, $user_source->state->force_active) . '</td></tr>' . "\n";
|
$html .= html_options('force_active', $options, $user_source->state->force_active) . '</td></tr>' . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($goodie_enabled) {
|
if ($goodie_enabled && $user_edit_shirt) {
|
||||||
// T-Shirt bekommen?
|
// T-Shirt bekommen?
|
||||||
if ($goodie_tshirt) {
|
if ($goodie_tshirt) {
|
||||||
$html .= ' <tr><td>' . __('T-Shirt') . '</td><td>' . "\n";
|
$html .= ' <tr><td>' . __('T-shirt') . '</td><td>' . "\n";
|
||||||
} else {
|
} else {
|
||||||
$html .= ' <tr><td>' . __('Goodie') . '</td><td>' . "\n";
|
$html .= ' <tr><td>' . __('Goodie') . '</td><td>' . "\n";
|
||||||
}
|
}
|
||||||
|
@ -120,27 +152,36 @@ function admin_user()
|
||||||
$html .= '</table>' . "\n" . '</td><td></td></tr>';
|
$html .= '</table>' . "\n" . '</td><td></td></tr>';
|
||||||
|
|
||||||
$html .= '</td></tr>' . "\n";
|
$html .= '</td></tr>' . "\n";
|
||||||
$html .= '</table>' . "\n" . '<br />' . "\n";
|
$html .= '</table>' . "\n" . '<br>' . "\n";
|
||||||
$html .= '<button type="submit" class="btn btn-primary">' . __('form.save') . '</button>' . "\n";
|
$html .= '<button type="submit" class="btn btn-primary">'
|
||||||
|
. icon('save') . __('form.save') . '</button>' . "\n";
|
||||||
$html .= '</form>';
|
$html .= '</form>';
|
||||||
|
|
||||||
$html .= '<hr />';
|
$html .= '<hr>';
|
||||||
|
|
||||||
$html .= form_info('', __('Please visit the angeltypes page or the users profile to manage the users angeltypes.'));
|
$html .= __('Here you can reset the password of this angel:');
|
||||||
|
|
||||||
$html .= ' ' . __('Here you can reset the password of this angel:') . '<form action="'
|
$html .= '<form action="'
|
||||||
. page_link_to('admin_user', ['action' => 'change_pw', 'id' => $user_id])
|
. url('/admin-user', ['action' => 'change_pw', 'id' => $user_id])
|
||||||
. '" method="post">' . "\n";
|
. '" method="post">' . "\n";
|
||||||
$html .= form_csrf();
|
$html .= form_csrf();
|
||||||
$html .= '<table>' . "\n";
|
$html .= '<table>' . "\n";
|
||||||
$html .= ' <tr><td>' . __('Password') . '</td><td>' . '<input type="password" size="40" name="new_pw" value="" class="form-control" autocomplete="new-password"></td></tr>' . "\n";
|
$html .= ' <tr><td>' . __('settings.password')
|
||||||
$html .= ' <tr><td>' . __('Confirm password') . '</td><td>' . '<input type="password" size="40" name="new_pw2" value="" class="form-control" autocomplete="new-password"></td></tr>' . "\n";
|
. ' <span class="bi bi-info-circle-fill text-info" data-bs-toggle="tooltip" title="'
|
||||||
|
. __('password.minimal_length', [config('min_password_length')]) . '"></span>'
|
||||||
|
. '</td><td>'
|
||||||
|
. '<input type="password" size="40" name="new_pw" value="" class="form-control" autocomplete="new-password">'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
|
$html .= ' <tr><td>' . __('password.reset.confirm') . '</td><td>'
|
||||||
|
. '<input type="password" size="40" name="new_pw2" value="" class="form-control" autocomplete="new-password">'
|
||||||
|
. '</td></tr>' . "\n";
|
||||||
|
|
||||||
$html .= '</table>' . "\n" . '<br />' . "\n";
|
$html .= '</table>' . "\n" . '<br>' . "\n";
|
||||||
$html .= '<button type="submit" class="btn btn-primary">' . __('form.save') . '</button>' . "\n";
|
$html .= '<button type="submit" class="btn btn-primary">'
|
||||||
|
. icon('save') . __('form.save') . '</button>' . "\n";
|
||||||
$html .= '</form>';
|
$html .= '</form>';
|
||||||
|
|
||||||
$html .= '<hr />';
|
$html .= '<hr>';
|
||||||
|
|
||||||
/** @var Group $my_highest_group */
|
/** @var Group $my_highest_group */
|
||||||
$my_highest_group = $user->groups()->orderByDesc('id')->first();
|
$my_highest_group = $user->groups()->orderByDesc('id')->first();
|
||||||
|
@ -158,7 +199,7 @@ function admin_user()
|
||||||
&& ($my_highest_group >= $angel_highest_group || is_null($angel_highest_group))
|
&& ($my_highest_group >= $angel_highest_group || is_null($angel_highest_group))
|
||||||
) {
|
) {
|
||||||
$html .= __('Here you can define the user groups of the angel:') . '<form action="'
|
$html .= __('Here you can define the user groups of the angel:') . '<form action="'
|
||||||
. page_link_to('admin_user', ['action' => 'save_groups', 'id' => $user_id])
|
. url('/admin-user', ['action' => 'save_groups', 'id' => $user_id])
|
||||||
. '" method="post">' . "\n";
|
. '" method="post">' . "\n";
|
||||||
$html .= form_csrf();
|
$html .= form_csrf();
|
||||||
$html .= '<div>';
|
$html .= '<div>';
|
||||||
|
@ -168,19 +209,22 @@ function admin_user()
|
||||||
$html .= '<div class="form-check">'
|
$html .= '<div class="form-check">'
|
||||||
. '<input class="form-check-input" type="checkbox" id="' . $group->id . '" name="groups[]" value="' . $group->id . '" '
|
. '<input class="form-check-input" type="checkbox" id="' . $group->id . '" name="groups[]" value="' . $group->id . '" '
|
||||||
. ($group->selected ? ' checked="checked"' : '')
|
. ($group->selected ? ' checked="checked"' : '')
|
||||||
. ' /><label class="form-check-label" for="' . $group->id . '">' . $group->name . '</label></div>';
|
. ' /><label class="form-check-label" for="' . $group->id . '">'
|
||||||
|
. htmlspecialchars($group->name)
|
||||||
|
. '</label></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$html .= '</div><br>';
|
$html .= '</div><br>';
|
||||||
|
|
||||||
$html .= '<button type="submit" class="btn btn-primary">' . __('form.save') . '</button>' . "\n";
|
$html .= '<button type="submit" class="btn btn-primary">'
|
||||||
|
. icon('save') . __('form.save') . '</button>' . "\n";
|
||||||
$html .= '</form>';
|
$html .= '</form>';
|
||||||
|
|
||||||
$html .= '<hr />';
|
$html .= '<hr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$html .= buttons([
|
$html .= buttons([
|
||||||
button(user_delete_link($user_source->id), icon('trash') . __('delete'), 'btn-danger'),
|
button(user_delete_link($user_source->id), icon('trash') . __('form.delete'), 'btn-danger'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$html .= '<hr>';
|
$html .= '<hr>';
|
||||||
|
@ -237,19 +281,21 @@ function admin_user()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'save':
|
case 'save':
|
||||||
$force_active = $user->state->force_active;
|
|
||||||
$user_source = User::find($user_id);
|
$user_source = User::find($user_id);
|
||||||
if (auth()->can('admin_active')) {
|
|
||||||
$force_active = $request->input('force_active');
|
$changed_email = false;
|
||||||
}
|
|
||||||
if ($user_source->settings->email_human) {
|
if ($user_source->settings->email_human) {
|
||||||
|
$changed_email = $user_source->email !== $request->postData('eemail');
|
||||||
$user_source->email = $request->postData('eemail');
|
$user_source->email = $request->postData('eemail');
|
||||||
}
|
}
|
||||||
|
|
||||||
$nick = trim($request->get('eNick'));
|
$nick = trim($request->get('eNick'));
|
||||||
$nickValid = (new Username())->validate($nick);
|
$nickValid = (new Username())->validate($nick);
|
||||||
|
|
||||||
if ($nickValid) {
|
$changed_nick = false;
|
||||||
|
$old_nick = $user_source->name;
|
||||||
|
if ($nickValid && $user_edit) {
|
||||||
|
$changed_nick = $user_source->name !== $nick;
|
||||||
$user_source->name = $nick;
|
$user_source->name = $nick;
|
||||||
}
|
}
|
||||||
$user_source->save();
|
$user_source->save();
|
||||||
|
@ -258,30 +304,45 @@ function admin_user()
|
||||||
$user_source->personalData->first_name = $request->postData('eVorname');
|
$user_source->personalData->first_name = $request->postData('eVorname');
|
||||||
$user_source->personalData->last_name = $request->postData('eName');
|
$user_source->personalData->last_name = $request->postData('eName');
|
||||||
}
|
}
|
||||||
if ($goodie_tshirt) {
|
if ($goodie_tshirt && $user_edit_shirt) {
|
||||||
$user_source->personalData->shirt_size = $request->postData('eSize');
|
$user_source->personalData->shirt_size = $request->postData('eSize');
|
||||||
}
|
}
|
||||||
$user_source->personalData->save();
|
$user_source->personalData->save();
|
||||||
|
|
||||||
$user_source->contact->mobile = $request->postData('eHandy');
|
$user_source->contact->mobile = $request->postData('eHandy');
|
||||||
$user_source->contact->dect = $request->postData('eDECT');
|
if (config('enable_dect')) {
|
||||||
|
$user_source->contact->dect = $request->postData('eDECT');
|
||||||
|
}
|
||||||
$user_source->contact->save();
|
$user_source->contact->save();
|
||||||
|
|
||||||
if ($goodie_enabled) {
|
if ($goodie_enabled && $user_edit_shirt) {
|
||||||
$user_source->state->got_shirt = $request->postData('eTshirt');
|
$user_source->state->got_shirt = $request->postData('eTshirt');
|
||||||
}
|
}
|
||||||
$user_source->state->active = $request->postData('eAktiv');
|
if ($user_info_edit) {
|
||||||
$user_source->state->force_active = $force_active;
|
$user_source->state->user_info = $request->postData('userInfo');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user_edit_shirt) {
|
||||||
|
$user_source->state->active = $request->postData('eAktiv');
|
||||||
|
}
|
||||||
|
if (auth()->can('admin_active')) {
|
||||||
|
$user_source->state->force_active = $request->input('force_active');
|
||||||
|
}
|
||||||
$user_source->state->save();
|
$user_source->state->save();
|
||||||
|
|
||||||
engelsystem_log(
|
engelsystem_log(
|
||||||
'Updated user: ' . $user_source->name . ' (' . $user_source->id . ')'
|
'Updated user: ' . ($changed_nick
|
||||||
. ($goodie_tshirt ? ', t-shirt: ' : '' . $user_source->personalData->shirt_size)
|
? ('nick modified form ' . $old_nick . ' to ' . $user_source->name)
|
||||||
|
: $user_source->name)
|
||||||
|
. ' (' . $user_source->id . ')'
|
||||||
|
. ($changed_email ? ', email modified' : '')
|
||||||
|
. ($goodie_tshirt ? ', t-shirt-size: ' . $user_source->personalData->shirt_size : '')
|
||||||
. ', active: ' . $user_source->state->active
|
. ', active: ' . $user_source->state->active
|
||||||
. ', force-active: ' . $user_source->state->force_active
|
. ', force-active: ' . $user_source->state->force_active
|
||||||
. ($goodie_tshirt ? ', tshirt: ' : ', goodie: ' . $user_source->state->got_shirt)
|
. ($goodie_tshirt ? ', t-shirt: ' : ', goodie: ' . $user_source->state->got_shirt)
|
||||||
|
. ($user_info_edit ? ', user-info: ' . $user_source->state->user_info : '')
|
||||||
);
|
);
|
||||||
$html .= success(__('Changes where saved.') . "\n", true);
|
$html .= success(__('Changes were saved.') . "\n", true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'change_pw':
|
case 'change_pw':
|
||||||
|
@ -303,9 +364,13 @@ function admin_user()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_with_title(__('Edit user'), [
|
$link = button(url('/users', ['action' => 'view', 'user_id' => $user_id]), icon('chevron-left'), 'btn-sm', '', __('general.back'));
|
||||||
|
return page_with_title(
|
||||||
|
$link . ' ' . __('Edit user'),
|
||||||
|
[
|
||||||
$html,
|
$html,
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,543 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Engelsystem\Database\Database;
|
|
||||||
use Engelsystem\Events\Listener\OAuth2;
|
|
||||||
use Engelsystem\Config\GoodieType;
|
|
||||||
use Engelsystem\Http\Validation\Rules\Username;
|
|
||||||
use Engelsystem\Models\AngelType;
|
|
||||||
use Engelsystem\Models\Group;
|
|
||||||
use Engelsystem\Models\OAuth;
|
|
||||||
use Engelsystem\Models\User\Contact;
|
|
||||||
use Engelsystem\Models\User\PersonalData;
|
|
||||||
use Engelsystem\Models\User\Settings;
|
|
||||||
use Engelsystem\Models\User\State;
|
|
||||||
use Engelsystem\Models\User\User;
|
|
||||||
use Illuminate\Database\Connection;
|
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function register_title()
|
|
||||||
{
|
|
||||||
return __('Register');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Engel registrieren
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function guest_register()
|
|
||||||
{
|
|
||||||
$authUser = auth()->user();
|
|
||||||
$tshirt_sizes = config('tshirt_sizes');
|
|
||||||
$goodie = GoodieType::from(config('goodie_type'));
|
|
||||||
$goodie_enabled = $goodie !== GoodieType::None;
|
|
||||||
$goodie_tshirt = $goodie === GoodieType::Tshirt;
|
|
||||||
$enable_user_name = config('enable_user_name');
|
|
||||||
$enable_dect = config('enable_dect');
|
|
||||||
$enable_planned_arrival = config('enable_planned_arrival');
|
|
||||||
$min_password_length = config('min_password_length');
|
|
||||||
$enable_password = config('enable_password');
|
|
||||||
$enable_pronoun = config('enable_pronoun');
|
|
||||||
$enable_mobile_show = config('enable_mobile_show');
|
|
||||||
$config = config();
|
|
||||||
$request = request();
|
|
||||||
$session = session();
|
|
||||||
/** @var Connection $db */
|
|
||||||
$db = app(Database::class)->getConnection();
|
|
||||||
$is_oauth = $session->has('oauth2_connect_provider');
|
|
||||||
|
|
||||||
$msg = '';
|
|
||||||
$nick = '';
|
|
||||||
$lastName = '';
|
|
||||||
$preName = '';
|
|
||||||
$dect = '';
|
|
||||||
$mobile = '';
|
|
||||||
$mobile_show = false;
|
|
||||||
$email = '';
|
|
||||||
$pronoun = '';
|
|
||||||
$email_shiftinfo = false;
|
|
||||||
$email_by_human_allowed = false;
|
|
||||||
$email_messages = false;
|
|
||||||
$email_news = false;
|
|
||||||
$email_goody = false;
|
|
||||||
$tshirt_size = '';
|
|
||||||
$password_hash = '';
|
|
||||||
$selected_angel_types = [];
|
|
||||||
$planned_arrival_date = null;
|
|
||||||
|
|
||||||
/** @var AngelType[]|Collection $angel_types_source */
|
|
||||||
$angel_types_source = AngelType::all();
|
|
||||||
$angel_types = [];
|
|
||||||
if (!empty($session->get('oauth2_groups'))) {
|
|
||||||
/** @var OAuth2 $oauth */
|
|
||||||
$oauth = app()->get(OAuth2::class);
|
|
||||||
$ssoTeams = $oauth->getSsoTeams($session->get('oauth2_connect_provider'));
|
|
||||||
foreach ($ssoTeams as $name => $team) {
|
|
||||||
if (in_array($name, $session->get('oauth2_groups'))) {
|
|
||||||
$selected_angel_types[] = $team['id'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($angel_types_source as $angel_type) {
|
|
||||||
if ($angel_type->hide_register) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$angel_types[$angel_type->id] = $angel_type->name
|
|
||||||
. ($angel_type->restricted ? ' (' . __('Requires introduction') . ')' : '');
|
|
||||||
if (!$angel_type->restricted) {
|
|
||||||
$selected_angel_types[] = $angel_type->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$oauth_enable_password = $session->get('oauth2_enable_password');
|
|
||||||
if (!is_null($oauth_enable_password)) {
|
|
||||||
$enable_password = $oauth_enable_password;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!auth()->can('register') // No registration permission
|
|
||||||
// Not authenticated and
|
|
||||||
|| (!$authUser && !config('registration_enabled') && !$session->get('oauth2_allow_registration')) // Registration disabled
|
|
||||||
|| (!$authUser && !$enable_password && !$is_oauth) // Password disabled and not oauth
|
|
||||||
) {
|
|
||||||
error(__('Registration is disabled.'));
|
|
||||||
|
|
||||||
return page_with_title(register_title(), [
|
|
||||||
msg(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->hasPostData('submit')) {
|
|
||||||
$valid = true;
|
|
||||||
|
|
||||||
if ($request->has('username')) {
|
|
||||||
$nick = trim($request->get('username'));
|
|
||||||
$nickValid = (new Username())->validate($nick);
|
|
||||||
|
|
||||||
if (!$nickValid) {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(sprintf(
|
|
||||||
__('Please enter a valid nick.') . ' ' . __('Use up to 24 letters, numbers or connecting punctuations for your nickname.'),
|
|
||||||
$nick
|
|
||||||
), true);
|
|
||||||
}
|
|
||||||
if (User::whereName($nick)->count() > 0) {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(sprintf(__('Your nick "%s" already exists.'), htmlspecialchars($nick)), true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(__('Please enter a nickname.'), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('mobile_show') && $enable_mobile_show) {
|
|
||||||
$mobile_show = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('email') && strlen(strip_request_item('email')) > 0) {
|
|
||||||
$email = strip_request_item('email');
|
|
||||||
if (!check_email($email)) {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(__('E-mail address is not correct.'), true);
|
|
||||||
}
|
|
||||||
if (User::whereEmail($email)->first()) {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(__('E-mail address is already used by another user.'), true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(__('Please enter your e-mail.'), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('email_shiftinfo')) {
|
|
||||||
$email_shiftinfo = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('email_by_human_allowed')) {
|
|
||||||
$email_by_human_allowed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('email_messages')) {
|
|
||||||
$email_messages = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('email_news')) {
|
|
||||||
$email_news = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('email_goody')) {
|
|
||||||
$email_goody = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($goodie_tshirt) {
|
|
||||||
if ($request->has('tshirt_size') && isset($tshirt_sizes[$request->input('tshirt_size')])) {
|
|
||||||
$tshirt_size = $request->input('tshirt_size');
|
|
||||||
} else {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(__('Please select your shirt size.'), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($enable_password && $request->has('password') && strlen($request->postData('password')) >= $min_password_length) {
|
|
||||||
if ($request->postData('password') != $request->postData('password2')) {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(__('Your passwords don\'t match.'), true);
|
|
||||||
}
|
|
||||||
} elseif ($enable_password) {
|
|
||||||
$valid = false;
|
|
||||||
$msg .= error(sprintf(
|
|
||||||
__('Your password is too short (please use at least %s characters).'),
|
|
||||||
$min_password_length
|
|
||||||
), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->has('planned_arrival_date') && $enable_planned_arrival) {
|
|
||||||
$tmp = parse_date('Y-m-d H:i', $request->input('planned_arrival_date') . ' 00:00');
|
|
||||||
$result = User_validate_planned_arrival_date($tmp);
|
|
||||||
$planned_arrival_date = $result->getValue();
|
|
||||||
if (!$result->isValid()) {
|
|
||||||
$valid = false;
|
|
||||||
error(__('Please enter your planned date of arrival. It should be after the buildup start date and before teardown end date.'));
|
|
||||||
}
|
|
||||||
} elseif ($enable_planned_arrival) {
|
|
||||||
$valid = false;
|
|
||||||
error(__('Please enter your planned date of arrival. It should be after the buildup start date and before teardown end date.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$selected_angel_types = [];
|
|
||||||
foreach (array_keys($angel_types) as $angel_type_id) {
|
|
||||||
if ($request->has('angel_types_' . $angel_type_id)) {
|
|
||||||
$selected_angel_types[] = $angel_type_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trivia
|
|
||||||
if ($enable_user_name && $request->has('lastname')) {
|
|
||||||
$lastName = strip_request_item('lastname');
|
|
||||||
}
|
|
||||||
if ($enable_user_name && $request->has('prename')) {
|
|
||||||
$preName = strip_request_item('prename');
|
|
||||||
}
|
|
||||||
if ($enable_pronoun && $request->has('pronoun')) {
|
|
||||||
$pronoun = strip_request_item('pronoun');
|
|
||||||
}
|
|
||||||
if ($enable_dect && $request->has('dect')) {
|
|
||||||
if (strlen(strip_request_item('dect')) <= 40) {
|
|
||||||
$dect = strip_request_item('dect');
|
|
||||||
} else {
|
|
||||||
$valid = false;
|
|
||||||
error(__('For dect numbers are only 40 digits allowed.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($request->has('mobile')) {
|
|
||||||
$mobile = strip_request_item('mobile');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($valid) {
|
|
||||||
// Safeguard against partially created user data
|
|
||||||
$db->beginTransaction();
|
|
||||||
|
|
||||||
$user = new User([
|
|
||||||
'name' => $nick,
|
|
||||||
'password' => $password_hash,
|
|
||||||
'email' => $email,
|
|
||||||
'api_key' => '',
|
|
||||||
'last_login_at' => null,
|
|
||||||
]);
|
|
||||||
$user->save();
|
|
||||||
|
|
||||||
$contact = new Contact([
|
|
||||||
'dect' => $dect,
|
|
||||||
'mobile' => $mobile,
|
|
||||||
]);
|
|
||||||
$contact->user()
|
|
||||||
->associate($user)
|
|
||||||
->save();
|
|
||||||
|
|
||||||
$personalData = new PersonalData([
|
|
||||||
'first_name' => $preName,
|
|
||||||
'last_name' => $lastName,
|
|
||||||
'pronoun' => $pronoun,
|
|
||||||
'shirt_size' => $tshirt_size,
|
|
||||||
'planned_arrival_date' => $enable_planned_arrival ? Carbon::createFromTimestamp($planned_arrival_date) : null,
|
|
||||||
]);
|
|
||||||
$personalData->user()
|
|
||||||
->associate($user)
|
|
||||||
->save();
|
|
||||||
|
|
||||||
$settings = new Settings([
|
|
||||||
'language' => $session->get('locale'),
|
|
||||||
'theme' => config('theme'),
|
|
||||||
'email_human' => $email_by_human_allowed,
|
|
||||||
'email_messages' => $email_messages,
|
|
||||||
'email_goody' => $email_goody,
|
|
||||||
'email_shiftinfo' => $email_shiftinfo,
|
|
||||||
'email_news' => $email_news,
|
|
||||||
'mobile_show' => $mobile_show,
|
|
||||||
]);
|
|
||||||
$settings->user()
|
|
||||||
->associate($user)
|
|
||||||
->save();
|
|
||||||
|
|
||||||
$state = new State([]);
|
|
||||||
if (config('autoarrive')) {
|
|
||||||
$state->arrived = true;
|
|
||||||
$state->arrival_date = new Carbon();
|
|
||||||
}
|
|
||||||
$state->user()
|
|
||||||
->associate($user)
|
|
||||||
->save();
|
|
||||||
|
|
||||||
if ($session->has('oauth2_connect_provider') && $session->has('oauth2_user_id')) {
|
|
||||||
$oauth = new OAuth([
|
|
||||||
'provider' => $session->get('oauth2_connect_provider'),
|
|
||||||
'identifier' => $session->get('oauth2_user_id'),
|
|
||||||
'access_token' => $session->get('oauth2_access_token'),
|
|
||||||
'refresh_token' => $session->get('oauth2_refresh_token'),
|
|
||||||
'expires_at' => $session->get('oauth2_expires_at'),
|
|
||||||
]);
|
|
||||||
$oauth->user()
|
|
||||||
->associate($user)
|
|
||||||
->save();
|
|
||||||
|
|
||||||
$session->remove('oauth2_connect_provider');
|
|
||||||
$session->remove('oauth2_user_id');
|
|
||||||
$session->remove('oauth2_access_token');
|
|
||||||
$session->remove('oauth2_refresh_token');
|
|
||||||
$session->remove('oauth2_expires_at');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign user-group and set password
|
|
||||||
$defaultGroup = Group::find(auth()->getDefaultRole());
|
|
||||||
$user->groups()->attach($defaultGroup);
|
|
||||||
if ($enable_password) {
|
|
||||||
auth()->setPassword($user, $request->postData('password'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign angel-types
|
|
||||||
$user_angel_types_info = [];
|
|
||||||
foreach ($selected_angel_types as $selected_angel_type_id) {
|
|
||||||
$angelType = AngelType::findOrFail($selected_angel_type_id);
|
|
||||||
$user->userAngelTypes()->attach($angelType);
|
|
||||||
$user_angel_types_info[] = $angelType->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit complete user data
|
|
||||||
$db->commit();
|
|
||||||
|
|
||||||
engelsystem_log(
|
|
||||||
'User ' . User_Nick_render($user, true)
|
|
||||||
. ' signed up as: ' . join(', ', $user_angel_types_info)
|
|
||||||
);
|
|
||||||
success(__('Angel registration successful!'));
|
|
||||||
|
|
||||||
// User is already logged in - that means a supporter has registered an angel. Return to register page.
|
|
||||||
if ($authUser) {
|
|
||||||
throw_redirect(page_link_to('register'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a welcome message is present, display it on the next page
|
|
||||||
if ($config->get('welcome_msg')) {
|
|
||||||
$session->set('show_welcome', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Login the user
|
|
||||||
if ($user->oauth->count()) {
|
|
||||||
/** @var OAuth $provider */
|
|
||||||
$provider = $user->oauth->first();
|
|
||||||
throw_redirect(url('/oauth/' . $provider->provider));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw_redirect(page_link_to('/'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$buildup_start_date = time();
|
|
||||||
$teardown_end_date = null;
|
|
||||||
if ($buildup = $config->get('buildup_start')) {
|
|
||||||
/** @var Carbon $buildup */
|
|
||||||
$buildup_start_date = $buildup->getTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($teardown = $config->get('teardown_end')) {
|
|
||||||
/** @var Carbon $teardown */
|
|
||||||
$teardown_end_date = $teardown->getTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
$form_data = $session->get('form_data');
|
|
||||||
$session->remove('form_data');
|
|
||||||
if (!$nick && !empty($form_data['name'])) {
|
|
||||||
$nick = $form_data['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$email && !empty($form_data['email'])) {
|
|
||||||
$email = $form_data['email'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$preName && !empty($form_data['first_name'])) {
|
|
||||||
$preName = $form_data['first_name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$lastName && !empty($form_data['last_name'])) {
|
|
||||||
$lastName = $form_data['last_name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return page_with_title(register_title(), [
|
|
||||||
__('By completing this form you\'re registering as a Chaos-Angel. This script will create you an account in the angel task scheduler.'),
|
|
||||||
form_info(entry_required() . ' = ' . __('Entry required!')),
|
|
||||||
$msg,
|
|
||||||
msg(),
|
|
||||||
form([
|
|
||||||
div('row', [
|
|
||||||
div('col', [
|
|
||||||
form_text(
|
|
||||||
'username',
|
|
||||||
__('Nick') . ' ' . entry_required(),
|
|
||||||
$nick,
|
|
||||||
false,
|
|
||||||
24,
|
|
||||||
'nickname'
|
|
||||||
),
|
|
||||||
form_info(
|
|
||||||
'',
|
|
||||||
__('Use up to 24 letters, numbers or connecting punctuations for your nickname.')
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
|
|
||||||
$enable_pronoun ? div('col', [
|
|
||||||
form_text('pronoun', __('Pronoun'), $pronoun, false, 15),
|
|
||||||
]) : '',
|
|
||||||
]),
|
|
||||||
|
|
||||||
$enable_user_name ? div('row', [
|
|
||||||
div('col', [
|
|
||||||
form_text('prename', __('First name'), $preName, false, 64, 'given-name'),
|
|
||||||
]),
|
|
||||||
div('col', [
|
|
||||||
form_text('lastname', __('Last name'), $lastName, false, 64, 'family-name'),
|
|
||||||
]),
|
|
||||||
]) : '',
|
|
||||||
|
|
||||||
div('row', [
|
|
||||||
div('col', [
|
|
||||||
form_email(
|
|
||||||
'email',
|
|
||||||
__('E-Mail') . ' ' . entry_required(),
|
|
||||||
$email,
|
|
||||||
false,
|
|
||||||
'email',
|
|
||||||
254
|
|
||||||
),
|
|
||||||
form_checkbox(
|
|
||||||
'email_shiftinfo',
|
|
||||||
__(
|
|
||||||
'settings.profile.email_shiftinfo',
|
|
||||||
[config('app_name')]
|
|
||||||
),
|
|
||||||
$email_shiftinfo
|
|
||||||
),
|
|
||||||
form_checkbox(
|
|
||||||
'email_news',
|
|
||||||
__('Notify me of new news'),
|
|
||||||
$email_news
|
|
||||||
),
|
|
||||||
form_checkbox(
|
|
||||||
'email_messages',
|
|
||||||
__('settings.profile.email_messages'),
|
|
||||||
$email_messages
|
|
||||||
),
|
|
||||||
form_checkbox(
|
|
||||||
'email_by_human_allowed',
|
|
||||||
__('Allow heaven angels to contact you by e-mail.'),
|
|
||||||
$email_by_human_allowed
|
|
||||||
),
|
|
||||||
$goodie_enabled ?
|
|
||||||
form_checkbox(
|
|
||||||
'email_goody',
|
|
||||||
__('To receive vouchers, give consent that nick, email address, worked hours and shirt size will be stored until the next similar event.')
|
|
||||||
. (config('privacy_email') ? ' ' . __('To withdraw your approval, send an email to <a href="mailto:%s">%1$s</a>.', [config('privacy_email')]) : ''),
|
|
||||||
$email_goody
|
|
||||||
) : '',
|
|
||||||
]),
|
|
||||||
|
|
||||||
$enable_dect ? div('col', [
|
|
||||||
form_text('dect', __('DECT'), $dect, false, 40, 'tel-local'),
|
|
||||||
]) : '',
|
|
||||||
|
|
||||||
div('col', [
|
|
||||||
form_text('mobile', __('Mobile'), $mobile, false, 40, 'tel-national'),
|
|
||||||
$enable_mobile_show ? form_checkbox(
|
|
||||||
'mobile_show',
|
|
||||||
__('Show mobile number to other users to contact me'),
|
|
||||||
$mobile_show
|
|
||||||
) : '',
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
|
|
||||||
div('row', [
|
|
||||||
$enable_password ? div('col', [
|
|
||||||
form_password('password', __('Password') . ' ' . entry_required(), 'new-password'),
|
|
||||||
]) : '',
|
|
||||||
|
|
||||||
$enable_planned_arrival ? div('col', [
|
|
||||||
form_date(
|
|
||||||
'planned_arrival_date',
|
|
||||||
__('Planned date of arrival') . ' ' . entry_required(),
|
|
||||||
$planned_arrival_date,
|
|
||||||
$buildup_start_date,
|
|
||||||
$teardown_end_date
|
|
||||||
),
|
|
||||||
]) : '',
|
|
||||||
]),
|
|
||||||
|
|
||||||
div('row', [
|
|
||||||
$enable_password ? div('col', [
|
|
||||||
form_password('password2', __('Confirm password') . ' ' . entry_required(), 'new-password'),
|
|
||||||
]) : '',
|
|
||||||
|
|
||||||
div('col', [
|
|
||||||
$goodie_tshirt ? form_select(
|
|
||||||
'tshirt_size',
|
|
||||||
__('Shirt size') . ' ' . entry_required(),
|
|
||||||
$tshirt_sizes,
|
|
||||||
$tshirt_size,
|
|
||||||
__('form.select_placeholder')
|
|
||||||
) : '',
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
|
|
||||||
div('row', [
|
|
||||||
div('col', [
|
|
||||||
form_checkboxes(
|
|
||||||
'angel_types',
|
|
||||||
__('What do you want to do?') . sprintf(
|
|
||||||
' (<a href="%s">%s</a>)',
|
|
||||||
url('/angeltypes/about'),
|
|
||||||
__('Description of job types')
|
|
||||||
),
|
|
||||||
$angel_types,
|
|
||||||
$selected_angel_types
|
|
||||||
),
|
|
||||||
form_info(
|
|
||||||
'',
|
|
||||||
__('Some angel types have to be confirmed later by a supporter at an introduction meeting. You can change your selection in the options section.')
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
]),
|
|
||||||
|
|
||||||
form_submit('submit', __('Register')),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function entry_required()
|
|
||||||
{
|
|
||||||
return icon('exclamation-triangle', 'text-info');
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ use Engelsystem\Helpers\Schedule\XmlParser;
|
||||||
use Engelsystem\Helpers\Uuid;
|
use Engelsystem\Helpers\Uuid;
|
||||||
use Engelsystem\Http\Request;
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Models\Room as RoomModel;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\Schedule as ScheduleUrl;
|
use Engelsystem\Models\Shifts\Schedule as ScheduleUrl;
|
||||||
use Engelsystem\Models\Shifts\ScheduleShift;
|
use Engelsystem\Models\Shifts\ScheduleShift;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
@ -110,10 +110,15 @@ class ImportSchedule extends BaseController
|
||||||
/** @var ScheduleUrl $schedule */
|
/** @var ScheduleUrl $schedule */
|
||||||
$schedule = ScheduleUrl::findOrNew($scheduleId);
|
$schedule = ScheduleUrl::findOrNew($scheduleId);
|
||||||
|
|
||||||
|
if ($request->request->has('delete')) {
|
||||||
|
return $this->delete($schedule);
|
||||||
|
}
|
||||||
|
|
||||||
$data = $this->validate($request, [
|
$data = $this->validate($request, [
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
'url' => 'required',
|
'url' => 'required',
|
||||||
'shift_type' => 'required|int',
|
'shift_type' => 'required|int',
|
||||||
|
'needed_from_shift_type' => 'optional|checked',
|
||||||
'minutes_before' => 'int',
|
'minutes_before' => 'int',
|
||||||
'minutes_after' => 'int',
|
'minutes_after' => 'int',
|
||||||
]);
|
]);
|
||||||
|
@ -125,17 +130,19 @@ class ImportSchedule extends BaseController
|
||||||
$schedule->name = $data['name'];
|
$schedule->name = $data['name'];
|
||||||
$schedule->url = $data['url'];
|
$schedule->url = $data['url'];
|
||||||
$schedule->shift_type = $data['shift_type'];
|
$schedule->shift_type = $data['shift_type'];
|
||||||
|
$schedule->needed_from_shift_type = (bool) $data['needed_from_shift_type'];
|
||||||
$schedule->minutes_before = $data['minutes_before'];
|
$schedule->minutes_before = $data['minutes_before'];
|
||||||
$schedule->minutes_after = $data['minutes_after'];
|
$schedule->minutes_after = $data['minutes_after'];
|
||||||
|
|
||||||
$schedule->save();
|
$schedule->save();
|
||||||
|
|
||||||
$this->log->info(
|
$this->log->info(
|
||||||
'Schedule {name}: Url {url}, Shift Type {shift_type}, minutes before/after {before}/{after}',
|
'Schedule {name}: Url {url}, Shift Type {shift_type}, ({need}), minutes before/after {before}/{after}',
|
||||||
[
|
[
|
||||||
'name' => $schedule->name,
|
'name' => $schedule->name,
|
||||||
'url' => $schedule->name,
|
'url' => $schedule->name,
|
||||||
'shift_type' => $schedule->shift_type,
|
'shift_type' => $schedule->shift_type,
|
||||||
|
'need' => $schedule->needed_from_shift_type ? 'from shift type' : 'from room',
|
||||||
'before' => $schedule->minutes_before,
|
'before' => $schedule->minutes_before,
|
||||||
'after' => $schedule->minutes_after,
|
'after' => $schedule->minutes_after,
|
||||||
]
|
]
|
||||||
|
@ -146,6 +153,33 @@ class ImportSchedule extends BaseController
|
||||||
return redirect('/admin/schedule/load/' . $schedule->id);
|
return redirect('/admin/schedule/load/' . $schedule->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function delete(ScheduleUrl $schedule): Response
|
||||||
|
{
|
||||||
|
foreach ($schedule->scheduleShifts as $scheduleShift) {
|
||||||
|
// Only guid is needed here
|
||||||
|
$event = new Event(
|
||||||
|
$scheduleShift->guid,
|
||||||
|
0,
|
||||||
|
new Room(''),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
Carbon::now(),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->deleteEvent($event, $schedule);
|
||||||
|
}
|
||||||
|
$schedule->delete();
|
||||||
|
|
||||||
|
$this->addNotification('schedule.delete.success');
|
||||||
|
return redirect('/admin/schedule');
|
||||||
|
}
|
||||||
|
|
||||||
public function loadSchedule(Request $request): Response
|
public function loadSchedule(Request $request): Response
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -179,7 +213,7 @@ class ImportSchedule extends BaseController
|
||||||
[
|
[
|
||||||
'schedule_id' => $scheduleUrl->id,
|
'schedule_id' => $scheduleUrl->id,
|
||||||
'schedule' => $schedule,
|
'schedule' => $schedule,
|
||||||
'rooms' => [
|
'locations' => [
|
||||||
'add' => $newRooms,
|
'add' => $newRooms,
|
||||||
],
|
],
|
||||||
'shifts' => [
|
'shifts' => [
|
||||||
|
@ -218,15 +252,15 @@ class ImportSchedule extends BaseController
|
||||||
$this->log('Started schedule "{name}" import', ['name' => $scheduleUrl->name]);
|
$this->log('Started schedule "{name}" import', ['name' => $scheduleUrl->name]);
|
||||||
|
|
||||||
foreach ($newRooms as $room) {
|
foreach ($newRooms as $room) {
|
||||||
$this->createRoom($room);
|
$this->createLocation($room);
|
||||||
}
|
}
|
||||||
|
|
||||||
$rooms = $this->getAllRooms();
|
$locations = $this->getAllLocations();
|
||||||
foreach ($newEvents as $event) {
|
foreach ($newEvents as $event) {
|
||||||
$this->createEvent(
|
$this->createEvent(
|
||||||
$event,
|
$event,
|
||||||
$shiftType,
|
$shiftType,
|
||||||
$rooms
|
$locations
|
||||||
->where('name', $event->getRoom()->getName())
|
->where('name', $event->getRoom()->getName())
|
||||||
->first(),
|
->first(),
|
||||||
$scheduleUrl
|
$scheduleUrl
|
||||||
|
@ -237,15 +271,15 @@ class ImportSchedule extends BaseController
|
||||||
$this->updateEvent(
|
$this->updateEvent(
|
||||||
$event,
|
$event,
|
||||||
$shiftType,
|
$shiftType,
|
||||||
$rooms
|
$locations
|
||||||
->where('name', $event->getRoom()->getName())
|
->where('name', $event->getRoom()->getName())
|
||||||
->first()
|
->first(),
|
||||||
|
$scheduleUrl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($deleteEvents as $event) {
|
foreach ($deleteEvents as $event) {
|
||||||
$this->fireDeleteShiftEntryEvents($event);
|
$this->deleteEvent($event, $scheduleUrl);
|
||||||
$this->deleteEvent($event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scheduleUrl->touch();
|
$scheduleUrl->touch();
|
||||||
|
@ -255,29 +289,30 @@ class ImportSchedule extends BaseController
|
||||||
return redirect($this->url, 303);
|
return redirect($this->url, 303);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createRoom(Room $room): void
|
protected function createLocation(Room $room): void
|
||||||
{
|
{
|
||||||
$roomModel = new RoomModel();
|
$location = new Location();
|
||||||
$roomModel->name = $room->getName();
|
$location->name = $room->getName();
|
||||||
$roomModel->save();
|
$location->save();
|
||||||
|
|
||||||
$this->log('Created schedule room "{room}"', ['room' => $room->getName()]);
|
$this->log('Created schedule location "{location}"', ['location' => $room->getName()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function fireDeleteShiftEntryEvents(Event $event): void
|
protected function fireDeleteShiftEntryEvents(Event $event, ScheduleUrl $schedule): void
|
||||||
{
|
{
|
||||||
$shiftEntries = $this->db
|
$shiftEntries = $this->db
|
||||||
->table('shift_entries')
|
->table('shift_entries')
|
||||||
->select([
|
->select([
|
||||||
'shift_types.name', 'shifts.title', 'angel_types.name AS type', 'rooms.id AS room_id',
|
'shift_types.name', 'shifts.title', 'angel_types.name AS type', 'locations.id AS location_id',
|
||||||
'shifts.start', 'shifts.end', 'shift_entries.user_id', 'shift_entries.freeloaded',
|
'shifts.start', 'shifts.end', 'shift_entries.user_id', 'shift_entries.freeloaded',
|
||||||
])
|
])
|
||||||
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
|
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
|
||||||
->join('schedule_shift', 'shifts.id', 'schedule_shift.shift_id')
|
->join('schedule_shift', 'shifts.id', 'schedule_shift.shift_id')
|
||||||
->join('rooms', 'rooms.id', 'shifts.room_id')
|
->join('locations', 'locations.id', 'shifts.location_id')
|
||||||
->join('angel_types', 'angel_types.id', 'shift_entries.angel_type_id')
|
->join('angel_types', 'angel_types.id', 'shift_entries.angel_type_id')
|
||||||
->join('shift_types', 'shift_types.id', 'shifts.shift_type_id')
|
->join('shift_types', 'shift_types.id', 'shifts.shift_type_id')
|
||||||
->where('schedule_shift.guid', $event->getGuid())
|
->where('schedule_shift.guid', $event->getGuid())
|
||||||
|
->where('schedule_shift.schedule_id', $schedule->id)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
foreach ($shiftEntries as $shiftEntry) {
|
foreach ($shiftEntries as $shiftEntry) {
|
||||||
|
@ -288,13 +323,13 @@ class ImportSchedule extends BaseController
|
||||||
'name' => $shiftEntry->name,
|
'name' => $shiftEntry->name,
|
||||||
'title' => $shiftEntry->title,
|
'title' => $shiftEntry->title,
|
||||||
'type' => $shiftEntry->type,
|
'type' => $shiftEntry->type,
|
||||||
'room' => RoomModel::find($shiftEntry->room_id),
|
'location' => Location::find($shiftEntry->location_id),
|
||||||
'freeloaded' => $shiftEntry->freeloaded,
|
'freeloaded' => $shiftEntry->freeloaded,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createEvent(Event $event, int $shiftTypeId, RoomModel $room, ScheduleUrl $scheduleUrl): void
|
protected function createEvent(Event $event, int $shiftTypeId, Location $location, ScheduleUrl $scheduleUrl): void
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$eventTimeZone = Carbon::now()->timezone;
|
$eventTimeZone = Carbon::now()->timezone;
|
||||||
|
@ -304,7 +339,7 @@ class ImportSchedule extends BaseController
|
||||||
$shift->shift_type_id = $shiftTypeId;
|
$shift->shift_type_id = $shiftTypeId;
|
||||||
$shift->start = $event->getDate()->copy()->timezone($eventTimeZone);
|
$shift->start = $event->getDate()->copy()->timezone($eventTimeZone);
|
||||||
$shift->end = $event->getEndDate()->copy()->timezone($eventTimeZone);
|
$shift->end = $event->getEndDate()->copy()->timezone($eventTimeZone);
|
||||||
$shift->room()->associate($room);
|
$shift->location()->associate($location);
|
||||||
$shift->url = $event->getUrl() ?? '';
|
$shift->url = $event->getUrl() ?? '';
|
||||||
$shift->transaction_id = Uuid::uuidBy($scheduleUrl->id, '5c4ed01e');
|
$shift->transaction_id = Uuid::uuidBy($scheduleUrl->id, '5c4ed01e');
|
||||||
$shift->createdBy()->associate($user);
|
$shift->createdBy()->associate($user);
|
||||||
|
@ -316,68 +351,81 @@ class ImportSchedule extends BaseController
|
||||||
$scheduleShift->save();
|
$scheduleShift->save();
|
||||||
|
|
||||||
$this->log(
|
$this->log(
|
||||||
'Created schedule shift "{shift}" in "{room}" ({from} {to}, {guid})',
|
'Created schedule shift "{shift}" in "{location}" ({from} {to}, {guid})',
|
||||||
[
|
[
|
||||||
'shift' => $shift->title,
|
'shift' => $shift->title,
|
||||||
'room' => $shift->room->name,
|
'location' => $shift->location->name,
|
||||||
'from' => $shift->start->format(DateTimeInterface::RFC3339),
|
'from' => $shift->start->format(DateTimeInterface::RFC3339),
|
||||||
'to' => $shift->end->format(DateTimeInterface::RFC3339),
|
'to' => $shift->end->format(DateTimeInterface::RFC3339),
|
||||||
'guid' => $scheduleShift->guid,
|
'guid' => $scheduleShift->guid,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function updateEvent(Event $event, int $shiftTypeId, RoomModel $room): void
|
protected function updateEvent(Event $event, int $shiftTypeId, Location $location, ScheduleUrl $schedule): void
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$eventTimeZone = Carbon::now()->timezone;
|
$eventTimeZone = Carbon::now()->timezone;
|
||||||
|
|
||||||
/** @var ScheduleShift $scheduleShift */
|
/** @var ScheduleShift $scheduleShift */
|
||||||
$scheduleShift = ScheduleShift::whereGuid($event->getGuid())->first();
|
$scheduleShift = ScheduleShift::whereGuid($event->getGuid())->where('schedule_id', $schedule->id)->first();
|
||||||
$shift = $scheduleShift->shift;
|
$shift = $scheduleShift->shift;
|
||||||
|
$oldShift = Shift::find($shift->id);
|
||||||
$shift->title = $event->getTitle();
|
$shift->title = $event->getTitle();
|
||||||
$shift->shift_type_id = $shiftTypeId;
|
$shift->shift_type_id = $shiftTypeId;
|
||||||
$shift->start = $event->getDate()->copy()->timezone($eventTimeZone);
|
$shift->start = $event->getDate()->copy()->timezone($eventTimeZone);
|
||||||
$shift->end = $event->getEndDate()->copy()->timezone($eventTimeZone);
|
$shift->end = $event->getEndDate()->copy()->timezone($eventTimeZone);
|
||||||
$shift->room()->associate($room);
|
$shift->location()->associate($location);
|
||||||
$shift->url = $event->getUrl() ?? '';
|
$shift->url = $event->getUrl() ?? '';
|
||||||
$shift->updatedBy()->associate($user);
|
$shift->updatedBy()->associate($user);
|
||||||
$shift->save();
|
$shift->save();
|
||||||
|
|
||||||
|
$this->fireUpdateShiftUpdateEvent($oldShift, $shift);
|
||||||
|
|
||||||
$this->log(
|
$this->log(
|
||||||
'Updated schedule shift "{shift}" in "{room}" ({from} {to}, {guid})',
|
'Updated schedule shift "{shift}" in "{location}" ({from} {to}, {guid})',
|
||||||
[
|
[
|
||||||
'shift' => $shift->title,
|
'shift' => $shift->title,
|
||||||
'room' => $shift->room->name,
|
'location' => $shift->location->name,
|
||||||
'from' => $shift->start->format(DateTimeInterface::RFC3339),
|
'from' => $shift->start->format(DateTimeInterface::RFC3339),
|
||||||
'to' => $shift->end->format(DateTimeInterface::RFC3339),
|
'to' => $shift->end->format(DateTimeInterface::RFC3339),
|
||||||
'guid' => $scheduleShift->guid,
|
'guid' => $scheduleShift->guid,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function deleteEvent(Event $event): void
|
protected function deleteEvent(Event $event, ScheduleUrl $schedule): void
|
||||||
{
|
{
|
||||||
/** @var ScheduleShift $scheduleShift */
|
/** @var ScheduleShift $scheduleShift */
|
||||||
$scheduleShift = ScheduleShift::whereGuid($event->getGuid())->first();
|
$scheduleShift = ScheduleShift::whereGuid($event->getGuid())->where('schedule_id', $schedule->id)->first();
|
||||||
$shift = $scheduleShift->shift;
|
$shift = $scheduleShift->shift;
|
||||||
$shift->delete();
|
$shift->delete();
|
||||||
|
|
||||||
|
$this->fireDeleteShiftEntryEvents($event, $schedule);
|
||||||
|
|
||||||
$this->log(
|
$this->log(
|
||||||
'Deleted schedule shift "{shift}" in {room} ({from} {to}, {guid})',
|
'Deleted schedule shift "{shift}" in {location} ({from} {to}, {guid})',
|
||||||
[
|
[
|
||||||
'shift' => $shift->title,
|
'shift' => $shift->title,
|
||||||
'room' => $shift->room->name,
|
'location' => $shift->location->name,
|
||||||
'from' => $shift->start->format(DateTimeInterface::RFC3339),
|
'from' => $shift->start->format(DateTimeInterface::RFC3339),
|
||||||
'to' => $shift->end->format(DateTimeInterface::RFC3339),
|
'to' => $shift->end->format(DateTimeInterface::RFC3339),
|
||||||
'guid' => $scheduleShift->guid,
|
'guid' => $scheduleShift->guid,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function fireUpdateShiftUpdateEvent(Shift $oldShift, Shift $newShift): void
|
||||||
|
{
|
||||||
|
event('shift.updating', [
|
||||||
|
'shift' => $newShift,
|
||||||
|
'oldShift' => $oldShift,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return Event[]|Room[]|RoomModel[]
|
* @return Event[]|Room[]|Location[]
|
||||||
* @throws ErrorException
|
* @throws ErrorException
|
||||||
*/
|
*/
|
||||||
protected function getScheduleData(Request $request)
|
protected function getScheduleData(Request $request)
|
||||||
|
@ -420,10 +468,10 @@ class ImportSchedule extends BaseController
|
||||||
protected function newRooms(array $scheduleRooms): array
|
protected function newRooms(array $scheduleRooms): array
|
||||||
{
|
{
|
||||||
$newRooms = [];
|
$newRooms = [];
|
||||||
$allRooms = $this->getAllRooms();
|
$allLocations = $this->getAllLocations();
|
||||||
|
|
||||||
foreach ($scheduleRooms as $room) {
|
foreach ($scheduleRooms as $room) {
|
||||||
if ($allRooms->where('name', $room->getName())->count()) {
|
if ($allLocations->where('name', $room->getName())->count()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +504,7 @@ class ImportSchedule extends BaseController
|
||||||
$scheduleEvents = [];
|
$scheduleEvents = [];
|
||||||
/** @var Event[] $deleteEvents */
|
/** @var Event[] $deleteEvents */
|
||||||
$deleteEvents = [];
|
$deleteEvents = [];
|
||||||
$rooms = $this->getAllRooms();
|
$locations = $this->getAllLocations();
|
||||||
$eventTimeZone = Carbon::now()->timezone;
|
$eventTimeZone = Carbon::now()->timezone;
|
||||||
|
|
||||||
foreach ($schedule->getDay() as $day) {
|
foreach ($schedule->getDay() as $day) {
|
||||||
|
@ -477,19 +525,19 @@ class ImportSchedule extends BaseController
|
||||||
|
|
||||||
$scheduleEventsGuidList = array_keys($scheduleEvents);
|
$scheduleEventsGuidList = array_keys($scheduleEvents);
|
||||||
$existingShifts = $this->getScheduleShiftsByGuid($scheduleUrl, $scheduleEventsGuidList);
|
$existingShifts = $this->getScheduleShiftsByGuid($scheduleUrl, $scheduleEventsGuidList);
|
||||||
foreach ($existingShifts as $shift) {
|
foreach ($existingShifts as $scheduleShift) {
|
||||||
$guid = $shift->guid;
|
$guid = $scheduleShift->guid;
|
||||||
/** @var Shift $shift */
|
/** @var Shift $shift */
|
||||||
$shift = Shift::with('room')->find($shift->shift_id);
|
$shift = Shift::with('location')->find($scheduleShift->shift_id);
|
||||||
$event = $scheduleEvents[$guid];
|
$event = $scheduleEvents[$guid];
|
||||||
$room = $rooms->where('name', $event->getRoom()->getName())->first();
|
$location = $locations->where('name', $event->getRoom()->getName())->first();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$shift->title != $event->getTitle()
|
$shift->title != $event->getTitle()
|
||||||
|| $shift->shift_type_id != $shiftType
|
|| $shift->shift_type_id != $shiftType
|
||||||
|| $shift->start != $event->getDate()
|
|| $shift->start != $event->getDate()
|
||||||
|| $shift->end != $event->getEndDate()
|
|| $shift->end != $event->getEndDate()
|
||||||
|| $shift->room_id != ($room->id ?? '')
|
|| $shift->location_id != ($location->id ?? '')
|
||||||
|| $shift->url != ($event->getUrl() ?? '')
|
|| $shift->url != ($event->getUrl() ?? '')
|
||||||
) {
|
) {
|
||||||
$changeEvents[$guid] = $event;
|
$changeEvents[$guid] = $event;
|
||||||
|
@ -503,8 +551,8 @@ class ImportSchedule extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
$scheduleShifts = $this->getScheduleShiftsWhereNotGuid($scheduleUrl, $scheduleEventsGuidList);
|
$scheduleShifts = $this->getScheduleShiftsWhereNotGuid($scheduleUrl, $scheduleEventsGuidList);
|
||||||
foreach ($scheduleShifts as $shift) {
|
foreach ($scheduleShifts as $scheduleShift) {
|
||||||
$event = $this->eventFromScheduleShift($shift);
|
$event = $this->eventFromScheduleShift($scheduleShift);
|
||||||
$deleteEvents[$event->getGuid()] = $event;
|
$deleteEvents[$event->getGuid()] = $event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,14 +561,13 @@ class ImportSchedule extends BaseController
|
||||||
|
|
||||||
protected function eventFromScheduleShift(ScheduleShift $scheduleShift): Event
|
protected function eventFromScheduleShift(ScheduleShift $scheduleShift): Event
|
||||||
{
|
{
|
||||||
/** @var Shift $shift */
|
$shift = $scheduleShift->shift;
|
||||||
$shift = Shift::with('room')->find($scheduleShift->shift_id);
|
|
||||||
$duration = $shift->start->diff($shift->end);
|
$duration = $shift->start->diff($shift->end);
|
||||||
|
|
||||||
return new Event(
|
return new Event(
|
||||||
$scheduleShift->guid,
|
$scheduleShift->guid,
|
||||||
0,
|
0,
|
||||||
new Room($shift->room->name),
|
new Room($shift->location->name),
|
||||||
$shift->title,
|
$shift->title,
|
||||||
'',
|
'',
|
||||||
'n/a',
|
'n/a',
|
||||||
|
@ -534,11 +581,11 @@ class ImportSchedule extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return RoomModel[]|Collection
|
* @return Location[]|Collection
|
||||||
*/
|
*/
|
||||||
protected function getAllRooms(): Collection
|
protected function getAllLocations(): Collection
|
||||||
{
|
{
|
||||||
return RoomModel::all();
|
return Location::all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,7 +8,7 @@ use Engelsystem\Models\User\User;
|
||||||
*/
|
*/
|
||||||
function myshifts_title()
|
function myshifts_title()
|
||||||
{
|
{
|
||||||
return __('My shifts');
|
return __('profile.my-shifts');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,23 +35,24 @@ function user_myshifts()
|
||||||
$shifts_user = User::find($shift_entry_id);
|
$shifts_user = User::find($shift_entry_id);
|
||||||
if ($request->has('reset')) {
|
if ($request->has('reset')) {
|
||||||
if ($request->input('reset') == 'ack') {
|
if ($request->input('reset') == 'ack') {
|
||||||
User_reset_api_key($user);
|
auth()->resetApiKey($user);
|
||||||
|
engelsystem_log(sprintf('API key resetted (%s).', User_Nick_render($user, true)));
|
||||||
success(__('Key changed.'));
|
success(__('Key changed.'));
|
||||||
throw_redirect(page_link_to('users', ['action' => 'view', 'user_id' => $shifts_user->id]));
|
throw_redirect(url('/users', ['action' => 'view', 'user_id' => $shifts_user->id]));
|
||||||
}
|
}
|
||||||
return page_with_title(__('Reset API key'), [
|
return page_with_title(__('Reset API key'), [
|
||||||
error(
|
error(
|
||||||
__('If you reset the key, the url to your iCal- and JSON-export and your atom/rss feed changes! You have to update it in every application using one of these exports.'),
|
__('If you reset the key, the url to your iCal- and JSON-export and your atom/rss feed changes! You have to update it in every application using one of these exports.'),
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
button(page_link_to('user_myshifts', ['reset' => 'ack']), __('Continue'), 'btn-danger'),
|
button(url('/user-myshifts', ['reset' => 'ack']), __('Continue'), 'btn-danger'),
|
||||||
]);
|
]);
|
||||||
} elseif ($request->has('edit') && preg_match('/^\d+$/', $request->input('edit'))) {
|
} elseif ($request->has('edit') && preg_match('/^\d+$/', $request->input('edit'))) {
|
||||||
$shift_entry_id = $request->input('edit');
|
$shift_entry_id = $request->input('edit');
|
||||||
/** @var ShiftEntry $shiftEntry */
|
/** @var ShiftEntry $shiftEntry */
|
||||||
$shiftEntry = ShiftEntry::where('id', $shift_entry_id)
|
$shiftEntry = ShiftEntry::where('id', $shift_entry_id)
|
||||||
->where('user_id', $shifts_user->id)
|
->where('user_id', $shifts_user->id)
|
||||||
->with(['shift', 'shift.shiftType', 'shift.room', 'user'])
|
->with(['shift', 'shift.shiftType', 'shift.location', 'user'])
|
||||||
->first();
|
->first();
|
||||||
if (!empty($shiftEntry)) {
|
if (!empty($shiftEntry)) {
|
||||||
$shift = $shiftEntry->shift;
|
$shift = $shiftEntry->shift;
|
||||||
|
@ -90,14 +91,14 @@ function user_myshifts()
|
||||||
. '. Freeloaded: ' . ($freeloaded ? 'YES Comment: ' . $freeloaded_comment : 'NO')
|
. '. Freeloaded: ' . ($freeloaded ? 'YES Comment: ' . $freeloaded_comment : 'NO')
|
||||||
);
|
);
|
||||||
success(__('Shift saved.'));
|
success(__('Shift saved.'));
|
||||||
throw_redirect(page_link_to('users', ['action' => 'view', 'user_id' => $shifts_user->id]));
|
throw_redirect(url('/users', ['action' => 'view', 'user_id' => $shifts_user->id]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ShiftEntry_edit_view(
|
return ShiftEntry_edit_view(
|
||||||
$shifts_user,
|
$shifts_user,
|
||||||
$shift->start->format(__('Y-m-d H:i')) . ', ' . shift_length($shift),
|
$shift->start->format(__('general.datetime')) . ', ' . shift_length($shift),
|
||||||
$shift->room->name,
|
$shift->location->name,
|
||||||
$shift->shiftType->name,
|
$shift->shiftType->name,
|
||||||
$shiftEntry->angelType->name,
|
$shiftEntry->angelType->name,
|
||||||
$shiftEntry->user_comment,
|
$shiftEntry->user_comment,
|
||||||
|
@ -106,10 +107,10 @@ function user_myshifts()
|
||||||
auth()->can('user_shifts_admin')
|
auth()->can('user_shifts_admin')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
throw_redirect(page_link_to('user_myshifts'));
|
throw_redirect(url('/user-myshifts'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_redirect(page_link_to('users', ['action' => 'view', 'user_id' => $shifts_user->id]));
|
throw_redirect(url('/users', ['action' => 'view', 'user_id' => $shifts_user->id]));
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use Engelsystem\Database\Db;
|
use Engelsystem\Database\Db;
|
||||||
use Engelsystem\Helpers\Carbon;
|
use Engelsystem\Helpers\Carbon;
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\UserAngelType;
|
use Engelsystem\Models\UserAngelType;
|
||||||
|
@ -34,7 +34,7 @@ function user_shifts()
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (auth()->user()->isFreeloader()) {
|
if (auth()->user()->isFreeloader()) {
|
||||||
throw_redirect(page_link_to('user_myshifts'));
|
throw_redirect(url('/user-myshifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('edit_shift')) {
|
if ($request->has('edit_shift')) {
|
||||||
|
@ -107,40 +107,42 @@ function update_ShiftsFilter(ShiftsFilter $shiftsFilter, $user_shifts_admin, $da
|
||||||
{
|
{
|
||||||
$shiftsFilter->setUserShiftsAdmin($user_shifts_admin);
|
$shiftsFilter->setUserShiftsAdmin($user_shifts_admin);
|
||||||
$shiftsFilter->setFilled(check_request_int_array('filled', $shiftsFilter->getFilled()));
|
$shiftsFilter->setFilled(check_request_int_array('filled', $shiftsFilter->getFilled()));
|
||||||
$shiftsFilter->setRooms(check_request_int_array('rooms', $shiftsFilter->getRooms()));
|
$shiftsFilter->setLocations(check_request_int_array('locations', $shiftsFilter->getLocations()));
|
||||||
$shiftsFilter->setTypes(check_request_int_array('types', $shiftsFilter->getTypes()));
|
$shiftsFilter->setTypes(check_request_int_array('types', $shiftsFilter->getTypes()));
|
||||||
update_ShiftsFilter_timerange($shiftsFilter, $days);
|
update_ShiftsFilter_timerange($shiftsFilter, $days);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Room[]|Collection
|
* @return Location[]|Collection
|
||||||
*/
|
*/
|
||||||
function load_rooms(bool $onlyWithActiveShifts = false)
|
function load_locations(bool $onlyWithActiveShifts = false)
|
||||||
{
|
{
|
||||||
$rooms = Room::orderBy('name');
|
$locations = Location::orderBy('name');
|
||||||
|
|
||||||
if ($onlyWithActiveShifts) {
|
if ($onlyWithActiveShifts) {
|
||||||
$roomIdsFromAngelType = NeededAngelType::query()
|
$locationIdsFromAngelType = NeededAngelType::query()
|
||||||
->whereNotNull('room_id')
|
->whereNotNull('location_id')
|
||||||
->select('room_id');
|
->select('location_id');
|
||||||
|
|
||||||
$roomIdsFromShift = Shift::query()
|
$locationIdsFromShift = Shift::query()
|
||||||
->leftJoin('needed_angel_types', 'shifts.id', 'needed_angel_types.shift_id')
|
->leftJoin('needed_angel_types', 'shifts.id', 'needed_angel_types.shift_id')
|
||||||
->whereNotNull('needed_angel_types.shift_id')
|
->leftJoin('needed_angel_types AS nast', 'shifts.shift_type_id', 'nast.shift_type_id')
|
||||||
->select('shifts.room_id');
|
->whereNotNull('needed_angel_types.id')
|
||||||
|
->orWhereNotNull('nast.id')
|
||||||
|
->select('shifts.location_id');
|
||||||
|
|
||||||
$rooms->whereIn('id', $roomIdsFromAngelType)
|
$locations->whereIn('id', $locationIdsFromAngelType)
|
||||||
->orWhereIn('id', $roomIdsFromShift);
|
->orWhereIn('id', $locationIdsFromShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
$rooms = $rooms->get();
|
$locations = $locations->get();
|
||||||
|
|
||||||
if ($rooms->isEmpty()) {
|
if ($locations->isEmpty()) {
|
||||||
error(__('The administration has not configured any rooms yet.'));
|
error(__('The administration has not configured any locations yet.'));
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rooms;
|
return $locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -162,7 +164,7 @@ function load_days()
|
||||||
error(__('The administration has not configured any shifts yet.'));
|
error(__('The administration has not configured any shifts yet.'));
|
||||||
// Do not try to redirect to the current page
|
// Do not try to redirect to the current page
|
||||||
if (config('home_site') != 'user_shifts') {
|
if (config('home_site') != 'user_shifts') {
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $days;
|
return $days;
|
||||||
|
@ -174,10 +176,11 @@ function load_days()
|
||||||
function load_types()
|
function load_types()
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
$isShico = auth()->can('admin_shifts');
|
||||||
|
|
||||||
if (!AngelType::count()) {
|
if (!AngelType::count()) {
|
||||||
error(__('The administration has not configured any angeltypes yet - or you are not subscribed to any angeltype.'));
|
error(__('The administration has not configured any angeltypes yet - or you are not subscribed to any angeltype.'));
|
||||||
throw_redirect(page_link_to('/'));
|
throw_redirect(url('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$types = Db::select(
|
$types = Db::select(
|
||||||
|
@ -197,8 +200,11 @@ function load_types()
|
||||||
ON (
|
ON (
|
||||||
`user_angel_type`.`angel_type_id`=`angel_types`.`id`
|
`user_angel_type`.`angel_type_id`=`angel_types`.`id`
|
||||||
AND `user_angel_type`.`user_id`=?
|
AND `user_angel_type`.`user_id`=?
|
||||||
)
|
)'
|
||||||
ORDER BY `angel_types`.`name`
|
. ($isShico ? '' :
|
||||||
|
'WHERE angel_types.hide_on_shift_view = 0
|
||||||
|
OR user_angel_type.user_id IS NOT NULL ') .
|
||||||
|
'ORDER BY `angel_types`.`name`
|
||||||
',
|
',
|
||||||
[
|
[
|
||||||
$user->id,
|
$user->id,
|
||||||
|
@ -229,7 +235,7 @@ function view_user_shifts()
|
||||||
|
|
||||||
$session = session();
|
$session = session();
|
||||||
$days = load_days();
|
$days = load_days();
|
||||||
$rooms = load_rooms(true);
|
$locations = load_locations(true);
|
||||||
$types = load_types();
|
$types = load_types();
|
||||||
$ownAngelTypes = [];
|
$ownAngelTypes = [];
|
||||||
|
|
||||||
|
@ -246,8 +252,8 @@ function view_user_shifts()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$session->has('shifts-filter')) {
|
if (!$session->has('shifts-filter')) {
|
||||||
$room_ids = $rooms->pluck('id')->toArray();
|
$location_ids = $locations->pluck('id')->toArray();
|
||||||
$shiftsFilter = new ShiftsFilter(auth()->can('user_shifts_admin'), $room_ids, $ownAngelTypes);
|
$shiftsFilter = new ShiftsFilter(auth()->can('user_shifts_admin'), $location_ids, $ownAngelTypes);
|
||||||
$session->set('shifts-filter', $shiftsFilter->sessionExport());
|
$session->set('shifts-filter', $shiftsFilter->sessionExport());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +265,7 @@ function view_user_shifts()
|
||||||
$shiftCalendarRenderer = shiftCalendarRendererByShiftFilter($shiftsFilter);
|
$shiftCalendarRenderer = shiftCalendarRendererByShiftFilter($shiftsFilter);
|
||||||
|
|
||||||
if (empty($user->api_key)) {
|
if (empty($user->api_key)) {
|
||||||
User_reset_api_key($user, false);
|
auth()->resetApiKey($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
$filled = [
|
$filled = [
|
||||||
|
@ -277,24 +283,29 @@ function view_user_shifts()
|
||||||
$end_day = $shiftsFilter->getEnd()->format('Y-m-d');
|
$end_day = $shiftsFilter->getEnd()->format('Y-m-d');
|
||||||
$end_time = $shiftsFilter->getEnd()->format('H:i');
|
$end_time = $shiftsFilter->getEnd()->format('H:i');
|
||||||
|
|
||||||
|
$canSignUpForShifts = true;
|
||||||
if (config('signup_requires_arrival') && !$user->state->arrived) {
|
if (config('signup_requires_arrival') && !$user->state->arrived) {
|
||||||
|
$canSignUpForShifts = false;
|
||||||
info(render_user_arrived_hint());
|
info(render_user_arrived_hint());
|
||||||
}
|
}
|
||||||
|
|
||||||
$formattedDays = collect($days)->map(function ($value) {
|
$formattedDays = collect($days)->map(function ($value) {
|
||||||
return Carbon::make($value)->format(__('Y-m-d'));
|
return dateWithEventDay(Carbon::make($value)->format('Y-m-d'));
|
||||||
})->toArray();
|
})->toArray();
|
||||||
|
|
||||||
|
$link = button(url('/admin-shifts'), icon('plus-lg'), 'add');
|
||||||
|
|
||||||
return page([
|
return page([
|
||||||
div('col-md-12', [
|
div('col-md-12', [
|
||||||
msg(),
|
msg(),
|
||||||
view(__DIR__ . '/../../resources/views/pages/user-shifts.html', [
|
view(__DIR__ . '/../../resources/views/pages/user-shifts.html', [
|
||||||
'title' => shifts_title(),
|
'title' => shifts_title(),
|
||||||
'room_select' => make_select(
|
'add_link' => auth()->can('admin_shifts') ? $link : '',
|
||||||
$rooms,
|
'location_select' => make_select(
|
||||||
$shiftsFilter->getRooms(),
|
$locations,
|
||||||
'rooms',
|
$shiftsFilter->getLocations(),
|
||||||
icon('pin-map-fill') . __('Rooms')
|
'locations',
|
||||||
|
icon('pin-map-fill') . __('Locations')
|
||||||
),
|
),
|
||||||
'start_select' => html_select_key(
|
'start_select' => html_select_key(
|
||||||
'start_day',
|
'start_day',
|
||||||
|
@ -314,7 +325,10 @@ function view_user_shifts()
|
||||||
$types,
|
$types,
|
||||||
$shiftsFilter->getTypes(),
|
$shiftsFilter->getTypes(),
|
||||||
'types',
|
'types',
|
||||||
icon('person-lines-fill') . __('Angeltypes') . '<sup>1</sup>',
|
icon('person-lines-fill') . __('angeltypes.angeltypes')
|
||||||
|
. ' <small><span class="bi bi-info-circle-fill text-info" data-bs-toggle="tooltip" title="'
|
||||||
|
. __('The tasks shown here are influenced by the angeltypes you joined already!')
|
||||||
|
. '"></span></small>',
|
||||||
$ownAngelTypes
|
$ownAngelTypes
|
||||||
),
|
),
|
||||||
'filled_select' => make_select(
|
'filled_select' => make_select(
|
||||||
|
@ -323,12 +337,6 @@ function view_user_shifts()
|
||||||
'filled',
|
'filled',
|
||||||
icon('person-fill-slash') . __('Occupancy')
|
icon('person-fill-slash') . __('Occupancy')
|
||||||
),
|
),
|
||||||
'task_notice' =>
|
|
||||||
'<sup>1</sup>'
|
|
||||||
. __('The tasks shown here are influenced by the angeltypes you joined already!')
|
|
||||||
. ' <a href="' . url('/angeltypes/about') . '">'
|
|
||||||
. __('Description of the jobs.')
|
|
||||||
. '</a>',
|
|
||||||
'shifts_table' => msg() . $shiftCalendarRenderer->render(),
|
'shifts_table' => msg() . $shiftCalendarRenderer->render(),
|
||||||
'ical_text' => div('mt-3', ical_hint()),
|
'ical_text' => div('mt-3', ical_hint()),
|
||||||
'filter' => __('Filter'),
|
'filter' => __('Filter'),
|
||||||
|
@ -340,7 +348,11 @@ function view_user_shifts()
|
||||||
'set_last_4h' => __('last 4h'),
|
'set_last_4h' => __('last 4h'),
|
||||||
'set_next_4h' => __('next 4h'),
|
'set_next_4h' => __('next 4h'),
|
||||||
'set_next_8h' => __('next 8h'),
|
'set_next_8h' => __('next 8h'),
|
||||||
'buttons' => button(
|
'random' => auth()->can('user_shifts') && $canSignUpForShifts ? button(
|
||||||
|
url('/shifts/random'),
|
||||||
|
icon('dice-4-fill') . __('shifts.random')
|
||||||
|
) : '',
|
||||||
|
'dashboard' => button(
|
||||||
public_dashboard_link(),
|
public_dashboard_link(),
|
||||||
icon('speedometer2') . __('Public Dashboard')
|
icon('speedometer2') . __('Public Dashboard')
|
||||||
),
|
),
|
||||||
|
@ -364,9 +376,9 @@ function ical_hint()
|
||||||
return heading(__('iCal export and API') . ' ' . button_help('user/ical'), 2)
|
return heading(__('iCal export and API') . ' ' . button_help('user/ical'), 2)
|
||||||
. '<p>' . sprintf(
|
. '<p>' . sprintf(
|
||||||
__('Export your own shifts. <a href="%s">iCal format</a> or <a href="%s">JSON format</a> available (please keep secret, otherwise <a href="%s">reset the api key</a>).'),
|
__('Export your own shifts. <a href="%s">iCal format</a> or <a href="%s">JSON format</a> available (please keep secret, otherwise <a href="%s">reset the api key</a>).'),
|
||||||
page_link_to('ical', ['key' => $user->api_key]),
|
url('/ical', ['key' => $user->api_key]),
|
||||||
page_link_to('shifts_json_export', ['key' => $user->api_key]),
|
url('/shifts-json-export', ['key' => $user->api_key]),
|
||||||
page_link_to('user_myshifts', ['reset' => 1])
|
url('/user-myshifts', ['reset' => 1])
|
||||||
)
|
)
|
||||||
. ' <button class="btn btn-sm btn-danger" type="button"
|
. ' <button class="btn btn-sm btn-danger" type="button"
|
||||||
data-bs-toggle="collapse" data-bs-target="#collapseApiKey"
|
data-bs-toggle="collapse" data-bs-target="#collapseApiKey"
|
||||||
|
@ -377,15 +389,6 @@ function ical_hint()
|
||||||
. '<p id="collapseApiKey" class="collapse"><code>' . $user->api_key . '</code></p>';
|
. '<p id="collapseApiKey" class="collapse"><code>' . $user->api_key . '</code></p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $array
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function get_ids_from_array($array)
|
|
||||||
{
|
|
||||||
return $array['id'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $items
|
* @param array $items
|
||||||
* @param array $selected
|
* @param array $selected
|
||||||
|
@ -418,7 +421,7 @@ function make_select($items, $selected, $name, $title = null, $ownSelect = [])
|
||||||
$htmlItems[] = '<div class="form-check">'
|
$htmlItems[] = '<div class="form-check">'
|
||||||
. '<input class="form-check-input" type="checkbox" id="' . $id . '" name="' . $name . '[]" value="' . $i['id'] . '" '
|
. '<input class="form-check-input" type="checkbox" id="' . $id . '" name="' . $name . '[]" value="' . $i['id'] . '" '
|
||||||
. (in_array($i['id'], $selected) ? ' checked="checked"' : '')
|
. (in_array($i['id'], $selected) ? ' checked="checked"' : '')
|
||||||
. '><label class="form-check-label" for="' . $id . '">' . $i['name'] . '</label>'
|
. '><label class="form-check-label" for="' . $id . '">' . htmlspecialchars($i['name']) . '</label>'
|
||||||
. (!isset($i['enabled']) || $i['enabled'] ? '' : icon('mortarboard-fill'))
|
. (!isset($i['enabled']) || $i['enabled'] ? '' : icon('mortarboard-fill'))
|
||||||
. '</div>';
|
. '</div>';
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,52 +24,28 @@ function form_hidden($name, $value)
|
||||||
* @param array $data_attributes
|
* @param array $data_attributes
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function form_spinner(string $name, string $label, int $value, array $data_attributes = [])
|
function form_spinner(string $name, string $label, int $value, array $data_attributes = [], bool $isDisabled = false)
|
||||||
{
|
{
|
||||||
$id = 'spinner-' . $name;
|
$id = 'spinner-' . $name;
|
||||||
$attr = '';
|
$attr = '';
|
||||||
foreach ($data_attributes as $attr_key => $attr_value) {
|
foreach ($data_attributes as $attr_key => $attr_value) {
|
||||||
$attr .= ' data-' . $attr_key . '="' . $attr_value . '"';
|
$attr .= ' data-' . $attr_key . '="' . $attr_value . '"';
|
||||||
}
|
}
|
||||||
|
$disabled = $isDisabled ? ' disabled' : '';
|
||||||
|
|
||||||
return form_element($label, '
|
return form_element($label, '
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="' . $id . '" class="form-control" type="number" min="0" step="1" name="' . $name . '" value="' . $value . '"' . $attr . ' />
|
<input id="' . $id . '" class="form-control" type="number" min="0" step="1" name="' . $name . '" value="' . $value . '"' . $attr . $disabled . '/>
|
||||||
<button class="btn btn-secondary spinner-down" type="button" data-input-id="' . $id . '"' . $attr . '>
|
<button class="btn btn-secondary spinner-down' . $disabled . '" type="button" data-input-id="' . $id . '"' . $attr . '>
|
||||||
' . icon('dash-lg') . '
|
' . icon('dash-lg') . '
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary spinner-up" type="button" data-input-id="' . $id . '"' . $attr . '>
|
<button class="btn btn-secondary spinner-up' . $disabled . '" type="button" data-input-id="' . $id . '"' . $attr . '>
|
||||||
' . icon('plus-lg') . '
|
' . icon('plus-lg') . '
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
', $id);
|
', $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a bootstrap datepicker
|
|
||||||
*
|
|
||||||
* @param string $name Name of the parameter
|
|
||||||
* @param string $label Label
|
|
||||||
* @param int|Carbon $value Unix Timestamp
|
|
||||||
* @param string $start_date Earliest possible date
|
|
||||||
* @param string $end_date
|
|
||||||
* @return string HTML
|
|
||||||
*/
|
|
||||||
function form_date($name, $label, $value, $start_date = '', $end_date = '')
|
|
||||||
{
|
|
||||||
$dom_id = $name . '-date';
|
|
||||||
$value = ($value instanceof Carbon) ? $value->getTimestamp() : $value;
|
|
||||||
$value = is_numeric($value) ? date('Y-m-d', $value) : '';
|
|
||||||
$start_date = is_numeric($start_date) ? date('Y-m-d', $start_date) : '';
|
|
||||||
$end_date = is_numeric($end_date) ? date('Y-m-d', $end_date) : '';
|
|
||||||
|
|
||||||
return form_element(
|
|
||||||
$label,
|
|
||||||
'<input class="form-control" id="' . $dom_id . '" type="date" placeholder="YYYY-MM-DD" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" min="' . $start_date . '" max="' . $end_date . '" name="' . $name . '" value="' . htmlspecialchars((string) $value) . '" autocomplete="off">',
|
|
||||||
$dom_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a bootstrap datepicker
|
* Render a bootstrap datepicker
|
||||||
*
|
*
|
||||||
|
@ -93,24 +69,6 @@ function form_datetime(string $name, string $label, $value)
|
||||||
', $dom_id, $name, htmlspecialchars($value ? $value->format('Y-m-d H:i') : '')), $dom_id);
|
', $dom_id, $name, htmlspecialchars($value ? $value->format('Y-m-d H:i') : '')), $dom_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Rendert eine Liste von Checkboxen für ein Formular
|
|
||||||
*
|
|
||||||
* @param string $name Die Namen der Checkboxen werden aus name_key gebildet
|
|
||||||
* @param string $label Die Beschriftung der Liste
|
|
||||||
* @param array $items Array mit den einzelnen Checkboxen
|
|
||||||
* @param array $selected Array mit den Keys, die ausgewählt sind
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function form_checkboxes($name, $label, $items, $selected)
|
|
||||||
{
|
|
||||||
$html = form_element($label, '');
|
|
||||||
foreach ($items as $key => $item) {
|
|
||||||
$html .= form_checkbox($name . '_' . $key, $item, in_array($key, $selected));
|
|
||||||
}
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rendert eine Checkbox
|
* Rendert eine Checkbox
|
||||||
*
|
*
|
||||||
|
@ -128,14 +86,15 @@ function form_checkbox($name, $label, $selected, $value = 'checked', $html_id =
|
||||||
}
|
}
|
||||||
|
|
||||||
return '<div class="form-check">'
|
return '<div class="form-check">'
|
||||||
. '<input class="form-check-input" type="checkbox" id="' . $html_id . '" name="' . $name . '" value="' . htmlspecialchars((string) $value) . '" '
|
. '<input class="form-check-input" type="checkbox" id="' . $html_id . '" '
|
||||||
|
. 'name="' . htmlspecialchars($name) . '" value="' . $value . '" '
|
||||||
. ($selected ? ' checked="checked"' : '') . ' /><label class="form-check-label" for="' . $html_id . '">'
|
. ($selected ? ' checked="checked"' : '') . ' /><label class="form-check-label" for="' . $html_id . '">'
|
||||||
. $label
|
. $label
|
||||||
. '</label></div>';
|
. '</label></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rendert einen Radio
|
* Renders a radio button
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param string $label
|
* @param string $label
|
||||||
|
@ -184,9 +143,9 @@ function form_info($label, $text = '')
|
||||||
* @param string $buttonType
|
* @param string $buttonType
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function form_submit($name, $label, $class = '', $wrapForm = true, $buttonType = 'primary')
|
function form_submit($name, $label, $class = '', $wrapForm = true, $buttonType = 'primary', $title = '')
|
||||||
{
|
{
|
||||||
$button = '<button class="btn btn-' . $buttonType . ($class ? ' ' . $class : '') . '" type="submit" name="' . $name . '">'
|
$button = '<button class="btn btn-' . $buttonType . ($class ? ' ' . $class : '') . '" type="submit" name="' . $name . '" title="' . $title . '">'
|
||||||
. $label
|
. $label
|
||||||
. '</button>';
|
. '</button>';
|
||||||
|
|
||||||
|
@ -232,67 +191,6 @@ function form_text($name, $label, $value, $disabled = false, $maxlength = null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a text input with placeholder instead of label.
|
|
||||||
*
|
|
||||||
* @param string $name Input name
|
|
||||||
* @param string $placeholder Placeholder
|
|
||||||
* @param string $value The value
|
|
||||||
* @param boolean $disabled Is the field enabled?
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function form_text_placeholder($name, $placeholder, $value, $disabled = false)
|
|
||||||
{
|
|
||||||
$disabled = $disabled ? ' disabled="disabled"' : '';
|
|
||||||
return form_element(
|
|
||||||
'',
|
|
||||||
'<input class="form-control" id="form_' . $name . '" type="text" name="' . $name
|
|
||||||
. '" value="' . htmlspecialchars((string) $value) . '" placeholder="' . $placeholder
|
|
||||||
. '" ' . $disabled . '/>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rendert ein Formular-Emailfeld
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param string $label
|
|
||||||
* @param string $value
|
|
||||||
* @param bool $disabled
|
|
||||||
* @param string|null $autocomplete
|
|
||||||
* @param int|null $maxlength
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function form_email($name, $label, $value, $disabled = false, $autocomplete = null, $maxlength = null)
|
|
||||||
{
|
|
||||||
$disabled = $disabled ? ' disabled="disabled"' : '';
|
|
||||||
$autocomplete = $autocomplete ? ' autocomplete="' . $autocomplete . '"' : '';
|
|
||||||
$maxlength = $maxlength ? ' maxlength=' . (int) $maxlength : '';
|
|
||||||
return form_element(
|
|
||||||
$label,
|
|
||||||
'<input class="form-control" id="form_' . $name . '" type="email" name="' . $name . '" value="'
|
|
||||||
. htmlspecialchars((string) $value) . '" ' . $disabled . $autocomplete . $maxlength . '/>',
|
|
||||||
'form_' . $name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rendert ein Formular-Dateifeld
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param string $label
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function form_file($name, $label)
|
|
||||||
{
|
|
||||||
return form_element(
|
|
||||||
$label,
|
|
||||||
sprintf('<input id="form_%1$s" type="file" name="%1$s" />', $name),
|
|
||||||
'form_' . $name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rendert ein Formular-Passwortfeld
|
* Rendert ein Formular-Passwortfeld
|
||||||
*
|
*
|
||||||
|
@ -308,7 +206,7 @@ function form_password($name, $label, $autocomplete, $disabled = false)
|
||||||
return form_element(
|
return form_element(
|
||||||
$label,
|
$label,
|
||||||
sprintf(
|
sprintf(
|
||||||
'<input class="form-control" id="form_%1$s" type="password" name="%1$s" minlength="%2$s" value="" autocomplete="%3$s"%4$s/>',
|
'<input class="form-control" id="form_%1$s" type="password" name="%1$s" minlength="%2$s" value="" autocomplete="%3$s" %4$s>',
|
||||||
$name,
|
$name,
|
||||||
config('min_password_length'),
|
config('min_password_length'),
|
||||||
$autocomplete,
|
$autocomplete,
|
||||||
|
@ -318,25 +216,6 @@ function form_password($name, $label, $autocomplete, $disabled = false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a password input with placeholder instead of label.
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param string $placeholder
|
|
||||||
* @param bool $disabled
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function form_password_placeholder($name, $placeholder, $disabled = false)
|
|
||||||
{
|
|
||||||
$disabled = $disabled ? ' disabled="disabled"' : '';
|
|
||||||
return form_element(
|
|
||||||
'',
|
|
||||||
'<input class="form-control" id="form_' . $name . '" type="password" name="'
|
|
||||||
. $name . '" value="" placeholder="' . $placeholder . '" ' . $disabled . '/>',
|
|
||||||
'form_' . $name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rendert ein Formular-Textfeld
|
* Rendert ein Formular-Textfeld
|
||||||
*
|
*
|
||||||
|
@ -406,14 +285,14 @@ function form_element($label, $input, $for = '', $class = '')
|
||||||
*
|
*
|
||||||
* @param string[] $elements
|
* @param string[] $elements
|
||||||
* @param string $action
|
* @param string $action
|
||||||
* @param bool $inline
|
* @param string $style
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function form($elements, $action = '', $inline = false, $btnGroup = false)
|
function form($elements, $action = '', $style = '', $btnGroup = false)
|
||||||
{
|
{
|
||||||
return '<form action="' . $action . '" enctype="multipart/form-data" method="post"'
|
return '<form action="' . $action . '" enctype="multipart/form-data" method="post"'
|
||||||
. ($btnGroup ? ' class="btn-group"' : '')
|
. ($btnGroup ? ' class="btn-group"' : '')
|
||||||
. ($inline ? ' style="float:left"' : '') . '>'
|
. ($style ? ' style="' . $style . '"' : '') . '>'
|
||||||
. join($elements)
|
. join($elements)
|
||||||
. form_csrf()
|
. form_csrf()
|
||||||
. '</form>';
|
. '</form>';
|
||||||
|
@ -463,9 +342,13 @@ function html_select_key($dom_id, $name, $rows, $selected, $selectText = '')
|
||||||
}
|
}
|
||||||
foreach ($rows as $key => $row) {
|
foreach ($rows as $key => $row) {
|
||||||
if (($key == $selected) || ($row === $selected)) {
|
if (($key == $selected) || ($row === $selected)) {
|
||||||
$html .= '<option value="' . $key . '" selected="selected">' . $row . '</option>';
|
$html .= '<option value="' . htmlspecialchars($key) . '" selected="selected">'
|
||||||
|
. htmlspecialchars($row)
|
||||||
|
. '</option>';
|
||||||
} else {
|
} else {
|
||||||
$html .= '<option value="' . $key . '">' . $row . '</option>';
|
$html .= '<option value="' . htmlspecialchars($key) . '">'
|
||||||
|
. htmlspecialchars($row)
|
||||||
|
. '</option>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$html .= '</select>';
|
$html .= '</select>';
|
||||||
|
|
|
@ -1,20 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Question;
|
use Engelsystem\Models\Question;
|
||||||
use Engelsystem\Models\Room;
|
|
||||||
use Engelsystem\UserHintsRenderer;
|
use Engelsystem\UserHintsRenderer;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $page
|
|
||||||
* @param array $parameters get parameters
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function page_link_to($page = '', $parameters = [])
|
|
||||||
{
|
|
||||||
$page = str_replace('_', '-', $page);
|
|
||||||
return url($page, $parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the user hints
|
* Render the user hints
|
||||||
*
|
*
|
||||||
|
@ -31,12 +20,17 @@ function header_render_hints()
|
||||||
$hints_renderer->addHint(user_angeltypes_unconfirmed_hint());
|
$hints_renderer->addHint(user_angeltypes_unconfirmed_hint());
|
||||||
$hints_renderer->addHint(render_user_departure_date_hint());
|
$hints_renderer->addHint(render_user_departure_date_hint());
|
||||||
$hints_renderer->addHint(user_driver_license_required_hint());
|
$hints_renderer->addHint(user_driver_license_required_hint());
|
||||||
|
$hints_renderer->addHint(user_ifsg_certificate_required_hint());
|
||||||
|
|
||||||
// Important hints:
|
// Important hints:
|
||||||
$hints_renderer->addHint(render_user_freeloader_hint(), true);
|
$hints_renderer->addHint(render_user_freeloader_hint(), true);
|
||||||
$hints_renderer->addHint(render_user_arrived_hint(), true);
|
$hints_renderer->addHint(render_user_arrived_hint(true), true);
|
||||||
|
$hints_renderer->addHint(render_user_pronoun_hint(), true);
|
||||||
|
$hints_renderer->addHint(render_user_firstname_hint(), true);
|
||||||
|
$hints_renderer->addHint(render_user_lastname_hint(), true);
|
||||||
$hints_renderer->addHint(render_user_tshirt_hint(), true);
|
$hints_renderer->addHint(render_user_tshirt_hint(), true);
|
||||||
$hints_renderer->addHint(render_user_dect_hint(), true);
|
$hints_renderer->addHint(render_user_dect_hint(), true);
|
||||||
|
$hints_renderer->addHint(render_user_mobile_hint(), true);
|
||||||
|
|
||||||
return $hints_renderer->render();
|
return $hints_renderer->render();
|
||||||
}
|
}
|
||||||
|
@ -62,10 +56,10 @@ function make_navigation()
|
||||||
$page = current_page();
|
$page = current_page();
|
||||||
$menu = [];
|
$menu = [];
|
||||||
$pages = [
|
$pages = [
|
||||||
'news' => __('News'),
|
'news' => __('news.title'),
|
||||||
'meetings' => [__('Meetings'), 'user_meetings'],
|
'meetings' => [__('news.title.meetings'), 'user_meetings'],
|
||||||
'user_shifts' => __('Shifts'),
|
'user_shifts' => __('Shifts'),
|
||||||
'angeltypes' => __('Angeltypes'),
|
'angeltypes' => __('angeltypes.angeltypes'),
|
||||||
'questions' => [__('Ask the Heaven'), 'question.add'],
|
'questions' => [__('Ask the Heaven'), 'question.add'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -75,23 +69,30 @@ function make_navigation()
|
||||||
}
|
}
|
||||||
|
|
||||||
$title = ((array) $options)[0];
|
$title = ((array) $options)[0];
|
||||||
$menu[] = toolbar_item_link(page_link_to($menu_page), '', $title, $menu_page == $page);
|
$menu[] = toolbar_item_link(
|
||||||
|
url(str_replace('_', '-', $menu_page)),
|
||||||
|
'',
|
||||||
|
$title,
|
||||||
|
$menu_page == $page
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$menu = make_room_navigation($menu);
|
$menu = make_location_navigation($menu);
|
||||||
|
|
||||||
$admin_menu = [];
|
$admin_menu = [];
|
||||||
$admin_pages = [
|
$admin_pages = [
|
||||||
// path => name
|
// Examples:
|
||||||
// path => [name, permission]
|
// path => name,
|
||||||
|
// path => [name, permission],
|
||||||
|
|
||||||
'admin_arrive' => 'Arrive angels',
|
'admin_arrive' => 'Arrive angels',
|
||||||
'admin_active' => 'Active angels',
|
'admin_active' => 'Active angels',
|
||||||
'users' => ['All Angels', 'admin_user'],
|
'users' => ['All Angels', 'admin_user'],
|
||||||
'admin_free' => 'Free angels',
|
'admin_free' => 'Free angels',
|
||||||
'admin/questions' => ['Answer questions', 'question.edit'],
|
'admin/questions' => ['Answer questions', 'question.edit'],
|
||||||
'shifttypes' => 'Shifttypes',
|
'admin/shifttypes' => ['shifttype.shifttypes', 'shifttypes'],
|
||||||
'admin_shifts' => 'Create shifts',
|
'admin_shifts' => 'Create shifts',
|
||||||
'admin/rooms' => ['room.rooms', 'admin_rooms'],
|
'admin/locations' => ['location.locations', 'admin_locations'],
|
||||||
'admin_groups' => 'Grouprights',
|
'admin_groups' => 'Grouprights',
|
||||||
'admin/schedule' => ['schedule.import', 'schedule.import'],
|
'admin/schedule' => ['schedule.import', 'schedule.import'],
|
||||||
'admin/logs' => ['log.log', 'admin_log'],
|
'admin/logs' => ['log.log', 'admin_log'],
|
||||||
|
@ -109,8 +110,8 @@ function make_navigation()
|
||||||
|
|
||||||
$title = ((array) $options)[0];
|
$title = ((array) $options)[0];
|
||||||
$admin_menu[] = toolbar_dropdown_item(
|
$admin_menu[] = toolbar_dropdown_item(
|
||||||
page_link_to($menu_page),
|
url(str_replace('_', '-', $menu_page)),
|
||||||
__($title),
|
htmlspecialchars(__($title)),
|
||||||
$menu_page == $page
|
$menu_page == $page
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -141,31 +142,36 @@ function menu_is_allowed(string $page, $options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds room navigation to the given menu.
|
* Adds location navigation to the given menu.
|
||||||
*
|
*
|
||||||
* @param string[] $menu Rendered menu
|
* @param string[] $menu Rendered menu
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
function make_room_navigation($menu)
|
function make_location_navigation($menu)
|
||||||
{
|
{
|
||||||
if (!auth()->can('view_rooms')) {
|
if (!auth()->can('view_locations')) {
|
||||||
return $menu;
|
return $menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a list of all rooms
|
// Get a list of all locations
|
||||||
$rooms = Room::orderBy('name')->get();
|
$locations = Location::orderBy('name')->get();
|
||||||
$room_menu = [];
|
$location_menu = [];
|
||||||
if (auth()->can('admin_rooms')) {
|
if (auth()->can('admin_locations')) {
|
||||||
$room_menu[] = toolbar_dropdown_item(page_link_to('admin/rooms'), __('Manage rooms'), false, 'list');
|
$location_menu[] = toolbar_dropdown_item(
|
||||||
|
url('/admin/locations'),
|
||||||
|
__('Manage locations'),
|
||||||
|
false,
|
||||||
|
'list'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (count($room_menu) > 0) {
|
if (count($location_menu) > 0) {
|
||||||
$room_menu[] = toolbar_dropdown_item_divider();
|
$location_menu[] = toolbar_dropdown_item_divider();
|
||||||
}
|
}
|
||||||
foreach ($rooms as $room) {
|
foreach ($locations as $location) {
|
||||||
$room_menu[] = toolbar_dropdown_item(room_link($room), $room->name, false, 'pin-map-fill');
|
$location_menu[] = toolbar_dropdown_item(location_link($location), $location->name, false, 'pin-map-fill');
|
||||||
}
|
}
|
||||||
if (count($room_menu) > 0) {
|
if (count($location_menu) > 0) {
|
||||||
$menu[] = toolbar_dropdown(__('Rooms'), $room_menu);
|
$menu[] = toolbar_dropdown(__('Locations'), $location_menu);
|
||||||
}
|
}
|
||||||
return $menu;
|
return $menu;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +215,7 @@ function admin_new_questions()
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return '<a href="' . page_link_to('/admin/questions') . '">'
|
return '<a href="' . url('/admin/questions') . '">'
|
||||||
. __('There are unanswered questions!')
|
. __('There are unanswered questions!')
|
||||||
. '</a>';
|
. '</a>';
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
use Engelsystem\Helpers\Carbon;
|
use Engelsystem\Helpers\Carbon;
|
||||||
use Engelsystem\Http\Exceptions\HttpTemporaryRedirect;
|
use Engelsystem\Http\Exceptions\HttpTemporaryRedirect;
|
||||||
use Engelsystem\Models\BaseModel;
|
|
||||||
use Engelsystem\ValidationResult;
|
use Engelsystem\ValidationResult;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide page/request helper functions
|
* Provide page/request helper functions
|
||||||
|
@ -63,41 +61,6 @@ function throw_redirect($url)
|
||||||
throw new HttpTemporaryRedirect($url);
|
throw new HttpTemporaryRedirect($url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Echoes given output and dies.
|
|
||||||
*
|
|
||||||
* @param string $output String to display
|
|
||||||
*/
|
|
||||||
function raw_output($output = '')
|
|
||||||
{
|
|
||||||
echo $output;
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function for transforming list of entities into array for select boxes.
|
|
||||||
*
|
|
||||||
* @param array|Collection $data The data array
|
|
||||||
* @param string $key_name name of the column to use as id/key
|
|
||||||
* @param string $value_name name of the column to use as displayed value
|
|
||||||
*
|
|
||||||
* @return array|Collection
|
|
||||||
*/
|
|
||||||
function select_array($data, $key_name, $value_name)
|
|
||||||
{
|
|
||||||
if ($data instanceof Collection) {
|
|
||||||
return $data->mapWithKeys(function (BaseModel $model) use ($key_name, $value_name) {
|
|
||||||
return [$model->{$key_name} => $model->{$value_name}];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$return = [];
|
|
||||||
foreach ($data as $value) {
|
|
||||||
$return[$value[$key_name]] = $value[$value_name];
|
|
||||||
}
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an int[] from given request param name.
|
* Returns an int[] from given request param name.
|
||||||
*
|
*
|
||||||
|
@ -185,23 +148,6 @@ function strip_request_item($name, $default_value = null)
|
||||||
return $default_value;
|
return $default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns REQUEST value or default value (null) if not set.
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param string|null $default_value
|
|
||||||
* @return mixed|null
|
|
||||||
*/
|
|
||||||
function strip_request_tags($name, $default_value = null)
|
|
||||||
{
|
|
||||||
$request = request();
|
|
||||||
if ($request->has($name)) {
|
|
||||||
return strip_tags($request->input($name));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $default_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Testet, ob der angegebene REQUEST Wert ein Integer ist, bzw.
|
* Testet, ob der angegebene REQUEST Wert ein Integer ist, bzw.
|
||||||
* eine ID sein könnte.
|
* eine ID sein könnte.
|
||||||
|
|
|
@ -72,17 +72,6 @@ function tabs($tabs, $selected = 0)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Display muted (grey) text.
|
|
||||||
*
|
|
||||||
* @param string $text
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function mute($text)
|
|
||||||
{
|
|
||||||
return '<span class="text-muted">' . $text . '</span>';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a bootstrap label with given content and class.
|
* Renders a bootstrap label with given content and class.
|
||||||
*
|
*
|
||||||
|
@ -188,7 +177,7 @@ function toolbar_item_link($href, $icon, $label, $active = false)
|
||||||
return '<li class="nav-item">'
|
return '<li class="nav-item">'
|
||||||
. '<a class="nav-link ' . ($active ? 'active" aria-current="page"' : '"') . ' href="' . $href . '">'
|
. '<a class="nav-link ' . ($active ? 'active" aria-current="page"' : '"') . ' href="' . $href . '">'
|
||||||
. ($icon != '' ? '<span class="bi bi-' . $icon . '"></span> ' : '')
|
. ($icon != '' ? '<span class="bi bi-' . $icon . '"></span> ' : '')
|
||||||
. $label
|
. htmlspecialchars($label)
|
||||||
. '</a>'
|
. '</a>'
|
||||||
. '</li>';
|
. '</li>';
|
||||||
}
|
}
|
||||||
|
@ -196,11 +185,11 @@ function toolbar_item_link($href, $icon, $label, $active = false)
|
||||||
function toolbar_dropdown_item(string $href, string $label, bool $active, string $icon = null): string
|
function toolbar_dropdown_item(string $href, string $label, bool $active, string $icon = null): string
|
||||||
{
|
{
|
||||||
return strtr(
|
return strtr(
|
||||||
'<li><a class="dropdown-item{active}"{aria} href="{href}">{icon} {label}</a></li>',
|
'<li><a class="dropdown-item{active}" {aria} href="{href}">{icon} {label}</a></li>',
|
||||||
[
|
[
|
||||||
'{href}' => $href,
|
'{href}' => $href,
|
||||||
'{icon}' => $icon === null ? '' : '<i class="bi bi-' . $icon . '"></i>',
|
'{icon}' => $icon === null ? '' : '<i class="bi bi-' . $icon . '"></i>',
|
||||||
'{label}' => $label,
|
'{label}' => htmlspecialchars($label),
|
||||||
'{active}' => $active ? ' active' : '',
|
'{active}' => $active ? ' active' : '',
|
||||||
'{aria}' => $active ? ' aria-current="page"' : '',
|
'{aria}' => $active ? ' aria-current="page"' : '',
|
||||||
]
|
]
|
||||||
|
@ -235,7 +224,7 @@ EOT;
|
||||||
$template,
|
$template,
|
||||||
[
|
[
|
||||||
'{class}' => $active ? ' active' : '',
|
'{class}' => $active ? ' active' : '',
|
||||||
'{label}' => $label,
|
'{label}' => htmlspecialchars($label),
|
||||||
'{submenu}' => join("\n", $submenu),
|
'{submenu}' => join("\n", $submenu),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -338,7 +327,7 @@ function render_table($columns, $rows, $data = true)
|
||||||
$html .= '</tr></thead>';
|
$html .= '</tr></thead>';
|
||||||
$html .= '<tbody>';
|
$html .= '<tbody>';
|
||||||
foreach ($rows as $row) {
|
foreach ($rows as $row) {
|
||||||
$html .= '<tr>';
|
$html .= '<tr' . (isset($row['row-class']) ? ' class="' . $row['row-class'] . '"' : '') . '>';
|
||||||
foreach ($columns as $key => $column) {
|
foreach ($columns as $key => $column) {
|
||||||
$value = ' ';
|
$value = ' ';
|
||||||
if (isset($row[$key])) {
|
if (isset($row[$key])) {
|
||||||
|
@ -362,7 +351,7 @@ function render_table($columns, $rows, $data = true)
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function button($href, $label, $class = '', $id = '')
|
function button($href, $label, $class = '', $id = '', $title = '')
|
||||||
{
|
{
|
||||||
if (!Str::contains(str_replace(['btn-sm', 'btn-xl'], '', $class), 'btn-')) {
|
if (!Str::contains(str_replace(['btn-sm', 'btn-xl'], '', $class), 'btn-')) {
|
||||||
$class = 'btn-secondary' . ($class ? ' ' . $class : '');
|
$class = 'btn-secondary' . ($class ? ' ' . $class : '');
|
||||||
|
@ -370,7 +359,8 @@ function button($href, $label, $class = '', $id = '')
|
||||||
|
|
||||||
$idAttribute = $id ? 'id="' . $id . '"' : '';
|
$idAttribute = $id ? 'id="' . $id . '"' : '';
|
||||||
|
|
||||||
return '<a ' . $idAttribute . ' href="' . $href . '" class="btn ' . $class . '">' . $label . '</a>';
|
return '<a ' . $idAttribute . ' href="' . $href
|
||||||
|
. '" class="btn ' . $class . '" title="' . $title . '">' . $label . '</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -396,9 +386,9 @@ function button_checkbox_selection($name, $label, $value)
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function button_icon($href, $icon, $class = '')
|
function button_icon($href, $icon, $class = '', $title = '')
|
||||||
{
|
{
|
||||||
return button($href, icon($icon), $class);
|
return button($href, icon($icon), $class, '', $title);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,7 +26,7 @@ function AngelType_name_render(AngelType $angeltype, $plain = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return '<a href="' . angeltype_link($angeltype->id) . '">'
|
return '<a href="' . angeltype_link($angeltype->id) . '">'
|
||||||
. ($angeltype->restricted ? icon('mortarboard-fill') : '') . $angeltype->name
|
. ($angeltype->restricted ? icon('mortarboard-fill') : '') . htmlspecialchars($angeltype->name)
|
||||||
. '</a>';
|
. '</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,12 +60,15 @@ function AngelType_render_membership(AngelType $user_angeltype)
|
||||||
*/
|
*/
|
||||||
function AngelType_delete_view(AngelType $angeltype)
|
function AngelType_delete_view(AngelType $angeltype)
|
||||||
{
|
{
|
||||||
return page_with_title(sprintf(__('Delete angeltype %s'), $angeltype->name), [
|
$link = button($angeltype->id
|
||||||
|
? url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id])
|
||||||
|
: url('/angeltypes'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
|
||||||
|
return page_with_title($link . ' ' . sprintf(__('Delete angeltype %s'), htmlspecialchars($angeltype->name)), [
|
||||||
info(sprintf(__('Do you want to delete angeltype %s?'), $angeltype->name), true),
|
info(sprintf(__('Do you want to delete angeltype %s?'), $angeltype->name), true),
|
||||||
form([
|
form([
|
||||||
buttons([
|
buttons([
|
||||||
button(page_link_to('angeltypes'), icon('x-lg') . __('cancel')),
|
button(url('/angeltypes'), icon('x-lg') . __('form.cancel')),
|
||||||
form_submit('delete', icon('trash') . __('delete'), 'btn-danger', false),
|
form_submit('delete', icon('trash'), 'btn-danger', false, 'primary', __('form.delete')),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
], true);
|
], true);
|
||||||
|
@ -80,56 +83,96 @@ function AngelType_delete_view(AngelType $angeltype)
|
||||||
*/
|
*/
|
||||||
function AngelType_edit_view(AngelType $angeltype, bool $supporter_mode)
|
function AngelType_edit_view(AngelType $angeltype, bool $supporter_mode)
|
||||||
{
|
{
|
||||||
return page_with_title(sprintf(__('Edit %s'), $angeltype->name), [
|
$link = button($angeltype->id
|
||||||
buttons([
|
? url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id])
|
||||||
button(page_link_to('angeltypes'), icon('person-lines-fill') . __('Angeltypes'), 'back'),
|
: url('/angeltypes'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
|
||||||
]),
|
return page_with_title(
|
||||||
msg(),
|
$link . ' ' . (
|
||||||
form([
|
$angeltype->id ?
|
||||||
$supporter_mode
|
sprintf(__('Edit %s'), htmlspecialchars((string) $angeltype->name)) :
|
||||||
? form_info(__('Name'), $angeltype->name)
|
__('Create angeltype')
|
||||||
: form_text('name', __('Name'), $angeltype->name),
|
),
|
||||||
$supporter_mode
|
[
|
||||||
? form_info(__('Requires introduction'), $angeltype->restricted ? __('Yes') : __('No'))
|
$angeltype->id ?
|
||||||
: form_checkbox('restricted', __('Requires introduction'), $angeltype->restricted),
|
buttons([
|
||||||
form_info(
|
button(url('/angeltypes'), icon('person-lines-fill') . __('angeltypes.angeltypes'), 'back'),
|
||||||
'',
|
]) : '',
|
||||||
__('Angel types which require introduction can only be used by an angel if enabled by a supporter (double opt-in).')
|
msg(),
|
||||||
),
|
form([
|
||||||
$supporter_mode
|
$supporter_mode
|
||||||
? form_info(__('No Self Sign Up allowed'), $angeltype->no_self_signup ? __('Yes') : __('No'))
|
? form_info(__('general.name'), htmlspecialchars($angeltype->name))
|
||||||
: form_checkbox('no_self_signup', __('No Self Sign Up allowed'), $angeltype->no_self_signup),
|
: form_text('name', __('general.name'), $angeltype->name),
|
||||||
$supporter_mode ?
|
$supporter_mode
|
||||||
|
? form_info(__('angeltypes.restricted'), $angeltype->restricted ? __('Yes') : __('No'))
|
||||||
|
: form_checkbox(
|
||||||
|
'restricted',
|
||||||
|
__('angeltypes.restricted') .
|
||||||
|
' <span class="bi bi-info-circle-fill text-info" data-bs-toggle="tooltip" title="' .
|
||||||
|
__('angeltypes.restricted.info') . '"></span>',
|
||||||
|
$angeltype->restricted
|
||||||
|
),
|
||||||
|
$supporter_mode
|
||||||
|
? form_info(__('shift.self_signup'), $angeltype->shift_self_signup ? __('Yes') : __('No'))
|
||||||
|
: form_checkbox(
|
||||||
|
'shift_self_signup',
|
||||||
|
__('shift.self_signup') .
|
||||||
|
' <span class="bi bi-info-circle-fill text-info" data-bs-toggle="tooltip" title="' .
|
||||||
|
__('angeltypes.shift.self_signup.info') . '"></span>',
|
||||||
|
$angeltype->shift_self_signup
|
||||||
|
),
|
||||||
|
$supporter_mode ?
|
||||||
|
form_info(
|
||||||
|
__('Requires driver license'),
|
||||||
|
$angeltype->requires_driver_license
|
||||||
|
? __('Yes')
|
||||||
|
: __('No')
|
||||||
|
) :
|
||||||
|
form_checkbox(
|
||||||
|
'requires_driver_license',
|
||||||
|
__('Requires driver license'),
|
||||||
|
$angeltype->requires_driver_license
|
||||||
|
),
|
||||||
|
$supporter_mode && config('ifsg_enabled') ?
|
||||||
|
form_info(
|
||||||
|
__('angeltype.ifsg.required'),
|
||||||
|
$angeltype->requires_ifsg_certificate
|
||||||
|
? __('Yes')
|
||||||
|
: __('No')
|
||||||
|
) :
|
||||||
|
form_checkbox(
|
||||||
|
'requires_ifsg_certificate',
|
||||||
|
__('angeltype.ifsg.required'),
|
||||||
|
$angeltype->requires_ifsg_certificate
|
||||||
|
),
|
||||||
|
$supporter_mode
|
||||||
|
? form_info(__('Show on dashboard'), $angeltype->show_on_dashboard ? __('Yes') : __('No'))
|
||||||
|
: form_checkbox('show_on_dashboard', __('Show on dashboard'), $angeltype->show_on_dashboard),
|
||||||
|
$supporter_mode
|
||||||
|
? form_info(__('Hide at Registration'), $angeltype->hide_register ? __('Yes') : __('No'))
|
||||||
|
: form_checkbox('hide_register', __('Hide at Registration'), $angeltype->hide_register),
|
||||||
|
$supporter_mode
|
||||||
|
? form_info(__('angeltypes.hide_on_shift_view'), $angeltype->hide_on_shift_view ? __('Yes') : __('No'))
|
||||||
|
: form_checkbox(
|
||||||
|
'hide_on_shift_view',
|
||||||
|
__('angeltypes.hide_on_shift_view') .
|
||||||
|
' <span class="bi bi-info-circle-fill text-info" data-bs-toggle="tooltip" title="' .
|
||||||
|
__('angeltypes.hide_on_shift_view.info') . '"></span>',
|
||||||
|
$angeltype->hide_on_shift_view
|
||||||
|
),
|
||||||
|
form_textarea('description', __('general.description'), $angeltype->description),
|
||||||
|
form_info('', __('Please use markdown for the description.')),
|
||||||
|
heading(__('Contact'), 3),
|
||||||
form_info(
|
form_info(
|
||||||
__('Requires driver license'),
|
'',
|
||||||
$angeltype->requires_driver_license
|
__('Primary contact person/desk for user questions.')
|
||||||
? __('Yes')
|
|
||||||
: __('No')
|
|
||||||
) :
|
|
||||||
form_checkbox(
|
|
||||||
'requires_driver_license',
|
|
||||||
__('Requires driver license'),
|
|
||||||
$angeltype->requires_driver_license
|
|
||||||
),
|
),
|
||||||
$supporter_mode
|
form_text('contact_name', __('general.name'), $angeltype->contact_name),
|
||||||
? form_info(__('Show on dashboard'), $angeltype->show_on_dashboard ? __('Yes') : __('No'))
|
config('enable_dect') ? form_text('contact_dect', __('general.dect'), $angeltype->contact_dect) : '',
|
||||||
: form_checkbox('show_on_dashboard', __('Show on dashboard'), $angeltype->show_on_dashboard),
|
form_text('contact_email', __('general.email'), $angeltype->contact_email),
|
||||||
$supporter_mode
|
form_submit('submit', icon('save') . __('form.save')),
|
||||||
? form_info(__('Hide at Registration'), $angeltype->hide_register ? __('Yes') : __('No'))
|
]),
|
||||||
: form_checkbox('hide_register', __('Hide at Registration'), $angeltype->hide_register),
|
]
|
||||||
form_textarea('description', __('Description'), $angeltype->description),
|
);
|
||||||
form_info('', __('Please use markdown for the description.')),
|
|
||||||
heading(__('Contact'), 3),
|
|
||||||
form_info(
|
|
||||||
'',
|
|
||||||
__('Primary contact person/desk for user questions.')
|
|
||||||
),
|
|
||||||
form_text('contact_name', __('Name'), $angeltype->contact_name),
|
|
||||||
config('enable_dect') ? form_text('contact_dect', __('DECT'), $angeltype->contact_dect) : '',
|
|
||||||
form_text('contact_email', __('E-Mail'), $angeltype->contact_email),
|
|
||||||
form_submit('submit', __('Save')),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,28 +194,40 @@ function AngelType_view_buttons(
|
||||||
$user_driver_license,
|
$user_driver_license,
|
||||||
$user
|
$user
|
||||||
) {
|
) {
|
||||||
$buttons = [
|
|
||||||
button(page_link_to('angeltypes'), icon('person-lines-fill') . __('Angeltypes'), 'back'),
|
|
||||||
];
|
|
||||||
|
|
||||||
if ($angeltype->requires_driver_license) {
|
if ($angeltype->requires_driver_license) {
|
||||||
$buttons[] = button(
|
$buttons[] = button(
|
||||||
user_driver_license_edit_link($user),
|
url('/settings/certificates'),
|
||||||
icon('person-vcard') . __('my driving license')
|
icon('person-vcard') . __('my driving license')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (config('isfg_enabled') && $angeltype->requires_ifsg_certificate) {
|
||||||
|
$buttons[] = button(
|
||||||
|
url('/settings/certificates'),
|
||||||
|
icon('card-checklist') . __('angeltype.ifsg.own')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_null($user_angeltype)) {
|
if (is_null($user_angeltype)) {
|
||||||
$buttons[] = button(
|
$buttons[] = button(
|
||||||
page_link_to('user_angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
|
url('/user-angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('box-arrow-in-right') . __('join'),
|
icon('box-arrow-in-right') . ($admin_angeltypes ? '' : __('Join')),
|
||||||
'add'
|
'add',
|
||||||
|
'',
|
||||||
|
($admin_angeltypes ? 'Join' : ''),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if ($angeltype->requires_driver_license && !$user_driver_license->wantsToDrive()) {
|
if ($angeltype->requires_driver_license && !$user_driver_license->wantsToDrive()) {
|
||||||
error(__('This angeltype requires a driver license. Please enter your driver license information!'));
|
error(__('This angeltype requires a driver license. Please enter your driver license information!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
config('ifsg_enabled') && $angeltype->requires_ifsg_certificate && !(
|
||||||
|
$user->license->ifsg_certificate_light || $user->license->ifsg_certificate
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
error(__('angeltype.ifsg.required.info'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($angeltype->restricted && !$user_angeltype->confirm_user_id) {
|
if ($angeltype->restricted && !$user_angeltype->confirm_user_id) {
|
||||||
error(sprintf(
|
error(sprintf(
|
||||||
__('You are unconfirmed for this angeltype. Please go to the introduction for %s to get confirmed.'),
|
__('You are unconfirmed for this angeltype. Please go to the introduction for %s to get confirmed.'),
|
||||||
|
@ -180,21 +235,30 @@ function AngelType_view_buttons(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
$buttons[] = button(
|
$buttons[] = button(
|
||||||
page_link_to('user_angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype->id]),
|
url('/user-angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype->id]),
|
||||||
icon('box-arrow-right') . __('leave')
|
icon('box-arrow-right') . ($admin_angeltypes ? '' : __('Leave')),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
($admin_angeltypes ? __('Leave') : ''),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($admin_angeltypes || $supporter) {
|
if ($admin_angeltypes || $supporter) {
|
||||||
$buttons[] = button(
|
$buttons[] = button(
|
||||||
page_link_to('angeltypes', ['action' => 'edit', 'angeltype_id' => $angeltype->id]),
|
url('/angeltypes', ['action' => 'edit', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('pencil') . __('edit')
|
icon('pencil'),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
__('form.edit')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ($admin_angeltypes) {
|
if ($admin_angeltypes) {
|
||||||
$buttons[] = button(
|
$buttons[] = button(
|
||||||
page_link_to('angeltypes', ['action' => 'delete', 'angeltype_id' => $angeltype->id]),
|
url('/angeltypes', ['action' => 'delete', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('trash') . __('delete')
|
icon('trash'),
|
||||||
|
'btn-danger',
|
||||||
|
'',
|
||||||
|
__('form.delete')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +282,7 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
||||||
foreach ($members as $member) {
|
foreach ($members as $member) {
|
||||||
$member->name = User_Nick_render($member) . User_Pronoun_render($member);
|
$member->name = User_Nick_render($member) . User_Pronoun_render($member);
|
||||||
if (config('enable_dect')) {
|
if (config('enable_dect')) {
|
||||||
$member['dect'] = $member->contact->dect;
|
$member['dect'] = htmlspecialchars((string) $member->contact->dect);
|
||||||
}
|
}
|
||||||
if ($angeltype->requires_driver_license) {
|
if ($angeltype->requires_driver_license) {
|
||||||
$member['wants_to_drive'] = icon_bool($member->license->wantsToDrive());
|
$member['wants_to_drive'] = icon_bool($member->license->wantsToDrive());
|
||||||
|
@ -229,23 +293,29 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
||||||
$member['has_license_12t_truck'] = icon_bool($member->license->drive_12t);
|
$member['has_license_12t_truck'] = icon_bool($member->license->drive_12t);
|
||||||
$member['has_license_forklift'] = icon_bool($member->license->drive_forklift);
|
$member['has_license_forklift'] = icon_bool($member->license->drive_forklift);
|
||||||
}
|
}
|
||||||
|
if ($angeltype->requires_ifsg_certificate && config('ifsg_enabled')) {
|
||||||
|
$member['ifsg_certificate'] = icon_bool($member->license->ifsg_certificate);
|
||||||
|
if (config('ifsg_light_enabled')) {
|
||||||
|
$member['ifsg_certificate_light'] = icon_bool($member->license->ifsg_certificate_light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($angeltype->restricted && empty($member->pivot->confirm_user_id)) {
|
if ($angeltype->restricted && empty($member->pivot->confirm_user_id)) {
|
||||||
$member['actions'] = table_buttons([
|
$member['actions'] = table_buttons([
|
||||||
button(
|
button(
|
||||||
page_link_to(
|
url(
|
||||||
'user_angeltypes',
|
'/user-angeltypes',
|
||||||
['action' => 'confirm', 'user_angeltype_id' => $member->pivot->id]
|
['action' => 'confirm', 'user_angeltype_id' => $member->pivot->id]
|
||||||
),
|
),
|
||||||
__('confirm'),
|
__('Confirm'),
|
||||||
'btn-sm'
|
'btn-sm'
|
||||||
),
|
),
|
||||||
button(
|
button(
|
||||||
page_link_to(
|
url(
|
||||||
'user_angeltypes',
|
'/user-angeltypes',
|
||||||
['action' => 'delete', 'user_angeltype_id' => $member->pivot->id]
|
['action' => 'delete', 'user_angeltype_id' => $member->pivot->id]
|
||||||
),
|
),
|
||||||
__('deny'),
|
__('Deny'),
|
||||||
'btn-sm'
|
'btn-sm'
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
@ -254,13 +324,15 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
||||||
if ($admin_angeltypes) {
|
if ($admin_angeltypes) {
|
||||||
$member['actions'] = table_buttons([
|
$member['actions'] = table_buttons([
|
||||||
button(
|
button(
|
||||||
page_link_to('user_angeltypes', [
|
url('/user-angeltypes', [
|
||||||
'action' => 'update',
|
'action' => 'update',
|
||||||
'user_angeltype_id' => $member->pivot->id,
|
'user_angeltype_id' => $member->pivot->id,
|
||||||
'supporter' => 0,
|
'supporter' => 0,
|
||||||
]),
|
]),
|
||||||
icon('person-fill-down') . __('Remove supporter rights'),
|
icon('person-fill-down'),
|
||||||
'btn-sm'
|
'btn-sm',
|
||||||
|
'',
|
||||||
|
__('Remove supporter rights'),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -272,22 +344,26 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
||||||
$member['actions'] = table_buttons([
|
$member['actions'] = table_buttons([
|
||||||
$admin_angeltypes ?
|
$admin_angeltypes ?
|
||||||
button(
|
button(
|
||||||
page_link_to('user_angeltypes', [
|
url('/user-angeltypes', [
|
||||||
'action' => 'update',
|
'action' => 'update',
|
||||||
'user_angeltype_id' => $member->pivot->id,
|
'user_angeltype_id' => $member->pivot->id,
|
||||||
'supporter' => 1,
|
'supporter' => 1,
|
||||||
]),
|
]),
|
||||||
icon('person-fill-up') . __('Add supporter rights'),
|
icon('person-fill-up'),
|
||||||
'btn-sm'
|
'btn-sm',
|
||||||
|
'',
|
||||||
|
__('Add supporter rights'),
|
||||||
) :
|
) :
|
||||||
'',
|
'',
|
||||||
button(
|
button(
|
||||||
page_link_to('user_angeltypes', [
|
url('/user-angeltypes', [
|
||||||
'action' => 'delete',
|
'action' => 'delete',
|
||||||
'user_angeltype_id' => $member->pivot->id,
|
'user_angeltype_id' => $member->pivot->id,
|
||||||
]),
|
]),
|
||||||
icon('trash') . __('remove'),
|
icon('trash'),
|
||||||
'btn-sm'
|
'btn-sm btn-danger',
|
||||||
|
'',
|
||||||
|
__('Remove'),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -313,27 +389,34 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
|
||||||
function AngelType_view_table_headers(AngelType $angeltype, $supporter, $admin_angeltypes)
|
function AngelType_view_table_headers(AngelType $angeltype, $supporter, $admin_angeltypes)
|
||||||
{
|
{
|
||||||
$headers = [
|
$headers = [
|
||||||
'name' => __('Nick'),
|
'name' => __('general.nick'),
|
||||||
'dect' => __('DECT'),
|
|
||||||
'actions' => '',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (config('enable_dect')) {
|
||||||
|
$headers['dect'] = __('general.dect');
|
||||||
|
}
|
||||||
|
|
||||||
if ($angeltype->requires_driver_license && ($supporter || $admin_angeltypes)) {
|
if ($angeltype->requires_driver_license && ($supporter || $admin_angeltypes)) {
|
||||||
$headers = [
|
$headers = array_merge($headers, [
|
||||||
'name' => __('Nick'),
|
|
||||||
'dect' => __('DECT'),
|
|
||||||
'wants_to_drive' => __('Driver'),
|
'wants_to_drive' => __('Driver'),
|
||||||
'has_car' => __('Has car'),
|
'has_car' => __('Has car'),
|
||||||
'has_license_car' => __('Car'),
|
'has_license_car' => __('settings.certificates.drive_car'),
|
||||||
'has_license_3_5t_transporter' => __('3,5t Transporter'),
|
'has_license_3_5t_transporter' => __('settings.certificates.drive_3_5t'),
|
||||||
'has_license_7_5t_truck' => __('7,5t Truck'),
|
'has_license_7_5t_truck' => __('settings.certificates.drive_7_5t'),
|
||||||
'has_license_12t_truck' => __('12t Truck'),
|
'has_license_12t_truck' => __('settings.certificates.drive_12t'),
|
||||||
'has_license_forklift' => __('Forklift'),
|
'has_license_forklift' => __('settings.certificates.drive_forklift'),
|
||||||
'actions' => '',
|
]);
|
||||||
];
|
|
||||||
}
|
}
|
||||||
if (!config('enable_dect')) {
|
|
||||||
unset($headers['dect']);
|
if (config('ifsg_enabled') && $angeltype->requires_ifsg_certificate && ($supporter || $admin_angeltypes)) {
|
||||||
|
if (config('ifsg_light_enabled')) {
|
||||||
|
$headers['ifsg_certificate_light'] = __('ifsg.certificate_light');
|
||||||
|
}
|
||||||
|
$headers['ifsg_certificate'] = __('ifsg.certificate');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$headers['actions'] = '';
|
||||||
|
|
||||||
return $headers;
|
return $headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,24 +449,29 @@ function AngelType_view(
|
||||||
ShiftCalendarRenderer $shiftCalendarRenderer,
|
ShiftCalendarRenderer $shiftCalendarRenderer,
|
||||||
$tab
|
$tab
|
||||||
) {
|
) {
|
||||||
return page_with_title(sprintf(__('Team %s'), $angeltype->name), [
|
$link = button(url('/angeltypes'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
|
||||||
AngelType_view_buttons($angeltype, $user_angeltype, $admin_angeltypes, $supporter, $user_driver_license, $user),
|
return page_with_title(
|
||||||
msg(),
|
$link . ' ' . sprintf(__('Team %s'), htmlspecialchars($angeltype->name)),
|
||||||
tabs([
|
[
|
||||||
__('Info') => AngelType_view_info(
|
AngelType_view_buttons($angeltype, $user_angeltype, $admin_angeltypes, $supporter, $user_driver_license, $user),
|
||||||
$angeltype,
|
msg(),
|
||||||
$members,
|
tabs([
|
||||||
$admin_user_angeltypes,
|
__('Info') => AngelType_view_info(
|
||||||
$admin_angeltypes,
|
$angeltype,
|
||||||
$supporter
|
$members,
|
||||||
),
|
$admin_user_angeltypes,
|
||||||
__('Shifts') => AngelType_view_shifts(
|
$admin_angeltypes,
|
||||||
$angeltype,
|
$supporter
|
||||||
$shiftsFilterRenderer,
|
),
|
||||||
$shiftCalendarRenderer
|
__('Shifts') => AngelType_view_shifts(
|
||||||
),
|
$angeltype,
|
||||||
], $tab),
|
$shiftsFilterRenderer,
|
||||||
], true);
|
$shiftCalendarRenderer
|
||||||
|
),
|
||||||
|
], $tab),
|
||||||
|
],
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -394,7 +482,7 @@ function AngelType_view(
|
||||||
*/
|
*/
|
||||||
function AngelType_view_shifts(AngelType $angeltype, $shiftsFilterRenderer, $shiftCalendarRenderer)
|
function AngelType_view_shifts(AngelType $angeltype, $shiftsFilterRenderer, $shiftCalendarRenderer)
|
||||||
{
|
{
|
||||||
$shifts = $shiftsFilterRenderer->render(page_link_to('angeltypes', [
|
$shifts = $shiftsFilterRenderer->render(url('/angeltypes', [
|
||||||
'action' => 'view',
|
'action' => 'view',
|
||||||
'angeltype_id' => $angeltype->id,
|
'angeltype_id' => $angeltype->id,
|
||||||
]), ['type' => $angeltype->id]);
|
]), ['type' => $angeltype->id]);
|
||||||
|
@ -423,10 +511,10 @@ function AngelType_view_info(
|
||||||
$info[] = AngelTypes_render_contact_info($angeltype);
|
$info[] = AngelTypes_render_contact_info($angeltype);
|
||||||
}
|
}
|
||||||
|
|
||||||
$info[] = '<h3>' . __('Description') . '</h3>';
|
$info[] = '<h3>' . __('general.description') . '</h3>';
|
||||||
$parsedown = new Parsedown();
|
$parsedown = new Parsedown();
|
||||||
if ($angeltype->description != '') {
|
if ($angeltype->description != '') {
|
||||||
$info[] = $parsedown->parse($angeltype->description);
|
$info[] = $parsedown->parse(htmlspecialchars($angeltype->description));
|
||||||
}
|
}
|
||||||
|
|
||||||
list($supporters, $members_confirmed, $members_unconfirmed) = AngelType_view_members(
|
list($supporters, $members_confirmed, $members_unconfirmed) = AngelType_view_members(
|
||||||
|
@ -462,11 +550,11 @@ function AngelType_view_info(
|
||||||
if ($admin_user_angeltypes) {
|
if ($admin_user_angeltypes) {
|
||||||
$info[] = buttons([
|
$info[] = buttons([
|
||||||
button(
|
button(
|
||||||
page_link_to(
|
url(
|
||||||
'user_angeltypes',
|
'/user-angeltypes',
|
||||||
['action' => 'add', 'angeltype_id' => $angeltype->id]
|
['action' => 'add', 'angeltype_id' => $angeltype->id]
|
||||||
),
|
),
|
||||||
__('Add'),
|
icon('plus-lg') . __('Add'),
|
||||||
'add'
|
'add'
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
@ -477,12 +565,12 @@ function AngelType_view_info(
|
||||||
$info[] = '<h3>' . __('Unconfirmed') . '</h3>';
|
$info[] = '<h3>' . __('Unconfirmed') . '</h3>';
|
||||||
$info[] = buttons([
|
$info[] = buttons([
|
||||||
button(
|
button(
|
||||||
page_link_to('user_angeltypes', ['action' => 'confirm_all', 'angeltype_id' => $angeltype->id]),
|
url('/user-angeltypes', ['action' => 'confirm_all', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('check-lg') . __('confirm all')
|
icon('check-lg') . __('Confirm all')
|
||||||
),
|
),
|
||||||
button(
|
button(
|
||||||
page_link_to('user_angeltypes', ['action' => 'delete_all', 'angeltype_id' => $angeltype->id]),
|
url('/user-angeltypes', ['action' => 'delete_all', 'angeltype_id' => $angeltype->id]),
|
||||||
icon('trash') . __('deny all')
|
icon('trash') . __('Deny all')
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
$info[] = table($table_headers, $members_unconfirmed);
|
$info[] = table($table_headers, $members_unconfirmed);
|
||||||
|
@ -500,9 +588,20 @@ function AngelType_view_info(
|
||||||
function AngelTypes_render_contact_info(AngelType $angeltype)
|
function AngelTypes_render_contact_info(AngelType $angeltype)
|
||||||
{
|
{
|
||||||
$info = [
|
$info = [
|
||||||
__('Name') => [$angeltype->contact_name, $angeltype->contact_name],
|
__('general.name') => [
|
||||||
__('DECT') => config('enable_dect') ? [sprintf('<a href="tel:%s">%1$s</a>', $angeltype->contact_dect), $angeltype->contact_dect] : null,
|
htmlspecialchars($angeltype->contact_name),
|
||||||
__('E-Mail') => [sprintf('<a href="mailto:%s">%1$s</a>', $angeltype->contact_email), $angeltype->contact_email],
|
htmlspecialchars($angeltype->contact_name),
|
||||||
|
],
|
||||||
|
__('general.dect') => config('enable_dect')
|
||||||
|
? [
|
||||||
|
sprintf('<a href="tel:%s">%1$s</a>', htmlspecialchars($angeltype->contact_dect)),
|
||||||
|
htmlspecialchars($angeltype->contact_dect),
|
||||||
|
]
|
||||||
|
: null,
|
||||||
|
__('general.email') => [
|
||||||
|
sprintf('<a href="mailto:%s">%1$s</a>', htmlspecialchars($angeltype->contact_email)),
|
||||||
|
htmlspecialchars($angeltype->contact_email),
|
||||||
|
],
|
||||||
];
|
];
|
||||||
$contactInfo = [];
|
$contactInfo = [];
|
||||||
foreach ($info as $name => $data) {
|
foreach ($info as $name => $data) {
|
||||||
|
@ -523,20 +622,22 @@ function AngelTypes_render_contact_info(AngelType $angeltype)
|
||||||
*/
|
*/
|
||||||
function AngelTypes_list_view($angeltypes, bool $admin_angeltypes)
|
function AngelTypes_list_view($angeltypes, bool $admin_angeltypes)
|
||||||
{
|
{
|
||||||
return page_with_title(angeltypes_title(), [
|
$link = button(url('/angeltypes', ['action' => 'edit']), icon('plus-lg'), 'add');
|
||||||
msg(),
|
return page_with_title(
|
||||||
buttons([
|
angeltypes_title() . ' ' . ($admin_angeltypes ? $link : ''),
|
||||||
$admin_angeltypes
|
[
|
||||||
? button(page_link_to('angeltypes', ['action' => 'edit']), __('New angeltype'), 'add')
|
msg(),
|
||||||
: '',
|
buttons([
|
||||||
button(url('/angeltypes/about'), __('angeltypes.about')),
|
button(url('/angeltypes/about'), __('angeltypes.about')),
|
||||||
]),
|
]),
|
||||||
table([
|
table([
|
||||||
'name' => __('Name'),
|
'name' => __('general.name'),
|
||||||
'is_restricted' => icon('mortarboard-fill') . __('Requires introduction'),
|
'is_restricted' => icon('mortarboard-fill') . __('angeltypes.restricted'),
|
||||||
'no_self_signup_allowed' => icon('pencil-square') . __('Self Sign Up Allowed'),
|
'shift_self_signup_allowed' => icon('pencil-square') . __('shift.self_signup.allowed'),
|
||||||
'membership' => __('Membership'),
|
'membership' => __('Membership'),
|
||||||
'actions' => '',
|
'actions' => '',
|
||||||
], $angeltypes),
|
], $angeltypes),
|
||||||
], true);
|
],
|
||||||
|
true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ function EventConfig_edit_view(
|
||||||
]),
|
]),
|
||||||
div('row', [
|
div('row', [
|
||||||
div('col-md-6', [
|
div('col-md-6', [
|
||||||
form_submit('submit', __('Save')),
|
form_submit('submit', icon('save') . __('form.save')),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Engelsystem\Models\Location;
|
||||||
|
use Engelsystem\ShiftCalendarRenderer;
|
||||||
|
use Engelsystem\ShiftsFilterRenderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param Location $location
|
||||||
|
* @param ShiftsFilterRenderer $shiftsFilterRenderer
|
||||||
|
* @param ShiftCalendarRenderer $shiftCalendarRenderer
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function location_view(Location $location, ShiftsFilterRenderer $shiftsFilterRenderer, ShiftCalendarRenderer $shiftCalendarRenderer)
|
||||||
|
{
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
$assignNotice = '';
|
||||||
|
if (config('signup_requires_arrival') && !$user->state->arrived) {
|
||||||
|
$assignNotice = info(render_user_arrived_hint(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$description = '';
|
||||||
|
if ($location->description) {
|
||||||
|
$description = '<h3>' . __('general.description') . '</h3>';
|
||||||
|
$parsedown = new Parsedown();
|
||||||
|
$description .= $parsedown->parse(htmlspecialchars($location->description));
|
||||||
|
}
|
||||||
|
|
||||||
|
$dect = '';
|
||||||
|
if (config('enable_dect') && $location->dect) {
|
||||||
|
$dect = heading(__('Contact'), 3)
|
||||||
|
. description([__('general.dect') => sprintf(
|
||||||
|
'<a href="tel:%s">%1$s</a>',
|
||||||
|
htmlspecialchars($location->dect)
|
||||||
|
)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tabs = [];
|
||||||
|
if ($location->map_url) {
|
||||||
|
$tabs[__('location.map_url')] = sprintf(
|
||||||
|
'<div class="map">'
|
||||||
|
. '<iframe style="width: 100%%; min-height: 400px; border: 0 none;" src="%s"></iframe>'
|
||||||
|
. '</div>',
|
||||||
|
htmlspecialchars($location->map_url)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tabs[__('Shifts')] = div('first', [
|
||||||
|
$shiftsFilterRenderer->render(url('/locations', [
|
||||||
|
'action' => 'view',
|
||||||
|
'location_id' => $location->id,
|
||||||
|
]), ['locations' => [$location->id]]),
|
||||||
|
$shiftCalendarRenderer->render(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$selected_tab = 0;
|
||||||
|
$request = request();
|
||||||
|
if ($request->has('shifts_filter_day')) {
|
||||||
|
$selected_tab = count($tabs) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$link = button(url('/admin/locations'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
|
||||||
|
return page_with_title(
|
||||||
|
(auth()->can('admin_locations') ? $link . ' ' : '') .
|
||||||
|
icon('pin-map-fill') . htmlspecialchars($location->name),
|
||||||
|
[
|
||||||
|
$assignNotice,
|
||||||
|
auth()->can('admin_locations') ? buttons([
|
||||||
|
button(
|
||||||
|
url('/admin/locations/edit/' . $location->id),
|
||||||
|
icon('pencil'),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
__('form.edit')
|
||||||
|
),
|
||||||
|
]) : '',
|
||||||
|
$dect,
|
||||||
|
$description,
|
||||||
|
tabs($tabs, $selected_tab),
|
||||||
|
],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param Location $location
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function location_name_render(Location $location)
|
||||||
|
{
|
||||||
|
if (auth()->can('view_locations')) {
|
||||||
|
return '<a href="' . location_link($location) . '">'
|
||||||
|
. icon('pin-map-fill') . htmlspecialchars($location->name)
|
||||||
|
. '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon('pin-map-fill') . htmlspecialchars($location->name);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Engelsystem\Helpers\DayOfEvent;
|
||||||
use Engelsystem\Models\News;
|
use Engelsystem\Models\News;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
@ -8,17 +9,19 @@ use Illuminate\Support\Collection;
|
||||||
*
|
*
|
||||||
* @param array $stats
|
* @param array $stats
|
||||||
* @param array[] $free_shifts
|
* @param array[] $free_shifts
|
||||||
* @param News[]|Collection $important_news
|
* @param News[]|Collection $highlighted_news
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function public_dashboard_view($stats, $free_shifts, $important_news)
|
function public_dashboard_view($stats, $free_shifts, $highlighted_news)
|
||||||
{
|
{
|
||||||
$needed_angels = '';
|
$needed_angels = '';
|
||||||
$news = '';
|
$news = '';
|
||||||
if ($important_news->isNotEmpty()) {
|
if ($highlighted_news->isNotEmpty()) {
|
||||||
$first_news = $important_news->first();
|
$first_news = $highlighted_news->first();
|
||||||
$news = div('alert alert-warning text-center', [
|
$news = div('alert alert-warning text-center', [
|
||||||
'<a href="' . url('/news/' . $first_news->id) . '"><strong>' . $first_news->title . '</strong></a>',
|
'<a href="' . url('/news/' . $first_news->id) . '">'
|
||||||
|
. '<strong>' . htmlspecialchars($first_news->title) . '</strong>'
|
||||||
|
. '</a>',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,17 +46,25 @@ function public_dashboard_view($stats, $free_shifts, $important_news)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$stats = [
|
||||||
|
stats(__('Angels needed in the next 3 hrs'), $stats['needed-3-hours']),
|
||||||
|
stats(__('Angels needed for nightshifts'), $stats['needed-night']),
|
||||||
|
stats(__('Angels currently working'), $stats['angels-working'], 'default'),
|
||||||
|
stats(__('Hours to be worked'), $stats['hours-to-work'], 'default'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$dayOfEvent = DayOfEvent::get();
|
||||||
|
|
||||||
|
if (config('enable_show_day_of_event') && $dayOfEvent !== null) {
|
||||||
|
$stats[] = stats(__('dashboard.day'), $dayOfEvent, 'default');
|
||||||
|
}
|
||||||
|
|
||||||
$isFiltered = request()->get('filtered');
|
$isFiltered = request()->get('filtered');
|
||||||
$filter = collect(session()->get('shifts-filter'))->only(['rooms', 'types'])->toArray();
|
$filter = collect(session()->get('shifts-filter'))->only(['locations', 'types'])->toArray();
|
||||||
return page([
|
return page([
|
||||||
div('wrapper', [
|
div('wrapper', [
|
||||||
div('public-dashboard', [
|
div('public-dashboard', [
|
||||||
div('first row', [
|
div('first row', $stats, 'statistics'),
|
||||||
stats(__('Angels needed in the next 3 hrs'), $stats['needed-3-hours']),
|
|
||||||
stats(__('Angels needed for nightshifts'), $stats['needed-night']),
|
|
||||||
stats(__('Angels currently working'), $stats['angels-working'], 'default'),
|
|
||||||
stats(__('Hours to be worked'), $stats['hours-to-work'], 'default'),
|
|
||||||
], 'statistics'),
|
|
||||||
$news,
|
$news,
|
||||||
$needed_angels,
|
$needed_angels,
|
||||||
], 'public-dashboard'),
|
], 'public-dashboard'),
|
||||||
|
@ -84,17 +95,17 @@ function public_dashboard_shift_render($shift)
|
||||||
$panel_body = icon('clock-history') . $shift['start'] . ' - ' . $shift['end'];
|
$panel_body = icon('clock-history') . $shift['start'] . ' - ' . $shift['end'];
|
||||||
$panel_body .= ' (' . $shift['duration'] . ' h)';
|
$panel_body .= ' (' . $shift['duration'] . ' h)';
|
||||||
|
|
||||||
$panel_body .= '<br>' . icon('list-task') . $shift['shifttype_name'];
|
$panel_body .= '<br>' . icon('list-task') . htmlspecialchars($shift['shifttype_name']);
|
||||||
if (!empty($shift['title'])) {
|
if (!empty($shift['title'])) {
|
||||||
$panel_body .= ' (' . $shift['title'] . ')';
|
$panel_body .= ' (' . htmlspecialchars($shift['title']) . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
$panel_body .= '<br>' . icon('pin-map-fill') . $shift['room_name'];
|
$panel_body .= '<br>' . icon('pin-map-fill') . htmlspecialchars($shift['location_name']);
|
||||||
|
|
||||||
foreach ($shift['needed_angels'] as $needed_angels) {
|
foreach ($shift['needed_angels'] as $needed_angels) {
|
||||||
$panel_body .= '<br>' . icon('person')
|
$panel_body .= '<br>' . icon('person')
|
||||||
. '<span class="text-' . $shift['style'] . '">'
|
. '<span class="text-' . $shift['style'] . '">'
|
||||||
. $needed_angels['need'] . ' × ' . $needed_angels['angeltype_name']
|
. $needed_angels['need'] . ' × ' . htmlspecialchars($needed_angels['angeltype_name'])
|
||||||
. '</span>';
|
. '</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Engelsystem\Models\Room;
|
|
||||||
use Engelsystem\ShiftCalendarRenderer;
|
|
||||||
use Engelsystem\ShiftsFilterRenderer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param Room $room
|
|
||||||
* @param ShiftsFilterRenderer $shiftsFilterRenderer
|
|
||||||
* @param ShiftCalendarRenderer $shiftCalendarRenderer
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function Room_view(Room $room, ShiftsFilterRenderer $shiftsFilterRenderer, ShiftCalendarRenderer $shiftCalendarRenderer)
|
|
||||||
{
|
|
||||||
$user = auth()->user();
|
|
||||||
|
|
||||||
$assignNotice = '';
|
|
||||||
if (config('signup_requires_arrival') && !$user->state->arrived) {
|
|
||||||
$assignNotice = info(render_user_arrived_hint(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$description = '';
|
|
||||||
if ($room->description) {
|
|
||||||
$description = '<h3>' . __('Description') . '</h3>';
|
|
||||||
$parsedown = new Parsedown();
|
|
||||||
$description .= $parsedown->parse($room->description);
|
|
||||||
}
|
|
||||||
|
|
||||||
$dect = '';
|
|
||||||
if (config('enable_dect') && $room->dect) {
|
|
||||||
$dect = heading(__('Contact'), 3)
|
|
||||||
. description([__('DECT') => sprintf('<a href="tel:%s">%1$s</a>', $room->dect)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$tabs = [];
|
|
||||||
if ($room->map_url) {
|
|
||||||
$tabs[__('Map')] = sprintf(
|
|
||||||
'<div class="map">'
|
|
||||||
. '<iframe style="width: 100%%; min-height: 400px; border: 0 none;" src="%s"></iframe>'
|
|
||||||
. '</div>',
|
|
||||||
$room->map_url
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$tabs[__('Shifts')] = div('first', [
|
|
||||||
$shiftsFilterRenderer->render(page_link_to('rooms', [
|
|
||||||
'action' => 'view',
|
|
||||||
'room_id' => $room->id,
|
|
||||||
]), ['rooms' => [$room->id]]),
|
|
||||||
$shiftCalendarRenderer->render(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$selected_tab = 0;
|
|
||||||
$request = request();
|
|
||||||
if ($request->has('shifts_filter_day')) {
|
|
||||||
$selected_tab = count($tabs) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return page_with_title(icon('pin-map-fill') . $room->name, [
|
|
||||||
$assignNotice,
|
|
||||||
auth()->can('admin_rooms') ? buttons([
|
|
||||||
button(
|
|
||||||
page_link_to('admin/rooms/edit/' . $room->id),
|
|
||||||
icon('pencil') . __('edit')
|
|
||||||
),
|
|
||||||
]) : '',
|
|
||||||
$dect,
|
|
||||||
$description,
|
|
||||||
tabs($tabs, $selected_tab),
|
|
||||||
], true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param Room $room
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function Room_name_render(Room $room)
|
|
||||||
{
|
|
||||||
if (auth()->can('view_rooms')) {
|
|
||||||
return '<a href="' . room_link($room) . '">' . icon('pin-map-fill') . $room->name . '</a>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return icon('pin-map-fill') . $room->name;
|
|
||||||
}
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Engelsystem;
|
namespace Engelsystem;
|
||||||
|
|
||||||
|
use Engelsystem\Helpers\Carbon;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
@ -61,28 +62,28 @@ class ShiftCalendarRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the shifts to different lanes per room if they collide
|
* Assigns the shifts to different lanes per location if they collide
|
||||||
*
|
*
|
||||||
* @param Shift[] $shifts The shifts to assign
|
* @param Shift[] $shifts The shifts to assign
|
||||||
* @return array Returns an array that assigns a room_id to an array of ShiftCalendarLane containing the shifts
|
* @return array Returns an array that assigns a location_id to an array of ShiftCalendarLane containing the shifts
|
||||||
*/
|
*/
|
||||||
private function assignShiftsToLanes($shifts)
|
private function assignShiftsToLanes($shifts)
|
||||||
{
|
{
|
||||||
// array that assigns a room id to a list of lanes (per room)
|
// array that assigns a location id to a list of lanes (per location)
|
||||||
$lanes = [];
|
$lanes = [];
|
||||||
|
|
||||||
foreach ($shifts as $shift) {
|
foreach ($shifts as $shift) {
|
||||||
$room = $shift->room;
|
$location = $shift->location;
|
||||||
$header = Room_name_render($room);
|
$header = location_name_render($location);
|
||||||
if (!isset($lanes[$room->id])) {
|
if (!isset($lanes[$location->id])) {
|
||||||
// initialize room with one lane
|
// initialize location with one lane
|
||||||
$lanes[$room->id] = [
|
$lanes[$location->id] = [
|
||||||
new ShiftCalendarLane($header),
|
new ShiftCalendarLane($header),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
// Try to add the shift to the existing lanes for this room
|
// Try to add the shift to the existing lanes for this location
|
||||||
$shift_added = false;
|
$shift_added = false;
|
||||||
foreach ($lanes[$room->id] as $lane) {
|
foreach ($lanes[$location->id] as $lane) {
|
||||||
/** @var ShiftCalendarLane $lane */
|
/** @var ShiftCalendarLane $lane */
|
||||||
if ($lane->shiftFits($shift)) {
|
if ($lane->shiftFits($shift)) {
|
||||||
$lane->addShift($shift);
|
$lane->addShift($shift);
|
||||||
|
@ -90,11 +91,11 @@ class ShiftCalendarRenderer
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If all lanes for this room are busy, create a new lane and add shift to it
|
// If all lanes for this location are busy, create a new lane and add shift to it
|
||||||
if (!$shift_added) {
|
if (!$shift_added) {
|
||||||
$newLane = new ShiftCalendarLane($header);
|
$newLane = new ShiftCalendarLane($header);
|
||||||
$newLane->addShift($shift);
|
$newLane->addShift($shift);
|
||||||
$lanes[$room->id][] = $newLane;
|
$lanes[$location->id][] = $newLane;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +154,8 @@ class ShiftCalendarRenderer
|
||||||
private function renderShiftLanes()
|
private function renderShiftLanes()
|
||||||
{
|
{
|
||||||
$html = '';
|
$html = '';
|
||||||
foreach ($this->lanes as $room_lanes) {
|
foreach ($this->lanes as $location_lanes) {
|
||||||
foreach ($room_lanes as $lane) {
|
foreach ($location_lanes as $lane) {
|
||||||
$html .= $this->renderLane($lane);
|
$html .= $this->renderLane($lane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,20 +213,21 @@ class ShiftCalendarRenderer
|
||||||
*/
|
*/
|
||||||
private function renderTick($time, $label = false)
|
private function renderTick($time, $label = false)
|
||||||
{
|
{
|
||||||
|
$time = Carbon::createFromTimestamp($time);
|
||||||
$class = $label ? 'tick bg-' . theme_type() : 'tick ';
|
$class = $label ? 'tick bg-' . theme_type() : 'tick ';
|
||||||
if ($time % (24 * 60 * 60) == 23 * 60 * 60) {
|
if ($time->isStartOfDay()) {
|
||||||
if (!$label) {
|
if (!$label) {
|
||||||
return div($class . ' day');
|
return div($class . ' day');
|
||||||
}
|
}
|
||||||
return div($class . ' day', [
|
return div($class . ' day', [
|
||||||
date(__('m-d'), $time) . '<br>' . date(__('H:i'), $time),
|
$time->format(__('m-d')) . '<br>' . $time->format(__('H:i')),
|
||||||
]);
|
]);
|
||||||
} elseif ($time % (60 * 60) == 0) {
|
} elseif ($time->isStartOfHour()) {
|
||||||
if (!$label) {
|
if (!$label) {
|
||||||
return div($class . ' hour');
|
return div($class . ' hour');
|
||||||
}
|
}
|
||||||
return div($class . ' hour', [
|
return div($class . ' hour', [
|
||||||
date(__('m-d'), $time) . '<br>' . date(__('H:i'), $time),
|
$time->format(__('m-d')) . '<br>' . $time->format(__('H:i')),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
return div($class);
|
return div($class);
|
||||||
|
@ -242,7 +244,7 @@ class ShiftCalendarRenderer
|
||||||
|
|
||||||
$time_slot = [
|
$time_slot = [
|
||||||
div('header ' . $bg, [
|
div('header ' . $bg, [
|
||||||
__('Time'),
|
__('log.time'),
|
||||||
]),
|
]),
|
||||||
];
|
];
|
||||||
for ($block = 0; $block < $this->getBlocksPerSlot(); $block++) {
|
for ($block = 0; $block < $this->getBlocksPerSlot(); $block++) {
|
||||||
|
@ -312,7 +314,7 @@ class ShiftCalendarRenderer
|
||||||
badge(__('Help needed'), 'danger'),
|
badge(__('Help needed'), 'danger'),
|
||||||
badge(__('Other angeltype needed / collides with my shifts'), 'warning'),
|
badge(__('Other angeltype needed / collides with my shifts'), 'warning'),
|
||||||
badge(__('Shift is full'), 'success'),
|
badge(__('Shift is full'), 'success'),
|
||||||
badge(__('Shift running/ended or you have not arrived'), 'secondary'),
|
badge(__('Shift is running/ended or you have not arrived'), 'secondary'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ class ShiftCalendarShiftRenderer
|
||||||
{
|
{
|
||||||
$info_text = '';
|
$info_text = '';
|
||||||
if ($shift->title != '') {
|
if ($shift->title != '') {
|
||||||
$info_text = icon('info-circle') . $shift->title . '<br>';
|
$info_text = icon('info-circle') . htmlspecialchars($shift->title) . '<br>';
|
||||||
}
|
}
|
||||||
list($shift_signup_state, $shifts_row) = $this->renderShiftNeededAngeltypes(
|
list($shift_signup_state, $shifts_row) = $this->renderShiftNeededAngeltypes(
|
||||||
$shift,
|
$shift,
|
||||||
|
@ -43,8 +43,6 @@ class ShiftCalendarShiftRenderer
|
||||||
$blocks = ceil(($shift->end->timestamp - $shift->start->timestamp) / ShiftCalendarRenderer::SECONDS_PER_ROW);
|
$blocks = ceil(($shift->end->timestamp - $shift->start->timestamp) / ShiftCalendarRenderer::SECONDS_PER_ROW);
|
||||||
$blocks = max(1, $blocks);
|
$blocks = max(1, $blocks);
|
||||||
|
|
||||||
$room = $shift->room;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
$blocks,
|
$blocks,
|
||||||
div(
|
div(
|
||||||
|
@ -57,7 +55,7 @@ class ShiftCalendarShiftRenderer
|
||||||
$this->renderShiftHead($shift, $class, $shift_signup_state->getFreeEntries()),
|
$this->renderShiftHead($shift, $class, $shift_signup_state->getFreeEntries()),
|
||||||
div('card-body ' . $this->classBg(), [
|
div('card-body ' . $this->classBg(), [
|
||||||
$info_text,
|
$info_text,
|
||||||
Room_name_render($room),
|
location_name_render($shift->location),
|
||||||
]),
|
]),
|
||||||
$shifts_row,
|
$shifts_row,
|
||||||
]
|
]
|
||||||
|
@ -192,14 +190,14 @@ class ShiftCalendarShiftRenderer
|
||||||
// No link and add a text hint, when the shift ended
|
// No link and add a text hint, when the shift ended
|
||||||
ShiftSignupStatus::NOT_ARRIVED => $inner_text . ' (' . __('please arrive for signup') . ')',
|
ShiftSignupStatus::NOT_ARRIVED => $inner_text . ' (' . __('please arrive for signup') . ')',
|
||||||
ShiftSignupStatus::NOT_YET => $inner_text . ' (' . __('not yet') . ')',
|
ShiftSignupStatus::NOT_YET => $inner_text . ' (' . __('not yet') . ')',
|
||||||
ShiftSignupStatus::ANGELTYPE => $angeltype->restricted
|
ShiftSignupStatus::ANGELTYPE => $angeltype->restricted || !$angeltype->shift_self_signup
|
||||||
// User has to be confirmed on the angeltype first
|
// User has to be confirmed on the angeltype first or can't sign up by themselves
|
||||||
? $inner_text . icon('mortarboard-fill')
|
? $inner_text . icon('mortarboard-fill')
|
||||||
// Add link to join the angeltype first
|
// Add link to join the angeltype first
|
||||||
: $inner_text . '<br />'
|
: $inner_text . '<br />'
|
||||||
. button(
|
. button(
|
||||||
page_link_to('user_angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
|
url('/user-angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
|
||||||
sprintf(__('Become %s'), $angeltype->name),
|
sprintf(__('Become %s'), htmlspecialchars($angeltype->name)),
|
||||||
'btn-sm'
|
'btn-sm'
|
||||||
),
|
),
|
||||||
// Shift collides or user is already signed up: No signup allowed
|
// Shift collides or user is already signed up: No signup allowed
|
||||||
|
@ -249,20 +247,24 @@ class ShiftCalendarShiftRenderer
|
||||||
if (auth()->can('admin_shifts')) {
|
if (auth()->can('admin_shifts')) {
|
||||||
$header_buttons = '<div class="ms-auto d-print-none">' . table_buttons([
|
$header_buttons = '<div class="ms-auto d-print-none">' . table_buttons([
|
||||||
button(
|
button(
|
||||||
page_link_to('user_shifts', ['edit_shift' => $shift->id]),
|
url('/user-shifts', ['edit_shift' => $shift->id]),
|
||||||
icon('pencil'),
|
icon('pencil'),
|
||||||
'btn-' . $class . ' btn-sm border-light text-white'
|
'btn-' . $class . ' btn-sm border-light text-white',
|
||||||
|
'',
|
||||||
|
__('form.edit')
|
||||||
),
|
),
|
||||||
button(
|
button(
|
||||||
page_link_to('user_shifts', ['delete_shift' => $shift->id]),
|
url('/user-shifts', ['delete_shift' => $shift->id]),
|
||||||
icon('trash'),
|
icon('trash'),
|
||||||
'btn-' . $class . ' btn-sm border-light text-white'
|
'btn-' . $class . ' btn-sm border-light text-white',
|
||||||
|
'',
|
||||||
|
__('form.delete')
|
||||||
),
|
),
|
||||||
]) . '</div>';
|
]) . '</div>';
|
||||||
}
|
}
|
||||||
$shift_heading = $shift->start->format('H:i') . ' ‐ '
|
$shift_heading = $shift->start->format('H:i') . ' ‐ '
|
||||||
. $shift->end->format('H:i') . ' — '
|
. $shift->end->format('H:i') . ' — '
|
||||||
. $shift->shiftType->name;
|
. htmlspecialchars($shift->shiftType->name);
|
||||||
|
|
||||||
if ($needed_angeltypes_count > 0) {
|
if ($needed_angeltypes_count > 0) {
|
||||||
$shift_heading = '<span class="badge bg-light text-danger me-1">' . $needed_angeltypes_count . '</span> ' . $shift_heading;
|
$shift_heading = '<span class="badge bg-light text-danger me-1">' . $needed_angeltypes_count . '</span> ' . $shift_heading;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue