Compare commits

..

794 Commits

Author SHA1 Message Date
philipp lang a456cc1889 Fix: Sort participants by created_at
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-12-16 14:18:02 +01:00
philipp lang 784b49c3dd Add invoice full text search
continuous-integration/drone/push Build is failing Details
2024-12-15 16:05:38 +01:00
philipp lang c3a0381a0a Fix invoice settings when fields are empty
continuous-integration/drone/push Build is passing Details
2024-12-15 12:06:44 +01:00
philipp lang 101ac7402a Add Phpunit to gitignore
continuous-integration/drone/push Build is passing Details
2024-12-15 11:56:13 +01:00
philipp lang 2c38488962 Remove cross
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-12-13 19:13:30 +01:00
philipp lang 8a26276e28 Rename document
continuous-integration/drone/push Build is passing Details
2024-12-13 19:03:40 +01:00
philipp lang 4651a4cb96 Lint
continuous-integration/drone/push Build is passing Details
2024-12-13 14:37:13 +01:00
philipp lang 688e10e230 Lint
continuous-integration/drone/push Build is failing Details
2024-12-13 11:56:02 +01:00
philipp lang 267da38c6b Lint
continuous-integration/drone/push Build is passing Details
2024-12-13 02:46:44 +01:00
philipp lang 499c61afff Lint 2024-12-13 02:44:08 +01:00
philipp lang 02531938b3 Lint 2024-12-13 02:42:08 +01:00
philipp lang 1c53e81f1a Lint 2024-12-13 02:40:33 +01:00
philipp lang 98712093b2 Lint 2024-12-13 02:36:17 +01:00
philipp lang a32ef33113 Move engine 2024-12-13 02:33:12 +01:00
philipp lang 088ea4f0a2 Lint 2024-12-13 02:28:41 +01:00
philipp lang 4ac89da124 Lint 2024-12-13 02:16:09 +01:00
philipp lang 286ceea0d4 Lint 2024-12-13 01:59:24 +01:00
philipp lang 52ac5937a4 Add validation 2024-12-13 01:59:09 +01:00
philipp lang 4690e86bbf Add gallier document 2024-12-13 01:54:02 +01:00
philipp lang 1a4a7c3652 Add base gallier document 2024-12-13 00:58:44 +01:00
philipp lang b05c5025c0 Add button to mark invoice as paid
continuous-integration/drone/push Build is passing Details
2024-12-12 21:26:51 +01:00
philipp lang acf7b94094 Update CHANGELOG
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is passing Details
2024-12-12 16:37:20 +01:00
philipp lang 57b1efb065 Add registration_from and registration_until to frontend api
continuous-integration/drone/push Build is passing Details
2024-12-12 15:42:35 +01:00
philipp lang 3e563f8390 Add registration_from and registration_to fields 2024-12-12 15:21:03 +01:00
philipp lang 0a5590d533 Remove CreatesApplication Trait 2024-12-12 13:56:13 +01:00
philipp lang 10deaf15a1 Update form edit view 2024-12-12 13:45:42 +01:00
philipp lang ae447a7a60 Add fileshare and web setting on bin/run 2024-12-12 13:45:26 +01:00
philipp lang baea21807a Update CHANGELOG
continuous-integration/drone/push Build is passing Details
2024-12-12 13:21:05 +01:00
philipp lang 58426c5537 Fix tests
continuous-integration/drone/push Build was killed Details
2024-12-12 12:18:49 +01:00
philipp lang 84cd13c085 Fix migration
continuous-integration/drone/push Build is failing Details
2024-12-12 03:12:26 +01:00
philipp lang b8d2b37057 Add sorting frontend for participants list
continuous-integration/drone/push Build is failing Details
2024-12-12 03:07:10 +01:00
philipp lang 44eb3719b9 Update tests
continuous-integration/drone/push Build is passing Details
2024-12-12 02:35:27 +01:00
philipp lang c65a208e34 Add frontend for sorting
continuous-integration/drone/push Build was killed Details
2024-12-12 02:33:10 +01:00
philipp lang 95a8d4d689 Fix page navigation 2024-12-12 02:27:58 +01:00
philipp lang e1e8669beb Fix tests
continuous-integration/drone/push Build is failing Details
2024-12-12 01:32:01 +01:00
philipp lang a3ecfa756d Add sorting to participant list
continuous-integration/drone/push Build was killed Details
2024-12-12 01:26:22 +01:00
philipp lang 70e085a49e Fix: Dont update form when not using meilisearch
continuous-integration/drone/push Build is failing Details
2024-12-12 00:50:05 +01:00
philipp lang 1178b011e0 Lint
continuous-integration/drone/push Build was killed Details
2024-12-12 00:36:56 +01:00
philipp lang 6a91e857d2 Add filtering for participant index
continuous-integration/drone/push Build was killed Details
2024-12-12 00:30:59 +01:00
philipp lang 82baf67a73 Lint 2024-12-11 22:37:49 +01:00
philipp lang 36466420f6 Lint 2024-12-11 22:36:25 +01:00
philipp lang 54c37fccd1 Add searchable participants via full text 2024-12-11 22:32:23 +01:00
philipp lang d03f036a2b Move ParticipantIndexActionTest to EndToEnd 2024-12-10 01:28:35 +01:00
philipp lang 75d11f9860 Update formsettings when copying db 2024-12-10 00:58:05 +01:00
philipp lang da4d553ea6 Update CHANGELOG
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-12-09 14:08:52 +01:00
philipp lang 5bad88c5f4 Add config for job batching
continuous-integration/drone/push Build is passing Details
2024-12-09 14:08:02 +01:00
philipp lang 75dc0d9769 Update CHANGELOG
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-11-20 11:11:26 +01:00
philipp lang 9fc8548504 Fix: Dont remember past events
continuous-integration/drone/push Build is passing Details
2024-11-20 11:10:24 +01:00
philipp lang c990ce3171 Fix Color of lilie svg
continuous-integration/drone/push Build is failing Details
2024-11-18 23:06:36 +01:00
philipp lang e7f63d19e5 Add imagick extension
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-11-13 19:44:40 +01:00
philipp lang f549b31862 Update medialibrary-helper
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-11-13 14:36:29 +01:00
philipp lang 1f4efb22d3 Install imagemagick 2024-11-13 14:35:54 +01:00
philipp lang 3e725d9842 Install imagick extension 2024-11-13 13:14:45 +01:00
philipp lang 16d3bc51a3 Fix php version of deploy
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-11-12 01:20:41 +01:00
philipp lang 0467f24ff6 Update composer in nginx.Dockerfile
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-11-12 00:39:40 +01:00
philipp lang ed1a8f30bc Update composer version in Dockerfile
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-11-11 23:43:17 +01:00
philipp lang e5066af192 Add instruction for building adrema-base image 2024-11-11 23:36:09 +01:00
philipp lang 31afa2e418 Add Changelog 2024-11-11 23:35:55 +01:00
philipp lang a897690e7a Add keepdata to member form
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-11-07 01:29:26 +01:00
philipp lang 24ed5d4ab9 Lint 2024-11-07 00:38:28 +01:00
philipp lang e807aff3e6 Remove default arch tests
continuous-integration/drone/push Build is passing Details
2024-10-28 23:54:21 +01:00
philipp lang 096224fe98 Lint
continuous-integration/drone/push Build is passing Details
2024-09-23 02:01:35 +02:00
philipp lang 646ce647da Move Dashboard Route to DashboardServiceProvider 2024-09-23 01:53:46 +02:00
philipp lang f858716e57 Add Arch tests
continuous-integration/drone/push Build is passing Details
2024-09-22 22:58:31 +02:00
philipp lang 1521aba1f8 Fix drone
continuous-integration/drone/push Build is passing Details
2024-09-22 19:39:36 +02:00
philipp lang 664b88564d Fix phpstan
continuous-integration/drone/push Build is failing Details
2024-09-22 18:25:42 +02:00
philipp lang d30a2336cf Fix tests
continuous-integration/drone/push Build is failing Details
2024-09-22 17:32:29 +02:00
philipp lang a5f1c90003 Fix tests
continuous-integration/drone/push Build is failing Details
2024-09-22 12:28:10 +02:00
philipp lang c3908b714b Update laravel-nami
continuous-integration/drone/push Build is failing Details
2024-09-22 03:02:15 +02:00
philipp lang 2f1e02151f Fix tests 2024-09-22 03:02:10 +02:00
philipp lang eaf014b7c7 Touch env file while testing with drone
continuous-integration/drone/push Build is failing Details
2024-09-22 02:30:25 +02:00
philipp lang 94d34d1afa Add Pail 2024-09-22 02:15:59 +02:00
philipp lang 9b700be889 Update laravel-nami
continuous-integration/drone/push Build was killed Details
2024-09-22 02:13:12 +02:00
philipp lang e1ec6ad9df update composer in drone
continuous-integration/drone/push Build is failing Details
2024-09-22 02:03:58 +02:00
philipp lang aaa236fcd5 Fix tests
continuous-integration/drone/push Build is failing Details
2024-09-22 01:41:56 +02:00
philipp lang 4d74e53fc2 Update Activity UpdateTest 2024-09-22 00:06:03 +02:00
philipp lang b8d389bdb9 Lint Activity EditTest 2024-09-21 23:43:51 +02:00
philipp lang 3a4c99f154 Add Laravel 11 support
continuous-integration/drone/push Build was killed Details
2024-09-21 22:46:38 +02:00
philipp lang fca7fc463e Update php to 8.3
continuous-integration/drone/push Build is passing Details
2024-09-21 21:55:16 +02:00
philipp lang 767df11e4f Fix tests
continuous-integration/drone/push Build is passing Details
2024-09-21 18:56:53 +02:00
philipp lang 295d85f4f8 Add Pestphp
continuous-integration/drone/push Build is failing Details
2024-09-21 18:29:47 +02:00
philipp lang 42ccd32740 Fix tests
continuous-integration/drone/push Build is failing Details
2024-09-21 17:46:07 +02:00
philipp lang bbcf2fd768 Update to laravel 10
continuous-integration/drone/push Build is failing Details
2024-09-21 17:42:11 +02:00
philipp lang b335c20777 Update CHANGELOG
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-09-12 11:17:45 +02:00
philipp lang c63c8316b5 Update adrema-form
continuous-integration/drone/push Build is passing Details
2024-09-12 11:15:58 +02:00
philipp lang 2e6c27b8f1 Update CHANGELOG
continuous-integration/drone/tag Build is failing Details
continuous-integration/drone/push Build is passing Details
2024-08-30 22:38:04 +02:00
philipp lang 1cf8d34b78 Fix tests
continuous-integration/drone/push Build is passing Details
2024-08-30 22:04:14 +02:00
philipp lang e3b52bf901 Fixed tests
continuous-integration/drone/push Build is failing Details
2024-08-30 21:06:16 +02:00
philipp lang 76e7b06630 Fix tests
continuous-integration/drone/push Build is failing Details
2024-08-30 20:06:10 +02:00
philipp lang 21def11ae9 Fixed: Dont display efz and ps for inactive memberships
continuous-integration/drone/push Build is failing Details
2024-08-30 19:04:18 +02:00
philipp lang 565b1ffbce Lint
continuous-integration/drone/push Build is failing Details
2024-08-28 21:02:53 +02:00
philipp lang ef70203c8a Remove Member toolbar button
continuous-integration/drone/push Build is failing Details
2024-08-28 16:30:26 +02:00
philipp lang b3a29c706c Lint 2024-08-28 13:32:52 +02:00
philipp lang 298140e387 Set default member model as meta 2024-08-28 13:26:30 +02:00
philipp lang 151477dbdd Lint 2024-08-27 23:21:10 +02:00
philipp lang a01e8adf8a Add backdrop 2024-08-27 18:19:52 +02:00
philipp lang 547c9edfd5 Update CHANGELOG
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-08-25 14:11:18 +02:00
philipp lang 6e09e2ec0d Fix: Show all groups in conditions 2024-08-25 14:10:22 +02:00
philipp lang 9d37ebefc5 Update CHANGELOG
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is passing Details
2024-08-25 10:39:45 +02:00
philipp lang 11b1e6a198 Lint migrations
continuous-integration/drone/push Build is passing Details
2024-08-23 22:25:25 +02:00
philipp lang 5008244de2 Add conditions for group fields
continuous-integration/drone/push Build is failing Details
2024-08-23 17:57:20 +02:00
philipp lang 8b3b3de9a8 Fix: update single name in migrations
continuous-integration/drone/push Build is failing Details
2024-08-02 12:05:21 +02:00
philipp lang d9adb526ce Remove Setting store actions
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-08-01 16:26:38 +02:00
philipp lang daf6e87814 Remove Middleware 2024-08-01 16:26:38 +02:00
philipp lang 2056e1ad6b Fixed tests 2024-08-01 16:26:38 +02:00
philipp lang a4eba23bff Remove viewable interface 2024-08-01 16:26:38 +02:00
philipp lang ad8cd58b4f Add SettingView action 2024-08-01 16:26:38 +02:00
philipp lang 3a4908f505 Move Indexable to Viewable 2024-08-01 16:26:38 +02:00
philipp lang 291eec3849 Update CHANGELOG
continuous-integration/drone/push Build is passing Details
2024-08-01 12:15:28 +02:00
philipp lang 0e0f23c17e Fix user principal
continuous-integration/drone/push Build is passing Details
2024-08-01 12:13:33 +02:00
philipp lang 6d204b948e Add avatar image
continuous-integration/drone/push Build is failing Details
2024-07-31 22:41:02 +02:00
philipp lang 977e427abb Lint 2024-07-31 22:30:13 +02:00
philipp lang 46e070a029 Lint 2024-07-31 22:25:54 +02:00
philipp lang 84e05fbc52 Update changelog 2024-07-31 21:39:14 +02:00
philipp lang 343b0d418d Add RememberWeeks setting for remembering invoices
continuous-integration/drone/push Build is passing Details
2024-07-31 21:37:18 +02:00
philipp lang fe258198f4 Add daily invoice sending 2024-07-31 21:19:02 +02:00
philipp lang 8317fdca90 Update changelog
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-07-30 23:12:12 +02:00
philipp lang 32ec479975 Display for_members field when nami field is set
continuous-integration/drone/push Build is passing Details
2024-07-30 23:10:24 +02:00
philipp lang ac45e0c8fa Fix tests
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-07-25 12:53:40 +02:00
philipp lang 6f1ab73bae Update changelog 2024-07-25 11:14:43 +02:00
philipp lang c95658ae65 Fix prevention moreps
continuous-integration/drone/push Build is failing Details
2024-07-25 11:13:40 +02:00
philipp lang d64ea85be6 Update Changelog
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-07-25 09:41:02 +02:00
philipp lang 22157b5d50 Add prevention items frontend
continuous-integration/drone/push Build is passing Details
2024-07-25 00:17:31 +02:00
philipp lang 107b616bc1 Update base 2024-07-24 22:26:52 +02:00
philipp lang d7cc80afe9 Lint
continuous-integration/drone/push Build is passing Details
2024-07-24 22:26:38 +02:00
philipp lang db6248999a Update CHANGELOG
continuous-integration/drone/push Build is failing Details
2024-07-24 16:13:36 +02:00
philipp lang 9c568176ce Fixed: Display all forms on index page
continuous-integration/drone/push Build is failing Details
2024-07-24 16:11:29 +02:00
philipp lang d56cb253a9 Add Excel export for participants
continuous-integration/drone/push Build is failing Details
2024-07-23 22:59:23 +02:00
philipp lang 5fcee5f284 Move Creation of excel document to own action 2024-07-23 22:59:23 +02:00
philipp lang b01ff9a677 Add prevention items 2024-07-23 22:59:23 +02:00
philipp lang 0d76b3cc5f Revert "Install adrema-form dependencies in docker"
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
This reverts commit eee0c64106.
2024-07-21 16:09:41 +02:00
philipp lang 0972ad65a7 Update changelog
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-07-18 16:03:10 +02:00
philipp lang 259465189f Update changelog
continuous-integration/drone/push Build is passing Details
2024-07-18 16:02:49 +02:00
philipp lang 306fef3e07 Add Verhaltenskodex prevention
continuous-integration/drone/push Build is passing Details
2024-07-18 13:58:21 +02:00
philipp lang ca0dd11336 Check for APP_KEY in every PHP Container
continuous-integration/drone/push Build is passing Details
2024-07-18 01:41:35 +02:00
philipp lang 89a8feb278 Clear node_modules in drone 2024-07-18 01:41:12 +02:00
philipp lang 8f7edadb99 Remove invoice volume 2024-07-18 01:40:55 +02:00
philipp lang eee0c64106 Install adrema-form dependencies in docker 2024-07-18 01:40:37 +02:00
philipp lang e50269d031 Move tex templates to invoice folder 2024-07-18 01:38:41 +02:00
philipp lang dc40728fca Mod helps
continuous-integration/drone/push Build is failing Details
2024-07-18 01:16:02 +02:00
philipp lang dfa17ed3db Update node version
continuous-integration/drone/push Build is failing Details
2024-07-18 00:59:15 +02:00
philipp lang 77c57794e1 Remove silvaletter dir
continuous-integration/drone/push Build is failing Details
2024-07-17 23:49:03 +02:00
philipp lang 1347347324 Add compose invoice dir
continuous-integration/drone/push Build is failing Details
2024-07-17 23:29:00 +02:00
philipp lang cd9cc607f4 Add silvaletter template
continuous-integration/drone/push Build is failing Details
2024-07-17 23:18:25 +02:00
philipp lang 6f1efb7470 Update silvaletter package 2024-07-17 22:54:50 +02:00
philipp lang 5fd050e116 Move template dir from default to invoice 2024-07-17 22:51:53 +02:00
philipp lang 3a53777dbd Update README 2024-07-17 22:45:16 +02:00
philipp lang 1ad2e6a978 Fix typo 2024-07-17 22:38:16 +02:00
philipp lang ac76d23941 Move template files of bill and remember invoice 2024-07-17 22:35:06 +02:00
philipp lang b67fa85539 Update Changelog
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-07-15 17:56:53 +02:00
philipp lang 5641006e2b Add mail data from template to form
continuous-integration/drone/push Build was killed Details
2024-07-15 17:13:23 +02:00
philipp lang 607038af6b Lint 2024-07-15 17:05:21 +02:00
philipp lang 189b83f2a5 Update migrations 2024-07-15 17:05:02 +02:00
philipp lang 3f4c655e5e Disable is_dirty when link not found 2024-07-15 17:00:42 +02:00
philipp lang 158cd2d352 Lint 2024-07-15 16:59:29 +02:00
philipp lang bf1388dbd9 Lint
continuous-integration/drone/push Build is passing Details
2024-07-14 22:16:34 +02:00
philipp lang aa20329a62 Lint
continuous-integration/drone/push Build is failing Details
2024-07-14 21:44:33 +02:00
philipp lang 09de9a5510 Add frontnd for formtemplate mails
continuous-integration/drone/push Build is failing Details
2024-07-14 20:53:26 +02:00
philipp lang 2982ae035f Lint 2024-07-14 20:53:15 +02:00
philipp lang 46740b14a2 Add mail_top and mail_bottom for formtemplates
continuous-integration/drone/push Build is failing Details
2024-07-14 20:20:56 +02:00
philipp lang 885eaa5df5 Fix migrations
continuous-integration/drone/push Build is failing Details
2024-07-14 20:19:17 +02:00
philipp lang 757042bdd2 Fix migrations
continuous-integration/drone/push Build is failing Details
2024-07-14 19:57:37 +02:00
philipp lang c3f6d3827b Add EditorData for forms texts
continuous-integration/drone/push Build is failing Details
2024-07-14 19:29:42 +02:00
philipp lang 1ef7995ec2 Update Changelog
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-07-14 12:13:59 +02:00
philipp lang c8676aef6d Fix tests
continuous-integration/drone/push Build is passing Details
2024-07-14 00:37:38 +02:00
philipp lang cf93b8eff0 Lint
continuous-integration/drone/push Build is failing Details
2024-07-14 00:11:18 +02:00
philipp lang e2a2d746a3 Fix tests
continuous-integration/drone/push Build is failing Details
2024-07-14 00:05:53 +02:00
philipp lang aabba32f89 Fix drone
continuous-integration/drone/push Build was killed Details
2024-07-13 23:31:17 +02:00
philipp lang 11b97a634b Fix drone
continuous-integration/drone/push Build was killed Details
2024-07-13 22:50:17 +02:00
philipp lang 26cb7fd9f1 Add drone nextcloud service
continuous-integration/drone/push Build is failing Details
2024-07-13 22:36:08 +02:00
philipp lang 2b48f42734 Add nextcloud connections
continuous-integration/drone/push Build was killed Details
2024-07-13 22:30:34 +02:00
philipp lang 74867cb09f Add file conversion to jpeg
continuous-integration/drone/push Build is failing Details
2024-07-13 19:49:50 +02:00
philipp lang d4057ff08f Add filter for participants
continuous-integration/drone/push Build is failing Details
2024-07-13 18:48:11 +02:00
philipp lang 657a648f46 Add: Store participant 2024-07-13 18:24:43 +02:00
philipp lang d9c45f5236 Fix participant update 2024-07-13 17:54:23 +02:00
philipp lang 5d48521875 Fix fileshare skeleton 2024-07-13 17:44:03 +02:00
philipp lang 98976700a9 Mod db maintain
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-07-13 14:08:42 +02:00
philipp lang 790332b25c Lint
continuous-integration/drone/push Build is passing Details
2024-07-12 20:42:30 +02:00
philipp lang 56c28ae00e Add form to edit
continuous-integration/drone/push Build is failing Details
2024-07-12 20:18:41 +02:00
philipp lang a603aca80c Add backend for update 2024-07-12 20:15:24 +02:00
philipp lang c05434a7fb Add participant fields link 2024-07-12 19:49:47 +02:00
philipp lang 248499dc60 Fixed condition default
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is passing Details
2024-07-12 19:18:35 +02:00
philipp lang ad7fe80236 Fix tests
continuous-integration/drone/push Build is failing Details
2024-07-12 18:27:18 +02:00
philipp lang dbde189575 Fix prevention for leaders
continuous-integration/drone/push Build is failing Details
2024-07-12 18:07:33 +02:00
philipp lang 146cbb0bef Add prevention conditions 2024-07-12 18:07:33 +02:00
philipp lang e6477fff2b Add conditions form 2024-07-12 18:07:33 +02:00
philipp lang 3c725c0efc Lint 2024-07-12 18:07:33 +02:00
philipp lang f632a8bb8f Lint 2024-07-12 18:07:33 +02:00
philipp lang 2f03dccebb Add data for conditions 2024-07-12 18:07:33 +02:00
philipp lang 235f439d51 Update adrema-form
continuous-integration/drone/push Build is passing Details
2024-07-11 15:15:50 +02:00
philipp lang cf77797512 Fix PreventionRememberAction
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-07-10 00:52:05 +02:00
philipp lang d44ad4bc53 Fix migration
continuous-integration/drone/tag Build is passing Details
2024-07-10 00:19:29 +02:00
philipp lang 94597e57c1 Fix migration
continuous-integration/drone/tag Build was killed Details
2024-07-10 00:18:18 +02:00
philipp lang a9ecdfe4bb Lint
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is failing Details
2024-07-08 23:17:14 +02:00
philipp lang 10a966c6ad Lint 2024-07-08 23:06:45 +02:00
philipp lang 3b63a73161 Fix tests
continuous-integration/drone/push Build is failing Details
2024-07-08 22:39:11 +02:00
philipp lang 4e453a73a6 Fix tests 2024-07-08 21:42:31 +02:00
philipp lang 96cf0b7dd5 Fix EditorData cache
continuous-integration/drone/push Build is failing Details
2024-07-08 20:48:08 +02:00
philipp lang b2e85211a7 Add prevention_text field
continuous-integration/drone/push Build is failing Details
2024-07-06 15:14:53 +02:00
philipp lang 3dacfb3e54 Add prevention_text to form 2024-07-06 15:08:13 +02:00
philipp lang c9ccebc8f3 Lint
continuous-integration/drone/push Build is failing Details
2024-07-04 23:58:46 +02:00
philipp lang b6aaf6b2e1 Add todos
continuous-integration/drone/push Build is failing Details
2024-07-04 23:56:47 +02:00
philipp lang 793e4bacbd Add mail view 2024-07-04 23:54:37 +02:00
philipp lang 6c44a25638 Composer update
continuous-integration/drone/push Build is failing Details
2024-07-04 23:38:38 +02:00
philipp lang 8609f1e9c6 Fix: Cast Data object from Settings 2024-07-04 22:29:29 +02:00
philipp lang 0d07975e53 Fix tests
continuous-integration/drone/push Build is failing Details
2024-07-04 22:12:45 +02:00
philipp lang f7d9328447 Fix: Dont Send mail to participants without mail 2024-07-04 22:09:24 +02:00
philipp lang d26bdd72fb Fix tests
continuous-integration/drone/push Build is failing Details
2024-07-04 21:42:19 +02:00
philipp lang ff40b9e805 Add prevention settings
continuous-integration/drone/push Build is failing Details
2024-07-04 21:01:14 +02:00
philipp lang 92997aa78f Lint 2024-07-04 20:04:51 +02:00
philipp lang ee02b8df3a Add prevention 2024-07-04 20:04:49 +02:00
philipp lang 8ec4e4eb59 Fix db maintain
continuous-integration/drone/push Build is passing Details
2024-07-04 01:40:43 +02:00
philipp lang fc70107aa3 Optimize telescope table when pruning
continuous-integration/drone/push Build is failing Details
2024-07-04 00:56:20 +02:00
philipp lang 5661d66770 Add search result component
continuous-integration/drone/push Build is passing Details
2024-07-03 17:43:49 +02:00
philipp lang 0a8ecedb0f Update search 2024-07-03 17:31:06 +02:00
philipp lang fd9aff25fe Add hits to searchModal 2024-07-03 17:20:47 +02:00
philipp lang c65a25ed2a Fix: Switch input should not be invisible 2024-07-03 17:17:44 +02:00
philipp lang ced2d577c0 Lint 2024-07-03 17:12:57 +02:00
philipp lang aafef695aa Lint 2024-07-03 17:12:32 +02:00
philipp lang 44a39fc5a8 Lint 2024-07-03 17:10:04 +02:00
philipp lang 46a353d674 Fix event name im contribution 2024-07-03 17:09:34 +02:00
philipp lang fed0e95f14 Fix switch with array 2024-07-03 17:07:14 +02:00
philipp lang d1dfcb3a04 Add dev url for search 2024-07-03 17:03:53 +02:00
philipp lang 7f9be4262c Lint 2024-07-03 16:37:58 +02:00
philipp lang 99a28f44dd Dont match Email Nami Field
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-07-03 11:01:16 +02:00
philipp lang 9c93b13032 Fix: Dont reset page when assigning members
continuous-integration/drone/push Build is passing Details
2024-07-02 21:42:38 +02:00
philipp lang 231ed3b4ad Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-07-02 18:44:42 +02:00
philipp lang ccfeb85e4b Fix tests
continuous-integration/drone/push Build is failing Details
2024-07-02 18:19:40 +02:00
philipp lang 445a8ae962 Add assign for participant
continuous-integration/drone/push Build is failing Details
2024-07-02 18:04:55 +02:00
philipp lang 0741984858 Lint 2024-07-02 17:44:28 +02:00
philipp lang 69a3ed2a60 Add member_id for participants 2024-07-02 16:04:07 +02:00
philipp lang bbdc9e9dfb Fix tests
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-07-01 12:08:59 +02:00
philipp lang 7e39a4da84 Fix tests
continuous-integration/drone/push Build is failing Details
2024-06-30 23:50:01 +02:00
philipp lang ae450ef9ae Add table export
continuous-integration/drone/push Build is failing Details
2024-06-30 23:36:44 +02:00
philipp lang 2425ff6638 Add adapter test 2024-06-30 21:04:54 +02:00
philipp lang 2586669c96 Delete skeleton dir when container starts 2024-06-30 21:04:20 +02:00
philipp lang af124f897b Fix Form export
continuous-integration/drone/push Build is passing Details
2024-06-30 18:51:14 +02:00
philipp lang c78c1cfee7 Make Export not nullable
continuous-integration/drone/push Build is failing Details
2024-06-30 18:10:53 +02:00
philipp lang bbd3237330 Add fields for form export
continuous-integration/drone/push Build is passing Details
2024-06-29 19:09:00 +02:00
philipp lang fcc01d26ac Lint
continuous-integration/drone/push Build is passing Details
2024-06-29 18:54:56 +02:00
philipp lang 93d30d10eb Add export to form
continuous-integration/drone/push Build is failing Details
2024-06-29 18:02:23 +02:00
philipp lang c7fc76466e Add fileshare to groups
continuous-integration/drone/push Build is passing Details
2024-06-29 14:36:35 +02:00
philipp lang 6aaeb75b2a Add remote selector
continuous-integration/drone/push Build is passing Details
2024-06-29 13:13:11 +02:00
philipp lang 8c3dc2211b Add loading component 2024-06-29 11:27:08 +02:00
philipp lang d06ae7acb5 Lint
continuous-integration/drone/push Build is passing Details
2024-06-29 11:23:33 +02:00
philipp lang 63c62dc958 Fix: Return Basename instead of Filename 2024-06-29 10:34:40 +02:00
philipp lang 71903936a3 Add api for listing subdirectories
continuous-integration/drone/push Build is failing Details
2024-06-28 23:56:34 +02:00
philipp lang 0ad6b40393 Add tests 2024-06-28 22:26:38 +02:00
philipp lang f04cf7a1b2 Install webdav filesystem 2024-06-28 22:26:09 +02:00
philipp lang 94cc0147bc Add fileshare api 2024-06-28 15:51:40 +02:00
philipp lang 73633d7628 Move component assertion 2024-06-28 15:51:40 +02:00
philipp lang 5482d47f0c Rename fileshare 2024-06-28 15:51:40 +02:00
philipp lang e1c3240290 Add update for fileshares 2024-06-28 15:51:40 +02:00
philipp lang e9e0be83cc Add: Store connection frontend 2024-06-28 15:51:40 +02:00
philipp lang 32e7f8c41d Rename test files 2024-06-28 15:51:40 +02:00
philipp lang 4cfa70e534 Lint 2024-06-28 15:51:40 +02:00
philipp lang 45597558e3 Add owncloud domain to drone 2024-06-28 15:51:40 +02:00
philipp lang c99a5a0369 Add owncloud application to drone 2024-06-28 15:51:40 +02:00
philipp lang 258093f2c4 Add fileshare storage 2024-06-28 15:51:40 +02:00
philipp lang f16b58dbc6 Add type information to index 2024-06-28 15:51:40 +02:00
philipp lang 8609a648fd Add fileshare index 2024-06-28 15:51:40 +02:00
philipp lang b15b806948 Remove switch and form css
continuous-integration/drone/push Build is passing Details
2024-06-28 15:50:40 +02:00
philipp lang 19b13133a6 Mod fields
continuous-integration/drone/push Build is passing Details
2024-06-28 14:26:12 +02:00
philipp lang d22e4b597f Add field appearance 2024-06-28 14:04:20 +02:00
philipp lang f100135f33 move classes 2024-06-28 13:43:38 +02:00
philipp lang efc9a397f3 Fix default for subscription 2024-06-28 12:47:41 +02:00
philipp lang ab06c7de5d Add validator for text modelValue 2024-06-28 12:45:43 +02:00
philipp lang a9dea10a17 Add recertified to member default 2024-06-28 12:45:23 +02:00
philipp lang dd4468808b Remove name prop from f-text component 2024-06-28 12:43:05 +02:00
philipp lang 1ef8cfdec8 Mod text component
continuous-integration/drone/push Build is passing Details
2024-06-28 12:13:08 +02:00
philipp lang b6c9eea8ea Cleanup 2024-06-28 12:13:08 +02:00
philipp lang 12eb5016c8 remove console log
continuous-integration/drone/push Build is passing Details
2024-06-28 12:12:02 +02:00
philipp lang 75d9301033 Add echo port via mode
continuous-integration/drone/push Build is passing Details
2024-06-28 12:10:18 +02:00
philipp lang 8c820ab24d Add cy data to invoice edit button
continuous-integration/drone/push Build is failing Details
2024-06-28 08:40:58 +02:00
philipp lang d26463d43c Add run script 2024-06-28 08:38:05 +02:00
philipp lang 4fda17d2c6 make siteName optional in api index 2024-06-28 08:36:57 +02:00
philipp lang 094a84c745 Lint text component 2024-06-28 08:30:35 +02:00
philipp lang 1630bce795 Add table toggle for participant index
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-21 00:25:14 +02:00
philipp lang cce9d4fa3e Add id to participant index 2024-06-21 00:24:27 +02:00
philipp lang 323f136e40 Add useTableToggle composable for group index 2024-06-21 00:23:31 +02:00
philipp lang 820b317b57 Add has_nami_field to participant component 2024-06-20 23:31:09 +02:00
philipp lang 43c528fc46 Add has_nami and two participant urls to form 2024-06-20 23:29:23 +02:00
philipp lang e9e8b193f4 Add pagination for participant api index parent 2024-06-20 23:25:47 +02:00
philipp lang 646b292249 Add has_nami to participant api index 2024-06-20 23:25:14 +02:00
philipp lang 0526b52b6b Lint 2024-06-20 00:12:15 +02:00
philipp lang 1a5675634f Add children filter to participant index
continuous-integration/drone/push Build is passing Details
2024-06-19 23:51:20 +02:00
philipp lang 73089ae654 Add TableToggleButton for group index
continuous-integration/drone/push Build is passing Details
2024-06-19 22:36:24 +02:00
philipp lang e4f195ee3e Add TableToggleButton component 2024-06-19 22:00:18 +02:00
philipp lang 87377dab06 Add toggle 2024-06-19 21:33:59 +02:00
philipp lang 668cf9d292 Fixed: Dont sync member when member is manual
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-19 13:05:45 +02:00
philipp lang 03c19aa5fb Validate fields for manual member
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-19 10:30:07 +02:00
philipp lang 40407214e3 Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-19 00:04:28 +02:00
philipp lang 49afcafbb2 Update adrema-form
continuous-integration/drone/push Build is failing Details
2024-06-18 23:55:30 +02:00
philipp lang 8f6b8e466a Fix: allow parent group field to have empty value 2024-06-18 23:54:55 +02:00
philipp lang af6dd35a5b Update adrema-form
continuous-integration/drone/push Build is passing Details
2024-06-18 21:50:08 +02:00
philipp lang 402e0fe5ee Update adrema-form 2024-06-18 21:36:06 +02:00
philipp lang 9252686e78 Fixed: Fill fields of manual member if nami type
continuous-integration/drone/push Build is passing Details
2024-06-18 21:21:02 +02:00
philipp lang c9885a8c9c Add intro field for existing sections
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-18 15:12:40 +02:00
philipp lang a71af994bb Fix tests
continuous-integration/drone/push Build is passing Details
2024-06-18 15:07:10 +02:00
philipp lang f03459de58 Fix: Update section intro
continuous-integration/drone/push Build is failing Details
2024-06-18 14:54:44 +02:00
philipp lang 3f3ecf0071 Add non nami members
continuous-integration/drone/push Build is passing Details
2024-06-18 02:00:36 +02:00
philipp lang fa2d93174a Add mobile phone nami type
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-12 00:47:25 +02:00
philipp lang cb3cc087d6 Add age nami field 2024-06-12 00:41:49 +02:00
philipp lang 86aaf55d21 Add gender as a nami field 2024-06-12 00:14:25 +02:00
philipp lang 700d69d1a2 Add male and female for member factory
continuous-integration/drone/push Build is passing Details
2024-06-12 00:04:13 +02:00
philipp lang 452505632e Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-10 18:51:06 +02:00
philipp lang 6ae61655de Add minmax for checkboxes
continuous-integration/drone/push Build is failing Details
2024-06-10 17:46:41 +02:00
philipp lang df202d9a9a Update adrema-form
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-10 16:52:28 +02:00
philipp lang da02a76e21 Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-10 11:16:28 +02:00
philipp lang edfd5dcbe7 Add: clear form frontend cache when form updated
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is failing Details
2024-06-10 00:17:14 +02:00
philipp lang ccea9ab094 Update adrema-form
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-06-07 01:03:42 +02:00
philipp lang 348fca4dd0 Fixed tests
continuous-integration/drone/push Build is passing Details
2024-06-07 01:02:07 +02:00
philipp lang 1ee2e72347 Add default value for intro
continuous-integration/drone/push Build is failing Details
2024-06-07 00:55:34 +02:00
philipp lang 393d1f391c Add nickname to nami fields
continuous-integration/drone/push Build is failing Details
2024-06-07 00:52:09 +02:00
philipp lang 7e152c017a Add intro to fields
continuous-integration/drone/push Build is failing Details
2024-06-07 00:48:54 +02:00
philipp lang 2b976ac03e Mod tab name in Form 2024-06-07 00:20:15 +02:00
philipp lang 68a47e3fb9 Fixed: Filter members for different memberships
continuous-integration/drone/push Build is passing Details
2024-05-28 00:17:18 +02:00
philipp lang 917a3932e1 Add export for forms
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-05-27 21:08:09 +02:00
philipp lang 5bd52e7b51 Add unique fields for mmebership filters
continuous-integration/drone/push Build is passing Details
2024-05-27 20:39:06 +02:00
philipp lang db640c8185 Add register url
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-05-27 19:47:28 +02:00
philipp lang 0fb259a373 Return active and private from forms api
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-05-27 19:14:55 +02:00
philipp lang e299e8b159 Lint 2024-05-27 19:14:42 +02:00
philipp lang 35a8c59055 Add private columns
continuous-integration/drone/push Build is failing Details
2024-05-27 18:53:44 +02:00
philipp lang 0c49166392 Add private state for forms 2024-05-27 18:49:11 +02:00
philipp lang c4aa9b1051 Add inactive forms 2024-05-27 18:30:05 +02:00
philipp lang e5008d127d Ignore _url when searching for members
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-05-26 01:17:05 +02:00
philipp lang a9eafb44be Ignore media-library storage
continuous-integration/drone/push Build is passing Details
2024-05-23 23:54:12 +02:00
philipp lang e10742d298 Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-05-14 09:38:18 +02:00
philipp lang c0daff972b Add filter for invoices
continuous-integration/drone/push Build is failing Details
2024-05-14 01:29:39 +02:00
philipp lang 30d670a575 Grab page limit from scout config
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-05-09 02:23:55 +02:00
philipp lang b1581bf9c8 Fix: Export all pages when exporting a csv
continuous-integration/drone/push Build is passing Details
2024-05-09 02:07:31 +02:00
philipp lang b3354e1474 Mod deletion of members when initializing
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-05-02 21:08:48 +02:00
philipp lang ce6cc215bd Update adrema-form
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is failing Details
2024-04-27 00:00:23 +02:00
philipp lang c4cec65249 Fix assert
continuous-integration/drone/push Build is passing Details
2024-04-26 23:46:23 +02:00
philipp lang 36a9b21028 Lint
continuous-integration/drone/push Build is failing Details
2024-04-26 23:33:34 +02:00
philipp lang 1c4b0b5e46 Mod Size of participants filters
continuous-integration/drone/push Build is failing Details
2024-04-26 23:24:14 +02:00
philipp lang 8f285b4aa6 Add filter for participants
continuous-integration/drone/push Build is failing Details
2024-04-26 23:20:03 +02:00
philipp lang 9954ba1ee4 Lint Select form field 2024-04-26 21:47:36 +02:00
philipp lang 35c817d1c2 Add subscription_id to nami fields 2024-04-25 23:48:51 +02:00
philipp lang 60c80deefe Fix editor
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-04-25 23:17:05 +02:00
philipp lang 868dc5cf02 Add description for condition blocks
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-25 22:49:07 +02:00
philipp lang 38ac195924 Add simple wrapper content for condition 2024-04-25 22:37:46 +02:00
philipp lang 36b195b78a Fix empty-option-value
continuous-integration/drone/push Build is passing Details
2024-04-25 22:01:55 +02:00
philipp lang 8e3054da49 Add: Delete participant
continuous-integration/drone/push Build is passing Details
2024-04-25 21:49:31 +02:00
philipp lang f05a919b9c Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-24 15:39:07 +02:00
philipp lang e0bd7c5add Fix tests
continuous-integration/drone/push Build is failing Details
2024-04-24 00:20:03 +02:00
philipp lang 47cbc3321c Fix tests
continuous-integration/drone/push Build is failing Details
2024-04-24 00:09:47 +02:00
philipp lang 2984ad9372 Fix tests
continuous-integration/drone/push Build is failing Details
2024-04-24 00:02:27 +02:00
philipp lang 0ba8c58c76 Fixed tests 2024-04-23 23:55:42 +02:00
philipp lang 0437511bf1 Add filter for attachments
continuous-integration/drone/push Build is failing Details
2024-04-23 23:48:09 +02:00
philipp lang 1328f359b2 Fix: Update active columns 2024-04-23 23:12:14 +02:00
philipp lang 4997895dfb Add heading in confirm registration mail 2024-04-23 23:03:29 +02:00
philipp lang 4f1c02acac Add test for blocks 2024-04-23 23:01:27 +02:00
philipp lang ae39c8dd31 Fix: Return emoty blocks
continuous-integration/drone/push Build is failing Details
2024-04-20 00:29:32 +02:00
philipp lang dbffb4b394 Change time for editorjs update
continuous-integration/drone/push Build is failing Details
2024-04-20 00:18:10 +02:00
philipp lang 1929c8c216 Add filter for mail top and mail bottom 2024-04-20 00:04:20 +02:00
philipp lang 21dfc4f0b2 Add findByKey to FieldCollection 2024-04-20 00:00:04 +02:00
philipp lang 5e2427ee81 Add condition for checkbox field 2024-04-19 23:57:05 +02:00
philipp lang 37c8f35b58 Add condition selector for mode 2024-04-19 22:13:55 +02:00
philipp lang 5310686b9c Mod condition data 2024-04-19 22:06:09 +02:00
philipp lang 2363be7d61 Add panel types in mail theme 2024-04-19 22:04:51 +02:00
philipp lang 2abe061c4f Update content tests 2024-04-19 17:42:59 +02:00
philipp lang fde1a9d169 Update mail views 2024-04-19 16:51:17 +02:00
philipp lang 1f4173caf8 Lint 2024-04-19 16:35:59 +02:00
philipp lang 6ad639730a Fix: hide form when tab is not opened
continuous-integration/drone/push Build is failing Details
2024-04-19 14:58:49 +02:00
philipp lang 096e44b767 Add conditions to files and email
continuous-integration/drone/push Build is failing Details
2024-04-19 13:49:47 +02:00
philipp lang e08ad63313 Add test for isDirty 2024-04-19 11:38:53 +02:00
philipp lang 594c45aede Fix: Store membership for non nami member
continuous-integration/drone/push Build is passing Details
2024-04-19 11:12:41 +02:00
philipp lang aa81843df1 Lint 2024-04-18 22:18:56 +02:00
philipp lang adf0ae183e Add condition for email files 2024-04-18 22:15:28 +02:00
philipp lang 4095d218bd Update adrema-form 2024-04-18 20:16:23 +02:00
philipp lang 4b2ac19b78 ignore groups file 2024-04-18 19:33:16 +02:00
philipp lang bf6e0fac85 Fix empty option
continuous-integration/drone/tag Build is passing Details
2024-04-18 19:01:54 +02:00
philipp lang 85560ebec2 Revert "Set hasEmptyOption"
This reverts commit daca017d96.
2024-04-18 18:59:58 +02:00
philipp lang daca017d96 Set hasEmptyOption
continuous-integration/drone/tag Build was killed Details
continuous-integration/drone/push Build was killed Details
2024-04-18 18:55:26 +02:00
philipp lang fd1e0bb9e1 Add empty option for group field
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-18 01:03:30 +02:00
philipp lang 913e45eb75 Add editorjs-alert package
continuous-integration/drone/push Build is passing Details
2024-04-17 23:46:29 +02:00
philipp lang 46ff7a0ca8 Add editor formatting for alerts
continuous-integration/drone/push Build is failing Details
2024-04-17 23:05:55 +02:00
philipp lang f70c0db783 Add draggable for fields
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is failing Details
2024-04-17 21:18:23 +02:00
philipp lang df4f911d8e Update adrema-form 2024-04-17 20:24:11 +02:00
philipp lang 2691894b78 Fixed tests
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-17 10:53:59 +02:00
philipp lang edffe0ef80 Fixed tests
continuous-integration/drone/push Build is failing Details
2024-04-17 10:19:56 +02:00
philipp lang 58bb5ec87f Update adrema-form
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is failing Details
2024-04-16 23:23:57 +02:00
philipp lang e480eb330e Add allowcustom field 2024-04-16 23:15:05 +02:00
philipp lang c62f8ec676 Fixed tests
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-15 16:37:36 +02:00
philipp lang 55d253aa7b Fixed tests
continuous-integration/drone/push Build is failing Details
2024-04-15 16:23:32 +02:00
philipp lang f84decbb52 Fixed tests 2024-04-15 16:20:29 +02:00
philipp lang 8117cfb4f4 Add number field
continuous-integration/drone/push Build is failing Details
2024-04-14 11:47:48 +02:00
philipp lang a6a8983ae9 Add mail attachments to registration mail 2024-04-14 10:49:44 +02:00
philipp lang 8b42a62b2d update adrema-form 2024-04-14 00:26:41 +02:00
philipp lang e6261d42ff Add mailattachments upload field for forms 2024-04-14 00:26:17 +02:00
philipp lang 56e0223492 Add test for email validation
continuous-integration/drone/push Build is failing Details
2024-04-13 21:57:58 +02:00
philipp lang 5e49e5bd59 Add test for checkbox field presenter 2024-04-13 21:49:29 +02:00
philipp lang 93d4511ee8 Add Email field
continuous-integration/drone/push Build is failing Details
2024-04-12 15:57:53 +02:00
philipp lang 63583b9b25 Add Boolean presenter for checkbox
continuous-integration/drone/push Build is failing Details
2024-04-12 15:42:43 +02:00
philipp lang 1509efd881 Add default required for field 2024-04-12 15:23:18 +02:00
philipp lang ab7e20becd Add searching for member
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is failing Details
2024-04-12 02:20:43 +02:00
philipp lang 0e2ebd9593 Add membership management 2024-04-12 02:11:30 +02:00
philipp lang 58feb20545 Add created_at column in participants table
continuous-integration/drone/push Build is failing Details
2024-04-12 00:14:02 +02:00
philipp lang a1b0f6496c Add: Remove option in FormBuilder
continuous-integration/drone/push Build is passing Details
2024-04-11 23:01:52 +02:00
philipp lang 45b559ea17 Add ActionButton in tables 2024-04-11 22:53:26 +02:00
philipp lang 34ab000e37 Update adrema-form
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-11 20:14:42 +02:00
philipp lang bd6ccf030b Add prefer_inner for group api
continuous-integration/drone/push Build is passing Details
2024-04-11 20:03:25 +02:00
philipp lang 2ba31a0678 Mod: Set relative url for member links in meilisearch response
continuous-integration/drone/push Build is passing Details
2024-04-10 16:23:50 +02:00
philipp lang edc7aaccd6 Add: default search option when searching for members
continuous-integration/drone/push Build is passing Details
2024-04-10 16:11:14 +02:00
philipp lang 5d1571012d Fix: hint should be optional
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-10 00:11:58 +02:00
philipp lang 43821ec416 Ad hint field
continuous-integration/drone/push Build is failing Details
2024-04-10 00:00:20 +02:00
philipp lang c3f58cebc6 Update adrema-form 2024-04-08 23:50:46 +02:00
philipp lang f05c85a035 Add other field matches for NamiField 2024-04-08 23:50:17 +02:00
philipp lang 0e69e7c7f1 Fix field replace
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-08 19:22:52 +02:00
philipp lang f3f092bdf5 fix adrema-form path
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-04-08 18:28:31 +02:00
philipp lang 44ea68cce7 Mod registration mail
continuous-integration/drone/push Build is failing Details
2024-03-24 11:09:56 +01:00
philipp lang c0096c0794 Remove adrema-plugin submodule
continuous-integration/drone/push Build is failing Details
2024-03-17 16:50:18 +01:00
philipp lang 05bcb376c8 Update oc-adrema-plugin 2024-03-17 16:42:47 +01:00
philipp lang 913cabc7a3 Mod Adrema plugin path
continuous-integration/drone/push Build is failing Details
2024-03-17 16:21:54 +01:00
philipp lang 7cc1f349a1 Update adrema-plugin 2024-03-17 02:08:14 +01:00
philipp lang 8d2f8ec03d Fix tests 2024-03-17 02:08:14 +01:00
philipp lang 9144ae1028 Add mail for registration 2024-03-17 02:08:14 +01:00
philipp lang c3a2417cac Lint 2024-03-17 02:08:14 +01:00
philipp lang 91943a6321 Add subject for participant mail 2024-03-17 02:08:14 +01:00
philipp lang 6f03063cba Add SpecialType to form field 2024-03-17 02:08:14 +01:00
philipp lang 5d576cda6a Add mail to participant 2024-03-17 02:08:14 +01:00
philipp lang 2a979d932e Add value for Participant fields 2024-03-17 02:08:14 +01:00
philipp lang 80def4abde --wip-- [skip ci] 2024-03-17 02:08:14 +01:00
philipp lang 64c2cb9408 Add value for field 2024-03-17 02:08:14 +01:00
philipp lang 78d6c6d864 Add participants parent and child in request filter 2024-03-17 02:08:14 +01:00
philipp lang a0842afd47 Add participants parent id 2024-03-17 02:08:14 +01:00
philipp lang 43846d1703 Add matching for member 2024-03-17 02:08:14 +01:00
philipp lang 171dd51200 Add email to NamiField 2024-03-17 02:08:14 +01:00
philipp lang c844f2143a Add data objects for form 2024-03-17 02:08:14 +01:00
philipp lang 6ac539417f Lint 2024-03-17 02:08:14 +01:00
philipp lang 56ad09c6fa Fix form 2024-03-17 02:08:14 +01:00
philipp lang 2f2e95cd23 Fix: Remove page param from search action input 2024-03-17 02:08:14 +01:00
philipp lang 3d270ce9a4 Fix: Remove active columns when field removed 2024-03-17 02:08:14 +01:00
philipp lang eaa880127d Add fresh Login for Remote login 2024-03-17 02:08:14 +01:00
philipp lang 6f334765bf Fix remote search 2024-03-17 02:08:13 +01:00
philipp lang b806cafc8b Add agegroups to form meta 2024-03-17 02:08:13 +01:00
philipp lang ada03a11ea Lint 2024-03-17 02:08:13 +01:00
philipp lang a12cb53274 Fixed tests 2024-03-17 02:08:13 +01:00
philipp lang 458c643615 Add remote search 2024-03-17 02:08:13 +01:00
philipp lang 60b0052622 Fix setting form meta when form has no fields 2024-03-17 02:08:13 +01:00
philipp lang 0bc00207b2 Add remote login 2024-03-17 02:08:13 +01:00
philipp lang 8cd2f74477 Add form meta route 2024-03-17 02:08:13 +01:00
philipp lang 9d11294fde Add update of active columns in participants table 2024-03-17 02:08:13 +01:00
philipp lang acec968963 Lint 2024-03-17 02:08:13 +01:00
philipp lang 3cbb4768e8 Add sorting and active_columns meta for form 2024-03-17 02:08:13 +01:00
philipp lang 09e3bcab9e Return namiTypes from form 2024-03-17 02:08:13 +01:00
philipp lang 66a76ad2b1 Fix: Match Group of member 2024-03-17 02:08:13 +01:00
philipp lang 5919082211 Add trait for creating form fields 2024-03-17 02:08:13 +01:00
philipp lang 2a5c203cc0 Lint 2024-03-17 02:08:13 +01:00
philipp lang 5f48b4e64d Add presenter for nami field 2024-03-17 02:08:13 +01:00
philipp lang 5f47729bb6 Add mitgliedsnr column to sub member 2024-03-17 02:08:13 +01:00
philipp lang c9cbf86626 Lint 2024-03-17 02:08:13 +01:00
philipp lang 8713f941c1 Fix: Register participant with no nami member 2024-03-17 02:08:13 +01:00
philipp lang 26ce8637c1 Mod field name of nami_type in FormBuilder 2024-03-17 02:08:13 +01:00
philipp lang ebf7a1d5c9 Add: Destroy formtemplate 2024-03-17 02:08:13 +01:00
philipp lang b86b2b6063 Add for_members field for sections 2024-03-17 02:08:13 +01:00
philipp lang 94397165c6 Lint 2024-03-17 02:08:13 +01:00
philipp lang 9d7d039530 Lint Registration 2024-03-17 02:08:13 +01:00
philipp lang 34fb96dabe Simplify test 2024-03-17 02:08:13 +01:00
philipp lang f601167893 Add FormTestCase 2024-03-17 02:08:13 +01:00
philipp lang 54b650fb91 Rename test method 2024-03-17 02:08:13 +01:00
philipp lang f24064b9f3 Add createMember method 2024-03-17 02:08:13 +01:00
philipp lang a96d879023 Set fields not fillable 2024-03-17 02:08:13 +01:00
philipp lang b194e77966 Add validation for other member fields 2024-03-17 02:08:13 +01:00
philipp lang a830f366ad Fix tests 2024-03-17 02:08:13 +01:00
philipp lang 974c73af71 Lint 2024-03-17 02:08:13 +01:00
philipp lang 445590e060 Add other fields from Member 2024-03-17 02:08:13 +01:00
philipp lang ef47480cc9 Add member registration via nami type 2024-03-17 02:08:13 +01:00
philipp lang 35b269c647 Add lastname nami field 2024-03-17 02:08:13 +01:00
philipp lang e508dd9e6f Add nami fields to form field 2024-03-17 02:08:13 +01:00
philipp lang 891f0c21ad Add presenters 2024-03-17 02:08:13 +01:00
philipp lang a0bcd99642 Lint 2024-03-17 02:08:13 +01:00
philipp lang 857051434e Lint 2024-03-17 02:08:13 +01:00
philipp lang c7b23df01e Add participant overview 2024-03-17 02:08:13 +01:00
philipp lang 7361dcccff Fix page navigation in useApiIndex 2024-03-17 02:08:13 +01:00
philipp lang 590696750b Add Backend for participant index 2024-03-17 02:08:13 +01:00
philipp lang 48383b25da Add participants count for form index 2024-03-17 02:08:13 +01:00
philipp lang de76e195e7 Move Api routes 2024-03-17 02:08:13 +01:00
philipp lang ff6c2bbc2c Update Adrema plugin 2024-03-17 02:08:13 +01:00
philipp lang 5d9d7a0ffc Add register action 2024-03-17 02:08:13 +01:00
philipp lang 89429f9812 Add options and maxToday method 2024-03-17 02:08:13 +01:00
philipp lang b813664632 Fix: snake method in tests 2024-03-17 02:08:13 +01:00
philipp lang a7394e12aa Add Type to FormtemplateFieldRequest 2024-03-17 02:08:13 +01:00
philipp lang ddb44d64d6 Add adrema_base_url 2024-03-17 02:08:13 +01:00
philipp lang 3d62970baf Fixed tests 2024-03-17 02:08:13 +01:00
philipp lang 9a3a0402d9 Set minHeight for editor 2024-03-17 02:08:13 +01:00
philipp lang 665b43c797 Add lists 2024-03-17 02:08:13 +01:00
philipp lang ee926467ed Add style for headings 2024-03-17 02:08:13 +01:00
philipp lang 4ffc14d503 Fix MemberTest 2024-03-17 02:08:13 +01:00
philipp lang 1edbdab8fd Add editorJS for Form Description 2024-03-17 02:08:13 +01:00
philipp lang 6e6a4595cd Lint 2024-03-17 02:08:13 +01:00
philipp lang e3a0ca7673 Fix searching via api 2024-03-17 02:08:13 +01:00
philipp lang 28c821eeaf Add searching and filtering for events 2024-03-17 02:08:13 +01:00
philipp lang e45a59c5ff Add from and to date to form index 2024-03-17 02:08:13 +01:00
philipp lang d3c1e89a03 Add media conversion for squared form header image format 2024-03-17 02:08:13 +01:00
Philipp Lang 6ede944d85 Remove laravel sail 2024-03-17 02:08:13 +01:00
Philipp Lang b69c895921 Add image to api response 2024-03-17 02:08:13 +01:00
Philipp Lang 539e41cffe Lint 2024-03-17 02:08:13 +01:00
philipp lang bdf3fa54a9 Add image component to form 2024-03-17 02:08:13 +01:00
philipp lang 97fabf0f24 Add image to form 2024-03-17 02:08:13 +01:00
philipp lang e011b52534 Add form api to display event overview on website 2024-03-17 02:08:13 +01:00
philipp lang e005ed0d0d lint 2024-03-17 02:08:13 +01:00
philipp lang ae19a6ed2b lint 2024-03-17 02:08:13 +01:00
philipp lang 4ce7d428d4 lint 2024-03-17 02:08:13 +01:00
philipp lang e6d0a30c7f lint 2024-03-17 02:08:12 +01:00
philipp lang d16f02c8b3 fix tests 2024-03-17 02:08:12 +01:00
philipp lang 888f4ee976 Lint 2024-03-17 02:08:12 +01:00
philipp lang 2a6e3aac03 Fix tests 2024-03-17 02:08:12 +01:00
philipp lang 7abf746897 Update Form Builder 2024-03-17 02:08:12 +01:00
philipp lang ed8e7b045d Fix drone 2024-03-17 02:08:12 +01:00
philipp lang 2a2cbd196d Add node 2024-03-17 02:08:12 +01:00
philipp lang 4690e0037f Mod adrema plugin 2024-03-17 02:08:12 +01:00
philipp lang 1d28827353 Update adrema-plugin 2024-03-17 02:08:12 +01:00
philipp lang 703084dbc1 update submodules 2024-03-17 02:08:12 +01:00
philipp lang 7aa445ca74 Mod modules 2024-03-17 02:08:12 +01:00
philipp lang a2d7a36fc1 mod submodule 2024-03-17 02:08:12 +01:00
philipp lang 23c60d4330 Fix submodules 2024-03-17 02:08:12 +01:00
philipp lang 79f1c71dd9 Fix tests 2024-03-17 02:08:12 +01:00
philipp lang 452416d0a4 fix tests 2024-03-17 02:08:12 +01:00
philipp lang 589b713907 Add form editor 2024-03-17 02:08:12 +01:00
philipp lang eb60852bbf Fix textarea hint 2024-03-17 02:08:12 +01:00
philipp lang c3db854eb5 Add formtemplate to form index 2024-03-17 02:08:12 +01:00
philipp lang 5cf49489d5 Add config to index 2024-03-17 02:08:12 +01:00
philipp lang 7d880c6e29 --wip-- [skip ci] 2024-03-17 02:08:12 +01:00
philipp lang 743c041c35 Add IndexAction for forms 2024-03-17 02:08:12 +01:00
philipp lang d3ad48ed30 Add more form fields 2024-03-17 02:08:12 +01:00
philipp lang 4776c0d71b Add eventform submodule 2024-03-17 02:08:12 +01:00
philipp lang 9355daee7e Lint 2024-03-17 02:08:12 +01:00
philipp lang 89b5cbd4b5 Add group field 2024-03-17 02:08:12 +01:00
philipp lang c8bc69ae30 Add date field 2024-03-17 02:08:12 +01:00
philipp lang 0fde33803b Add slot for meta info to formbuilder 2024-03-17 02:08:12 +01:00
philipp lang 1b5c83a414 add StoreForm route 2024-03-17 02:08:12 +01:00
philipp lang e0558e4b13 update form 2024-03-17 02:08:12 +01:00
philipp lang b421f85d89 Move Config to FormBuilder 2024-03-17 02:08:12 +01:00
philipp lang 0eb8928b22 Fix TextField Meta 2024-03-17 02:08:12 +01:00
philipp lang f1d4d3e428 Add StoreAction for form 2024-03-17 02:08:12 +01:00
philipp lang 5b2a290b49 Add FormtemplateUpdateActionTest 2024-03-17 02:08:12 +01:00
philipp lang f55c174019 Fix tests 2024-03-17 02:08:12 +01:00
philipp lang d597d5ea2b Add fakers for fields 2024-03-17 02:08:12 +01:00
Philipp Lang d4c8fdff3f Remove test for name 2024-03-17 02:08:12 +01:00
philipp lang b26935fc07 Add deleteSection 2024-03-17 02:08:12 +01:00
philipp lang 4ddf76943d Add column selector 2024-03-17 02:08:12 +01:00
philipp lang d7e7fb3c27 Add faker for TextField 2024-03-17 02:08:12 +01:00
philipp lang 87ee15936d Add default value for field to Request 2024-03-17 02:08:12 +01:00
Philipp Lang 6262ccdd28 Add validation for update 2024-03-17 02:08:12 +01:00
Philipp Lang b109d40ebb add field meta 2024-03-17 02:08:12 +01:00
Philipp Lang 3c81dfe7db Add fields 2024-03-17 02:08:12 +01:00
philipp lang cc52437568 fix field 2024-03-17 02:08:12 +01:00
philipp lang ac28466c8d Add checkboxes 2024-03-17 02:08:12 +01:00
philipp lang bde8d48807 Add fields 2024-03-17 02:08:12 +01:00
philipp lang 288533efd3 Add update for form 2024-03-17 02:08:12 +01:00
philipp lang 104b04b639 Add field management 2024-03-17 02:08:12 +01:00
philipp lang 8bf0019c98 Add form builder 2024-03-17 02:08:12 +01:00
philipp lang 9f85809195 Mod FormtemplateResource 2024-03-17 02:08:12 +01:00
philipp lang 131690262e Lint 2024-03-17 02:08:12 +01:00
philipp lang edb1eeb0d8 Add path alias for packages 2024-03-17 02:08:12 +01:00
philipp lang 2ecd4b9643 Ad backend for index and store 2024-03-17 02:08:12 +01:00
Philipp Lang ae679641d7 Add event module 2024-03-17 02:08:12 +01:00
philipp lang d692cf3bdf Set default text for subscription child
continuous-integration/drone/push Build is passing Details
2024-03-15 02:27:04 +01:00
philipp lang 339e76d874 Lint 2024-03-15 02:26:18 +01:00
Arwed Molitor 2d02c79c86 Set default text for subscription 2024-03-15 02:21:27 +01:00
Arwed Molitor e21e818ac6 Improve contribution BDKJ Hesse
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-03-12 14:06:19 +01:00
Arwed Molitor fecd461aef Improve contribution Frankfurt 2024-03-12 13:52:10 +01:00
philipp lang 58d7c5671f Lint
continuous-integration/drone/push Build is passing Details
2024-03-09 00:57:25 +01:00
philipp lang 54cf187ff5 Fix tests
continuous-integration/drone/push Build is failing Details
2024-03-09 00:45:29 +01:00
philipp lang 0575fe4e5c Lint
continuous-integration/drone/push Build is failing Details
2024-03-09 00:30:44 +01:00
philipp lang 3567dc3620 Update tex package
continuous-integration/drone/push Build is failing Details
2024-03-09 00:14:22 +01:00
philipp lang 4fcdf91414 Update laravel-nami
continuous-integration/drone/push Build is failing Details
2024-03-09 00:13:32 +01:00
philipp lang 94f8ea3b67 Add first_activity_id when existing member is stored in nami 2024-03-08 23:44:40 +01:00
philipp lang 32cc9feee0 Lint Member Store Test 2024-03-08 22:59:43 +01:00
philipp lang 4445304ef3 Update laravel-nami
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-03-08 22:26:52 +01:00
philipp lang d29f7b6e8a Fix member search for membership when one param is empty 2024-03-08 22:26:16 +01:00
philipp lang a25d983de0 Add efz for members
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-03-07 21:24:12 +01:00
philipp lang b80b7ea600 Add new invoice for member frontend
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-02-11 20:21:33 +01:00
philipp lang b0e4017780 Add subscriptions to invoice index
continuous-integration/drone/push Build is passing Details
2024-02-10 01:45:41 +01:00
philipp lang 1c93a977bf Add route for new invoice 2024-02-10 01:42:51 +01:00
philipp lang b738dd8192 Lint
continuous-integration/drone/push Build is passing Details
2024-02-10 01:17:24 +01:00
philipp lang 82c3ed2875 Lint
continuous-integration/drone/push Build is failing Details
2024-02-10 00:41:06 +01:00
philipp lang fe578beb9b Add mobile search modal
continuous-integration/drone/push Build is passing Details
2024-01-29 20:43:10 +01:00
philipp lang 0f8cef6490 lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-01-29 02:12:54 +01:00
philipp lang dde4336cb3 Add global search
continuous-integration/drone/push Build is failing Details
2024-01-29 01:37:28 +01:00
philipp lang 9985ed9e44 Add membership filter
continuous-integration/drone/push Build is failing Details
2024-01-29 00:13:03 +01:00
philipp lang cc8428e6b8 Add memory limit to base container 2024-01-28 21:53:54 +01:00
philipp lang 631725c0f9 Redirect meilisearch to container
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2024-01-28 19:14:12 +01:00
philipp lang f5d1313858 Fix meilisearch config
continuous-integration/drone/push Build is passing Details
2024-01-28 19:10:31 +01:00
philipp lang 3e6b81aab0 Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2024-01-28 18:38:20 +01:00
philipp lang 52b7e39d4c Lint
continuous-integration/drone/push Build is failing Details
2024-01-28 18:28:09 +01:00
philipp lang d14a373a76 ignore docker files
continuous-integration/drone/push Build is failing Details
2024-01-28 18:12:40 +01:00
philipp lang b5f87f2368 Add jpeg support to base container 2024-01-28 18:12:17 +01:00
philipp lang 6fd0ba50b9 Fix drone
continuous-integration/drone/push Build is failing Details
2024-01-28 11:43:43 +01:00
philipp lang 4e378c8a57 Add member search via meilisearch 2024-01-28 11:43:43 +01:00
philipp lang 26d0f49568 Lint 2024-01-28 11:43:42 +01:00
philipp lang 994700e34a Ignore psych dir
continuous-integration/drone/push Build is passing Details
2024-01-28 00:03:39 +01:00
philipp lang ff4ad5daa3 Mod IndexTest
continuous-integration/drone/push Build is passing Details
2024-01-26 15:33:12 +01:00
philipp lang 998eb8931b Lint
continuous-integration/drone/push Build is failing Details
2024-01-26 15:06:16 +01:00
philipp lang e7ef0a38c8 Fix popup height and overflow
continuous-integration/drone/push Build is failing Details
2024-01-26 15:04:22 +01:00
philipp lang 5b0bb1c81c sleep before test
continuous-integration/drone/push Build is failing Details
2024-01-26 14:52:51 +01:00
philipp lang 18d57b1f4b Mod tests 2024-01-26 14:52:33 +01:00
philipp lang 9788ce8fe6 Fix tests
continuous-integration/drone/push Build is failing Details
2024-01-26 10:33:53 +01:00
philipp lang e5d03e862d Fix MemberIndexTest
continuous-integration/drone/push Build is failing Details
2024-01-26 10:28:05 +01:00
philipp lang 21b0d08864 Remove search test
continuous-integration/drone/push Build is failing Details
2024-01-26 01:13:36 +01:00
philipp lang 294d0c3cb5 Add meilisearch key to drone
continuous-integration/drone/push Build is failing Details
2024-01-26 00:54:32 +01:00
philipp lang c481359962 Fix drone
continuous-integration/drone/push Build is failing Details
2024-01-26 00:48:19 +01:00
philipp lang 96ef8f2198 Remove SearchTest 2024-01-26 00:47:22 +01:00
philipp lang 515af7724a Remove port from meilisearch container
continuous-integration/drone/push Build is failing Details
2024-01-26 00:41:49 +01:00
philipp lang 83a6421bfc Add meilisearch host 2024-01-26 00:41:38 +01:00
philipp lang 24b8ac182e Fix member index test
continuous-integration/drone/push Build is failing Details
2024-01-26 00:35:00 +01:00
philipp lang 21ea72047c Add meilisearch sync to deploy
continuous-integration/drone/push Build is failing Details
2024-01-26 00:21:27 +01:00
philipp lang baeed70886 Remove meilisearch from testing
continuous-integration/drone/push Build is failing Details
2024-01-26 00:18:46 +01:00
philipp lang 6be4697867 Add drone command for meilisearch
continuous-integration/drone/push Build is failing Details
2024-01-25 23:49:12 +01:00
philipp lang f1797ed049 Add meilisearch env to drone and docker
continuous-integration/drone/push Build encountered an error Details
2024-01-25 23:46:09 +01:00
philipp lang f204f10b21 Add meilisearch
continuous-integration/drone/push Build is failing Details
2024-01-25 23:40:29 +01:00
philipp lang 5e0dd8df62 Fix toast response error 2024-01-25 23:14:12 +01:00
philipp lang c14cff9118 Fix search fulltext reset
continuous-integration/drone/push Build is passing Details
2024-01-25 20:36:48 +01:00
philipp lang 857c397692 Mod volumes
continuous-integration/drone/push Build is passing Details
2024-01-01 22:39:47 +01:00
philipp lang 9e2b5411d8 Mod storage path for webservice container 2024-01-01 21:46:48 +01:00
philipp lang 8c32b881bc fix internal name
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-12-30 23:02:08 +01:00
philipp lang 221815fb7e fix syntax error
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-12-30 22:39:26 +01:00
philipp lang 3469aeef93 Add actions slot and fullwidth to popup
continuous-integration/drone/push Build is failing Details
2023-12-30 22:33:19 +01:00
philipp lang 6b0e0c37a5 Add group internal name and layer 2023-12-30 22:21:08 +01:00
philipp lang d630d8d6b4 Add listener for succeeded event 2023-12-30 19:28:25 +01:00
philipp lang 1dc797948e Lint 2023-12-30 19:02:15 +01:00
philipp lang b896c37c31 Fix tests 2023-12-30 18:46:47 +01:00
philipp lang eb14189bf0 Add group bulkstore backend 2023-12-30 17:52:29 +01:00
philipp lang 6972091ad0 Move group link to memberships 2023-12-30 17:51:08 +01:00
philipp lang 4cc47e64b2 Add popup group
continuous-integration/drone/push Build is passing Details
2023-12-22 00:49:19 +01:00
philipp lang b017d12e2e Fix namespace of MemberPaymentBlockTest
continuous-integration/drone/push Build is passing Details
2023-12-21 23:25:28 +01:00
Philipp Lang 12f6852299 Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-12-21 13:38:42 +01:00
Philipp Lang fd75345675 Add texlive-extra-utils 2023-12-21 13:37:56 +01:00
Philipp Lang 225ea8f41d Add Poppler Utils to base container 2023-12-21 00:10:47 +01:00
Philipp Lang ebf856252c Add event for mass store
continuous-integration/drone/push Build is failing Details
2023-12-20 23:38:09 +01:00
Philipp Lang cc650ebf45 Add plugins dir to docker 2023-12-20 23:06:28 +01:00
Philipp Lang 267aaa1776 Only display promised_at when is_age_group
continuous-integration/drone/push Build is failing Details
2023-12-20 22:58:26 +01:00
Philipp Lang 11fe883b5c Remove split payments
continuous-integration/drone/push Build is failing Details
2023-12-20 22:11:07 +01:00
Philipp Lang acf280346f Add migration for invoices 2023-12-20 21:45:37 +01:00
Philipp Lang 3a3b20ed72 Remove Sendpayment form
continuous-integration/drone/push Build is failing Details
2023-12-19 02:45:09 +01:00
Philipp Lang 5d5b08ed78 Remove ports for socketi
continuous-integration/drone/push Build is failing Details
2023-12-19 02:19:18 +01:00
Philipp Lang 3697885bca Fix views 2023-12-19 02:18:58 +01:00
Philipp Lang 2a6fd1152b Remove old payments 2023-12-19 02:00:42 +01:00
Philipp Lang 156b92f765 Add Remember mail for sending 2023-12-18 02:17:31 +01:00
Philipp Lang afbfdf7ca2 Remove mail_name 2023-12-18 01:56:58 +01:00
Philipp Lang be29a284d5 Fix Send invoices 2023-12-18 01:15:16 +01:00
Philipp Lang 68a654494d Add display remember pdf 2023-12-18 00:16:58 +01:00
Philipp Lang f5ad0d46fd Mod Stub 2023-12-18 00:06:04 +01:00
Philipp Lang 8d0d05463f Mod usage in MassStoreAction 2023-12-17 23:29:01 +01:00
Philipp Lang 19dea7a061 Add link to invoice PDF to frontend 2023-12-17 23:27:55 +01:00
Philipp Lang f4dc8b24bc Add usage to invoice 2023-12-17 23:00:52 +01:00
Philipp Lang b0534279b6 Add DisplayPdfAction for invoices 2023-12-17 22:33:29 +01:00
Philipp Lang 551c658fa3 Lint 2023-12-17 21:59:51 +01:00
Philipp Lang 07a0c22a69 Remove old actions 2023-12-17 21:24:16 +01:00
Philipp Lang 2e8c41d5d9 Mod InvoicePosition in member overview 2023-12-17 21:13:52 +01:00
Philipp Lang 703c74a9f4 Lint 2023-12-17 02:03:39 +01:00
Philipp Lang bf8f6c87a8 Fix MemberPaymentsBlock 2023-12-17 01:49:12 +01:00
Philipp Lang 0f80844d20 Lint
continuous-integration/drone/push Build is failing Details
2023-12-17 01:10:26 +01:00
Philipp Lang a7b25e9b5f Fix: Delete invoice positions when deleting member 2023-12-17 01:02:56 +01:00
Philipp Lang 451680bd70 Add remove for invoice 2023-12-17 00:55:31 +01:00
Philipp Lang c598508ceb Add update for invoices 2023-12-17 00:45:03 +01:00
Philipp Lang 0b9eb77e77 Add: Store invoice 2023-12-16 23:53:18 +01:00
Philipp Lang ebeb9bc0b0 Add member meta to InvoiceResource 2023-12-16 23:52:41 +01:00
Philipp Lang 5a87d3e7f6 remove requestCallback from useIndex 2023-12-16 23:52:03 +01:00
Philipp Lang 02cd70e0ca Add innerWidth for Popup component 2023-12-16 22:59:25 +01:00
Philipp Lang 457d433722 Add Mets for InvoiceResource 2023-12-16 22:30:56 +01:00
Philipp Lang e37d98f168 Close popup after sending massstore 2023-12-16 20:35:40 +01:00
Philipp Lang 380c18a70e Add meta for InvoiceIndex 2023-12-16 20:35:28 +01:00
Philipp Lang 5b6380b429 Add deprecated for Status 2023-12-16 20:35:06 +01:00
Philipp Lang ff2d725714 Lint 2023-12-16 20:29:17 +01:00
Philipp Lang b738c5e6ca Add views for invoice index 2023-12-16 13:08:17 +01:00
Philipp Lang a755d63197 Add track jobs to mass store action 2023-12-16 11:44:32 +01:00
Philipp Lang 2ecdf6e362 Lint 2023-12-16 11:36:49 +01:00
Philipp Lang 58798146d4 Add via to invoice 2023-12-16 11:18:00 +01:00
Philipp Lang 27cbf8bcd9 Add InvoiceIndexAction 2023-12-16 01:13:49 +01:00
Philipp Lang 15b62e59fc Mod AllPayment so that it creates an invoice 2023-12-16 00:30:36 +01:00
Philipp Lang 5c40b4e64d Add InvoiceStoreAction
continuous-integration/drone/push Build is failing Details
2023-12-13 00:35:39 +01:00
Philipp Lang ad8511874d Add payment show pdf
continuous-integration/drone/push Build is failing Details
2023-12-10 04:38:11 +01:00
Philipp Lang 566ed704a6 Add payment_data for payments 2023-12-10 04:38:11 +01:00
Philipp Lang fc1b647b54 Lint 2023-12-10 04:38:10 +01:00
Philipp Lang 20836e7228 fix typo
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-11-24 14:46:18 +01:00
Philipp Lang 6e1f3f3a0a Add Stammgruppierung to member view
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-11-24 13:43:52 +01:00
Philipp Lang ebd321d166 fix tabs classes 2023-11-24 13:37:35 +01:00
Philipp Lang 69794b900f fix typo 2023-11-24 13:33:46 +01:00
Philipp Lang a1790e7126 Add Recertification field for members
continuous-integration/drone/push Build is passing Details
2023-11-24 13:31:34 +01:00
Philipp Lang 1e836b2a28 Fix bill table
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2023-11-16 12:10:07 +01:00
Philipp Lang f01c4f9d02 Lint 2023-11-16 12:07:07 +01:00
Philipp Lang 613096220f Add module management 2023-11-16 10:53:17 +01:00
Philipp Lang fc368bcd1a improve search performance in contribution member search
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-10-31 11:01:22 +01:00
Philipp Lang 972b1845ed ignore debugbar dir 2023-10-31 10:39:07 +01:00
Philipp Lang 7121e57cbb Improve search performance
continuous-integration/drone/push Build is passing Details
2023-10-31 10:38:32 +01:00
Philipp Lang a2b0de44b9 Update mariadb in drone 2023-10-31 09:26:48 +01:00
philipp lang e3d581626c Add NaMi Settings to change NaMi Login
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-10-31 00:11:32 +01:00
philipp lang fafac446c3 fix debounce
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-10-30 23:46:41 +01:00
philipp lang 56a5ec5885 Fix tests
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-10-30 23:11:10 +01:00
philipp lang a104adeb5a Fix: Add keypress event for FSelect 2023-10-30 23:09:47 +01:00
philipp lang 41d6a71d2f Fix rawurldecode
continuous-integration/drone/push Build is failing Details
2023-10-30 22:58:25 +01:00
philipp lang 97668add7e Fix: Allow umlauts in Contribution generator
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-10-27 00:48:50 +02:00
philipp lang 50d98c0335 Fix: Set From long name in City solingen document
continuous-integration/drone/push Build is passing Details
2023-10-27 00:15:02 +02:00
Philipp Lang bda8b9c293 fix tests
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-10-18 18:38:26 +02:00
Philipp Lang 7b6616c292 set memory limit for php container
continuous-integration/drone/push Build is failing Details
2023-10-18 18:30:18 +02:00
Philipp Lang 026e7674dd Lint
continuous-integration/drone/push Build is failing Details
2023-10-18 18:14:07 +02:00
Philipp Lang 3dc9513923 fix drone
continuous-integration/drone/push Build is failing Details
2023-10-18 18:07:56 +02:00
Philipp Lang 5207374e8b fix server
continuous-integration/drone/push Build is failing Details
2023-10-18 18:06:02 +02:00
Philipp Lang 8e733d899e mod drone
continuous-integration/drone/push Build was killed Details
2023-10-18 18:00:52 +02:00
Philipp Lang 89bcaf12c4 fix mysql ping
continuous-integration/drone/push Build was killed Details
2023-10-18 17:58:50 +02:00
Philipp Lang b83f30e35c fix mariadb in drone
continuous-integration/drone/push Build was killed Details
2023-10-18 17:50:18 +02:00
Philipp Lang e345ace428 use docker container for copydb
continuous-integration/drone/push Build encountered an error Details
2023-10-18 16:52:30 +02:00
Philipp Lang 9a898315a0 fix deleting actions 2023-10-18 16:52:30 +02:00
Philipp Lang a84d9f428d fix course destroy 2023-10-18 16:52:30 +02:00
Philipp Lang 36c0ebced0 Update course actions 2023-10-18 16:52:30 +02:00
Philipp Lang 6d4dda869a Add DestroyAction for payment 2023-10-18 16:52:30 +02:00
Philipp Lang 9813482741 Add update for payment 2023-10-18 16:52:30 +02:00
Philipp Lang 1e74a6055e Add Payment store 2023-10-18 16:52:30 +02:00
Philipp Lang c764f3d3b7 Add payment index 2023-10-18 16:52:30 +02:00
Philipp Lang 8846adef5b Fix tests 2023-10-18 16:52:30 +02:00
Philipp Lang 20833426ca Add queue events for memberships 2023-10-18 16:52:30 +02:00
Philipp Lang e60bc94b80 Add TracksJob to membership store action 2023-10-18 16:52:30 +02:00
Philipp Lang 356a69507e Mod: Set get method for membership 2023-10-18 16:52:30 +02:00
Philipp Lang 1fb2dd19e7 Rename Group actions 2023-10-18 16:52:30 +02:00
Philipp Lang 767239fb62 Fixed tests 2023-10-18 16:52:30 +02:00
Philipp Lang 2fbad36700 Remove MembershipController 2023-10-18 16:52:30 +02:00
Philipp Lang 37a6dd8330 Add sidebar for payments 2023-10-18 16:52:30 +02:00
Philipp Lang bfc4663ba4 Add loading for memberships sidebar 2023-10-18 16:52:30 +02:00
Philipp Lang 450e715acd Lint 2023-10-18 16:52:30 +02:00
Philipp Lang 128d9af3ee Lint 2023-10-18 16:52:30 +02:00
philipp lang a26f064698 Fix: Do not store maildispatcher members with same email address multiple times
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-10-11 23:13:59 +02:00
Philipp Lang ff245397d5 Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-09-19 20:14:52 +02:00
Philipp Lang e4ff680e4f fixed PluginTest
continuous-integration/drone/push Build is passing Details
2023-09-19 20:06:41 +02:00
Philipp Lang 3420a03fbc Cleanup after PluginsTest
continuous-integration/drone/push Build was killed Details
2023-09-19 19:57:40 +02:00
Philipp Lang 6780068ca1 fix mkdir
continuous-integration/drone/push Build was killed Details
2023-09-19 19:56:19 +02:00
Philipp Lang be0a8a3ddb Add Plugin manager
continuous-integration/drone/tag Build is failing Details
continuous-integration/drone/push Build was killed Details
2023-09-19 00:13:36 +02:00
Philipp Lang 3d154c4154 Add api for fetching memberships
continuous-integration/drone/push Build is passing Details
2023-09-12 16:54:13 +02:00
Philipp Lang 85f0d6c515 Update README
continuous-integration/drone/push Build is passing Details
2023-09-12 12:19:10 +02:00
philipp lang 17eaa2e564 Add Password Reset
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-09-08 00:29:37 +02:00
philipp lang 6f4ee0b02d Lint 2023-09-07 22:52:33 +02:00
Philipp Lang dc832503b4 Fixed: subscription_id validation
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-09-07 16:48:51 +02:00
Philipp Lang 3a96b00307 Fixed: Add default model for members 2023-09-07 16:33:40 +02:00
Philipp Lang c89973032b Fix: Close mobile menu when navigating
continuous-integration/drone/push Build is passing Details
2023-09-07 16:06:17 +02:00
Philipp Lang 20c9b84e6e Lint
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-09-07 14:40:46 +02:00
Philipp Lang c554e506ea Update README 2023-09-07 14:40:44 +02:00
Philipp Lang 80dfebf63b Add Host-ENV for nginx webservice 2023-09-07 14:40:31 +02:00
Philipp Lang 6c9c27d6ab Add volume to redis container 2023-09-07 14:38:21 +02:00
Philipp Lang 554e1af245 Add BDKJ-Hesse to contribution generator
continuous-integration/drone/push Build is failing Details
2023-09-07 13:12:57 +02:00
Philipp Lang 349d821638 Add Frankfurt/Main to contribution generator 2023-09-07 13:12:57 +02:00
Philipp Lang ff6c0e462e Fix tests
continuous-integration/drone/push Build is passing Details
2023-09-07 13:12:47 +02:00
Philipp Lang 639d1850c7 Rename contribution documents
continuous-integration/drone/push Build is failing Details
2023-09-07 12:04:13 +02:00
philipp lang 38bd73cf5b Fix tests
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-09-07 00:28:53 +02:00
philipp lang f1ad653ba8 Fixed tests
continuous-integration/drone/push Build is failing Details
2023-09-07 00:22:44 +02:00
philipp lang 560881725d Upgrade ui-bool
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2023-09-06 23:45:45 +02:00
philipp lang 71da52791d Fixed date in member ShowTest
continuous-integration/drone/push Build is passing Details
2023-09-06 23:45:13 +02:00
philipp lang 946a6c93b2 Fixed tests 2023-09-06 23:45:03 +02:00
Philipp Lang b28525be7c Update .gitignore and change cookies volumes
continuous-integration/drone/tag Build is failing Details
continuous-integration/drone/push Build was killed Details
2023-09-05 16:42:39 +02:00
Philipp Lang 0de90be8c3 Add membership status to member view
continuous-integration/drone/push Build is failing Details
2023-09-05 16:29:22 +02:00
Arwed Molitor 59c2c527fb Change tag order
continuous-integration/drone/push Build is passing Details
2023-08-30 15:08:45 +02:00
Arwed Molitor a009fabb15 Minor typo fixes 2023-08-30 15:08:45 +02:00
Arwed Molitor 5e416e5ed7 Enhance pagination 2023-08-30 15:08:44 +02:00
philipp lang cd22d41f28 Fix deploy
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-08-25 01:12:44 +02:00
philipp lang 1bdcc55d2a Fix useIndex
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details
2023-08-25 00:26:21 +02:00
philipp lang 2e9ab78203 Add Membership management
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build was killed Details
2023-08-25 00:23:38 +02:00
Philipp Lang a134be5f5b Add memory_limit for schedule
continuous-integration/drone/push Build is passing Details
2023-08-21 14:15:29 +02:00
philipp lang 8d54c5b47c Add dpsg köln to envoy
continuous-integration/drone/push Build is passing Details
2023-08-20 23:39:57 +02:00
philipp lang 391de0edde Add mobile version for member filter
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-08-20 23:37:11 +02:00
philipp lang 232917a8e6 Add composable dir to tailwind content 2023-08-20 23:36:38 +02:00
philipp lang 74b162cc23 Lint 2023-08-20 23:36:26 +02:00
philipp lang 37107915a1 Eslint: ignore multi word component rule 2023-08-20 23:35:57 +02:00
philipp lang 1ef4689d15 Fix: Load member list in mobile view 2023-08-20 22:47:17 +02:00
philipp lang ac2428caac Fix: memory_limit for drone tests
continuous-integration/drone/push Build is passing Details
2023-08-20 22:33:15 +02:00
Philipp Lang c260fcb4e4 Add trait for Queue event handling
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is failing Details
2023-08-17 12:46:48 +02:00
philipp lang 687ec80069 update github push
continuous-integration/drone/push Build is passing Details
2023-08-16 01:27:07 +02:00
philipp lang 74c5faaebd Add exception for deleting member
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-08-16 01:07:48 +02:00
philipp lang aeb926e165 Add Broadcast event when deleting member
continuous-integration/drone/push Build is passing Details
2023-08-16 00:43:28 +02:00
philipp lang 3263e93da7 Move member deletion to action 2023-08-15 23:03:51 +02:00
philipp lang 0ae11f753f Move nami delete member action 2023-08-15 23:00:01 +02:00
Philipp Lang 6dffb8d4ff Add base image
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-08-15 16:42:15 +02:00
Philipp Lang e8e309fccd mod default pusher host
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-08-15 16:28:10 +02:00
Philipp Lang a858fd40a7 Add DatabaseTransactions
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-08-15 15:24:03 +02:00
Philipp Lang 925754bd26 Add check for geolocation
continuous-integration/drone/push Build is failing Details
2023-08-15 15:11:12 +02:00
Philipp Lang 0e023a06ec Add wss port
continuous-integration/drone/push Build is passing Details
2023-08-15 15:07:55 +02:00
philipp lang 716c6079fe Lint
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-08-15 00:17:17 +02:00
philipp lang 658414c979 Add ClientMessage to payment controller
continuous-integration/drone/tag Build was killed Details
continuous-integration/drone/push Build is failing Details
2023-08-15 00:05:45 +02:00
philipp lang 4738c077d1 Fixed tests
continuous-integration/drone/push Build is failing Details
2023-08-15 00:01:12 +02:00
philipp lang f178d3ec86 Update client index when Member deleted 2023-08-14 23:57:15 +02:00
philipp lang 7e4961f3d8 Update DeleteJob as Action 2023-08-14 23:48:38 +02:00
philipp lang 2d9f79ee15 Update composer packages 2023-08-14 23:48:11 +02:00
Philipp Lang 6f133954ff Lint 2023-08-10 16:33:36 +02:00
Philipp Lang 59117682d0 Lint 2023-08-10 16:33:36 +02:00
philipp lang 1ac30202b1 Add composable for index 2023-08-10 16:33:36 +02:00
Philipp Lang 69afeeda65 Add eslint prettier 2023-08-10 16:33:36 +02:00
Philipp Lang eb5f03bd5a update envoy file
continuous-integration/drone/push Build is passing Details
2023-08-10 16:27:01 +02:00
Philipp Lang 215d08aeeb Add setting for seeder
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-08-07 21:32:56 +02:00
philipp lang 0c45e1b2f4 ignore log file
continuous-integration/drone/push Build is passing Details
2023-08-07 20:14:32 +02:00
philipp lang ae2eed10af add workers to example env
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2023-08-07 19:57:43 +02:00
philipp lang 0f88427dd5 Add config for horizon workers
continuous-integration/drone/push Build is passing Details
2023-08-07 19:53:48 +02:00
philipp lang 5e259e9455 Lint 2023-08-07 19:52:42 +02:00
Philipp Lang 891e4deac1 Add ResyncAction for Maildispatcher when updating memberships
continuous-integration/drone/push Build is passing Details
2023-07-30 11:09:03 +02:00
Philipp Lang 65aeb4aeaf Add websocket
continuous-integration/drone/push Build is passing Details
2023-07-25 17:23:48 +02:00
692 changed files with 34746 additions and 13056 deletions

View File

@ -3,7 +3,6 @@ APP_ENV=production
APP_KEY=YOUR_APP_KEY
APP_DEBUG=false
APP_URL=http://localhost:8000
APP_MODE=stamm
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
@ -16,3 +15,12 @@ MAIL_FROM_NAME=me
DB_PASSWORD=secret_db_password
MYSQL_PASSWORD=secret_db_password
MEILI_MASTER_KEY=secret_meilisearch_password
PUSHER_APP_HOST=socketi
WORKERS=5
USER_EMAIL=admin@example.com
USER_PASSWORD=admin

View File

@ -1,2 +0,0 @@
\App\User::factory()->create();
\App\User::factory()->create();

14
.docker/base.Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM php:8.3.11-fpm as php
WORKDIR /app
RUN ls /app
RUN apt-get update
RUN apt-get install -y rsync libcurl3-dev apt-utils zlib1g-dev libpng-dev libicu-dev libonig-dev unzip poppler-utils libpng-dev libjpeg-dev default-mysql-client libzip-dev imagemagick libmagickwand-dev
RUN apt-get install -y --no-install-recommends texlive-base texlive-latex-base texlive-pictures texlive-latex-extra texlive-lang-german texlive-plain-generic texlive-fonts-recommended texlive-fonts-extra texlive-extra-utils
RUN docker-php-ext-install pdo_mysql curl exif intl mbstring pcntl zip
RUN pecl install redis && docker-php-ext-enable redis
RUN pecl install imagick && docker-php-ext-enable imagick
RUN docker-php-ext-configure gd --with-jpeg
RUN docker-php-ext-install gd
RUN usermod -s /bin/bash www-data
RUN echo 'memory_limit = 2G' >> /usr/local/etc/php/conf.d/99-custom-php-memlimit.ini

6
.docker/bin/build_base Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
docker buildx build -f .docker/base.Dockerfile .
docker image tag sha256:... zoomyboy/adrema-base
docker push zoomyboy/adrema-base

View File

@ -1,11 +1,11 @@
FROM composer:2.2.7 as composer
FROM composer:2.7.9 as composer
WORKDIR /app
COPY . /app
RUN composer install --ignore-platform-reqs --no-dev
RUN php artisan telescope:publish
RUN php artisan horizon:publish
FROM node:17.9.0-slim as node
FROM node:20.15.0-slim as node
WORKDIR /app
COPY . /app
RUN npm install && npm run prod && npm run img && rm -R node_modules
@ -15,9 +15,8 @@ WORKDIR /app
COPY --from=node /app /app
COPY --from=composer /app/public/vendor /app/public/vendor
COPY ./.docker/nginx/nginx.conf /etc/nginx/nginx.conf
RUN cd public && ln -s ../storage/app/public ./storage
EXPOSE 80
VOLUME ["/app/storage/app"]
VOLUME ["/app/public/storage"]
CMD ["nginx", "-g", "daemon off;"]

View File

@ -25,6 +25,28 @@ http {
root /app/public;
charset utf-8;
index index.php;
location /app/adremakey {
proxy_pass http://socketi:6001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
proxy_read_timeout 60;
proxy_connect_timeout 60;
}
location /indexes/members/search {
proxy_pass http://meilisearch:7700/indexes/members/search;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
proxy_read_timeout 60;
proxy_connect_timeout 60;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}

View File

@ -1,24 +1,17 @@
FROM composer:2.2.7 as composer
FROM composer:2.7.9 as composer
WORKDIR /app
COPY . /app
RUN composer install --ignore-platform-reqs --no-dev
FROM node:17.9.0-slim as node
FROM node:20.15.0-slim as node
WORKDIR /app
COPY . /app
RUN npm install && npm run prod && npm run img && rm -R node_modules
FROM php:8.1.6-fpm as php
WORKDIR /app
RUN apt-get update
RUN apt-get install -y rsync libcurl3-dev apt-utils zlib1g-dev libpng-dev libicu-dev libonig-dev unzip
RUN apt-get install -y --no-install-recommends texlive-base texlive-latex-base texlive-pictures texlive-latex-extra texlive-lang-german texlive-plain-generic texlive-fonts-recommended texlive-fonts-extra
RUN docker-php-ext-install pdo_mysql curl gd exif intl mbstring pcntl
RUN pecl install redis && docker-php-ext-enable redis
FROM zoomyboy/adrema-base:latest as php
COPY --chown=www-data:www-data . /app
COPY --chown=www-data:www-data --from=node /app/public /app/public
COPY --chown=www-data:www-data --from=composer /app/vendor /app/vendor
RUN usermod -s /bin/bash www-data
USER www-data
RUN php artisan telescope:publish
@ -27,7 +20,7 @@ RUN php artisan horizon:publish
USER root
COPY ./.docker/php /bin
VOLUME ["/app/packages/laravel-nami/.cookies", "/app/storage/app"]
VOLUME ["/app/packages/laravel-nami/.cookies", "/app/storage/app", "/app/resources/views/tex/invoice"]
EXPOSE 9000

View File

@ -10,11 +10,16 @@ function wait_for_db {
done
}
mkdir /app/packages/laravel-nami/.cookies || true
mkdir /app/storage/app || true
mkdir -p /app/packages/laravel-nami/.cookies || true
mkdir -p /app/storage/app/public || true
chown -R www-data:www-data /app/packages/laravel-nami/.cookies
chown -R www-data:www-data /app/storage/app
if [ $APP_KEY = "YOUR_APP_KEY" ]; then
echo "----------------------- Keinen APP KEY gefunden. Key wird generiert: $(su www-data -c 'php artisan key:generate --show') ----------------------- Füge diesen Key als APP_KEY ein ---------------------"
exit 1
fi
if [ $1 == "horizon" ]; then
wait_for_db
su www-data -c 'php artisan horizon'
@ -22,13 +27,10 @@ fi
if [ $1 == "app" ]; then
# --------------------------- ensure appkey is set ----------------------------
if [ $APP_KEY = "YOUR_APP_KEY" ]; then
echo "----------------------- Keinen APP KEY gefunden. Key wird generiert: $(su www-data -c 'php artisan key:generate --show') ----------------------- Füge diesen Key als APP_KEY ein ---------------------"
exit 1
fi
wait_for_db
php -r '$connection = new PDO("mysql:host='$DB_HOST';dbname='$DB_DATABASE'", "'$DB_USERNAME'", "'$DB_PASSWORD'"); $connection->query("DESCRIBE migrations");' > /dev/null || php artisan migrate --seed --force
su www-data -c 'php artisan migrate --force'
php artisan scout:sync-index-settings
php-fpm -F -R -O
fi

View File

@ -1,11 +1,17 @@
node_modules
**/node_modules
data
vendor
**/vendor
public/build
public/vendor
bootstrap/cache/services.php
bootstrap/cache/packages.php
bootstrap/cache/routes.php
packages/laravel-nami/.cookies
app/storage/app
storage/logs/**
storage/temp/**
storage/debugbar/**
storage/app/tmp/**
cookies
storage/logs/laravel.log
.git
doc

View File

@ -12,32 +12,38 @@ steps:
- git submodule update --init --recursive
- name: composer_dev
image: composer:2.2.7
image: composer:2.7.9
commands:
- composer install --ignore-platform-reqs --dev
- name: mysql_healthcheck
image: mariadb/server:10.3
image: mysql:oracle
commands:
- while ! mysqladmin ping -h db -u db -pdb --silent; do sleep 1; done
- name: node
image: node:17.9.0-slim
- name: ocdb_healthcheck
image: mysql:oracle
commands:
- npm ci && npm run img && npm run prod && rm -R node_modules
- while ! mysqladmin ping -h ownclouddb -u owncloud -powncloud --silent; do sleep 1; done
- name: oc_healthcheck
image: zoomyboy/adrema-base:latest
commands:
- while ! curl --silent 'http://owncloudserver:8080/ocs/v1.php/cloud/capabilities?format=json' -u admin:admin | grep '"status":"ok"'; do sleep 1; done
- name: node
image: node:20.15.0-slim
commands:
- npm ci && cd packages/adrema-form && npm ci && npm run build && rm -R node_modules && cd ../../ && npm run img && npm run prod && rm -R node_modules
- name: tests
image: php:8.1.6
image: zoomyboy/adrema-base:latest
commands:
- apt-get update > /dev/null
- apt-get install -y rsync libcurl3-dev apt-utils zlib1g-dev libpng-dev libicu-dev libonig-dev unzip > /dev/null
- apt-get install -y --no-install-recommends texlive-base texlive-latex-base texlive-pictures texlive-latex-extra texlive-lang-german texlive-plain-generic texlive-fonts-recommended texlive-fonts-extra > /dev/null
- docker-php-ext-install pdo_mysql curl gd exif intl mbstring pcntl > /dev/null
- pecl install redis && docker-php-ext-enable redis > /dev/null
- touch .env
- php artisan migrate
- php artisan test
- rm -f .env
- vendor/bin/phpstan analyse --memory-limit=2G
- vendor/bin/phpstan analyse
environment:
APP_NAME: Scoutrobot
APP_KEY:
@ -45,7 +51,6 @@ steps:
APP_ENV: local
APP_DEBUG: true
APP_URL: http://scoutrobot.test
APP_MODE: stamm
LOG_CHANNEL: stack
DB_CONNECTION: mysql
DB_HOST: db
@ -62,6 +67,10 @@ steps:
MAIL_FROM_NAME: '${APP_NAME}'
PDFLATEX_BIN: /usr/bin/pdflatex
XELATEX_BIN: /usr/bin/xelatex
SCOUT_DRIVER: database
MEILI_MASTER_KEY: abc
TEST_OWNCLOUD_DOMAIN: http://owncloudserver:8080
TEST_NEXTCLOUD_DOMAIN: http://nextcloudserver:80
- name: docker_app_push
image: plugins/docker
@ -94,7 +103,7 @@ steps:
event: tag
- name: deploy
image: php:8.1.6
image: zoomyboy/adrema-base:latest
environment:
SSH_KEY:
from_secret: deploy_private_key
@ -112,13 +121,22 @@ steps:
- name: github push
image: alpine/git
environment:
SSH_KEY:
from_secret: github_private_key
commands:
- mkdir $HOME/.ssh
- git config core.sshCommand "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
- echo "$SSH_KEY" > $HOME/.ssh/id_rsa
- chmod 600 $HOME/.ssh/id_rsa
- git remote add gh git@github.com:zoomyboy/adrema.git
- git push -f gh HEAD:master
when:
branch: master
event: push
- name: composer_no_dev
image: composer:2.2.7
image: composer:2.7.9
commands:
- composer install --ignore-platform-reqs --no-dev
@ -143,14 +161,59 @@ steps:
services:
- name: db
image: mariadb/server:10.3
image: mariadb:10.6.5
environment:
MARIADB_DATABASE: db
MARIADB_USER: db
MARIADB_PASSWORD: db
MARIADB_ALLOW_EMPTY_PASSWORD: yes
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: yes
- name: redis
image: redis
- name: meilisearch
image: getmeili/meilisearch:v1.6
commands:
- meilisearch --master-key="abc"
- name: ownclouddb
image: mariadb:10.11
environment:
MYSQL_ROOT_PASSWORD: owncloud
MYSQL_USER: owncloud
MYSQL_PASSWORD: owncloud
MYSQL_DATABASE: owncloud
MARIADB_AUTO_UPGRADE: 1
- name: owncloudserver
image: owncloud/server:10.10.0
environment:
OWNCLOUD_DOMAIN: http://owncloudserver:8080
OWNCLOUD_TRUSTED_DOMAINS: owncloudserver
OWNCLOUD_DB_TYPE: mysql
OWNCLOUD_DB_NAME: owncloud
OWNCLOUD_DB_USERNAME: owncloud
OWNCLOUD_DB_PASSWORD: owncloud
OWNCLOUD_DB_HOST: ownclouddb
OWNCLOUD_ADMIN_USERNAME: admin
OWNCLOUD_ADMIN_PASSWORD: admin
OWNCLOUD_MYSQL_UTF8MB4: true
OWNCLOUD_REDIS_ENABLED: false
OWNCLOUD_REDIS_HOST: false
- name: nextclouddb
image: mariadb:10.11
environment:
MYSQL_ROOT_PASSWORD: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: nextcloud
MYSQL_DATABASE: nextcloud
MARIADB_AUTO_UPGRADE: 1
- name: nextcloudserver
image: nextcloud
environment:
MYSQL_PASSWORD: nextcloud
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_HOST: nextclouddb
NEXTCLOUD_ADMIN_USER: admin
NEXTCLOUD_ADMIN_PASSWORD: admin
NEXTCLOUD_TRUSTED_DOMAINS: nextcloudserver
trigger:
event:

View File

@ -5,7 +5,8 @@
},
"extends": [
"eslint:recommended",
"plugin:vue/essential"
"plugin:vue/vue3-recommended",
"prettier"
],
"parserOptions": {
"ecmaVersion": "latest",
@ -14,6 +15,14 @@
"plugins": [
"vue"
],
"overrides": [
{
"files": [
"*.vue"
],
"rules": {
"vue/multi-word-component-names": "off"
}
}
]
}

54
.gitignore vendored
View File

@ -1,27 +1,43 @@
/node_modules
/public/build
/public/sprite.svg
/public/hot
/public/vendor
/storage/*.key
/vendor
.env
.env.backup
.env.testing
.phpunit.result.cache
Homestead.json
Homestead.yaml
node_modules/
npm-debug.log
yarn-error.log
tags
/storage/temp
/bootstrap/compiled.php
/app/storage/
/public/storage
/public/hot
/public/build
/public/vendor
storage/*.key
/storage/media-library/*
/vendor/
Homestead.yaml
Homestead.json
.vagrant/
.phpunit.result.cache
/storage/temp/
/storage/debugbar/
/tests/Fileshare/oc_tmp/*
# User data files
/data/
/.app.env
.config/psysh
# Development files
/docker-compose.yml
/.env
/.env.backup
/.env.testing
# Editor config files
/.vscode/
# Temporary files
*.swp
*.swo
*.swm
resources/img/sprite.svg
/resources/img/sprite.svg
/public/sprite.svg
/.php-cs-fixer.cache
/data
.app.env
cookies
/groups.sql
/.phpunit.cache

16
.gitmodules vendored
View File

@ -1,9 +1,19 @@
[submodule "packages/silvaletter"]
path = packages/silvaletter
url = https://git.zoomyboy.de/silva/silvaletter.git
[submodule "packages/laravel-nami"]
path = packages/laravel-nami
url = https://git.zoomyboy.de/silva/laravel-nami-api
[submodule "packages/tex"]
path = packages/tex
url = https://git.zoomyboy.de/pille/tex
[submodule "packages/adrema-form"]
path = packages/adrema-form
url = https://git.zoomyboy.de/silva/adrema-form.git
[submodule "packages/medialibrary-helper"]
path = packages/medialibrary-helper
url = https://git.zoomyboy.de/zoomyboy/medialibrary-helper.git
branch = version2
[submodule "packages/flysystem-webdav"]
path = packages/flysystem-webdav
url = https://github.com/zoomyboy/flysystem-webdav.git
[submodule "packages/table-document"]
path = packages/table-document
url = https://git.zoomyboy.de/zoomyboy/table-document.git

94
CHANGELOG.md Normal file
View File

@ -0,0 +1,94 @@
# Letzte Änderungen
### 1.12.2
- Zuschussliste Gallier
### 1.12.1
- In Teilnehmer-Liste von Veranstaltungen kann nun sortiert und gefiltert werden.
- Formulare: Feld Registrierung von / bis
### 1.11.5
- Fix: Synchronisation von NaMi-Mitgliedern
### 1.11.4
- Fix: Nicht an Präventions-Unterlagen für vergangene Veranstaltungen erinnern
### 1.11.1
- Es kann nun auch das Feld "Datenweiterverwendung" über Adrema gepflegt werden.
### 1.10.20
- Fixed: Bei Textfeldern wird nun die Einleitung dargestellt
### 1.10.19
- Fixed: Erweiterte Führungszeugnisse und Präventionsschulungen nur für aktive Mitgliedschaften auf Dashboard anzeigen
### 1.10.18
- Fixed: All Gruppen als Option anbieten bei Bedingungen
### 1.10.17
- Es können nun auch Bedingungen für Felder vom Typ Gruppierung definiert werden
### 1.10.16
- Rechnungen und Erinnerungen werden nun automatisch täglich um 10 Uhr verschickt
- Es kann eingestellt werden, nach wie vielen Wochen an Rechnungen erinnert werden soll (Standard: 12)
- Name und Profilbild des angemeldeten Benutzers wird nun oben rechts angezeigt
### 1.10.15
- "Für Mitglieder zusätzlich abfragen" kann nun im Formular auch gesetzt werden, wenn ein NaMi Feld ausgewählt ist.
### 1.10.14
- Fixed: Ist eine Präventionsschulung älter als 5 Jahre, so ist nur eine Auffrischungs-Schulung erforderlich
### 1.10.13
- Bei Veranstaltungs-Übersicht alle Veranstaltungen anzeigen
- Download von Teilnehmern als Tabellen-Dokument
- Spalte "Prävention" bei TN-Liste eingefügt für benötigte Unterlagen
### 1.10.11
- Bei Prävention auch an Verhaltenskodex erinnern
### 1.10.10
- Eine Formular-Vorlage kann nun auch Mail-Inhalte enthalten, die für die Formulare übernommen werden
### 1.10.9
- Nextcloud als neuen Type bei Datei-Verbindungen angelegt
### 1.10.8
- Anmeldeformulare: Bearbeiten von Teilnehmer\*innen ist nun möglich
### 1.10.7
- Anmeldeformulare: Versenden von Präventions-Unterlagen können nun an eine Feld-Bedingung geknüpft werden innerhalb der Veranstaltung
### 1.10.6
- Kleinere Fehler behoben
### 1.10.5
- Kleinere Fehler behoben
### 1.10.4
- Anmeldeformular: Erinnerung an Präventions-Unterlagen bei Teilnehmer\*innnen
### 1.10.3
- Anmeldeformulare: Ist NaMi-Feld "E-Mail" ausgewählt bei Formular-Feldern, muss die E-Mail-Adresse nun nicht mehr auf das Mitglied matchen. Dies ist nur noch bei Formular-Feldern mit NaMi-Feldern "Vorname", "Nachname" und "Geburtsdatum" der Fall.

View File

@ -1,4 +1,4 @@
@servers(['docker' => ['stammsilva@zoomyboy.de']])
@servers(['docker' => ['stammsilva@zoomyboy.de', 'stammgallier@stamm-gallier.de', 'dpsg-lennep@zoomyboy.de', 'dpsgbergischland@zoomyboy.de', 'dpsg-koeln@dpsg-koeln.de']])
@task('deploy', ['on' => 'docker'])
cd $ADREMA_PATH

131
README.md
View File

@ -1,6 +1,6 @@
# Adrema
__Schön, dass du den Weg hierhin gefunden hast!__
**Schön, dass du den Weg hierhin gefunden hast!**
Da du diese Seite besuchst, gehörst du sicherlich zu den Leuten, die möglichst einfach die Daten ihrer Mitglieder pfelgen wollen. Das ist offiziell in der DPSG nur mit NaMi möglich.
@ -12,78 +12,115 @@ AdReMa kann von jedem und jeder genutzt werden, die einen NaMi-Account besitzt u
## Was kann ich mit AdReMa machen?
* Basisdaten von Mitgliedern anzeigen und bearbeiten
* Einfacher Filter nach Gruppierung, Tätigkeit, etc
* Detailansichten mit allen zugehörigen Daten
* Führungszeugnisse und Präventionssulungen nachhalten
* Beitragszahlungen eintragen
* Automatisches Rechunungssystem
* Eigene Beiträge hinterlegen (z.B. interner Stammes-Jahresbeitrag)
* Generieren von Zuschusslisten (aktuell RdP NRW)
* Einpflegen von internen Tätigkeiten, die nicht in NaMi vorhanden sind (um z.B. stammes-interne AGs / AKs zu verwalten)
* Automatisches Erstellen und managen von E-Mail-Verteilern mittels Mailman 3.0
* eFz-Bescheinigung abrufen für alle Leitenden (das kann normalerweise nur jede*r einzelne für sich selbst)
* Ausbildungen eintragen (WBK-Bausteine)
* Abrufen von Kontakten ins eigene Telefonbuch (mittels CardDAV)
- Basisdaten von Mitgliedern anzeigen und bearbeiten
- Einfacher Filter nach Gruppierung, Tätigkeit, etc
- Detailansichten mit allen zugehörigen Daten
- Führungszeugnisse und Präventionssulungen nachhalten
- Beitragszahlungen eintragen
- Automatische Rechunungserstellung
- Eigenen Beitragssatz hinterlegen (z.B. interner Stammes-Jahresbeitrag)
- Generieren von Zuschusslisten (aktuell RdP NRW, Bdkj Hessen, Stadt Solingen, Stadt Remscheid, Stadt Frankfurt a. M.)
- Einpflegen von internen Tätigkeiten, die nicht in NaMi vorhanden sind (um z.B. stammes-interne AGs / AKs zu verwalten)
- Automatisches Erstellen und Managen von E-Mail-Verteilern mittels Mailman 3.0
- eFz-Bescheinigung abrufen für alle Leitenden (das kann in NaMi nur jede\*r für sich selbst)
- Ausbildungen eintragen (WBK-Bausteine)
- Abrufen von Kontakten ins eigene Telefonbuch (mittels CardDAV)
Ziel dieses Projektes ist es, viele Dinge, die man normalerweise manuell zu tun hat so gut es geht zu automatisieren oder zumindest zu vereinfachen. So kann man sich als Leitende*r / Vorstand auf die wichtigeren Dinge konzentrieren wie Gruppenstunden, Lager, Leiterrunden, etc.
Ziel dieses Projektes ist es, viele Dinge, die man normalerweise manuell zu tun hat so gut es geht zu automatisieren oder zumindest zu vereinfachen. So kann man sich als Leitende\*r / Vorstand auf die wichtigeren Dinge konzentrieren wie Gruppenstunden, Lager, Leiterrunden, etc.
Außerdem ist AdReMa auch problemlos auf Handys und Tablets bedienbar ("mobiles Design")
# Installation
## Installation des Produktivsystems
## App Key generieren
1. Herunterladen der Beispiel Docker-Compose
Kopiere .app.env.example nach .app.env
```cmd
curl https://git.zoomyboy.de/silva/adrema/raw/branch/master/docker-compose.prod.yml -o docker-compose.yml
```
```
cp .app.env.example .app.env
```
2. Herunterladen der Beispiel Environmentvariablen-Datei
Services starten:
```cmd
curl https://git.zoomyboy.de/silva/adrema/raw/branch/master/.app.env.example -o .app.env
```
```
docker compose up
```
3. In der `.app.env` notwendige Einstellungen vornehmen:
Es wird die ein App Key generiert: ``Keinen APP KEY gefunden. Key wird generiert: base64:..........``
- `APP_URL`: Hier sollte die URL (mit HTTPS) stehen, unter der Adrema erreichbar sein soll (z.B. `https://adrema.stamm-bipi.de`)
- Mail-Server Einstellungen `MAIL_PORT`, `MAIL_HOST`, `MAIL_USERNAME`, `MAIL_PASSWORD` und `MAIL_ENCRYPTION` anpassen
- `MAIL_FROM_NAME`: Der Name, der als Absender von E-Mails gesetzt wird (z.B. `Stamm Bipi Service`)
- `MAIL_FROM_ADDRESS`: Die dazu gehörige E-Mail-Adresse, die natürlich für antworten erreichbar sein sollte (z.B. `vorstand@stamm-bipi.de`)
- `DB_PASSWORD` und `MYSQL_PASSWORD`: Mit dem selben sicheren Passwort für die Datenbank versehen
- `USER_EMAIL` und `USER_PASSWORD`: Einstellen des standard Adrema Logins
Kopiere diesen App key und setze in in .app.env als APP_KEY ein (APP_KEY=base64:........).
4. Container zur Gennerierung des App-Key starten
## Einstellungen
```cmd
docker compose up php
```
Passe in der .app.env dann folgende Einstellungen an:
Nach einiger zeit wird ein App-Key generiert:
### APP_URL
```cmd
Keinen APP KEY gefunden. Key wird generiert: base64:xxx
```
Hier sollte die URL (mit HTTPS) stehen, unter der Adrema erreichbar sein soll (z.B. https://adrema.stamm-bipi.de)
Container herunterfahren und entfernen
### Mail
```cmd
docker compose down
```
Setze nun die Einstellungen für den Mail-Versand ein. Du solltest mindestens MAIL_PORT, MAIL_HOST, MAIL_USERNAME, MAIL_PASSWORD und MAIL_ENCRYPTION setzen.
5. Der generierte App-Key muss als Environmentvariable (`APP_KEY`) mit in den Docker-Container gegeben werden. Kopiere den App-Key in die Datei `.app.env`
MAIL_FROM_NAME ist der Name, der als Absender von E-Mails gesetzt wird. z.B. "Stamm Bipi Service".
```env
APP_KEY=base64:xxx
```
MAIL_FROM_ADDRESS die dazu gehörige E-Mail-Adresse, die natürlich erreichbar sein sollte (z.B. "vorstand@stamm-bipi.de").
6. Alle Container starten
### DB Passwort
```cmd
docker compose up -d
```
Setze die beiden letzten Variablen (da wo "secret_db_password" steht) auf ein generiertes sicheres Passwort. Bei beiden Variablen muss der gleiche Wert eingestellt werden (also so wie vorher, nur sicherer :D )
7. Nach kurzer Zeit ist AdReMa über <http://localhost:8000> erreichbar und es kann sich mit dem zuvor festgelegten Login eingeloggt werden
## Starten
### Individuelle anpassungen
Führe nun den DB Container aus, um eine erste Version der Datenbank zu erstellen.
#### Rechnungswesen
```
docker-compose up db -d
```
Bei dem Setup wird im Daten-Verzeichniss ein Ordner `./data/setup` angelegt. Hier kann das Logo des Stammes in den Briefkopf eingefügt werden. Zusätzlich kann der Text der Rechnung und der Zahlungserinnerung angepasst werden, dafür ist ein grundlegendes Verständnis für `.tex` Datein erforderlich.
Nun kannst du auf localhost:8000 die App öffnen, einen LB verwenden, den Port mit CLI Optionen ändern, etc.
## Nutzen des Entwicklungssystmes
## Standard Login
1. Klonen des Reposetories
Beim ersten Starten wird ein Benutzer mit folgenden Zugangsdaten erstellt:
```cmd
git clone https://git.zoomyboy.de/silva/adrema.git
```
* E-Mail-Adresse: admin@example.com
* Passwort: admin
2. Kopieren der Beispiel Docker-Compose für das Entwickeln und nach Wünschen anpassen
```cmd
cp docker-compose.dev.yml docker-compose.yml
```
3. Kopieren der Beispiel Environmentvariablen-Datei
```cmd
cp .app.env.example .app.env
```
4. Submodule aktuallisieren
```cmd
git submodule update --init
```
5. Container erstellen
```cmd
docker compose build
```
6. Mit Schritt 3 und den folgenden der [Installation des Produktivsystems](#installation-des-produktivsystems) fortfahren

View File

@ -0,0 +1,23 @@
<?php
namespace App\Actions;
use DB;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Http;
use Laravel\Telescope\Console\PruneCommand;
use Lorisleiva\Actions\Concerns\AsAction;
class DbMaintainAction
{
use AsAction;
public string $commandSignature = 'db:maintain';
public function handle(): void
{
Artisan::call(PruneCommand::class, ['--hours' => 168]); // 168h = 7 Tage
DB::select('optimize table telescope_entries');
Http::post('https://zoomyboy.de/maintain', ['url' => url()->current()]);
}
}

View File

@ -50,6 +50,7 @@ class InsertMemberAction
'nationality_id' => Nationality::where('nami_id', $member->nationalityId)->firstOrFail()->id,
'mitgliedsnr' => $member->memberId,
'version' => $member->version,
'keepdata' => $member->keepdata,
]);
}

View File

@ -2,16 +2,16 @@
namespace App;
use App\Http\Views\ActivityFilterScope;
use App\Nami\HasNamiField;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\Builder;
use Database\Factories\ActivityFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Activity extends Model
{
/** @use HasFactory<ActivityFactory> */
use HasFactory;
use HasNamiField;
use Sluggable;
@ -33,16 +33,6 @@ class Activity extends Model
];
}
/**
* @param Builder<self> $query
*
* @return Builder<self>
*/
public function scopeWithFilter(Builder $query, ActivityFilterScope $filter): Builder
{
return $filter->apply($query);
}
/**
* @return BelongsToMany<Subactivity>
*/

View File

@ -4,7 +4,6 @@ namespace App\Activity\Actions;
use App\Activity;
use App\Activity\Resources\ActivityResource;
use App\Http\Views\ActivityFilterScope;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Inertia\Inertia;
use Inertia\Response;
@ -15,19 +14,18 @@ class IndexAction
{
use AsAction;
public function handle(ActivityFilterScope $filter): AnonymousResourceCollection
public function handle(): AnonymousResourceCollection
{
return ActivityResource::collection(Activity::withFilter($filter)->paginate(20));
return ActivityResource::collection(Activity::paginate(20));
}
public function asController(ActionRequest $request): Response
{
session()->put('menu', 'activity');
session()->put('title', 'Tätigkeiten');
$filter = ActivityFilterScope::fromRequest($request->input('filter'));
return Inertia::render('activity/VIndex', [
'data' => $this->handle($filter),
'data' => $this->handle(),
]);
}
}

View File

@ -3,7 +3,6 @@
namespace App\Activity\Resources;
use App\Activity;
use App\Http\Views\ActivityFilterScope;
use App\Lib\HasMeta;
use App\Resources\SubactivityResource;
use App\Subactivity;
@ -51,10 +50,10 @@ class ActivityResource extends JsonResource
{
return [
'subactivities' => SubactivityResource::collectionWithoutMeta(Subactivity::get()),
'filter' => ActivityFilterScope::fromRequest(request()->input('filter')),
'links' => [
'index' => route('activity.index'),
'create' => route('activity.create'),
'membership_masslist' => route('membership.masslist.index'),
],
];
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Auth;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Lang;
use Illuminate\Auth\Notifications\ResetPassword as BaseResetPassword;
class ResetPassword extends BaseResetPassword
{
/**
* Get the reset password notification mail message for the given URL.
*
* @param string $url
* @return MailMessage
*/
protected function buildMailMessage($url)
{
return (new MailMessage)
->subject(Lang::get('Passwort zurücksetzen | Adrema'))
->line(Lang::get('Du erhälst diese E-Mail, weil du eine Anfrage zum zurücksetzen deines Account-Passworts gestellt hast.'))
->action(Lang::get('Passwort zurücksetzen'), $url)
->line(Lang::get('Dieser Link wird in :count Minuten ablaufen.', ['count' => config('auth.passwords.' . config('auth.defaults.passwords') . '.expire')]))
->line(Lang::get('Wenn du die Anfrage nicht selbst gestellt hast, ist keine weitere Aktion erforderlich.'));
}
}

View File

@ -2,11 +2,13 @@
namespace App;
use Database\Factories\ConfessionFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Confession extends Model
{
/** @use HasFactory<ConfessionFactory> */
use HasFactory;
public $fillable = ['name', 'nami_id', 'is_null'];

View File

@ -2,11 +2,12 @@
namespace App\Console;
use App\Actions\DbMaintainAction;
use App\Form\Actions\PreventionRememberAction;
use App\Initialize\InitializeMembers;
use App\Invoice\Actions\InvoiceSendAction;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Laravel\Telescope\Console\PruneCommand;
class Kernel extends ConsoleKernel
{
@ -18,6 +19,8 @@ class Kernel extends ConsoleKernel
protected $commands = [
InvoiceSendAction::class,
InitializeMembers::class,
DbMaintainAction::class,
PreventionRememberAction::class,
];
/**
@ -27,8 +30,10 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
$schedule->command(PruneCommand::class, ['--hours' => 168])->daily(); // 168h = 7 Tage
$schedule->command(DbMaintainAction::class)->daily();
$schedule->command(InitializeMembers::class)->dailyAt('03:00');
$schedule->command(PreventionRememberAction::class)->dailyAt('11:00');
$schedule->command(InvoiceSendAction::class)->dailyAt('10:00');
}
/**
@ -38,7 +43,7 @@ class Kernel extends ConsoleKernel
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}

View File

@ -49,6 +49,6 @@ class GenerateAction
*/
private function payload(ActionRequest $request): array
{
return json_decode(base64_decode($request->input('payload', '')), true);
return json_decode(rawurldecode(base64_decode($request->input('payload', ''))), true);
}
}

View File

@ -2,10 +2,13 @@
namespace App\Contribution;
use App\Contribution\Documents\BdkjHesse;
use App\Contribution\Documents\ContributionDocument;
use App\Contribution\Documents\DvDocument;
use App\Contribution\Documents\RemscheidDocument;
use App\Contribution\Documents\SolingenDocument;
use App\Contribution\Documents\RdpNrwDocument;
use App\Contribution\Documents\CityRemscheidDocument;
use App\Contribution\Documents\CitySolingenDocument;
use App\Contribution\Documents\CityFrankfurtMainDocument;
use App\Contribution\Documents\WuppertalDocument;
use Illuminate\Support\Collection;
use Illuminate\Validation\Rule;
@ -15,18 +18,21 @@ class ContributionFactory
* @var array<int, class-string<ContributionDocument>>
*/
private array $documents = [
DvDocument::class,
SolingenDocument::class,
RemscheidDocument::class,
RdpNrwDocument::class,
CitySolingenDocument::class,
CityRemscheidDocument::class,
CityFrankfurtMainDocument::class,
BdkjHesse::class,
WuppertalDocument::class,
];
/**
* @return Collection<int, array{title: mixed, class: mixed}>
* @return Collection<int, array{title: string, class: class-string<ContributionDocument>}>
*/
public function compilerSelect(): Collection
{
return collect($this->documents)->map(fn ($document) => [
'title' => $document::getName(),
'title' => $document::buttonName(),
'class' => $document,
]);
}

View File

@ -29,7 +29,7 @@ class MemberData extends Data
*/
public static function fromModels(array $ids): Collection
{
return Member::whereIn('id', $ids)->orderByRaw('lastname, firstname')->get()->map(fn ($member) => self::withoutMagicalCreationFrom([
return Member::whereIn('id', $ids)->orderByRaw('lastname, firstname')->get()->map(fn ($member) => self::factory()->withoutMagicalCreation()->from([
...$member->toArray(),
'birthday' => $member->birthday->toAtomString(),
'isLeader' => $member->isLeader(),
@ -44,7 +44,7 @@ class MemberData extends Data
*/
public static function fromApi(array $data): Collection
{
return collect($data)->map(fn ($member) => self::withoutMagicalCreationFrom([
return collect($data)->map(fn ($member) => self::factory()->withoutMagicalCreation()->from([
...$member,
'birthday' => Carbon::parse($member['birthday'])->toAtomString(),
'gender' => Gender::fromString($member['gender']),
@ -54,21 +54,41 @@ class MemberData extends Data
public function fullname(): string
{
return $this->firstname.' '.$this->lastname;
return $this->firstname . ' ' . $this->lastname;
}
public function separatedName(): string
{
return $this->lastname.', '.$this->firstname;
return $this->lastname . ', ' . $this->firstname;
}
public function fullAddress(): string
{
return $this->address.', '.$this->zip.' '.$this->location;
return $this->address . ', ' . $this->zip . ' ' . $this->location;
}
public function age(): string
public function city(): string
{
return (string) $this->birthday->diffInYears(now()) ?: '';
return $this->zip . ' ' . $this->location;
}
public function age(): int
{
return intval($this->birthday->diffInYears(now()));
}
public function birthYear(): string
{
return (string) $this->birthday->year;
}
public function birthdayHuman(): string
{
return $this->birthday->format('d.m.Y');
}
public function genderLetter(): string
{
return $this->gender->short;
}
}

View File

@ -3,14 +3,16 @@
namespace App\Contribution\Documents;
use App\Contribution\Data\MemberData;
use App\Contribution\Traits\HasPdfBackground;
use App\Country;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Zoomyboy\Tex\Engine;
use Zoomyboy\Tex\Template;
class DvDocument extends ContributionDocument
class BdkjHesse extends ContributionDocument
{
use HasPdfBackground;
/**
* @param Collection<int, Collection<int, MemberData>> $members
*/
@ -20,16 +22,21 @@ class DvDocument extends ContributionDocument
public string $zipLocation,
public ?Country $country,
public Collection $members,
public string $eventName,
public ?string $filename = '',
public string $type = 'F',
) {
$this->setEventName($eventName);
}
public function dateRange(): string
public function dateFrom(): string
{
return Carbon::parse($this->dateFrom)->format('d.m.Y')
.' - '
.Carbon::parse($this->dateUntil)->format('d.m.Y');
return Carbon::parse($this->dateFrom)->format('d.m.Y');
}
public function dateUntil(): string
{
return Carbon::parse($this->dateUntil)->format('d.m.Y');
}
/**
@ -42,7 +49,8 @@ class DvDocument extends ContributionDocument
dateUntil: $request['dateUntil'],
zipLocation: $request['zipLocation'],
country: Country::where('id', $request['country'])->firstOrFail(),
members: MemberData::fromModels($request['members'])->chunk(17),
members: MemberData::fromModels($request['members'])->chunk(20),
eventName: $request['eventName'],
);
}
@ -56,7 +64,8 @@ class DvDocument extends ContributionDocument
dateUntil: $request['dateUntil'],
zipLocation: $request['zipLocation'],
country: Country::where('id', $request['country'])->firstOrFail(),
members: MemberData::fromApi($request['member_data'])->chunk(17),
members: MemberData::fromApi($request['member_data'])->chunk(20),
eventName: $request['eventName'],
);
}
@ -65,9 +74,22 @@ class DvDocument extends ContributionDocument
return $this->country->name;
}
public function memberShort(MemberData $member): string
public function durationDays(): int
{
return $member->isLeader ? 'L' : '';
return intVal(Carbon::parse($this->dateUntil)->diffInDays(Carbon::parse($this->dateFrom))) + 1;
}
/**
* @param Collection<int, MemberData> $chunk
*/
public function membersDays(Collection $chunk): int
{
return $this->durationDays() * $chunk->count();
}
public function pages(): int
{
return count($this->members);
}
public function memberName(MemberData $member): string
@ -75,9 +97,9 @@ class DvDocument extends ContributionDocument
return $member->separatedName();
}
public function memberAddress(MemberData $member): string
public function memberCity(MemberData $member): string
{
return $member->fullAddress();
return $member->city();
}
public function memberGender(MemberData $member): string
@ -89,41 +111,14 @@ class DvDocument extends ContributionDocument
return strtolower(substr($member->gender->name, 0, 1));
}
public function memberAge(MemberData $member): string
public function memberBirthYear(MemberData $member): string
{
return $member->age();
}
public function basename(): string
{
return 'zuschuesse-dv';
}
public function view(): string
{
return 'tex.zuschuss-dv';
}
public function template(): Template
{
return Template::make('tex.templates.contribution');
}
public function setFilename(string $filename): static
{
$this->filename = $filename;
return $this;
}
public function getEngine(): Engine
{
return Engine::PDFLATEX;
return $member->birthYear();
}
public static function getName(): string
{
return 'Für DV erstellen';
return 'BDKJ Hessen';
}
/**
@ -136,7 +131,6 @@ class DvDocument extends ContributionDocument
'dateUntil' => 'required|string|date_format:Y-m-d',
'country' => 'required|integer|exists:countries,id',
'zipLocation' => 'required|string',
'eventName' => 'required|string',
];
}
}

View File

@ -0,0 +1,93 @@
<?php
namespace App\Contribution\Documents;
use App\Contribution\Data\MemberData;
use App\Contribution\Traits\FormatsDates;
use App\Contribution\Traits\HasPdfBackground;
use App\Country;
use App\Invoice\InvoiceSettings;
use Illuminate\Support\Collection;
class CityFrankfurtMainDocument extends ContributionDocument
{
use HasPdfBackground;
use FormatsDates;
public string $fromName;
/**
* @param Collection<int, Collection<int, MemberData>> $members
*/
public function __construct(
public string $dateFrom,
public string $dateUntil,
public string $zipLocation,
public ?Country $country,
public Collection $members,
public string $eventName,
public ?string $filename = '',
public string $type = 'F',
) {
$this->setEventName($eventName);
$this->fromName = app(InvoiceSettings::class)->from_long;
}
/**
* {@inheritdoc}
*/
public static function fromRequest(array $request): self
{
return new self(
dateFrom: $request['dateFrom'],
dateUntil: $request['dateUntil'],
zipLocation: $request['zipLocation'],
country: Country::where('id', $request['country'])->firstOrFail(),
members: MemberData::fromModels($request['members'])->chunk(15),
eventName: $request['eventName'],
);
}
/**
* {@inheritdoc}
*/
public static function fromApiRequest(array $request): self
{
return new self(
dateFrom: $request['dateFrom'],
dateUntil: $request['dateUntil'],
zipLocation: $request['zipLocation'],
country: Country::where('id', $request['country'])->firstOrFail(),
members: MemberData::fromApi($request['member_data'])->chunk(15),
eventName: $request['eventName'],
);
}
public function countryName(): string
{
return $this->country->name;
}
public function pages(): int
{
return count($this->members);
}
public static function getName(): string
{
return 'Frankfurt';
}
/**
* @return array<string, mixed>
*/
public static function rules(): array
{
return [
'dateFrom' => 'required|string|date_format:Y-m-d',
'dateUntil' => 'required|string|date_format:Y-m-d',
'country' => 'required|integer|exists:countries,id',
'zipLocation' => 'required|string',
];
}
}

View File

@ -3,15 +3,17 @@
namespace App\Contribution\Documents;
use App\Contribution\Data\MemberData;
use App\Contribution\Traits\FormatsDates;
use App\Contribution\Traits\HasPdfBackground;
use App\Country;
use App\Member\Member;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Zoomyboy\Tex\Engine;
use Zoomyboy\Tex\Template;
class RemscheidDocument extends ContributionDocument
class CityRemscheidDocument extends ContributionDocument
{
use HasPdfBackground;
use FormatsDates;
/**
* @param Collection<int, Collection<int, Member>> $leaders
* @param Collection<int, Collection<int, Member>> $children
@ -25,17 +27,9 @@ class RemscheidDocument extends ContributionDocument
public Collection $children,
public ?string $filename = '',
public string $type = 'F',
public string $eventName = '',
) {
}
public function niceDateFrom(): string
{
return Carbon::parse($this->dateFrom)->format('d.m.Y');
}
public function niceDateUntil(): string
{
return Carbon::parse($this->dateUntil)->format('d.m.Y');
$this->setEventName($eventName);
}
/**
@ -52,6 +46,7 @@ class RemscheidDocument extends ContributionDocument
country: Country::where('id', $request['country'])->firstOrFail(),
leaders: $leaders->values()->toBase()->chunk(6),
children: $children->values()->toBase()->chunk(20),
eventName: $request['eventName'],
);
}
@ -70,39 +65,13 @@ class RemscheidDocument extends ContributionDocument
country: Country::where('id', $request['country'])->firstOrFail(),
leaders: $leaders->values()->toBase()->chunk(6),
children: $children->values()->toBase()->chunk(20),
eventName: $request['eventName'],
);
}
public function basename(): string
{
return 'zuschuesse-remscheid';
}
public function view(): string
{
return 'tex.zuschuss-remscheid';
}
public function template(): Template
{
return Template::make('tex.templates.contribution');
}
public function setFilename(string $filename): static
{
$this->filename = $filename;
return $this;
}
public function getEngine(): Engine
{
return Engine::PDFLATEX;
}
public static function getName(): string
{
return 'Für Remscheid erstellen';
return 'Remscheid';
}
/**

View File

@ -3,14 +3,15 @@
namespace App\Contribution\Documents;
use App\Contribution\Data\MemberData;
use App\Invoice\InvoiceSettings;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Zoomyboy\Tex\Engine;
use Zoomyboy\Tex\Template;
class SolingenDocument extends ContributionDocument
class CitySolingenDocument extends ContributionDocument
{
public string $fromName;
/**
* @param Collection<int, MemberData> $members
*/
@ -22,6 +23,8 @@ class SolingenDocument extends ContributionDocument
public string $eventName,
public string $type = 'F',
) {
$this->setEventName($eventName);
$this->fromName = app(InvoiceSettings::class)->from_long;
}
/**
@ -70,34 +73,19 @@ class SolingenDocument extends ContributionDocument
return Carbon::parse($this->dateUntil)->format('d.m.Y');
}
public function template(): Template
{
return Template::make('tex.templates.contribution');
}
public function checkboxes(): string
{
$output = '';
$firstRow = collect(['B' => 'Jugendbildungsmaßnahme', 'G' => 'Gruppenleiter/innenschulung', 'FK' => 'Ferienkolonie', 'F' => 'Freizeitnaßnahme'])->map(function ($item, $key) {
return ($this->type === $key ? '\\checkedcheckbox' : '\\checkbox').'{'.$item.'}';
})->implode(' & ').' \\\\';
return ($this->type === $key ? '\\checkedcheckbox' : '\\checkbox') . '{' . $item . '}';
})->implode(' & ') . ' \\\\';
$secondRow = collect(['I' => 'Int. Jugendbegegnung', 'P' => 'politische Jugendbildung', 'PR' => 'Projekte'])->map(function ($item, $key) {
return ($this->type === $key ? '\\checkedcheckbox' : '\\checkbox').'{'.$item.'}';
})->implode(' & ').' & \\emptycheckbox \\\\';
return ($this->type === $key ? '\\checkedcheckbox' : '\\checkbox') . '{' . $item . '}';
})->implode(' & ') . ' & \\emptycheckbox \\\\';
return $firstRow."\n".$secondRow;
}
public function basename(): string
{
return 'zuschuesse-solingen-'.Str::slug($this->eventName);
}
public function view(): string
{
return 'tex.zuschuss-stadt';
return $firstRow . "\n" . $secondRow;
}
public function getEngine(): Engine
@ -107,7 +95,7 @@ class SolingenDocument extends ContributionDocument
public static function getName(): string
{
return 'Für Stadt Solingen erstellen';
return 'Stadt Solingen';
}
/**
@ -119,7 +107,6 @@ class SolingenDocument extends ContributionDocument
'dateFrom' => 'required|string|date_format:Y-m-d',
'dateUntil' => 'required|string|date_format:Y-m-d',
'zipLocation' => 'required|string',
'eventName' => 'required|string',
];
}
}

View File

@ -3,9 +3,12 @@
namespace App\Contribution\Documents;
use Zoomyboy\Tex\Document;
use Zoomyboy\Tex\Template;
abstract class ContributionDocument extends Document
{
private string $eventName;
abstract public static function getName(): string;
/**
@ -29,8 +32,34 @@ abstract class ContributionDocument extends Document
public static function globalRules(): array
{
return [
'eventName' => 'required|string',
'members' => 'present|array|min:1',
'members.*' => 'integer|exists:members,id',
];
}
public static function buttonName(): string
{
return 'Für ' . static::getName() . ' erstellen';;
}
public function setEventName(string $eventName): void
{
$this->eventName = $eventName;
}
public function basename(): string
{
return str('Zuschüsse ')->append($this->getName())->append(' ')->append($this->eventName)->slug();
}
public function template(): Template
{
return Template::make('tex.templates.contribution');
}
public function view(): string
{
return 'tex.contribution.' . str(class_basename(static::class))->replace('Document', '')->kebab()->toString();
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace App\Contribution\Documents;
use App\Contribution\Data\MemberData;
use App\Contribution\Traits\FormatsDates;
use App\Contribution\Traits\HasPdfBackground;
use App\Country;
use Illuminate\Support\Collection;
class RdpNrwDocument extends ContributionDocument
{
use HasPdfBackground;
use FormatsDates;
/**
* @param Collection<int, Collection<int, MemberData>> $members
*/
public function __construct(
public string $dateFrom,
public string $dateUntil,
public string $zipLocation,
public ?Country $country,
public Collection $members,
public ?string $filename = '',
public string $type = 'F',
public string $eventName = '',
) {
$this->setEventName($eventName);
}
/**
* {@inheritdoc}
*/
public static function fromRequest(array $request): self
{
return new self(
dateFrom: $request['dateFrom'],
dateUntil: $request['dateUntil'],
zipLocation: $request['zipLocation'],
country: Country::where('id', $request['country'])->firstOrFail(),
members: MemberData::fromModels($request['members'])->chunk(17),
eventName: $request['eventName'],
);
}
/**
* {@inheritdoc}
*/
public static function fromApiRequest(array $request): self
{
return new self(
dateFrom: $request['dateFrom'],
dateUntil: $request['dateUntil'],
zipLocation: $request['zipLocation'],
country: Country::where('id', $request['country'])->firstOrFail(),
members: MemberData::fromApi($request['member_data'])->chunk(17),
eventName: $request['eventName'],
);
}
public function countryName(): string
{
return $this->country->name;
}
public static function getName(): string
{
return 'RdP NRW';
}
/**
* @return array<string, mixed>
*/
public static function rules(): array
{
return [
'dateFrom' => 'required|string|date_format:Y-m-d',
'dateUntil' => 'required|string|date_format:Y-m-d',
'country' => 'required|integer|exists:countries,id',
'zipLocation' => 'required|string',
];
}
}

View File

@ -0,0 +1,79 @@
<?php
namespace App\Contribution\Documents;
use App\Contribution\Data\MemberData;
use App\Contribution\Traits\FormatsDates;
use App\Contribution\Traits\HasPdfBackground;
use App\Country;
use Illuminate\Support\Collection;
class WuppertalDocument extends ContributionDocument
{
use HasPdfBackground;
use FormatsDates;
/**
* @param Collection<int, Collection<int, MemberData>> $members
*/
public function __construct(
public string $dateFrom,
public string $dateUntil,
public string $zipLocation,
public ?Country $country,
public Collection $members,
public ?string $filename = '',
public string $type = 'F',
public string $eventName = '',
) {
$this->setEventName($eventName);
}
/**
* {@inheritdoc}
*/
public static function fromRequest(array $request): self
{
return new self(
dateFrom: $request['dateFrom'],
dateUntil: $request['dateUntil'],
zipLocation: $request['zipLocation'],
country: Country::where('id', $request['country'])->firstOrFail(),
members: MemberData::fromModels($request['members'])->chunk(14),
eventName: $request['eventName'],
);
}
/**
* {@inheritdoc}
*/
public static function fromApiRequest(array $request): self
{
return new self(
dateFrom: $request['dateFrom'],
dateUntil: $request['dateUntil'],
zipLocation: $request['zipLocation'],
country: Country::where('id', $request['country'])->firstOrFail(),
members: MemberData::fromApi($request['member_data'])->chunk(14),
eventName: $request['eventName'],
);
}
public static function getName(): string
{
return 'Wuppertal';
}
/**
* @return array<string, mixed>
*/
public static function rules(): array
{
return [
'dateFrom' => 'required|string|date_format:Y-m-d',
'dateUntil' => 'required|string|date_format:Y-m-d',
'zipLocation' => 'required|string',
];
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Contribution\Traits;
use Carbon\Carbon;
trait FormatsDates
{
public function niceDateFrom(): string
{
return Carbon::parse($this->dateFrom)->format('d.m.Y');
}
public function niceDateUntil(): string
{
return Carbon::parse($this->dateUntil)->format('d.m.Y');
}
public function dateRange(): string
{
return implode(' - ', [$this->niceDateFrom(), $this->niceDateUntil()]);
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Contribution\Traits;
use Zoomyboy\Tex\Engine;
trait HasPdfBackground
{
public function getEngine(): Engine
{
return Engine::PDFLATEX;
}
}

View File

@ -3,11 +3,13 @@
namespace App;
use App\Nami\HasNamiField;
use Database\Factories\CountryFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Country extends Model
{
/** @use HasFactory<CountryFactory> */
use HasFactory;
use HasNamiField;

View File

@ -0,0 +1,46 @@
<?php
namespace App\Course\Actions;
use App\Course\Models\CourseMember;
use App\Lib\JobMiddleware\JobChannels;
use App\Lib\JobMiddleware\WithJobState;
use App\Lib\Queue\TracksJob;
use App\Setting\NamiSettings;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\Concerns\AsAction;
class CourseDestroyAction
{
use AsAction;
use TracksJob;
public function handle(int $courseId): void
{
$course = CourseMember::find($courseId);
app(NamiSettings::class)->login()->deleteCourse($course->member->nami_id, $course->nami_id);
$course->delete();
}
public function asController(CourseMember $course): JsonResponse
{
$this->startJob($course->id, $course->member->fullname);
return response()->json([]);
}
/**
* @param mixed $parameters
*/
public function jobState(WithJobState $jobState, ...$parameters): WithJobState
{
$memberFullname = $parameters[1];
return $jobState
->before('Ausbildung für ' . $memberFullname . ' wird gelöscht')
->after('Ausbildung für ' . $memberFullname . ' gelöscht')
->failed('Fehler beim Löschen der Ausbildung für ' . $memberFullname)
->shouldReload(JobChannels::make()->add('member')->add('course'));
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Course\Actions;
use App\Course\Models\CourseMember;
use App\Course\Resources\CourseMemberResource;
use App\Member\Member;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Lorisleiva\Actions\Concerns\AsAction;
class CourseIndexAction
{
use AsAction;
/**
* @return Collection<int, CourseMember>
*/
public function handle(Member $member): Collection
{
return $member->courses()->with('course')->get();
}
public function asController(Member $member): AnonymousResourceCollection
{
return CourseMemberResource::collection($this->handle($member))
->additional([
'meta' => CourseMemberResource::memberMeta($member),
]);
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace App\Course\Actions;
use App\Course\Models\Course;
use App\Lib\JobMiddleware\JobChannels;
use App\Lib\JobMiddleware\WithJobState;
use App\Lib\Queue\TracksJob;
use App\Member\Member;
use App\Setting\NamiSettings;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class CourseStoreAction
{
use AsAction;
use TracksJob;
/**
* @param array<string, mixed> $attributes
*/
public function handle(Member $member, array $attributes): void
{
$course = Course::where('id', $attributes['course_id'])->firstOrFail();
$payload = collect($attributes)->only(['event_name', 'completed_at', 'organizer'])->merge([
'course_id' => $course->nami_id,
])->toArray();
$namiId = app(NamiSettings::class)->login()->createCourse($member->nami_id, $payload);
$member->courses()->create([
...$attributes,
'nami_id' => $namiId,
]);
}
/**
* @return array<string, string>
*/
public function rules(): array
{
return [
'organizer' => 'required|max:255',
'event_name' => 'required|max:255',
'completed_at' => 'required|date',
'course_id' => 'required|exists:courses,id',
];
}
public function asController(Member $member, ActionRequest $request): JsonResponse
{
$this->startJob($member, $request->validated());
return response()->json([]);
}
/**
* @param mixed $parameters
*/
public function jobState(WithJobState $jobState, ...$parameters): WithJobState
{
$member = $parameters[0];
return $jobState
->before('Ausbildung für ' . $member->fullname . ' wird gespeichert')
->after('Ausbildung für ' . $member->fullname . ' gespeichert')
->failed('Fehler beim Erstellen der Ausbildung für ' . $member->fullname)
->shouldReload(JobChannels::make()->add('member')->add('course'));
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace App\Course\Actions;
use App\Course\Models\Course;
use App\Course\Models\CourseMember;
use App\Lib\JobMiddleware\JobChannels;
use App\Lib\JobMiddleware\WithJobState;
use App\Lib\Queue\TracksJob;
use App\Setting\NamiSettings;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class CourseUpdateAction
{
use AsAction;
use TracksJob;
/**
* @param array<string, string> $attributes
*/
public function handle(CourseMember $course, array $attributes): void
{
app(NamiSettings::class)->login()->updateCourse(
$course->member->nami_id,
$course->nami_id,
[
...$attributes,
'course_id' => Course::find($attributes['course_id'])->nami_id,
]
);
$course->update($attributes);
}
/**
* @return array<string, string>
*/
public function rules()
{
return [
'organizer' => 'required|max:255',
'event_name' => 'required|max:255',
'completed_at' => 'required|date',
'course_id' => 'required|exists:courses,id',
];
}
public function asController(CourseMember $course, ActionRequest $request): JsonResponse
{
$this->startJob($course, $request->validated());
return response()->json([]);
}
/**
* @param mixed $parameters
*/
public function jobState(WithJobState $jobState, ...$parameters): WithJobState
{
$member = $parameters[0]->member;
return $jobState
->before('Ausbildung für ' . $member->fullname . ' wird gespeichert')
->after('Ausbildung für ' . $member->fullname . ' gespeichert')
->failed('Fehler beim Erstellen der Ausbildung für ' . $member->fullname)
->shouldReload(JobChannels::make()->add('member')->add('course'));
}
}

View File

@ -1,36 +0,0 @@
<?php
namespace App\Course\Controllers;
use App\Course\Models\CourseMember;
use App\Course\Requests\DestroyRequest;
use App\Course\Requests\StoreRequest;
use App\Course\Requests\UpdateRequest;
use App\Http\Controllers\Controller;
use App\Member\Member;
use App\Setting\NamiSettings;
use Illuminate\Http\RedirectResponse;
class CourseController extends Controller
{
public function store(Member $member, StoreRequest $request, NamiSettings $settings): RedirectResponse
{
$request->persist($member, $settings);
return redirect()->back()->success('Ausbildung erstellt');
}
public function update(Member $member, CourseMember $course, UpdateRequest $request, NamiSettings $settings): RedirectResponse
{
$request->persist($member, $course, $settings);
return redirect()->back()->success('Ausbildung aktualisiert');
}
public function destroy(Member $member, CourseMember $course, DestroyRequest $request, NamiSettings $settings): RedirectResponse
{
$request->persist($member, $course, $settings);
return redirect()->back()->success('Ausbildung gelöscht');
}
}

View File

@ -3,11 +3,13 @@
namespace App\Course\Models;
use App\Nami\HasNamiField;
use Database\Factories\Course\Models\CourseFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
{
/** @use HasFactory<CourseFactory> */
use HasFactory;
use HasNamiField;
@ -22,4 +24,12 @@ class Course extends Model
->trim()
->replaceMatches('/ - .*/', '');
}
/**
* @return array<int, array{id: int, name: string}>
*/
public static function forSelect(): array
{
return static::select('name', 'id')->get()->toArray();
}
}

View File

@ -2,12 +2,15 @@
namespace App\Course\Models;
use App\Member\Member;
use Database\Factories\Course\Models\CourseMemberFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class CourseMember extends Model
{
/** @use HasFactory<CourseMemberFactory> */
use HasFactory;
/** @var array<int, string> */
@ -20,4 +23,12 @@ class CourseMember extends Model
{
return $this->belongsTo(Course::class);
}
/**
* @return BelongsTo<Member, self>
*/
public function member(): BelongsTo
{
return $this->belongsTo(Member::class);
}
}

View File

@ -1,38 +0,0 @@
<?php
namespace App\Course\Requests;
use App\Course\Models\CourseMember;
use App\Member\Member;
use App\Setting\NamiSettings;
use Illuminate\Foundation\Http\FormRequest;
class DestroyRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, string>
*/
public function rules()
{
return [];
}
public function persist(Member $member, CourseMember $course, NamiSettings $settings): void
{
$settings->login()->deleteCourse($member->nami_id, $course->nami_id);
$course->delete();
}
}

View File

@ -1,49 +0,0 @@
<?php
namespace App\Course\Requests;
use App\Course\Models\Course;
use App\Member\Member;
use App\Setting\NamiSettings;
use Illuminate\Foundation\Http\FormRequest;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, string>
*/
public function rules()
{
return [
'organizer' => 'required|max:255',
'event_name' => 'required|max:255',
'completed_at' => 'required|date',
'course_id' => 'required|exists:courses,id',
];
}
public function persist(Member $member, NamiSettings $settings): void
{
$course = Course::where('id', $this->input('course_id'))->firstOrFail();
$payload = collect($this->input())->only(['event_name', 'completed_at', 'organizer'])->merge([
'course_id' => $course->nami_id,
])->toArray();
$namiId = $settings->login()->createCourse($member->nami_id, $payload);
$member->courses()->create($this->safe()->collect()->put('nami_id', $namiId)->toArray());
}
}

View File

@ -1,48 +0,0 @@
<?php
namespace App\Course\Requests;
use App\Course\Models\Course;
use App\Course\Models\CourseMember;
use App\Member\Member;
use App\Setting\NamiSettings;
use Illuminate\Foundation\Http\FormRequest;
class UpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, string>
*/
public function rules()
{
return [
'organizer' => 'required|max:255',
'event_name' => 'required|max:255',
'completed_at' => 'required|date',
'course_id' => 'required|exists:courses,id',
];
}
public function persist(Member $member, CourseMember $course, NamiSettings $settings): void
{
$settings->login()->updateCourse(
$member->nami_id,
$course->nami_id,
$this->safe()->merge(['course_id' => Course::find($this->input('course_id'))->nami_id])->toArray()
);
$course->update($this->safe()->toArray());
}
}

View File

@ -2,6 +2,8 @@
namespace App\Course\Resources;
use App\Course\Models\Course;
use App\Member\Member;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
@ -28,6 +30,29 @@ class CourseMemberResource extends JsonResource
'course_name' => $this->course->name,
'course_id' => $this->course->id,
'course' => new CourseResource($this->whenLoaded('course')),
'links' => [
'update' => route('course.update', ['course' => $this->getModel()]),
'destroy' => route('course.destroy', ['course' => $this->getModel()]),
]
];
}
/**
* @return array<string, mixed>
*/
public static function memberMeta(Member $member): array
{
return [
'default' => [
'event_name' => '',
'completed_at' => null,
'course_id' => null,
'organizer' => ''
],
'courses' => Course::forSelect(),
'links' => [
'store' => route('member.course.store', ['member' => $member]),
]
];
}
}

View File

@ -3,7 +3,6 @@
namespace App\Dashboard\Actions;
use App\Dashboard\DashboardFactory;
use Illuminate\Http\Request;
use Inertia;
use Inertia\Response;
use Lorisleiva\Actions\Concerns\AsAction;
@ -22,7 +21,7 @@ class IndexAction
];
}
public function asController(Request $request): Response
public function asController(): Response
{
session()->put('menu', 'dashboard');
session()->put('title', 'Dashboard');

View File

@ -4,10 +4,10 @@ namespace App\Dashboard;
use App\Dashboard\Blocks\Block;
use App\Efz\EfzPendingBlock;
use App\Invoice\MemberPaymentBlock;
use App\Member\PsPendingBlock;
use App\Membership\AgeGroupCountBlock;
use App\Membership\TestersBlock;
use App\Payment\MemberPaymentBlock;
class DashboardFactory
{

View File

@ -2,7 +2,9 @@
namespace App\Dashboard;
use Illuminate\Routing\Router;
use Illuminate\Support\ServiceProvider;
use App\Dashboard\Actions\IndexAction as DashboardIndexAction;
class DashboardServiceProvider extends ServiceProvider
{
@ -23,5 +25,8 @@ class DashboardServiceProvider extends ServiceProvider
*/
public function boot()
{
app(Router::class)->middleware(['web', 'auth:web'])->group(function ($router) {
$router->get('/', DashboardIndexAction::class)->name('home');
});
}
}

View File

@ -8,9 +8,6 @@ use Sabre\CardDAV\Backend\AbstractBackend;
use Sabre\DAV\PropPatch;
use Sabre\VObject\Component\VCard;
/**
* @template M as array{lastmodified: int, etag: string, uri: string, id: int, size: int}
*/
class AddressBookBackend extends AbstractBackend
{
/**
@ -115,7 +112,7 @@ class AddressBookBackend extends AbstractBackend
*
* @param mixed $addressbookId
*
* @return array<int, M>
* @return array<int, AddressBookCard>
*/
public function getCards($addressbookId): array
{
@ -133,7 +130,7 @@ class AddressBookBackend extends AbstractBackend
* @param mixed $addressBookId
* @param string $cardUri
*
* @return M
* @return AddressBookCard|bool
*/
public function getCard($addressBookId, $cardUri)
{
@ -158,8 +155,9 @@ class AddressBookBackend extends AbstractBackend
* If the backend supports this, it may allow for some speed-ups.
*
* @param mixed $addressBookId
* @param array<int, string> $uris
*
* @return array
* @return array<int, mixed>
*/
public function getMultipleCards($addressBookId, array $uris)
{
@ -248,13 +246,13 @@ class AddressBookBackend extends AbstractBackend
}
/**
* @return M
* @return AddressBookCard
*/
private function cardMeta(Member $member): array
{
return [
'lastmodified' => $member->updated_at->timestamp,
'etag' => '"'.$member->etag.'"',
'etag' => '"' . $member->etag . '"',
'uri' => $member->slug,
'id' => $member->id,
'size' => strlen($member->toVcard()->serialize()),

View File

@ -136,10 +136,11 @@ class Principal implements PrincipalBackendInterface
*
* @param string $principal
*
* @return array
* @return array<int, string>|null
*/
public function getGroupMemberSet($principal)
{
return [];
}
/**
@ -147,7 +148,7 @@ class Principal implements PrincipalBackendInterface
*
* @param string $principal
*
* @return array
* @return array<int, string>|null
*/
public function getGroupMembership($principal)
{
@ -155,7 +156,7 @@ class Principal implements PrincipalBackendInterface
return null;
}
return ['addressbooks/'.$matches[1]];
return ['addressbooks/' . $matches[1]];
}
/**
@ -164,6 +165,8 @@ class Principal implements PrincipalBackendInterface
* The principals should be passed as a list of uri's.
*
* @param string $principal
* @param array<int, string> $members
* @return void
*/
public function setGroupMemberSet($principal, array $members)
{
@ -175,8 +178,8 @@ class Principal implements PrincipalBackendInterface
private function userToPrincipal(User $user): array
{
return [
'{DAV:}displayname' => $user->name,
'uri' => 'principals/'.$user->email,
'{DAV:}displayname' => $user->firstname . ' ' . $user->lastname,
'uri' => 'principals/' . $user->email,
'{http://sabredav.org/ns}email-address' => $user->email,
];
}

View File

@ -9,6 +9,7 @@ use Sabre\CardDAV\AddressBookRoot;
use Sabre\CardDAV\Plugin as CardDAVPlugin;
use Sabre\DAV\Auth\Plugin as AuthPlugin;
use Sabre\DAV\Browser\Plugin as BrowserPlugin;
use Sabre\DAV\ServerPlugin;
use Sabre\DAVACL\AbstractPrincipalCollection;
use Sabre\DAVACL\Plugin as AclPlugin;
use Sabre\DAVACL\PrincipalCollection;
@ -50,6 +51,9 @@ class ServiceProvider extends BaseServiceProvider
];
}
/**
* @return array<int, ServerPlugin>
*/
private function plugins(): array
{
$authBackend = new AuthBackend();

View File

@ -19,7 +19,7 @@ class EfzPendingBlock extends Block
})
->whereCurrentGroup()
->orderByRaw('lastname, firstname')
->whereHas('memberships', fn ($builder) => $builder->isLeader());
->whereHas('memberships', fn ($builder) => $builder->isLeader()->active());
}
/**

View File

@ -12,15 +12,14 @@ class Handler extends ExceptionHandler
/**
* A list of the exception types that are not reported.
*
* @var string[]
* @var array<int, class-string<Throwable>>
*/
protected $dontReport = [
];
protected $dontReport = [];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var string[]
* @var array<int, string>
*/
protected $dontFlash = [
'password',

View File

@ -4,12 +4,14 @@ namespace App;
use App\Nami\HasNamiField;
use App\Payment\Subscription;
use Database\Factories\FeeFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Fee extends Model
{
/** @use HasFactory<FeeFactory> */
use HasFactory;
use HasNamiField;

View File

@ -0,0 +1,21 @@
<?php
namespace App\Fileshare\Actions;
use App\Fileshare\Models\Fileshare;
use App\Fileshare\Resources\FileshareResource;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Lorisleiva\Actions\Concerns\AsAction;
class FileshareApiIndexAction
{
use AsAction;
public function handle(): AnonymousResourceCollection
{
session()->put('menu', 'setting');
session()->put('title', 'Datei-Verbindungen');
return FileshareResource::collection(Fileshare::paginate(15));
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Fileshare\Actions;
use App\Fileshare\Models\Fileshare;
use App\Lib\Events\Succeeded;
use Illuminate\Validation\ValidationException;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class FileshareStoreAction
{
use AsAction;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'type' => 'required|string|max:255|exclude',
'config' => 'array|exclude',
];
}
public function asController(ActionRequest $request): void
{
$type = $request->input('type')::from($request->input('config'));
if (!$type->check()) {
throw ValidationException::withMessages(['type' => 'Verbindung fehlgeschlagen']);
}
Fileshare::create([
...$request->validated(),
'type' => $type,
]);
Succeeded::message('Verbindung erstellt.')->dispatch();
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Fileshare\Actions;
use App\Fileshare\Models\Fileshare;
use App\Lib\Events\Succeeded;
use Illuminate\Validation\ValidationException;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class FileshareUpdateAction
{
use AsAction;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'type' => 'required|string|max:255|exclude',
'config' => 'array|exclude',
];
}
public function handle(ActionRequest $request, Fileshare $fileshare): void
{
$type = $request->input('type')::from($request->input('config'));
if (!$type->check()) {
throw ValidationException::withMessages(['type' => 'Verbindung fehlgeschlagen']);
}
$fileshare->update([
...$request->validated(),
'type' => $type,
]);
Succeeded::message('Verbindung bearbeitet.')->dispatch();
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Fileshare\Actions;
use App\Fileshare\Data\ResourceData;
use App\Fileshare\Models\Fileshare;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
use Spatie\LaravelData\DataCollection;
class ListFilesAction
{
use AsAction;
/**
* @return DataCollection<int, ResourceData>
*/
public function handle(ActionRequest $request, Fileshare $fileshare): DataCollection
{
return ResourceData::collect($fileshare->type->getSubDirectories($request->input('parent')), DataCollection::class)->wrap('data');
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace App\Fileshare\ConnectionTypes;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Collection;
use Spatie\LaravelData\Data;
abstract class ConnectionType extends Data
{
abstract public function check(): bool;
/**
* @return array<string, mixed>
*/
abstract public static function defaults(): array;
abstract public static function title(): string;
abstract public function getFilesystem(): FilesystemAdapter;
/**
* @return array<int, array{label: string, key: string, type: string}>
*/
abstract public static function fields(): array;
/**
* @return array<int, mixed>
*/
public static function forSelect(): array
{
return self::types()
->map(fn ($file) => ['id' => $file, 'name' => $file::title(), 'defaults' => $file::defaults(), 'fields' => $file::fields()])
->toArray();
}
/**
* @return array<int, string>
*/
public function getSubDirectories(?string $parent): array
{
$filesystem = $this->getFilesystem();
return $filesystem->directories($parent ?: '/');
}
/**
* @return Collection<int, class-string<ConnectionType>>
*/
private static function types(): Collection
{
return collect(glob(base_path('app/Fileshare/ConnectionTypes/*')))
->map(fn ($file) => 'App\\Fileshare\\ConnectionTypes\\' . pathinfo($file, PATHINFO_FILENAME))
->filter(fn ($file) => $file !== static::class)
->values();
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace App\Fileshare\ConnectionTypes;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Facades\Http;
use League\Flysystem\Filesystem;
use League\Flysystem\WebDAV\WebDAVAdapter;
use Sabre\DAV\Client;
class NextcloudConnection extends OwncloudConnection
{
public function check(): bool
{
try {
$response = Http::withoutVerifying()
->withBasicAuth($this->user, $this->password)
->withHeaders(['OCS-APIRequest' => 'true'])
->acceptJson()
->get($this->baseUrl . '/ocs/v2.php/cloud/capabilities');
return $response->ok();
} catch (ConnectionException $e) {
return false;
}
}
public static function title(): string
{
return 'Nextcloud';
}
public function getFilesystem(): FilesystemAdapter
{
$adapter = new WebDAVAdapter(new Client([
'baseUri' => $this->baseUrl . '/remote.php/dav/files/' . $this->user,
'userName' => $this->user,
'password' => $this->password,
]), '/remote.php/dav/files/' . $this->user);
return new FilesystemAdapter(new Filesystem($adapter), $adapter);
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace App\Fileshare\ConnectionTypes;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Facades\Http;
use League\Flysystem\Filesystem;
use League\Flysystem\WebDAV\WebDAVAdapter;
use Sabre\DAV\Client;
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Attributes\MapOutputName;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
#[MapInputName(SnakeCaseMapper::class)]
#[MapOutputName(SnakeCaseMapper::class)]
class OwncloudConnection extends ConnectionType
{
public function __construct(
public string $user,
public string $password,
public string $baseUrl,
) {
}
public function check(): bool
{
try {
$response = Http::withoutVerifying()->withBasicAuth($this->user, $this->password)->acceptJson()->get($this->baseUrl . '/ocs/v1.php/cloud/capabilities?format=json');
return $response->ok();
} catch (ConnectionException $e) {
return false;
}
}
/**
* @inheritdoc
*/
public static function defaults(): array
{
return [
'user' => '',
'password' => '',
'base_url' => '',
];
}
public static function title(): string
{
return 'Owncloud';
}
/**
* @inheritdoc
*/
public static function fields(): array
{
return [
['label' => 'URL', 'key' => 'base_url', 'type' => 'text'],
['label' => 'Benutzer', 'key' => 'user', 'type' => 'text'],
['label' => 'Passwort', 'key' => 'password', 'type' => 'password'],
];
}
public function getFilesystem(): FilesystemAdapter
{
$adapter = new WebDAVAdapter(new Client([
'baseUri' => $this->baseUrl . '/remote.php/dav/files/' . $this->user,
'userName' => $this->user,
'password' => $this->password,
]), '/remote.php/dav/files/' . $this->user);
return new FilesystemAdapter(new Filesystem($adapter), $adapter);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Fileshare\Data;
use App\Fileshare\Models\Fileshare;
use Illuminate\Filesystem\FilesystemAdapter;
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Attributes\MapOutputName;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
#[MapInputName(SnakeCaseMapper::class)]
#[MapOutputName(SnakeCaseMapper::class)]
class FileshareResourceData extends Data
{
public function __construct(public int $connectionId, public string $resource)
{
}
public function getConnection(): Fileshare
{
return Fileshare::find($this->connectionId);
}
public function getStorage(): FilesystemAdapter
{
return $this->getConnection()->type->getFilesystem();
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Fileshare\Data;
use Spatie\LaravelData\Data;
class ResourceData extends Data
{
public function __construct(public string $name, public string $path, public string $parent)
{
}
public static function fromString(string $path): self
{
$dir = '/' . trim($path, '\\/');
return self::from([
'path' => $dir,
'name' => pathinfo($dir, PATHINFO_BASENAME),
'parent' => pathinfo($dir, PATHINFO_DIRNAME),
]);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Fileshare;
use App\Fileshare\Models\Fileshare;
use App\Fileshare\Resources\FileshareResource;
use App\Setting\LocalSettings;
class FileshareSettings extends LocalSettings
{
public static function group(): string
{
return 'fileshare';
}
public static function title(): string
{
return 'Datei-Verbindungen';
}
/**
* @inheritdoc
*/
public function viewData(): array
{
return [
'data' => FileshareResource::collection(Fileshare::paginate(15))
];
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Fileshare\Models;
use App\Fileshare\ConnectionTypes\ConnectionType;
use Database\Factories\Fileshare\Models\FileshareFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Fileshare extends Model
{
/** @use HasFactory<FileshareFactory> */
use HasFactory;
public $guarded = [];
public $casts = [
'type' => ConnectionType::class,
];
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Fileshare\Resources;
use App\Fileshare\ConnectionTypes\ConnectionType;
use App\Fileshare\Models\Fileshare;
use App\Lib\HasMeta;
use Illuminate\Http\Resources\Json\JsonResource;
/**
* @mixin Fileshare
*/
class FileshareResource extends JsonResource
{
use HasMeta;
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array<string, mixed>
*/
public function toArray($request)
{
return [
'name' => $this->name,
'is_active' => $this->type->check(),
'type' => get_class($this->type),
'config' => $this->type->toArray(),
'id' => $this->id,
'type_human' => $this->type::title(),
'links' => [
'update' => route('fileshare.update', ['fileshare' => $this->getModel()]),
]
];
}
/**
* @return array<string, mixed>
*/
public static function meta(): array
{
return [
'default' => [
'name' => '',
'type' => null,
'config' => null,
],
'types' => ConnectionType::forSelect(),
'links' => [
'store' => route('fileshare.store'),
]
];
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Form\Actions;
use App\Form\FormSettings;
use Illuminate\Support\Facades\Http;
use Lorisleiva\Actions\Concerns\AsAction;
class ClearFrontendCacheAction
{
use AsAction;
public function handle(): void
{
Http::get(app(FormSettings::class)->clearCacheUrl);
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use Illuminate\Database\Eloquent\Collection;
use Lorisleiva\Actions\Concerns\AsAction;
use Zoomyboy\TableDocument\SheetData;
use Zoomyboy\TableDocument\TableDocumentData;
class CreateExcelDocumentAction
{
use AsAction;
public Form $form;
/**
* @param Collection<int, Participant> $participants
*/
public function handle(Form $form, Collection $participants): string
{
$this->form = $form;
return file_get_contents($this->allSheet($participants)->compile($this->tempPath()));
}
/**
* @param Collection<int, Participant> $participants
*/
private function allSheet(Collection $participants): TableDocumentData
{
$document = TableDocumentData::from(['title' => 'Anmeldungen für ' . $this->form->name, 'sheets' => []]);
$headers = $this->form->getFields()->map(fn ($field) => $field->name)->toArray();
$document->addSheet(SheetData::from([
'header' => $headers,
'data' => $participants
->map(fn ($participant) => $this->form->getFields()->map(fn ($field) => $participant->getFields()->find($field)->presentRaw())->toArray())
->toArray(),
'name' => 'Alle',
]));
if ($this->form->export->groupBy) {
$groups = $participants->groupBy(fn ($participant) => $participant->getFields()->findByKey($this->form->export->groupBy)->presentRaw());
foreach ($groups as $name => $participants) {
$document->addSheet(SheetData::from([
'header' => $headers,
'data' => $participants
->map(fn ($participant) => $this->form->getFields()->map(fn ($field) => $participant->getFields()->find($field)->presentRaw())->toArray())
->toArray(),
'name' => $name,
]));
}
$document->addSheet(SheetData::from([
'header' => ['Wert', 'Anzahl'],
'data' => $groups->map(fn ($participants, $name) => [$name, (string) count($participants)])->toArray(),
'name' => 'Statistik',
]));
}
return $document;
}
private function tempPath(): string
{
return sys_get_temp_dir() . '/' . str()->uuid()->toString();
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use Illuminate\Support\Facades\Storage;
use League\Csv\Writer;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\HttpFoundation\StreamedResponse;
class ExportAction
{
use AsAction;
public function handle(Form $form): string
{
return CreateExcelDocumentAction::run($form, $form->participants);
}
public function asController(Form $form, ActionRequest $request): StreamedResponse
{
$contents = $this->handle($form);
$filename = 'tn-' . $form->slug . '.xlsx';
Storage::disk('temp')->put($filename, $contents);
return Storage::disk('temp')->download($filename);
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use App\Group;
use Lorisleiva\Actions\Concerns\AsAction;
class ExportSyncAction
{
use AsAction;
public Form $form;
public function handle(Form $form): void
{
if (!$form->export->root) {
return;
}
$storage = $form->export->root->getStorage();
$storage->put($form->export->root->resource . '/Anmeldungen ' . $form->name . '.xlsx', CreateExcelDocumentAction::run($form, $form->participants));
if ($form->export->toGroupField) {
foreach ($form->participants->groupBy(fn ($participant) => $participant->data[$form->export->toGroupField]) as $groupId => $participants) {
$group = Group::find($groupId);
if (!$group?->fileshare) {
continue;
}
$group->fileshare->getStorage()->put($group->fileshare->resource . '/Anmeldungen ' . $form->name . '.xlsx', CreateExcelDocumentAction::run($form, $participants));
}
}
}
public function asJob(int $formId): void
{
$this->handle(Form::find($formId));
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Form\Actions;
use App\Form\Scopes\FormFilterScope;
use App\Form\Models\Form;
use App\Form\Resources\FormApiResource;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Pagination\LengthAwarePaginator;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class FormApiListAction
{
use AsAction;
/**
* @param string $filter
* @return LengthAwarePaginator<Form>
*/
public function handle(string $filter, int $perPage): LengthAwarePaginator
{
return FormFilterScope::fromRequest($filter)->getQuery()->paginate($perPage);
}
public function asController(ActionRequest $request): AnonymousResourceCollection
{
return FormApiResource::collection($this->handle(
$request->input('filter', ''),
$request->input('perPage', 9999)
));
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use App\Lib\Events\Succeeded;
use Lorisleiva\Actions\Concerns\AsAction;
class FormDestroyAction
{
use AsAction;
public function asController(Form $form): void
{
$form->delete();
ClearFrontendCacheAction::run();
Succeeded::message('Veranstaltung gelöscht.')->dispatch();
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace App\Form\Actions;
use App\Form\Scopes\FormFilterScope;
use App\Form\Models\Form;
use App\Form\Resources\FormResource;
use Illuminate\Pagination\LengthAwarePaginator;
use Inertia\Inertia;
use Inertia\Response;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class FormIndexAction
{
use AsAction;
/**
* @return LengthAwarePaginator<Form>
*/
public function handle(string $filter): LengthAwarePaginator
{
return FormFilterScope::fromRequest($filter)->getQuery()->query(fn ($query) => $query->withCount('participants'))->paginate(15);
}
public function asController(ActionRequest $request): Response
{
session()->put('menu', 'form');
session()->put('title', 'Veranstaltungen');
return Inertia::render('form/Index', [
'data' => FormResource::collection($this->handle($request->input('filter', ''))),
]);
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use App\Lib\Events\Succeeded;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\Concerns\AsAction;
use Lorisleiva\Actions\ActionRequest;
class FormStoreAction
{
use AsAction;
use HasValidation;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
...$this->globalRules(),
'description.time' => 'required|integer',
'description.blocks' => 'required|array',
'description.version' => 'required|string',
'excerpt' => 'required|string|max:130',
'from' => 'required|date',
'to' => 'required|date',
'registration_from' => 'present|nullable|date',
'registration_until' => 'present|nullable|date',
'header_image' => 'required|exclude',
'mailattachments' => 'present|array|exclude',
'is_active' => 'boolean',
'is_private' => 'boolean',
'export' => 'nullable|array',
'needs_prevention' => 'present|boolean',
'prevention_text' => 'array',
'prevention_conditions' => 'array',
];
}
/**
* @param array<string, mixed> $attributes
*/
public function handle(array $attributes): Form
{
return tap(Form::create($attributes), function ($form) {
$form->setDeferredUploads(request()->input('header_image'));
$form->setDeferredUploads(request()->input('mailattachments'));
ClearFrontendCacheAction::run();
});
}
/**
* @return array<string, mixed>
*/
public function getValidationAttributes(): array
{
return [
...$this->globalValidationAttributes(),
'from' => 'Start',
'to' => 'Ende',
'header_image' => 'Bild',
'description.blocks' => 'Beschreibung',
];
}
public function asController(ActionRequest $request): JsonResponse
{
$this->handle($request->validated());
Succeeded::message('Veranstaltung gespeichert.')->dispatch();
return response()->json([]);
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use App\Lib\Editor\Condition;
use App\Lib\Events\Succeeded;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\Concerns\AsAction;
use Lorisleiva\Actions\ActionRequest;
class FormUpdateAction
{
use AsAction;
use HasValidation;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
...$this->globalRules(),
'description' => 'required|array',
'description.time' => 'required|integer',
'description.blocks' => 'required|array',
'description.version' => 'required|string',
'excerpt' => 'required|string|max:130',
'from' => 'required|date',
'to' => 'required|date',
'registration_from' => 'present|nullable|date',
'registration_until' => 'present|nullable|date',
'is_active' => 'boolean',
'is_private' => 'boolean',
'export' => 'nullable|array',
'needs_prevention' => 'present|boolean',
'prevention_text' => 'array',
'prevention_conditions' => 'array',
];
}
/**
* @param array<string, mixed> $attributes
*/
public function handle(Form $form, array $attributes): Form
{
$form->update($attributes);
ClearFrontendCacheAction::run();
return $form;
}
/**
* @return array<string, mixed>
*/
public function getValidationAttributes(): array
{
return [
...$this->globalValidationAttributes(),
'from' => 'Start',
'to' => 'Ende',
'description.blocks' => 'Beschreibung',
];
}
public function asController(Form $form, ActionRequest $request): JsonResponse
{
$this->handle($form, $request->validated());
Succeeded::message('Veranstaltung aktualisiert.')->dispatch();
return response()->json([]);
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use Illuminate\Validation\Rule;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\HttpFoundation\JsonResponse;
class FormUpdateMetaAction
{
use AsAction;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
/** @var Form */
$form = request()->route('form');
return [
'sorting' => 'array',
'sorting.by' => 'required|string',
'sorting.direction' => 'required|boolean',
'active_columns' => 'array',
'active_columns.*' => ['string', Rule::in([...$form->getFields()->pluck('key')->toArray(), 'created_at', 'prevention'])]
];
}
/**
* @param array<string, mixed> $input
*/
public function handle(Form $form, array $input): void
{
$form->update(['meta' => $input]);
}
public function asController(Form $form, ActionRequest $request): JsonResponse
{
$this->handle($form, $request->validated());
return response()->json($form->fresh()->meta);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Formtemplate;
use App\Lib\Events\Succeeded;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\Concerns\AsAction;
class FormtemplateDestroyAction
{
use AsAction;
public function handle(Formtemplate $formtemplate): void
{
$formtemplate->delete();
}
public function asController(Formtemplate $formtemplate): JsonResponse
{
$this->handle($formtemplate);
Succeeded::message('Vorlage gelöscht.')->dispatch();
return response()->json([]);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Formtemplate;
use App\Form\Resources\FormtemplateResource;
use Illuminate\Pagination\LengthAwarePaginator;
use Inertia\Inertia;
use Inertia\Response;
use Lorisleiva\Actions\Concerns\AsAction;
class FormtemplateIndexAction
{
use AsAction;
/**
* @return LengthAwarePaginator<Formtemplate>
*/
public function handle(): LengthAwarePaginator
{
return Formtemplate::paginate(15);
}
public function asController(): Response
{
session()->put('menu', 'form');
session()->put('title', 'Formular-Vorlagen');
return Inertia::render('formtemplate/Index', [
'data' => FormtemplateResource::collection($this->handle()),
]);
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Formtemplate;
use App\Lib\Events\Succeeded;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class FormtemplateStoreAction
{
use AsAction;
use HasValidation;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
...$this->globalRules(),
];
}
/**
* @return array<string, mixed>
*/
public function getValidationAttributes(): array
{
return [
...$this->globalValidationAttributes(),
];
}
/**
* @param array<string, mixed> $attributes
*/
public function handle(array $attributes): Formtemplate
{
return Formtemplate::create($attributes);
}
public function asController(ActionRequest $request): JsonResponse
{
$this->handle($request->validated());
Succeeded::message('Vorlage gespeichert.')->dispatch();
return response()->json([]);
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Formtemplate;
use App\Lib\Events\Succeeded;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class FormtemplateUpdateAction
{
use AsAction;
use HasValidation;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
...$this->globalRules(),
];
}
/**
* @return array<string, mixed>
*/
public function getValidationAttributes(): array
{
return [
...$this->globalValidationAttributes(),
];
}
/**
* @param array<string, mixed> $attributes
*/
public function handle(Formtemplate $formtemplate, array $attributes): void
{
$formtemplate->update($attributes);
}
public function asController(Formtemplate $formtemplate, ActionRequest $request): JsonResponse
{
$this->handle($formtemplate, $request->validated());
Succeeded::message('Vorlage aktualisiert.')->dispatch();
return response()->json([]);
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace App\Form\Actions;
use Illuminate\Validation\Rule;
use App\Form\Fields\Field;
use Illuminate\Validation\Validator;
use Lorisleiva\Actions\ActionRequest;
trait HasValidation
{
/**
* @return array<string, mixed>
*/
public function globalRules(): array
{
return [
'name' => 'required|string|max:255',
'config' => 'array',
'config.sections.*.name' => 'required',
'config.sections.*.intro' => 'nullable|string',
'config.sections.*.fields' => 'array',
'config.sections.*.fields.*.name' => 'required|string',
'config.sections.*.fields.*.type' => ['required', 'string', Rule::in(array_column(Field::asMeta(), 'id'))],
'config.sections.*.fields.*.key' => ['required', 'string', 'regex:/^[a-zA-Z_]*$/'],
'config.sections.*.fields.*.columns' => 'required|array',
'config.sections.*.fields.*.*' => '',
'config.sections.*.fields.*.columns.mobile' => 'required|numeric|gt:0|lte:2',
'config.sections.*.fields.*.columns.tablet' => 'required|numeric|gt:0|lte:4',
'config.sections.*.fields.*.columns.desktop' => 'required|numeric|gt:0|lte:6',
'mail_top' => 'array',
'mail_bottom' => 'array',
];
}
/**
* @return array<string, mixed>
*/
public function globalValidationAttributes(): array
{
return [
'config.sections.*.name' => 'Sektionsname',
'config.sections.*.fields.*.name' => 'Feldname',
'config.sections.*.fields.*.type' => 'Feldtyp',
'config.sections.*.fields.*.key' => 'Feldkey',
];
}
public function withValidator(Validator $validator, ActionRequest $request): void
{
if (!$validator->passes()) {
return;
}
foreach ($request->input('config.sections') as $sindex => $section) {
foreach (data_get($section, 'fields') as $findex => $field) {
$fieldClass = Field::classFromType($field['type']);
if (!$fieldClass) {
continue;
}
foreach ($fieldClass::metaRules() as $fieldName => $rules) {
$validator->addRules(["config.sections.{$sindex}.fields.{$findex}.{$fieldName}" => $rules]);
}
foreach ($fieldClass::metaAttributes() as $fieldName => $attribute) {
$validator->addCustomAttributes(["config.sections.{$sindex}.fields.{$findex}.{$fieldName}" => $attribute]);
}
}
}
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class IsDirtyAction
{
use AsAction;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'config' => 'array|present',
];
}
public function handle(Form $form, ActionRequest $request): JsonResponse
{
$form->config = $request->input('config');
return response()->json([
'result' => $form->isDirty('config'),
]);
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Participant;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class ParticipantAssignAction
{
use AsAction;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'member_id' => 'required|exists:members,id',
];
}
public function handle(Participant $participant, ActionRequest $request): void
{
$participant->update(['member_id' => $request->input('member_id')]);
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Participant;
use App\Lib\JobMiddleware\JobChannels;
use App\Lib\JobMiddleware\WithJobState;
use App\Lib\Queue\TracksJob;
use Lorisleiva\Actions\Concerns\AsAction;
class ParticipantDestroyAction
{
use AsAction;
use TracksJob;
public function handle(int $participantId): void
{
Participant::findOrFail($participantId)->delete();
}
public function asController(Participant $participant): void
{
$this->startJob($participant->id);
}
/**
* @param mixed $parameters
*/
public function jobState(WithJobState $jobState, ...$parameters): WithJobState
{
return $jobState
->after('Teilnehmer gelöscht.')
->failed('Löschen von Teilnehmer fehlgeschlagen.')
->shouldReload(JobChannels::make()->add('participant'));
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Participant;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\Concerns\AsAction;
class ParticipantFieldsAction
{
use AsAction;
public function handle(Participant $participant): JsonResponse
{
return response()->json([
'data' => [
'id' => $participant->id,
'config' => $participant->getConfig(),
]
]);
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Form\Resources\ParticipantResource;
use App\Form\Scopes\ParticipantFilterScope;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Laravel\Scout\Builder;
use Lorisleiva\Actions\Concerns\AsAction;
class ParticipantIndexAction
{
use AsAction;
/**
* @return Builder<Participant>
*/
protected function getQuery(Form $form, ParticipantFilterScope $filter): Builder
{
return $filter->setForm($form)->getQuery()
->query(fn ($q) => $q->withCount('children')->with('form'));
}
public function asController(Form $form, ?int $parent = null): AnonymousResourceCollection
{
$filter = ParticipantFilterScope::fromRequest(request()->input('filter', ''))->parent($parent);
$data = match ($parent) {
null => $this->getQuery($form, $filter)->paginate(15), // initial all elements - paginate
-1 => $this->getQuery($form, $filter)->paginate(15), // initial root elements - parinate
default => $this->getQuery($form, $filter)->get(), // specific parent element - show all
};
return ParticipantResource::collection($data)->additional(['meta' => ParticipantResource::meta($form)]);
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Lib\Events\Succeeded;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class ParticipantStoreAction
{
use AsAction;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationRules();
}
/**
* @return array<string, mixed>
*/
public function getValidationAttributes(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationAttributes();
}
/**
* @return array<string, mixed>
*/
public function getValidationMessages(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationMessages();
}
public function handle(Form $form, ActionRequest $request): JsonResponse
{
$form->participants()->create(['data' => $request->validated()]);
ExportSyncAction::dispatch($form->id);
Succeeded::message('Teilnehmer*in erstellt.')->dispatch();
return response()->json([]);
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Participant;
use App\Lib\Events\Succeeded;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class ParticipantUpdateAction
{
use AsAction;
/**
* @return array<string, mixed>
*/
public function rules(): array
{
/** @var Participant */
$participant = request()->route('participant');
return $participant->form->getRegistrationRules();
}
/**
* @return array<string, mixed>
*/
public function getValidationAttributes(): array
{
/** @var Participant */
$participant = request()->route('participant');
return $participant->form->getRegistrationAttributes();
}
/**
* @return array<string, mixed>
*/
public function getValidationMessages(): array
{
/** @var Participant */
$participant = request()->route('participant');
return $participant->form->getRegistrationMessages();
}
public function handle(Participant $participant, ActionRequest $request): JsonResponse
{
$participant->update(['data' => [...$participant->data, ...$request->validated()]]);
ExportSyncAction::dispatch($participant->form->id);
Succeeded::message('Teilnehmer*in bearbeitet.')->dispatch();
return response()->json([]);
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace App\Form\Actions;
use App\Form\Editor\FormConditionResolver;
use App\Form\Models\Participant;
use App\Prevention\Mails\PreventionRememberMail;
use App\Prevention\PreventionSettings;
use Illuminate\Support\Facades\Mail;
use Lorisleiva\Actions\Concerns\AsAction;
class PreventionRememberAction
{
use AsAction;
public string $commandSignature = 'prevention:remember';
public function handle(): void
{
$query = Participant::whereHas(
'form',
fn ($form) => $form
->where('needs_prevention', true)
->where('from', '>=', now())
)
->where(
fn ($q) => $q
->where('last_remembered_at', '<=', now()->subWeeks(2))
->orWhereNull('last_remembered_at')
);
foreach ($query->get() as $participant) {
if (!app(FormConditionResolver::class)->forParticipant($participant)->filterCondition($participant->form->prevention_conditions)) {
continue;
}
if ($participant->getFields()->getMailRecipient() === null || count($participant->preventions()) === 0) {
continue;
}
$body = app(PreventionSettings::class)->refresh()->formmail
->placeholder('formname', $participant->form->name)
->append($participant->form->prevention_text);
Mail::send(new PreventionRememberMail($participant, $body));
$participant->update(['last_remembered_at' => now()]);
}
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace App\Form\Actions;
use App\Form\Data\FieldCollection;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use App\Member\Member;
use Illuminate\Http\JsonResponse;
use Illuminate\Validation\ValidationException;
use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction;
class RegisterAction
{
use AsAction;
/**
* @param array<string, mixed> $input
*/
public function handle(Form $form, array $input): Participant
{
if (!$form->canRegister()) {
throw ValidationException::withMessages(['event' => 'Anmeldung zzt nicht möglich.']);
}
$memberQuery = FieldCollection::fromRequest($form, $input)
->withNamiType()
->reduce(fn ($query, $field) => $field->namiType->performQuery($query, $field->value), (new Member())->newQuery());
$member = $form->getFields()->withNamiType()->count() && $memberQuery->count() === 1 ? $memberQuery->first() : null;
$participant = $form->participants()->create([
'data' => $input,
'member_id' => $member?->id,
]);
$form->getFields()->each(fn ($field) => $field->afterRegistration($form, $participant, $input));
$participant->sendConfirmationMail();
ExportSyncAction::dispatch($form->id);
return $participant;
}
/**
* @return array<string, mixed>
*/
public function rules(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationRules();
}
/**
* @return array<string, mixed>
*/
public function getValidationAttributes(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationAttributes();
}
/**
* @return array<string, mixed>
*/
public function getValidationMessages(): array
{
/** @var Form */
$form = request()->route('form');
return $form->getRegistrationMessages();
}
public function asController(ActionRequest $request, Form $form): JsonResponse
{
$participant = $this->handle($form, $request->validated());
return response()->json($participant);
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Form\Actions;
use App\Form\Models\Form;
use Lorisleiva\Actions\Concerns\AsAction;
class UpdateParticipantSearchIndexAction
{
use AsAction;
public function handle(Form $form): void
{
if (config('scout.driver') !== 'meilisearch') {
return;
}
$form->searchableUsing()->updateIndexSettings(
$form->participantsSearchableAs(),
[
'filterableAttributes' => [...$form->getFields()->filterables()->getKeys(), 'parent-id'],
'searchableAttributes' => $form->getFields()->searchables()->getKeys(),
'sortableAttributes' => [...$form->getFields()->sortables()->getKeys(), 'id', 'created_at'],
'displayedAttributes' => [...$form->getFields()->filterables()->getKeys(), ...$form->getFields()->searchables()->getKeys(), 'id'],
'pagination' => [
'maxTotalHits' => 1000000,
]
]
);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Form\Casts;
use App\Form\Fields\Field;
use Illuminate\Support\Collection;
use Spatie\LaravelData\Casts\Cast;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Support\Creation\CreationContext;
use Spatie\LaravelData\Support\DataProperty;
class CollectionCast implements Cast
{
/**
* @param class-string<Data> $target
*/
public function __construct(public string $target)
{
}
/**
* @param array<int, array<string, mixed>> $value
* @return Collection<int, Data>
*/
public function cast(DataProperty $property, mixed $value, array $properties, CreationContext $context): mixed
{
return collect($value)->map(fn ($item) => $this->target::from($item));
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Form\Casts;
use App\Form\Data\FieldCollection;
use App\Form\Fields\Field;
use Spatie\LaravelData\Casts\Cast;
use Spatie\LaravelData\Support\Creation\CreationContext;
use Spatie\LaravelData\Support\DataProperty;
class FieldCollectionCast implements Cast
{
/**
* @param array<int, array<string, string>> $value
* @return FieldCollection
*/
public function cast(DataProperty $property, mixed $value, array $properties, CreationContext $context): mixed
{
return new FieldCollection(collect($value)->map(fn ($value) => Field::classFromType($value['type'])::from($value))->all());
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Form\Contracts;
interface Filterable
{
/** @param mixed $value */
public function filter($value): string;
}

View File

@ -0,0 +1,16 @@
<?php
namespace App\Form\Data;
use Spatie\LaravelData\Data;
class ColumnData extends Data
{
public function __construct(
public int $mobile,
public int $tablet,
public int $desktop,
) {
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Form\Data;
use App\Fileshare\Data\FileshareResourceData;
use App\Form\Fields\Field;
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Attributes\MapOutputName;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
#[MapInputName(SnakeCaseMapper::class)]
#[MapOutputName(SnakeCaseMapper::class)]
class ExportData extends Data
{
public function __construct(public ?FileshareResourceData $root = null, public ?string $groupBy = null, public ?string $toGroupField = null)
{
}
}

View File

@ -0,0 +1,144 @@
<?php
namespace App\Form\Data;
use App\Form\Contracts\Filterable;
use App\Form\Enums\SpecialType;
use App\Form\Fields\Field;
use App\Form\Fields\NamiField;
use App\Form\Models\Form;
use Illuminate\Support\Collection;
use stdClass;
/**
* @extends Collection<int, Field>
*/
class FieldCollection extends Collection
{
public function forMembers(): self
{
return $this->filter(fn ($field) => $field->forMembers === true);
}
public function withNamiType(): self
{
return $this->filter(fn ($field) => $field->namiType !== null);
}
public function noNamiType(): self
{
return $this->filter(fn ($field) => $field->namiType === null);
}
public function noNamiField(): self
{
return $this->filter(fn ($field) => !is_a($field, NamiField::class));
}
public function hasNamiField(): bool
{
return $this->first(fn ($field) => is_a($field, NamiField::class)) !== null;
}
/**
* @return stdClass
*/
public function getMailRecipient(): ?stdClass
{
$email = $this->findBySpecialType(SpecialType::EMAIL)?->value;
return $this->getFullname() && $email
? (object) [
'name' => $this->getFullname(),
"email" => $email,
] : null;
}
public function getFullname(): ?string
{
$firstname = $this->findBySpecialType(SpecialType::FIRSTNAME)?->value;
$lastname = $this->findBySpecialType(SpecialType::LASTNAME)?->value;
return $firstname && $lastname ? "$firstname $lastname" : null;
}
/**
* @param array<string, mixed> $input
*/
public static function fromRequest(Form $form, array $input): self
{
return $form->getFields()->map(function ($field) use ($input) {
$field->value = array_key_exists($field->key, $input) ? $input[$field->key] : $field->default();
return $field;
});
}
public function find(Field $givenField): ?Field
{
return $this->findByKey($givenField->key);
}
public function findByKey(string $key): ?Field
{
return $this->first(fn ($field) => $field->key === $key);
}
/**
* @return array<string, mixed>
*/
public function present(): array
{
$attributes = collect([]);
foreach ($this as $field) {
$attributes = $attributes->merge($field->present());
}
return $attributes->toArray();
}
/**
* @return array<int, string>
*/
public function names(): array
{
return $this->map(fn ($field) => $field->name)->toArray();
}
/**
* @return array<int, string>
*/
public function presentValues(): array
{
return $this->map(fn ($field) => $field->presentRaw())->toArray();
}
private function findBySpecialType(SpecialType $specialType): ?Field
{
return $this->first(fn ($field) => $field->specialType === $specialType);
}
public function searchables(): self
{
return $this;
}
public function sortables(): self
{
return $this;
}
public function filterables(): self
{
return $this->filter(fn ($field) => $field instanceof Filterable);
}
/**
* @return array<int, string>
*/
public function getKeys(): array
{
return $this->map(fn ($field) => $field->key)->toArray();
}
}

Some files were not shown because too many files have changed in this diff Show More