aboutsummaryrefslogtreecommitdiff
path: root/app/views
diff options
context:
space:
mode:
Diffstat (limited to 'app/views')
-rw-r--r--app/views/admin/additional/index.php38
-rw-r--r--app/views/admin/api/config.php29
-rw-r--r--app/views/admin/api/edit.php129
-rw-r--r--app/views/admin/api/index.php70
-rw-r--r--app/views/admin/api/permissions.php53
-rw-r--r--app/views/admin/autoinsert/_search.php20
-rw-r--r--app/views/admin/autoinsert/_status.php17
-rw-r--r--app/views/admin/autoinsert/index.php106
-rw-r--r--app/views/admin/autoinsert/manual.php169
-rw-r--r--app/views/admin/banner/datetime-picker.php18
-rw-r--r--app/views/admin/banner/edit.php109
-rw-r--r--app/views/admin/banner/index.php69
-rw-r--r--app/views/admin/banner/info.php80
-rw-r--r--app/views/admin/banner/new.php100
-rw-r--r--app/views/admin/cache/_stats_entry.php10
-rw-r--r--app/views/admin/cache/settings.php6
-rw-r--r--app/views/admin/cache/stats.php15
-rw-r--r--app/views/admin/configuration/configuration.php31
-rw-r--r--app/views/admin/configuration/edit_configuration.php65
-rw-r--r--app/views/admin/configuration/edit_range_config.php22
-rw-r--r--app/views/admin/configuration/range_configuration.php15
-rw-r--r--app/views/admin/configuration/table-header.php14
-rw-r--r--app/views/admin/configuration/table-row.php29
-rw-r--r--app/views/admin/configuration/type-edit.php28
-rw-r--r--app/views/admin/content_terms_of_use/delete.php42
-rw-r--r--app/views/admin/content_terms_of_use/edit.php63
-rw-r--r--app/views/admin/content_terms_of_use/index.php46
-rw-r--r--app/views/admin/course_wizard_steps/edit.php43
-rw-r--r--app/views/admin/course_wizard_steps/index.php79
-rw-r--r--app/views/admin/courseplanning/index.php53
-rw-r--r--app/views/admin/courseplanning/nonconform.php28
-rw-r--r--app/views/admin/courseplanning/pick_color.php14
-rw-r--r--app/views/admin/courseplanning/rename_column.php10
-rw-r--r--app/views/admin/courseplanning/viewcolumns.php46
-rw-r--r--app/views/admin/courseplanning/weekday.php63
-rw-r--r--app/views/admin/courses/_course.php207
-rw-r--r--app/views/admin/courses/add_to_archive.php3
-rw-r--r--app/views/admin/courses/additional_inputs.php28
-rw-r--r--app/views/admin/courses/admission_locked.php6
-rw-r--r--app/views/admin/courses/aux-select.php13
-rw-r--r--app/views/admin/courses/aux_preselect.php15
-rw-r--r--app/views/admin/courses/courses.php235
-rw-r--r--app/views/admin/courses/export_csv.php16
-rw-r--r--app/views/admin/courses/get_subcourses.php3
-rw-r--r--app/views/admin/courses/index.php14
-rw-r--r--app/views/admin/courses/lock.php12
-rw-r--r--app/views/admin/courses/lock_preselect.php12
-rw-r--r--app/views/admin/courses/notice-action.php16
-rw-r--r--app/views/admin/courses/notice.php20
-rw-r--r--app/views/admin/courses/sidebar.php68
-rw-r--r--app/views/admin/courses/visibility.php6
-rw-r--r--app/views/admin/cronjobs/logs/display.php34
-rw-r--r--app/views/admin/cronjobs/logs/index.php142
-rw-r--r--app/views/admin/cronjobs/schedules/display.php78
-rw-r--r--app/views/admin/cronjobs/schedules/edit.php241
-rw-r--r--app/views/admin/cronjobs/schedules/index.php163
-rw-r--r--app/views/admin/cronjobs/schedules/parameters.php69
-rw-r--r--app/views/admin/cronjobs/schedules/periodic-schedule.php41
-rw-r--r--app/views/admin/cronjobs/tasks/execute.php14
-rw-r--r--app/views/admin/cronjobs/tasks/index.php91
-rw-r--r--app/views/admin/datafields/config.php18
-rw-r--r--app/views/admin/datafields/edit.php201
-rw-r--r--app/views/admin/datafields/index.php173
-rw-r--r--app/views/admin/datafields/new.php172
-rw-r--r--app/views/admin/datafields/preview.php17
-rw-r--r--app/views/admin/datafields/type_select.php30
-rw-r--r--app/views/admin/domain/edit.php48
-rw-r--r--app/views/admin/domain/index.php52
-rw-r--r--app/views/admin/holidays/edit.php36
-rw-r--r--app/views/admin/holidays/index.php77
-rwxr-xr-xapp/views/admin/ilias_interface/add_ilias.php26
-rwxr-xr-xapp/views/admin/ilias_interface/edit_content.php99
-rwxr-xr-xapp/views/admin/ilias_interface/edit_interface_settings.php54
-rwxr-xr-xapp/views/admin/ilias_interface/edit_permissions.php25
-rwxr-xr-xapp/views/admin/ilias_interface/edit_server.php87
-rwxr-xr-xapp/views/admin/ilias_interface/index.php94
-rwxr-xr-xapp/views/admin/ilias_interface/soap_methods.php40
-rw-r--r--app/views/admin/install/finish.php19
-rw-r--r--app/views/admin/install/index.php51
-rw-r--r--app/views/admin/install/install-basic.php42
-rw-r--r--app/views/admin/install/install.php54
-rw-r--r--app/views/admin/install/layout.php74
-rw-r--r--app/views/admin/install/mysql.php35
-rw-r--r--app/views/admin/install/mysql_check.php66
-rw-r--r--app/views/admin/install/permissions.php34
-rw-r--r--app/views/admin/install/php_check.php97
-rw-r--r--app/views/admin/install/prepare.php88
-rw-r--r--app/views/admin/install/root.php49
-rw-r--r--app/views/admin/install/session_error.php4
-rw-r--r--app/views/admin/licenses/edit.php45
-rw-r--r--app/views/admin/licenses/index.php54
-rw-r--r--app/views/admin/lockrules/_form.php98
-rw-r--r--app/views/admin/lockrules/edit.php4
-rw-r--r--app/views/admin/lockrules/index.php65
-rw-r--r--app/views/admin/lockrules/new.php5
-rw-r--r--app/views/admin/login_style/index.php64
-rw-r--r--app/views/admin/login_style/newpic.php33
-rw-r--r--app/views/admin/lti/edit.php71
-rw-r--r--app/views/admin/lti/index.php59
-rw-r--r--app/views/admin/overlapping/admin_info.php27
-rw-r--r--app/views/admin/overlapping/conflicts.php96
-rw-r--r--app/views/admin/overlapping/courses.php32
-rw-r--r--app/views/admin/overlapping/index.php7
-rw-r--r--app/views/admin/overlapping/modul.php29
-rw-r--r--app/views/admin/overlapping/overlapping.php31
-rw-r--r--app/views/admin/overlapping/selection.php69
-rw-r--r--app/views/admin/plugin/activation-error-form.php32
-rw-r--r--app/views/admin/plugin/default_activation.php45
-rw-r--r--app/views/admin/plugin/edit_automaticupdate.php64
-rw-r--r--app/views/admin/plugin/index.php200
-rw-r--r--app/views/admin/plugin/manifest.php25
-rw-r--r--app/views/admin/plugin/search.php91
-rw-r--r--app/views/admin/plugin/unregistered.php41
-rw-r--r--app/views/admin/plugin/update_info.php26
-rw-r--r--app/views/admin/plugin/upload-drag-and-drop.php8
-rw-r--r--app/views/admin/role/add.php21
-rw-r--r--app/views/admin/role/add_plugin.php32
-rw-r--r--app/views/admin/role/assign_plugin_role.php70
-rw-r--r--app/views/admin/role/assign_role.php134
-rw-r--r--app/views/admin/role/assign_role_institutes.php39
-rw-r--r--app/views/admin/role/index.php58
-rw-r--r--app/views/admin/role/show_role.php216
-rw-r--r--app/views/admin/sem_classes/_sem_type.php31
-rw-r--r--app/views/admin/sem_classes/add_sem_type.php28
-rw-r--r--app/views/admin/sem_classes/content_plugin.php19
-rw-r--r--app/views/admin/sem_classes/details.php267
-rw-r--r--app/views/admin/sem_classes/overview.php53
-rw-r--r--app/views/admin/semester/edit.php103
-rw-r--r--app/views/admin/semester/index.php155
-rw-r--r--app/views/admin/semester/lock.php44
-rw-r--r--app/views/admin/smileys/edit.php58
-rw-r--r--app/views/admin/smileys/index.php86
-rw-r--r--app/views/admin/smileys/statistics.php13
-rw-r--r--app/views/admin/smileys/upload.php40
-rw-r--r--app/views/admin/specification/_field.php36
-rw-r--r--app/views/admin/specification/edit.php90
-rw-r--r--app/views/admin/specification/index.php56
-rw-r--r--app/views/admin/statusgroups/_edit_subgroupselect.php9
-rw-r--r--app/views/admin/statusgroups/_group-nestable.php10
-rw-r--r--app/views/admin/statusgroups/_group.php61
-rw-r--r--app/views/admin/statusgroups/_members.php21
-rw-r--r--app/views/admin/statusgroups/delete.php17
-rw-r--r--app/views/admin/statusgroups/deleteGroup.php17
-rw-r--r--app/views/admin/statusgroups/editGroup.php76
-rw-r--r--app/views/admin/statusgroups/index.php6
-rw-r--r--app/views/admin/statusgroups/sortAlphabetic.php17
-rw-r--r--app/views/admin/statusgroups/sortGroups.php20
-rw-r--r--app/views/admin/user/_activities_no_courses.php3
-rw-r--r--app/views/admin/user/_course_files.php76
-rw-r--r--app/views/admin/user/_course_list.php60
-rw-r--r--app/views/admin/user/_delete.php70
-rw-r--r--app/views/admin/user/_institute_files.php58
-rw-r--r--app/views/admin/user/_priority_list.php47
-rw-r--r--app/views/admin/user/_results.php241
-rw-r--r--app/views/admin/user/_waiting_list.php49
-rw-r--r--app/views/admin/user/activities.php74
-rw-r--r--app/views/admin/user/edit.php611
-rw-r--r--app/views/admin/user/edit_institute.php65
-rw-r--r--app/views/admin/user/index.php214
-rw-r--r--app/views/admin/user/list_files.php58
-rw-r--r--app/views/admin/user/lock_comment.php17
-rw-r--r--app/views/admin/user/migrate.php55
-rw-r--r--app/views/admin/user/new.php212
-rw-r--r--app/views/admin/webservice_access/index.php82
-rw-r--r--app/views/admin/webservice_access/test.php38
-rw-r--r--app/views/admission/courseset/_institute_choose.php68
-rw-r--r--app/views/admission/courseset/applications_list.php21
-rw-r--r--app/views/admission/courseset/configure.php244
-rw-r--r--app/views/admission/courseset/configure_courses.php77
-rw-r--r--app/views/admission/courseset/delete.php7
-rw-r--r--app/views/admission/courseset/factored_users.php18
-rw-r--r--app/views/admission/courseset/index.php102
-rw-r--r--app/views/admission/courseset/instcourses.php62
-rw-r--r--app/views/admission/courseset/institutes.php17
-rw-r--r--app/views/admission/restricted_courses/_institute_choose.php39
-rw-r--r--app/views/admission/restricted_courses/index.php49
-rw-r--r--app/views/admission/rule/configure.php14
-rw-r--r--app/views/admission/rule/save.php16
-rw-r--r--app/views/admission/rule/select_type.php30
-rw-r--r--app/views/admission/rule/validate.php5
-rw-r--r--app/views/admission/rule_administration/check_activation.php100
-rw-r--r--app/views/admission/rule_administration/compatibility.php55
-rw-r--r--app/views/admission/rule_administration/index.php54
-rw-r--r--app/views/admission/user_list/configure.php103
-rw-r--r--app/views/admission/user_list/delete.php9
-rw-r--r--app/views/admission/user_list/index.php49
-rw-r--r--app/views/api/authorizations/index.php44
-rw-r--r--app/views/api/oauth/authorize.php33
-rw-r--r--app/views/api/oauth/authorized.php0
-rw-r--r--app/views/archive/forum.php5
-rw-r--r--app/views/archive/overview.php5
-rw-r--r--app/views/archive/wiki.php5
-rw-r--r--app/views/avatar/update.php65
-rw-r--r--app/views/bb/index.php39
-rw-r--r--app/views/blubber/add_member_to_private.php10
-rw-r--r--app/views/blubber/compose.php117
-rw-r--r--app/views/blubber/dialog.php12
-rw-r--r--app/views/blubber/index.php21
-rw-r--r--app/views/blubber/leave_private.php14
-rw-r--r--app/views/blubber/private_to_studygroup.php26
-rw-r--r--app/views/calendar/contentbox/_termin.php53
-rw-r--r--app/views/calendar/contentbox/display.php37
-rw-r--r--app/views/calendar/group/_attendees.php82
-rw-r--r--app/views/calendar/group/_tooltip.php27
-rw-r--r--app/views/calendar/group/_tooltip_year.php21
-rw-r--r--app/views/calendar/group/day.php130
-rw-r--r--app/views/calendar/group/month.php110
-rw-r--r--app/views/calendar/group/week.php146
-rw-r--r--app/views/calendar/group/year.php122
-rw-r--r--app/views/calendar/instschedule/_entry_details.php29
-rw-r--r--app/views/calendar/instschedule/index.php15
-rw-r--r--app/views/calendar/schedule/_colorpicker.php12
-rw-r--r--app/views/calendar/schedule/_dialog.php12
-rw-r--r--app/views/calendar/schedule/_entry_course.php90
-rw-r--r--app/views/calendar/schedule/_entry_inst.php59
-rw-r--r--app/views/calendar/schedule/_entry_schedule.php73
-rw-r--r--app/views/calendar/schedule/_semester_chooser.php22
-rw-r--r--app/views/calendar/schedule/entry.php9
-rw-r--r--app/views/calendar/schedule/index.php84
-rw-r--r--app/views/calendar/schedule/settings.php41
-rw-r--r--app/views/calendar/single/_attendees.php31
-rw-r--r--app/views/calendar/single/_calhead.php16
-rw-r--r--app/views/calendar/single/_calhead_label_day.php3
-rw-r--r--app/views/calendar/single/_calhead_label_week.php3
-rw-r--r--app/views/calendar/single/_day.php90
-rw-r--r--app/views/calendar/single/_day_cell.php54
-rw-r--r--app/views/calendar/single/_day_dayevents.php33
-rw-r--r--app/views/calendar/single/_day_table.php28
-rw-r--r--app/views/calendar/single/_edit_status.php48
-rw-r--r--app/views/calendar/single/_event_data.php100
-rw-r--r--app/views/calendar/single/_include_month.php132
-rw-r--r--app/views/calendar/single/_jump_to.php13
-rw-r--r--app/views/calendar/single/_select_calendar.php80
-rw-r--r--app/views/calendar/single/_select_category.php16
-rw-r--r--app/views/calendar/single/_semester_filter.php30
-rw-r--r--app/views/calendar/single/_tooltip.php113
-rw-r--r--app/views/calendar/single/day.php17
-rw-r--r--app/views/calendar/single/edit.php456
-rw-r--r--app/views/calendar/single/edit_status.php3
-rw-r--r--app/views/calendar/single/event.php1
-rw-r--r--app/views/calendar/single/export_calendar.php56
-rw-r--r--app/views/calendar/single/import.php28
-rw-r--r--app/views/calendar/single/manage_access.php99
-rw-r--r--app/views/calendar/single/month.php111
-rw-r--r--app/views/calendar/single/seminar_events.php104
-rw-r--r--app/views/calendar/single/share.php62
-rw-r--r--app/views/calendar/single/week.php201
-rw-r--r--app/views/calendar/single/year.php139
-rw-r--r--app/views/calendar/stylesheet.php13
-rw-r--r--app/views/consultation/admin/book.php48
-rw-r--r--app/views/consultation/admin/cancel_block.php38
-rw-r--r--app/views/consultation/admin/cancel_slot.php50
-rw-r--r--app/views/consultation/admin/cancel_slots.php57
-rw-r--r--app/views/consultation/admin/create.php191
-rw-r--r--app/views/consultation/admin/edit_room.php21
-rw-r--r--app/views/consultation/admin/index.php202
-rw-r--r--app/views/consultation/admin/note.php32
-rw-r--r--app/views/consultation/admin/reason.php20
-rw-r--r--app/views/consultation/admin/tab.php17
-rw-r--r--app/views/consultation/admin/ungrouped.php281
-rw-r--r--app/views/consultation/block-description.php28
-rw-r--r--app/views/consultation/export/print.php144
-rw-r--r--app/views/consultation/overview/book.php49
-rw-r--r--app/views/consultation/overview/booked.php58
-rw-r--r--app/views/consultation/overview/cancel.php30
-rw-r--r--app/views/consultation/overview/index.php71
-rw-r--r--app/views/consultation/overview/ungrouped.php97
-rw-r--r--app/views/consultation/slot-bookings.php33
-rw-r--r--app/views/consultation/slot-details.php7
-rw-r--r--app/views/consultation/slot-occupation.php27
-rw-r--r--app/views/contact/editGroup.php26
-rw-r--r--app/views/contact/index.php118
-rw-r--r--app/views/contact/vcard.php1
-rwxr-xr-xapp/views/contents/courseware/bookmarks.php29
-rw-r--r--app/views/contents/courseware/courses_overview.php34
-rwxr-xr-xapp/views/contents/courseware/courseware.php8
-rwxr-xr-xapp/views/contents/courseware/courseware_manager.php1
-rwxr-xr-xapp/views/contents/courseware/create_project.php125
-rwxr-xr-xapp/views/contents/courseware/index.php40
-rwxr-xr-xapp/views/contents/overview/index.php23
-rw-r--r--app/views/course/admission/_change_admission.php13
-rw-r--r--app/views/course/admission/edit_courseset.php1
-rw-r--r--app/views/course/admission/index.php233
-rw-r--r--app/views/course/admission/instant_course_set.php20
-rw-r--r--app/views/course/archive/archive.php43
-rw-r--r--app/views/course/archive/confirm.php77
-rw-r--r--app/views/course/basicdata/_input.php101
-rw-r--r--app/views/course/basicdata/view.php336
-rw-r--r--app/views/course/block_appointments/index.php153
-rw-r--r--app/views/course/cancel_dates/index.php31
-rw-r--r--app/views/course/courseware/action_widget.php1
-rwxr-xr-xapp/views/course/courseware/dashboard.php9
-rwxr-xr-xapp/views/course/courseware/index.php9
-rwxr-xr-xapp/views/course/courseware/manager.php1
-rwxr-xr-xapp/views/course/courseware/view_widget.php1
-rw-r--r--app/views/course/dates/_date_row-exdate.php29
-rw-r--r--app/views/course/dates/_date_row.php75
-rw-r--r--app/views/course/dates/_topic_li.php11
-rw-r--r--app/views/course/dates/create_folders.php50
-rw-r--r--app/views/course/dates/details-edit.php166
-rw-r--r--app/views/course/dates/details.php98
-rw-r--r--app/views/course/dates/export.php72
-rw-r--r--app/views/course/dates/index.php101
-rw-r--r--app/views/course/dates/new_topic.php48
-rw-r--r--app/views/course/dates/singledate.php57
-rw-r--r--app/views/course/details/index.php506
-rw-r--r--app/views/course/elearning/edit.php142
-rw-r--r--app/views/course/elearning/show.php42
-rw-r--r--app/views/course/enrolment/_priocourses.php134
-rw-r--r--app/views/course/enrolment/apply.php63
-rw-r--r--app/views/course/enrolment/prelim.php18
-rw-r--r--app/views/course/feedback/_add_edit_entry_form.php28
-rw-r--r--app/views/course/feedback/_entry.php48
-rw-r--r--app/views/course/feedback/_feedback.php47
-rw-r--r--app/views/course/feedback/_feedback_stream.php36
-rw-r--r--app/views/course/feedback/_new_edit_feedback_form.php46
-rw-r--r--app/views/course/feedback/_results.php63
-rw-r--r--app/views/course/feedback/config.php33
-rw-r--r--app/views/course/feedback/create_form.php8
-rw-r--r--app/views/course/feedback/edit_form.php8
-rw-r--r--app/views/course/feedback/entry_edit_form.php6
-rw-r--r--app/views/course/feedback/index.php116
-rw-r--r--app/views/course/feedback/index_for.php22
-rw-r--r--app/views/course/gradebook/_progress.php3
-rw-r--r--app/views/course/gradebook/lecturers/_weight.php7
-rw-r--r--app/views/course/gradebook/lecturers/custom_definitions.php74
-rw-r--r--app/views/course/gradebook/lecturers/edit_custom_definition.php14
-rw-r--r--app/views/course/gradebook/lecturers/edit_custom_definitions.php66
-rw-r--r--app/views/course/gradebook/lecturers/index.php74
-rw-r--r--app/views/course/gradebook/lecturers/new_custom_definition.php14
-rw-r--r--app/views/course/gradebook/lecturers/weights.php27
-rw-r--r--app/views/course/gradebook/students/index.php58
-rw-r--r--app/views/course/grouping/_perm_level.php137
-rw-r--r--app/views/course/grouping/child_course_members.php21
-rw-r--r--app/views/course/grouping/children.php39
-rw-r--r--app/views/course/grouping/create_children.php51
-rw-r--r--app/views/course/grouping/find_members_to_add.php20
-rw-r--r--app/views/course/grouping/members.php87
-rw-r--r--app/views/course/grouping/move_members_target.php23
-rw-r--r--app/views/course/grouping/parent.php44
-rw-r--r--app/views/course/grouping/parent_only_members.php21
-rwxr-xr-xapp/views/course/ilias_interface/add_groups.php32
-rwxr-xr-xapp/views/course/ilias_interface/add_object.php130
-rwxr-xr-xapp/views/course/ilias_interface/edit_moduletitle.php11
-rwxr-xr-xapp/views/course/ilias_interface/edit_object_assignment.php30
-rwxr-xr-xapp/views/course/ilias_interface/index.php129
-rwxr-xr-xapp/views/course/ilias_interface/view_object.php23
-rw-r--r--app/views/course/lti/add_link.php15
-rw-r--r--app/views/course/lti/config.php20
-rw-r--r--app/views/course/lti/edit.php110
-rw-r--r--app/views/course/lti/grades.php39
-rw-r--r--app/views/course/lti/grades_user.php33
-rw-r--r--app/views/course/lti/iframe.php17
-rw-r--r--app/views/course/lti/index.php67
-rw-r--r--app/views/course/lti/outcome.php32
-rw-r--r--app/views/course/lvgselector/entry.php45
-rw-r--r--app/views/course/lvgselector/entry_trails.php11
-rw-r--r--app/views/course/lvgselector/form.php64
-rw-r--r--app/views/course/lvgselector/index.php100
-rw-r--r--app/views/course/lvgselector/locked_form.php23
-rw-r--r--app/views/course/lvgselector/selected_entries.php11
-rw-r--r--app/views/course/lvgselector/selected_entry.php28
-rw-r--r--app/views/course/lvgselector/subtree.php23
-rw-r--r--app/views/course/lvgselector/tree.php27
-rw-r--r--app/views/course/management/index.php25
-rw-r--r--app/views/course/management/lock.php26
-rw-r--r--app/views/course/members/_studycourse.php21
-rw-r--r--app/views/course/members/accepted_list.php176
-rw-r--r--app/views/course/members/add_comment.php19
-rw-r--r--app/views/course/members/add_dozent.php37
-rw-r--r--app/views/course/members/add_member.php99
-rw-r--r--app/views/course/members/add_tutor.php34
-rw-r--r--app/views/course/members/additional.php34
-rw-r--r--app/views/course/members/additional_input.php30
-rw-r--r--app/views/course/members/autor_list.php225
-rw-r--r--app/views/course/members/awaiting_list.php163
-rw-r--r--app/views/course/members/csv_manual_assignment.php43
-rw-r--r--app/views/course/members/dozent_list.php119
-rw-r--r--app/views/course/members/import_autorlist.php46
-rw-r--r--app/views/course/members/index.php36
-rw-r--r--app/views/course/members/select_course.php32
-rw-r--r--app/views/course/members/tutor_list.php186
-rw-r--r--app/views/course/members/user_list.php186
-rw-r--r--app/views/course/overview/index.php81
-rw-r--r--app/views/course/plus/edittool.php25
-rw-r--r--app/views/course/plus/index.php268
-rw-r--r--app/views/course/plus/sorttools.php15
-rw-r--r--app/views/course/room_requests/_request.php1
-rw-r--r--app/views/course/room_requests/_request_edit_header.php22
-rw-r--r--app/views/course/room_requests/_request_form_footer.php28
-rw-r--r--app/views/course/room_requests/_request_form_header.php4
-rw-r--r--app/views/course/room_requests/index.php144
-rw-r--r--app/views/course/room_requests/new.php47
-rw-r--r--app/views/course/room_requests/request_select_properties.php65
-rw-r--r--app/views/course/room_requests/request_select_room.php78
-rw-r--r--app/views/course/room_requests/request_start.php85
-rw-r--r--app/views/course/room_requests/request_summary.php102
-rw-r--r--app/views/course/scm/edit.php61
-rw-r--r--app/views/course/scm/index.php35
-rw-r--r--app/views/course/statusgroups/_askcancel_members.php16
-rw-r--r--app/views/course/statusgroups/_askdelete_groups.php22
-rw-r--r--app/views/course/statusgroups/_askdelete_members.php17
-rw-r--r--app/views/course/statusgroups/_copy_members.php25
-rw-r--r--app/views/course/statusgroups/_edit_groups_selfassign.php42
-rw-r--r--app/views/course/statusgroups/_edit_groups_size.php24
-rw-r--r--app/views/course/statusgroups/_group.php142
-rw-r--r--app/views/course/statusgroups/_member.php85
-rw-r--r--app/views/course/statusgroups/_move_members.php25
-rw-r--r--app/views/course/statusgroups/batch_action.php28
-rw-r--r--app/views/course/statusgroups/create_groups.php146
-rw-r--r--app/views/course/statusgroups/edit.php117
-rw-r--r--app/views/course/statusgroups/getgroup.php134
-rw-r--r--app/views/course/statusgroups/groupinfo.php101
-rw-r--r--app/views/course/statusgroups/index.php43
-rw-r--r--app/views/course/statusgroups/joinables.php18
-rw-r--r--app/views/course/statusgroups/move_member.php2
-rw-r--r--app/views/course/study_areas/show.php14
-rw-r--r--app/views/course/studygroup/_choose_founders.php43
-rw-r--r--app/views/course/studygroup/_feedback.php15
-rw-r--r--app/views/course/studygroup/_members_gallery.php32
-rw-r--r--app/views/course/studygroup/_members_list.php92
-rw-r--r--app/views/course/studygroup/_members_options.php17
-rw-r--r--app/views/course/studygroup/_replace_founder.php28
-rw-r--r--app/views/course/studygroup/details.php31
-rw-r--r--app/views/course/studygroup/edit.php54
-rw-r--r--app/views/course/studygroup/globalmodules.php80
-rw-r--r--app/views/course/studygroup/members.php161
-rw-r--r--app/views/course/timesrooms/_cancel_form.php19
-rw-r--r--app/views/course/timesrooms/_cycleRow.php148
-rw-r--r--app/views/course/timesrooms/_irregularEvents.php138
-rw-r--r--app/views/course/timesrooms/_regularEvents.php185
-rw-r--r--app/views/course/timesrooms/_roomRequest.php33
-rw-r--r--app/views/course/timesrooms/_roomRequestInfo.php14
-rw-r--r--app/views/course/timesrooms/_select_semester_range.php14
-rw-r--r--app/views/course/timesrooms/_stack_actions.php6
-rw-r--r--app/views/course/timesrooms/cancel.php9
-rw-r--r--app/views/course/timesrooms/cancelStack.php15
-rw-r--r--app/views/course/timesrooms/createCycle.php135
-rw-r--r--app/views/course/timesrooms/createSingleDate.php101
-rw-r--r--app/views/course/timesrooms/editDate.php239
-rw-r--r--app/views/course/timesrooms/editSemester.php43
-rw-r--r--app/views/course/timesrooms/editStack.php134
-rw-r--r--app/views/course/timesrooms/index.php32
-rw-r--r--app/views/course/topics/_topiclist.php6
-rw-r--r--app/views/course/topics/copy.php39
-rw-r--r--app/views/course/topics/edit.php94
-rw-r--r--app/views/course/topics/index.php124
-rw-r--r--app/views/course/wizard/ajax.php1
-rw-r--r--app/views/course/wizard/step.php29
-rw-r--r--app/views/course/wizard/steps/advancedbasicdata/index.php26
-rw-r--r--app/views/course/wizard/steps/basicdata/_institute.php5
-rw-r--r--app/views/course/wizard/steps/basicdata/_user.php5
-rw-r--r--app/views/course/wizard/steps/basicdata/index.php179
-rw-r--r--app/views/course/wizard/steps/basicdata/index_studygroup.php79
-rw-r--r--app/views/course/wizard/steps/lvgroups/_node.php42
-rw-r--r--app/views/course/wizard/steps/lvgroups/index.php93
-rw-r--r--app/views/course/wizard/steps/lvgroups/lvgroup_entry.php23
-rw-r--r--app/views/course/wizard/steps/lvgroups/lvgroup_searchentry.php19
-rw-r--r--app/views/course/wizard/steps/studyareas/_assigned_node.php12
-rw-r--r--app/views/course/wizard/steps/studyareas/_node.php30
-rw-r--r--app/views/course/wizard/steps/studyareas/index.php89
-rw-r--r--app/views/course/wizard/summary.php52
-rw-r--r--app/views/dialog/confirm_dialog.php13
-rw-r--r--app/views/elearning/my_accounts.php48
-rw-r--r--app/views/evaluation/_actions.php4
-rw-r--r--app/views/evaluation/_admin_list_vote.php27
-rw-r--r--app/views/evaluation/_buttons.php22
-rw-r--r--app/views/evaluation/_evaluation.php57
-rw-r--r--app/views/evaluation/display.php27
-rw-r--r--app/views/event_log/admin.php50
-rw-r--r--app/views/event_log/edit.php45
-rw-r--r--app/views/event_log/show.php135
-rw-r--r--app/views/fachabschluss/abschluesse/abschluss.php47
-rw-r--r--app/views/fachabschluss/abschluesse/details.php28
-rw-r--r--app/views/fachabschluss/abschluesse/index.php76
-rw-r--r--app/views/fachabschluss/faecher/details.php23
-rw-r--r--app/views/fachabschluss/faecher/details_fachbereich.php22
-rw-r--r--app/views/fachabschluss/faecher/fach.php110
-rw-r--r--app/views/fachabschluss/faecher/fachbereiche.php29
-rw-r--r--app/views/fachabschluss/faecher/index.php74
-rw-r--r--app/views/fachabschluss/kategorien/details.php16
-rw-r--r--app/views/fachabschluss/kategorien/index.php75
-rw-r--r--app/views/fachabschluss/kategorien/kategorie.php59
-rw-r--r--app/views/file/_file_aside.php62
-rw-r--r--app/views/file/_folder_aside.php37
-rw-r--r--app/views/file/_terms_of_use_select.php49
-rw-r--r--app/views/file/add_files_window.php100
-rw-r--r--app/views/file/add_from_library.php177
-rw-r--r--app/views/file/add_url.php43
-rw-r--r--app/views/file/choose_destination.php100
-rw-r--r--app/views/file/choose_file.php177
-rw-r--r--app/views/file/choose_file_from_course.php66
-rw-r--r--app/views/file/choose_folder.php211
-rw-r--r--app/views/file/choose_folder_from_course.php74
-rw-r--r--app/views/file/choose_folder_from_institute.php75
-rw-r--r--app/views/file/edit.php56
-rw-r--r--app/views/file/edit_folder.php25
-rw-r--r--app/views/file/edit_license.php26
-rw-r--r--app/views/file/edit_urlfile.php73
-rw-r--r--app/views/file/file_details.php55
-rw-r--r--app/views/file/folder_details.php38
-rw-r--r--app/views/file/link.php1
-rw-r--r--app/views/file/new_edit_folder_form.php55
-rw-r--r--app/views/file/new_folder.php16
-rw-r--r--app/views/file/unzipquestion.php15
-rw-r--r--app/views/file/update.php40
-rw-r--r--app/views/file/upload_window.php18
-rw-r--r--app/views/files/_fileref_tr.php93
-rw-r--r--app/views/files/_files_thead.php48
-rw-r--r--app/views/files/_flat_tfoot.php58
-rw-r--r--app/views/files/_folder_tr.php126
-rw-r--r--app/views/files/_overview.php107
-rw-r--r--app/views/files/all_files.php51
-rw-r--r--app/views/files/configure.php8
-rw-r--r--app/views/files/flat.php101
-rw-r--r--app/views/files/index.php119
-rw-r--r--app/views/files/my_public_files.php34
-rw-r--r--app/views/files/my_uploaded_files.php38
-rw-r--r--app/views/files/overview.php5
-rw-r--r--app/views/files/upload-drag-and-drop.php3
-rw-r--r--app/views/files_dashboard/_input-group-search.php20
-rw-r--r--app/views/files_dashboard/_search_active_filters.php43
-rw-r--r--app/views/files_dashboard/_search_time.php7
-rw-r--r--app/views/files_dashboard/_search_tr.php97
-rw-r--r--app/views/files_dashboard/search.php91
-rw-r--r--app/views/global_search/settings.php92
-rw-r--r--app/views/help_content/admin_conflicts.php44
-rw-r--r--app/views/help_content/admin_overview.php62
-rw-r--r--app/views/help_content/delete.php21
-rw-r--r--app/views/help_content/edit.php43
-rw-r--r--app/views/institute/basicdata/index.php152
-rw-r--r--app/views/institute/members/_table_body.php173
-rw-r--r--app/views/institute/members/index.php35
-rw-r--r--app/views/institute/overview/index.php69
-rw-r--r--app/views/library_file/_add_edit_form.php52
-rw-r--r--app/views/library_file/create.php14
-rw-r--r--app/views/library_file/edit.php8
-rw-r--r--app/views/library_file/select_type.php21
-rw-r--r--app/views/localizations/show.php44
-rw-r--r--app/views/lvgruppen/lvgruppen/details.php151
-rw-r--r--app/views/lvgruppen/lvgruppen/export_xls.php39
-rw-r--r--app/views/lvgruppen/lvgruppen/index.php101
-rw-r--r--app/views/lvgruppen/lvgruppen/lvgruppe.php27
-rw-r--r--app/views/lvgruppen/lvgruppen/trails_table_lvgruppe.php26
-rw-r--r--app/views/materialien/files/add_dokument.php130
-rw-r--r--app/views/materialien/files/add_files_to_range.php17
-rw-r--r--app/views/materialien/files/add_ranges_to_file.php37
-rw-r--r--app/views/materialien/files/details.php82
-rw-r--r--app/views/materialien/files/index.php129
-rw-r--r--app/views/materialien/files/new_dokument.php17
-rw-r--r--app/views/materialien/files/range.php113
-rw-r--r--app/views/materialien/files/select_range.php25
-rw-r--r--app/views/materialien/files/select_range_type.php17
-rw-r--r--app/views/materialien/files/sort.php28
-rw-r--r--app/views/messages/_message_row.php52
-rw-r--r--app/views/messages/overview.php102
-rw-r--r--app/views/messages/print.php30
-rw-r--r--app/views/messages/read.php102
-rw-r--r--app/views/messages/send.php5
-rw-r--r--app/views/messages/write.php179
-rw-r--r--app/views/module/download/doc.php60
-rw-r--r--app/views/module/download/pdf.php33
-rw-r--r--app/views/module/institute/details.php17
-rw-r--r--app/views/module/institute/index.php35
-rw-r--r--app/views/module/modul_teile/index.php3
-rw-r--r--app/views/module/module/approve.php12
-rw-r--r--app/views/module/module/assignments.php13
-rw-r--r--app/views/module/module/copy_form.php95
-rw-r--r--app/views/module/module/details.php87
-rw-r--r--app/views/module/module/diff.php172
-rw-r--r--app/views/module/module/diff_select.php44
-rw-r--r--app/views/module/module/index.php38
-rw-r--r--app/views/module/module/lvgruppe.php28
-rw-r--r--app/views/module/module/modul.php699
-rw-r--r--app/views/module/module/module.php125
-rw-r--r--app/views/module/module/modulteil.php483
-rw-r--r--app/views/module/module/modulteil_lvg.php66
-rw-r--r--app/views/multipersonsearch/js_form.php56
-rw-r--r--app/views/multipersonsearch/no_js_form.php88
-rw-r--r--app/views/my_courses/_course.php142
-rw-r--r--app/views/my_courses/_deputy_bosses.php48
-rw-r--r--app/views/my_courses/_dozent.php4
-rw-r--r--app/views/my_courses/_exportcourse.php80
-rw-r--r--app/views/my_courses/archive.php76
-rw-r--r--app/views/my_courses/courseexport.php32
-rw-r--r--app/views/my_courses/groups.php59
-rw-r--r--app/views/my_courses/index.php11
-rw-r--r--app/views/my_courses/waiting_list.php102
-rwxr-xr-xapp/views/my_ilias_accounts/_ilias_module.php67
-rwxr-xr-xapp/views/my_ilias_accounts/add_object.php27
-rwxr-xr-xapp/views/my_ilias_accounts/index.php149
-rwxr-xr-xapp/views/my_ilias_accounts/new_account.php15
-rwxr-xr-xapp/views/my_ilias_accounts/redirect.php0
-rwxr-xr-xapp/views/my_ilias_accounts/view_object.php11
-rw-r--r--app/views/my_institutes/index.php110
-rw-r--r--app/views/my_studygroups/_course.php66
-rw-r--r--app/views/my_studygroups/index.php30
-rw-r--r--app/views/new_password/index.php18
-rw-r--r--app/views/new_password/send_mail.php5
-rw-r--r--app/views/new_password/set.php23
-rw-r--r--app/views/news/_actions.php53
-rw-r--r--app/views/news/_commentbox.php9
-rw-r--r--app/views/news/_comments.php40
-rw-r--r--app/views/news/admin_news.php168
-rw-r--r--app/views/news/display.php72
-rw-r--r--app/views/news/edit_news.php283
-rw-r--r--app/views/news/rss_config.php9
-rw-r--r--app/views/oer/addfile/choose_file.php23
-rwxr-xr-xapp/views/oer/admin/add_new_host.php10
-rwxr-xr-xapp/views/oer/admin/hosts.php120
-rw-r--r--app/views/oer/embed/_link.php7
-rw-r--r--app/views/oer/embed/audio.php13
-rw-r--r--app/views/oer/embed/standard.php4
-rw-r--r--app/views/oer/embed/url.php11
-rw-r--r--app/views/oer/embed/video.php6
-rwxr-xr-xapp/views/oer/endpoints/index.php66
-rwxr-xr-xapp/views/oer/market/_details_file.php21
-rwxr-xr-xapp/views/oer/market/_material_short.php31
-rwxr-xr-xapp/views/oer/market/_materials.php3
-rw-r--r--app/views/oer/market/_searchform.php175
-rw-r--r--app/views/oer/market/abo.php15
-rwxr-xr-xapp/views/oer/market/add_to_course.php50
-rw-r--r--app/views/oer/market/add_to_course_select_class.php19
-rwxr-xr-xapp/views/oer/market/details.php366
-rwxr-xr-xapp/views/oer/market/discussion.php35
-rw-r--r--app/views/oer/market/embed.php30
-rwxr-xr-xapp/views/oer/market/index.php68
-rwxr-xr-xapp/views/oer/market/licenseinfo.php37
-rwxr-xr-xapp/views/oer/market/profile.php26
-rwxr-xr-xapp/views/oer/market/review.php17
-rw-r--r--app/views/oer/market/search.php19
-rw-r--r--app/views/oer/market/type.php7
-rwxr-xr-xapp/views/oer/mymaterial/_material_list.php68
-rwxr-xr-xapp/views/oer/mymaterial/edit.php276
-rwxr-xr-xapp/views/oer/mymaterial/index.php5
-rw-r--r--app/views/oer/mymaterial/statistics.php20
-rwxr-xr-xapp/views/oer/oai/badPrefix.php9
-rwxr-xr-xapp/views/oer/oai/badVerb.php9
-rwxr-xr-xapp/views/oer/oai/getRecord.php97
-rwxr-xr-xapp/views/oer/oai/idNotExists.php9
-rwxr-xr-xapp/views/oer/oai/identify.php20
-rwxr-xr-xapp/views/oer/oai/listIdentifiers.php43
-rwxr-xr-xapp/views/oer/oai/listMetadataFormats.php28
-rwxr-xr-xapp/views/oer/oai/listRecords.php105
-rwxr-xr-xapp/views/oer/oai/listSets.php17
-rwxr-xr-xapp/views/oer/oai/noRecordsMatch.php10
-rwxr-xr-xapp/views/oer/oai/noSets.php9
-rw-r--r--app/views/online/index.php128
-rw-r--r--app/views/online/user-row.php52
-rw-r--r--app/views/privacy/index.php54
-rw-r--r--app/views/privacy/landing.php22
-rw-r--r--app/views/privacy/print.php25
-rw-r--r--app/views/profile/extern.php16
-rw-r--r--app/views/profile/index.php150
-rw-r--r--app/views/profile/not_available.php4
-rw-r--r--app/views/profile/public_files.php42
-rw-r--r--app/views/profile/seminare.php22
-rw-r--r--app/views/profile/widget-avatar.php34
-rw-r--r--app/views/profile/working_place.php45
-rw-r--r--app/views/profile_modules/index.php102
-rw-r--r--app/views/public_courses/index.php78
-rw-r--r--app/views/questionnaire/_overview_questionnaire.php130
-rw-r--r--app/views/questionnaire/_question.php28
-rw-r--r--app/views/questionnaire/_widget_questionnaire.php55
-rw-r--r--app/views/questionnaire/add_to_context.php23
-rw-r--r--app/views/questionnaire/answer.php62
-rw-r--r--app/views/questionnaire/assign.php82
-rw-r--r--app/views/questionnaire/assign_step1.php70
-rw-r--r--app/views/questionnaire/assign_step2.php84
-rw-r--r--app/views/questionnaire/context.php103
-rw-r--r--app/views/questionnaire/edit.php76
-rw-r--r--app/views/questionnaire/evaluate.php59
-rw-r--r--app/views/questionnaire/overview.php45
-rwxr-xr-xapp/views/questionnaire/question_types/freetext/freetext_answer.php19
-rwxr-xr-xapp/views/questionnaire/question_types/freetext/freetext_edit.php18
-rwxr-xr-xapp/views/questionnaire/question_types/freetext/freetext_evaluation.php28
-rw-r--r--app/views/questionnaire/question_types/test/_answer.php18
-rw-r--r--app/views/questionnaire/question_types/test/test_edit.php62
-rw-r--r--app/views/questionnaire/question_types/test/test_evaluation.php122
-rw-r--r--app/views/questionnaire/question_types/vote/_answer.php10
-rw-r--r--app/views/questionnaire/question_types/vote/vote_answer.php52
-rw-r--r--app/views/questionnaire/question_types/vote/vote_edit.php59
-rw-r--r--app/views/questionnaire/question_types/vote/vote_evaluation.php111
-rw-r--r--app/views/questionnaire/thank_you.php0
-rw-r--r--app/views/questionnaire/widget.php39
-rw-r--r--app/views/resources/_common/_grouped_room_list.php70
-rw-r--r--app/views/resources/_common/_permission_table.php215
-rw-r--r--app/views/resources/_common/_request_info.php103
-rw-r--r--app/views/resources/_common/_request_tr.php161
-rw-r--r--app/views/resources/_common/_resource_tr.php291
-rw-r--r--app/views/resources/_common/_resource_tree_item.php31
-rw-r--r--app/views/resources/_common/_room_search_result.php105
-rw-r--r--app/views/resources/_common/_room_thead.php21
-rw-r--r--app/views/resources/_common/_room_tr.php78
-rw-r--r--app/views/resources/_common/building.php33
-rw-r--r--app/views/resources/_common/location.php19
-rw-r--r--app/views/resources/admin/booking_log.php104
-rw-r--r--app/views/resources/admin/categories.php76
-rw-r--r--app/views/resources/admin/configuration.php118
-rw-r--r--app/views/resources/admin/global_locks.php54
-rw-r--r--app/views/resources/admin/permissions.php1
-rw-r--r--app/views/resources/admin/properties.php68
-rw-r--r--app/views/resources/admin/property_groups.php162
-rw-r--r--app/views/resources/admin/separable_rooms.php173
-rw-r--r--app/views/resources/admin/user_permissions.php213
-rw-r--r--app/views/resources/booking/_add_edit_form.php606
-rw-r--r--app/views/resources/booking/add.php1
-rw-r--r--app/views/resources/booking/add_from_request.php50
-rw-r--r--app/views/resources/booking/copy.php51
-rw-r--r--app/views/resources/booking/copy_to_semester.php42
-rw-r--r--app/views/resources/booking/delete.php31
-rw-r--r--app/views/resources/booking/duplicate.php1
-rw-r--r--app/views/resources/booking/edit.php33
-rw-r--r--app/views/resources/booking/index.php175
-rw-r--r--app/views/resources/booking/move.php55
-rw-r--r--app/views/resources/building/_add_edit_form.php68
-rw-r--r--app/views/resources/building/add.php1
-rw-r--r--app/views/resources/building/delete.php13
-rw-r--r--app/views/resources/building/edit.php1
-rw-r--r--app/views/resources/building/index.php113
-rw-r--r--app/views/resources/building/lock.php21
-rw-r--r--app/views/resources/building/new.php1
-rw-r--r--app/views/resources/building/select_category.php18
-rw-r--r--app/views/resources/category/_add_edit_form.php157
-rw-r--r--app/views/resources/category/add.php1
-rw-r--r--app/views/resources/category/delete.php52
-rw-r--r--app/views/resources/category/details.php33
-rw-r--r--app/views/resources/category/edit.php1
-rw-r--r--app/views/resources/category/show_resources.php36
-rw-r--r--app/views/resources/export/resource_bookings.php38
-rw-r--r--app/views/resources/export/select_booking_sources.php106
-rw-r--r--app/views/resources/global_locks/_add_edit_form.php45
-rw-r--r--app/views/resources/global_locks/add.php6
-rw-r--r--app/views/resources/global_locks/delete.php24
-rw-r--r--app/views/resources/global_locks/edit.php8
-rw-r--r--app/views/resources/location/_add_edit_form.php48
-rw-r--r--app/views/resources/location/add.php1
-rw-r--r--app/views/resources/location/delete.php13
-rw-r--r--app/views/resources/location/edit.php1
-rw-r--r--app/views/resources/location/index.php87
-rw-r--r--app/views/resources/location/select_category.php18
-rw-r--r--app/views/resources/messages/index.php143
-rw-r--r--app/views/resources/print/clipboard_rooms.php169
-rw-r--r--app/views/resources/print/individual_booking_plan.php36
-rw-r--r--app/views/resources/property/_add_edit_form.php67
-rw-r--r--app/views/resources/property/add.php15
-rw-r--r--app/views/resources/property/edit.php15
-rw-r--r--app/views/resources/resource/_add_edit_form.php49
-rw-r--r--app/views/resources/resource/_standard_properties_display_part.php101
-rw-r--r--app/views/resources/resource/_standard_properties_form_part.php30
-rw-r--r--app/views/resources/resource/add.php1
-rw-r--r--app/views/resources/resource/booking_plan.php53
-rw-r--r--app/views/resources/resource/delete.php11
-rw-r--r--app/views/resources/resource/delete_bookings.php36
-rw-r--r--app/views/resources/resource/edit.php1
-rw-r--r--app/views/resources/resource/export_bookings.php38
-rw-r--r--app/views/resources/resource/files.php102
-rw-r--r--app/views/resources/resource/index.php34
-rw-r--r--app/views/resources/resource/lock.php25
-rw-r--r--app/views/resources/resource/permissions.php72
-rw-r--r--app/views/resources/resource/temporary_permissions.php247
-rw-r--r--app/views/resources/room/_add_edit_form.php69
-rw-r--r--app/views/resources/room/add.php1
-rw-r--r--app/views/resources/room/delete.php14
-rw-r--r--app/views/resources/room/edit.php1
-rw-r--r--app/views/resources/room/index.php113
-rw-r--r--app/views/resources/room/select_category.php19
-rw-r--r--app/views/resources/room_group/permissions.php66
-rw-r--r--app/views/resources/room_planning/_sidebar_date_selection.php20
-rw-r--r--app/views/resources/room_planning/booking_plan.php129
-rw-r--r--app/views/resources/room_planning/overbooked_rooms.php55
-rw-r--r--app/views/resources/room_planning/semester_plan.php160
-rw-r--r--app/views/resources/room_request/_add_edit_form.php55
-rw-r--r--app/views/resources/room_request/add.php1
-rw-r--r--app/views/resources/room_request/decline.php56
-rw-r--r--app/views/resources/room_request/delete.php15
-rw-r--r--app/views/resources/room_request/edit.php1
-rw-r--r--app/views/resources/room_request/index.php3
-rw-r--r--app/views/resources/room_request/overview.php61
-rw-r--r--app/views/resources/room_request/planning.php305
-rw-r--r--app/views/resources/room_request/rerequest_booking.php23
-rw-r--r--app/views/resources/room_request/resolve.php389
-rw-r--r--app/views/resources/room_request/resolve_room_tr.php93
-rw-r--r--app/views/resources/search/rooms.php38
-rw-r--r--app/views/resources/statistics/room_load.php4
-rw-r--r--app/views/room_management/overview/buildings.php94
-rw-r--r--app/views/room_management/overview/index.php127
-rw-r--r--app/views/room_management/overview/locations.php55
-rw-r--r--app/views/room_management/overview/public_booking_plans.php4
-rw-r--r--app/views/room_management/overview/rooms.php48
-rw-r--r--app/views/room_management/overview/structure.php9
-rw-r--r--app/views/room_management/planning/booking_comments.php129
-rw-r--r--app/views/room_management/planning/booking_comments_html_export_frame.php23
-rw-r--r--app/views/room_management/planning/copy_bookings.php247
-rw-r--r--app/views/room_management/planning/index.php96
-rw-r--r--app/views/room_management/planning/semester_plan.php100
-rw-r--r--app/views/score/index.php124
-rw-r--r--app/views/search/angebot/detail.php19
-rw-r--r--app/views/search/angebot/index.php41
-rw-r--r--app/views/search/angebot/info.php2
-rw-r--r--app/views/search/archive/index.php145
-rw-r--r--app/views/search/breadcrumb.php28
-rw-r--r--app/views/search/courses/index.php2
-rw-r--r--app/views/search/globalsearch/index.php54
-rw-r--r--app/views/search/module/_drill_down_list.php58
-rw-r--r--app/views/search/module/_infobox_info.php7
-rw-r--r--app/views/search/module/_modul.php31
-rw-r--r--app/views/search/module/details.php3
-rw-r--r--app/views/search/module/index.php63
-rw-r--r--app/views/search/module/show.php158
-rw-r--r--app/views/search/stgtable/index.php32
-rw-r--r--app/views/search/studiengaenge/_studiengang.php38
-rw-r--r--app/views/search/studiengaenge/einfach.php10
-rw-r--r--app/views/search/studiengaenge/index.php16
-rw-r--r--app/views/search/studiengaenge/info.php205
-rw-r--r--app/views/search/studiengaenge/kategorie.php21
-rw-r--r--app/views/search/studiengaenge/kommentar.php1
-rw-r--r--app/views/search/studiengaenge/mehrfach.php37
-rw-r--r--app/views/search/studiengaenge/verlauf.php131
-rw-r--r--app/views/seminar/details/show_module_pathes.php24
-rw-r--r--app/views/settings/account/index.php160
-rw-r--r--app/views/settings/account/logout.php5
-rw-r--r--app/views/settings/calendar.php159
-rw-r--r--app/views/settings/categories.php80
-rw-r--r--app/views/settings/deputies.php68
-rw-r--r--app/views/settings/details.php109
-rw-r--r--app/views/settings/general.php148
-rw-r--r--app/views/settings/messaging.php122
-rw-r--r--app/views/settings/notification.php98
-rw-r--r--app/views/settings/password.php28
-rw-r--r--app/views/settings/privacy.php185
-rw-r--r--app/views/settings/statusgruppen/_optgroup.php10
-rw-r--r--app/views/settings/statusgruppen/_options.php17
-rw-r--r--app/views/settings/statusgruppen/assign.php21
-rw-r--r--app/views/settings/statusgruppen/index.php110
-rw-r--r--app/views/settings/statusgruppen/modify.php85
-rw-r--r--app/views/settings/statusgruppen/modify_institute.php85
-rw-r--r--app/views/settings/studies/index.php2
-rw-r--r--app/views/settings/studies/institute.php108
-rw-r--r--app/views/settings/studies/studiengang.php163
-rw-r--r--app/views/settings/userdomains.php117
-rw-r--r--app/views/shared/abschluss_filter.php9
-rw-r--r--app/views/shared/chooser.php14
-rw-r--r--app/views/shared/chooser_form.php18
-rw-r--r--app/views/shared/contacts/add_ansprechpartner.php135
-rw-r--r--app/views/shared/contacts/add_ranges_to_contact.php44
-rw-r--r--app/views/shared/contacts/details.php82
-rw-r--r--app/views/shared/contacts/index.php103
-rw-r--r--app/views/shared/contacts/new_ansprechpartner.php17
-rw-r--r--app/views/shared/contacts/range.php83
-rw-r--r--app/views/shared/contacts/select_range.php20
-rw-r--r--app/views/shared/contacts/select_range_type.php17
-rw-r--r--app/views/shared/contacts/sort.php28
-rw-r--r--app/views/shared/content.php1
-rw-r--r--app/views/shared/content_overlay.php1
-rw-r--r--app/views/shared/deskriptor_language.php11
-rw-r--r--app/views/shared/download/mhb.php85
-rw-r--r--app/views/shared/fachbereich_filter.php9
-rw-r--r--app/views/shared/filter.php124
-rw-r--r--app/views/shared/form_dokumente.php103
-rw-r--r--app/views/shared/include_edit.php10
-rw-r--r--app/views/shared/info_search.php11
-rw-r--r--app/views/shared/inst_chooser.php25
-rw-r--r--app/views/shared/js_url.php3
-rw-r--r--app/views/shared/kategorie_filter.php9
-rw-r--r--app/views/shared/language_chooser.php14
-rw-r--r--app/views/shared/log_event/show.php68
-rw-r--r--app/views/shared/modul/_modul.php235
-rw-r--r--app/views/shared/modul/_modul_ohne_lv.php37
-rw-r--r--app/views/shared/modul/_modullv.php102
-rw-r--r--app/views/shared/modul/_modullvs.php82
-rw-r--r--app/views/shared/modul/_pruefungen.php50
-rw-r--r--app/views/shared/modul/_regularien.php38
-rw-r--r--app/views/shared/modul/description.php22
-rw-r--r--app/views/shared/modul/overview.php180
-rw-r--r--app/views/shared/modul_variants.php11
-rw-r--r--app/views/shared/mvv_tree.php23
-rw-r--r--app/views/shared/sort_link.php18
-rw-r--r--app/views/shared/studiengang/_stgteilversion.php50
-rw-r--r--app/views/shared/studiengang/_studiengang.php251
-rw-r--r--app/views/shared/studiengang/_studiengang_info.php55
-rw-r--r--app/views/shared/studiengang/_studiengangteil.php46
-rw-r--r--app/views/shared/studiengang/description.php12
-rw-r--r--app/views/shared/trails_table.php7
-rw-r--r--app/views/shared/version/_version.php68
-rw-r--r--app/views/shared/version/_versionmodule.php115
-rw-r--r--app/views/siteinfo/delete.php28
-rw-r--r--app/views/siteinfo/edit.php58
-rw-r--r--app/views/siteinfo/help.php73
-rw-r--r--app/views/siteinfo/markup/adminList.php31
-rw-r--r--app/views/siteinfo/markup/indicator.php11
-rw-r--r--app/views/siteinfo/markup/rootlist.php17
-rw-r--r--app/views/siteinfo/markup/toplist.php25
-rw-r--r--app/views/siteinfo/markup/uniContact.php7
-rw-r--r--app/views/siteinfo/markup/userinfo.php10
-rw-r--r--app/views/siteinfo/markup/userlink.php10
-rw-r--r--app/views/siteinfo/new.php56
-rw-r--r--app/views/siteinfo/show.php6
-rw-r--r--app/views/sitemap/index.php9
-rw-r--r--app/views/sitemap/navigation.php18
-rw-r--r--app/views/smileys/index.php117
-rw-r--r--app/views/smileys/picker.php77
-rw-r--r--app/views/start/_widget.php35
-rw-r--r--app/views/start/add.php30
-rw-r--r--app/views/start/edit_defaults.php58
-rw-r--r--app/views/start/edit_mail_address.php25
-rw-r--r--app/views/start/index.php37
-rw-r--r--app/views/studiengaenge/abschluesse/index.php44
-rw-r--r--app/views/studiengaenge/abschnitte/index.php3
-rw-r--r--app/views/studiengaenge/fachbereiche/index.php45
-rw-r--r--app/views/studiengaenge/fachbereichestgteile/index.php39
-rw-r--r--app/views/studiengaenge/faecher/index.php63
-rw-r--r--app/views/studiengaenge/informationen/degree.php45
-rw-r--r--app/views/studiengaenge/informationen/index.php39
-rw-r--r--app/views/studiengaenge/informationen/showdegree.php31
-rw-r--r--app/views/studiengaenge/informationen/showstudycourse.php32
-rw-r--r--app/views/studiengaenge/kategorien/index.php45
-rw-r--r--app/views/studiengaenge/stgteilbezeichnungen/details.php67
-rw-r--r--app/views/studiengaenge/stgteilbezeichnungen/index.php68
-rw-r--r--app/views/studiengaenge/stgteilbezeichnungen/stgteilbezeichnung.php44
-rw-r--r--app/views/studiengaenge/studiengaenge/approve.php35
-rw-r--r--app/views/studiengaenge/studiengaenge/aufbaustg_edit.php23
-rw-r--r--app/views/studiengaenge/studiengaenge/aufbaustg_edit__.php12
-rw-r--r--app/views/studiengaenge/studiengaenge/aufbaustg_info.php10
-rw-r--r--app/views/studiengaenge/studiengaenge/aufbaustg_select.php19
-rw-r--r--app/views/studiengaenge/studiengaenge/aufbaustg_table.php86
-rw-r--r--app/views/studiengaenge/studiengaenge/details.php11
-rw-r--r--app/views/studiengaenge/studiengaenge/export.php57
-rw-r--r--app/views/studiengaenge/studiengaenge/index.php52
-rw-r--r--app/views/studiengaenge/studiengaenge/stgteil_bezeichnungen.php69
-rw-r--r--app/views/studiengaenge/studiengaenge/studiengaenge.php86
-rw-r--r--app/views/studiengaenge/studiengaenge/studiengang.php359
-rw-r--r--app/views/studiengaenge/studiengaenge/studiengangteile.php87
-rw-r--r--app/views/studiengaenge/studiengangteile/approve.php10
-rw-r--r--app/views/studiengaenge/studiengangteile/details.php10
-rw-r--r--app/views/studiengaenge/studiengangteile/details_grouped.php47
-rw-r--r--app/views/studiengaenge/studiengangteile/index.php115
-rw-r--r--app/views/studiengaenge/studiengangteile/stgteil.php105
-rw-r--r--app/views/studiengaenge/versionen/abschnitt.php32
-rw-r--r--app/views/studiengaenge/versionen/abschnitte.php89
-rw-r--r--app/views/studiengaenge/versionen/approve.php10
-rw-r--r--app/views/studiengaenge/versionen/details_abschnitt.php75
-rw-r--r--app/views/studiengaenge/versionen/diff.php70
-rw-r--r--app/views/studiengaenge/versionen/diff_select.php18
-rw-r--r--app/views/studiengaenge/versionen/export.php56
-rw-r--r--app/views/studiengaenge/versionen/index.php43
-rw-r--r--app/views/studiengaenge/versionen/modul_zuordnung.php41
-rw-r--r--app/views/studiengaenge/versionen/modulteil_semester.php61
-rw-r--r--app/views/studiengaenge/versionen/modulteile.php23
-rw-r--r--app/views/studiengaenge/versionen/version.php146
-rw-r--r--app/views/studiengaenge/versionen/versionen.php91
-rw-r--r--app/views/study_area/tree.php22
-rw-r--r--app/views/studygroup/browse.php105
-rw-r--r--app/views/terms/index.php32
-rw-r--r--app/views/tfa/index.php7
-rw-r--r--app/views/tfa/setup.php28
-rw-r--r--app/views/tour/admin_conflicts.php63
-rw-r--r--app/views/tour/admin_details.php192
-rw-r--r--app/views/tour/admin_overview.php105
-rw-r--r--app/views/tour/edit_step.php196
-rw-r--r--app/views/tour/import.php49
-rw-r--r--app/views/userfilter/field/configure.php35
-rw-r--r--app/views/userfilter/filter/add.php9
-rw-r--r--app/views/userfilter/filter/configure.php19
-rw-r--r--app/views/web_migrate/history.php83
-rw-r--r--app/views/web_migrate/index.php91
-rw-r--r--app/views/wiki/change_courseperms.php26
-rw-r--r--app/views/wiki/change_page_config.php74
-rw-r--r--app/views/wiki/create.php30
-rw-r--r--app/views/wiki/import.php141
-rw-r--r--app/views/wiki/info.php84
971 files changed, 60251 insertions, 0 deletions
diff --git a/app/views/admin/additional/index.php b/app/views/admin/additional/index.php
new file mode 100644
index 0000000..f906f44
--- /dev/null
+++ b/app/views/admin/additional/index.php
@@ -0,0 +1,38 @@
+<? if ($list): ?>
+ <form class='default' method='post'>
+ <fieldset>
+ <legend><?= _('Zusatzangaben') ?></legend>
+ <label>
+ <?= _('Set') ?>
+ <select name='aux_data'>
+ <option value='0'>
+ <?= '-- '._('Keine Zusatzdaten')." --" ?>
+ </option>
+ <? foreach ($list as $aux): ?>
+ <option value='<?= $aux->id ?>' <?= $course->aux_lock_rule && $course->aux->id == $aux->id ? "selected" : "" ?>>
+ <?= htmlReady($aux->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <input type='checkbox' name='forced' value='1' <?= $course->aux_lock_rule_forced ? "checked" : "" ?>>
+ <?= _('Eingaben erzwingen') ?>
+ </label>
+
+ <? if($count): ?>
+ <label>
+ <input type='checkbox' name='delete' value='1'>
+ <?= $count." "._('Datensätze vorhanden') ?> -
+ <?= _('Löschen?') ?>
+ </label>
+ <? endif; ?>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::create(_('Übernehmen'), 'save') ?>
+ </footer>
+ </form>
+<? else: ?>
+ <? _('Keine Zusatzangaben vorhanden') ?>
+<? endif; ?>
diff --git a/app/views/admin/api/config.php b/app/views/admin/api/config.php
new file mode 100644
index 0000000..426db12
--- /dev/null
+++ b/app/views/admin/api/config.php
@@ -0,0 +1,29 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<form class="default" action="<?= $controller->url_for('admin/api/config') ?>" method="post">
+ <fieldset>
+ <legend><?= _('Konfiguration') ?></legend>
+
+ <input type="hidden" name="active" value="0">
+ <label>
+ <input type="checkbox" name="active" value="1" <? if ($config['API_ENABLED']) echo 'checked'; ?>>
+ <?= _('REST-API aktiviert') ?>
+ </label>
+
+
+ <label class="caption" for="auth">
+ <?= _('Standard-Authentifizierung beim Login') ?>
+ <select name="auth" id="auth">
+ <? foreach ($GLOBALS['STUDIP_AUTH_PLUGIN'] as $plugin): ?>
+ <option <? if ($config['API_OAUTH_AUTH_PLUGIN'] === $plugin) echo 'selected'; ?>>
+ <?= $plugin ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+ <footer>
+ <?= Button::createAccept(_('Speichern')) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/api')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/api/edit.php b/app/views/admin/api/edit.php
new file mode 100644
index 0000000..65af5e9
--- /dev/null
+++ b/app/views/admin/api/edit.php
@@ -0,0 +1,129 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<? if ($consumer->id): ?>
+ <h1>
+ <?= sprintf(
+ _('Registrierte Applikation "%s" bearbeiten'),
+ htmlReady($consumer->title)
+ ) ?>
+ </h1>
+<? else: ?>
+ <h1 class="hide-in-dialog">
+ <?= _('Neue Applikation registrieren') ?>
+ </h1>
+<? endif; ?>
+
+<form class="settings default"
+ action="<?= $controller->url_for('admin/api/edit', $consumer->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Grundeinstellungen') ?></legend>
+
+ <label for="active">
+ <input type="checkbox" class="switch" id="active" name="active" value="1"
+ <?= $consumer->active ? 'checked' : '' ?>>
+ <?= _('Aktiviert') ?>
+ </label>
+
+
+ <label for="title">
+ <?= _('Titel') ?>
+ <input required type="text" id="title" name="title"
+ placeholder="<?= _('Beispiel-Applikation') ?>"
+ value="<?= htmlReady($consumer->title) ?>"
+ maxlength="128">
+ </label>
+
+ <label for="contact">
+ <?= _('Kontaktperson') ?>
+ <input required type="text" id="contact" name="contact"
+ placeholder="John Doe"
+ value="<?= htmlReady($consumer->contact) ?>"
+ maxlength="255">
+ </label>
+
+ <label for="email">
+ <?= _('Kontaktadresse') ?>
+ <input required type="text" id="email" name="email"
+ placeholder="support@appsite.tld"
+ value="<?= htmlReady($consumer->email) ?>"
+ maxlength="255">
+ </label>
+
+ <label for="callback">
+ <?= _('Callback URL') ?>
+ <input required type="text" id="callback" name="callback"
+ placeholder="http://appsite.tld/auth"
+ value="<?= htmlReady($consumer->callback) ?>"
+ maxlength="255">
+ </label>
+
+ <? if ($consumer->id): ?>
+ <label for="consumer_key">
+ <?= _('Consumer Key') ?>
+ <input readonly type="text" id="consumer_key"
+ value="<?= htmlReady($consumer->auth_key) ?>">
+ </label>
+
+ <label for="consumer_secret">
+ <?= _('Consumer Secret') ?>
+ <input readonly type="text" id="consumer_secret"
+ value="<?= htmlReady($consumer->auth_secret) ?>">
+ </label>
+
+ <div class="centered">
+ <?= strftime(_('Erstellt am %d.%m.%Y %H:%M:%S'), $consumer->mkdate) ?><br>
+ <? if ($consumer->mkdate != $consumer->chdate): ?>
+ <?= strftime(_('Zuletzt geändert am %d.%m.%Y %H:%M:%S'), $consumer->chdate) ?>
+ <? endif; ?>
+ </div>
+ <? endif; ?>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Applikation-Details') ?></legend>
+
+ <label for="commercial">
+ <input type="checkbox" class="switch" id="commercial" name="commercial" value="1"
+ <?= $consumer->commercial ? 'checked' : '' ?>>
+ <?= _('Kommerziell') ?>
+ </label>
+
+ <label for="description">
+ <?= _('Beschreibung') ?>
+ <textarea id="description" name="description" maxlength="65535"><?= htmlReady($consumer->description) ?></textarea>
+ </label>
+
+ <label for="url">
+ <?= _('URL') ?>
+ <input type="text" id="url" name="url"
+ placeholder="http://appsite.tld"
+ value="<?= htmlReady($consumer->url) ?>"
+ maxlength="255">
+ </label>
+
+ <label for="type">
+ <?= _('Typ') ?>
+ <select name="type" id="type">
+ <option value="">- <?= _('Keine Angabe') ?> -</option>
+ <? foreach ($types as $type => $label): ?>
+ <option value="<?= $type ?>" <?= $consumer->type == $type ? 'selected' : '' ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+
+ <label for="notes">
+ <?= _('Notizen') ?>
+ <textarea id="notes" name="notes" maxlength="65535"><?= htmlReady($consumer->notes) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Speichern'), 'store') ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/api')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/api/index.php b/app/views/admin/api/index.php
new file mode 100644
index 0000000..8a79dca
--- /dev/null
+++ b/app/views/admin/api/index.php
@@ -0,0 +1,70 @@
+<? if (!empty($consumers)): ?>
+<form action="#" method="post" class="default">
+<table class="default">
+ <caption><?= _('Registrierte Applikationen') ?></caption>
+ <thead>
+ <tr>
+ <th><?= ('Aktiv') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Kontakt') ?></th>
+ <th><?= _('Kommerziell') ?></th>
+ <th>&nbsp;</th>
+ </tr>
+ </thead>
+ <tbody>
+<? foreach ($consumers as $consumer): ?>
+ <tr>
+ <td id="<?= $consumer->id ?>">
+ <a href="<?= $controller->url_for('admin/api/toggle', $consumer->id, $consumer->active ? 'off' : 'on') ?>">
+ <?= Icon::create('checkbox-' . ($consumer->active ? '' : 'un') . 'checked', 'clickable')->asImg() ?>
+ </a>
+ </td>
+ <td>
+ <? if ($consumer->url): ?>
+ <a href="<?= htmlReady($consumer->url) ?>" target="_blank" rel="noopener noreferrer">
+ <?= htmlReady($consumer->title) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($consumer->title) ?>
+ <? endif; ?>
+ </td>
+ <td><?= $types[$consumer->type] ?: '&nbsp;' ?></td>
+ <td>
+ <a href="mailto:<?= htmlReady($consumer->email) ?>">
+ <?= htmlReady($consumer->contact) ?>
+ </a>
+ </td>
+
+ <td><?= Icon::create('checkbox-' . ($consumer->commercial ? '' : 'un') . 'checked', 'clickable')->asImg() ?></td>
+ <td class="actions">
+ <a href="<?= $controller->url_for('admin/api/keys', $consumer->id) ?>"
+ data-dialog="size=auto"
+ title="<?= htmlReady(sprintf(_('Schlüssel anzeigen für Applikation "%s"'), $consumer->title)) ?>">
+ <?= Icon::create('info-circle', 'clickable')->asImg() ?>
+ </a>
+ <a href="<?= $controller->url_for('admin/api/edit', $consumer->id) ?>" title="<?= _('Applikation bearbeiten') ?>" data-dialog>
+ <?= Icon::create('edit', 'clickable')->asImg() ?>
+ </a>
+ <a href="<?= $controller->url_for('admin/api/permissions', $consumer->id) ?>" title="<?= _('Zugriffsberechtigungen verwalten') ?>">
+ <?= Icon::create('admin', 'clickable')->asImg() ?>
+ </a>
+ <?= Icon::create('trash')->asInput([
+ 'formaction' => $controller->url_for('admin/api/delete/', $consumer->id),
+ 'title' => sprintf(_('Applikation "%s" entfernen'), $consumer->title),
+ 'data-confirm' => '',
+ 'style' => 'vertical-align: middle'
+ ]) ?>
+ </td>
+ </tr>
+<? endforeach; ?>
+ </tbody>
+</table>
+</form>
+
+<? else: ?>
+<p>
+ <?= MessageBox::info(_('Es wurde noch keine Applikation registriert.'),
+ [sprintf(_('Klicken Sie <a href="%s">hier</a>, um eine Applikation zu registrieren.'), $controller->url_for('admin/api/edit'))]) ?>
+</p>
+<? endif; ?>
diff --git a/app/views/admin/api/permissions.php b/app/views/admin/api/permissions.php
new file mode 100644
index 0000000..07441d6
--- /dev/null
+++ b/app/views/admin/api/permissions.php
@@ -0,0 +1,53 @@
+<form action="<?= $controller->url_for('admin/api/permissions', $consumer_id) ?>" method="post" class="default">
+<table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Zugriff') ?></th>
+ <th><?= _('Route') ?></th>
+ <th><?= _('Methoden') ?></th>
+ <th><?= _('Zugriff auf') ?></th>
+ <th><?= _('Quelle') ?></th>
+ </tr>
+ </thead>
+<? foreach ($routes as $route => $methods): ?>
+ <tbody>
+
+ <? $i = 0; ?>
+ <? foreach ($methods as $method => $info): ?>
+ <tr style="vertical-align: top;">
+ <td>
+ <input type="hidden" name="permission[<?= urlencode($route) ?>][<?= urlencode($method) ?>]" value="0">
+ <input type="checkbox" name="permission[<?= urlencode($route) ?>][<?= urlencode($method) ?>]"
+ <? if (!$global || $global->check($route, $method)): ?>
+ <? if ($permissions->check($route, $method)) echo 'checked'; ?>
+ <? else: ?>
+ disabled
+ <? endif; ?>
+ value="1">
+ </td>
+ <? if ($i++): ?>
+ <td>&nbsp;</td>
+ <? else: ?>
+ <td><?= htmlReady($route) ?></td>
+ <? endif; ?>
+ <td><?= htmlReady($method) ?></td>
+ <td><?= htmlReady($info['description']) ?></td>
+ <td><?= $info['source'] ?></td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+<? endforeach; ?>
+ <tfoot>
+ <tr>
+ <td>
+ <label>
+ <input type="checkbox" data-proxyfor="[name^=permission]:checkbox"> <?= _('Alle') ?>
+ </label>
+ </td>
+ <td colspan="4">
+ <?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+</form>
diff --git a/app/views/admin/autoinsert/_search.php b/app/views/admin/autoinsert/_search.php
new file mode 100644
index 0000000..10890f6
--- /dev/null
+++ b/app/views/admin/autoinsert/_search.php
@@ -0,0 +1,20 @@
+<fieldset>
+ <legend>
+ <?= _('Suche nach Veranstaltungen')?>
+ </legend>
+ <label>
+ <?= _('Semester') ?>
+ <?= Semester::getSemesterSelector(
+ ['name' => 'sem_select', 'id' => 'sem_select', 'class' => 'user_form'],
+ $sem_select, 'semester_id',
+ true
+ )?>
+ </label>
+ <label>
+ <?= _('Veranstaltung') ?>
+ <input type="text" name="sem_search" value="<?= htmlReady($sem_search) ?>" id="sem_search" class="user_form" required>
+ </label>
+</fieldset>
+<footer>
+ <?= Studip\Button::create(_('Suchen'),'suchen')?>
+</footer>
diff --git a/app/views/admin/autoinsert/_status.php b/app/views/admin/autoinsert/_status.php
new file mode 100644
index 0000000..22b4001
--- /dev/null
+++ b/app/views/admin/autoinsert/_status.php
@@ -0,0 +1,17 @@
+<td>
+ <? foreach ($domains as $domain) : ?>
+ <div>
+
+ <? if (isset($auto_sem['status'][$domain['id']]) && in_array($status, $auto_sem['status'][$domain['id']])) : ?>
+ <a href="<?= $controller->url_for('admin/autoinsert/edit/' . $auto_sem['seminar_id'], ['domain_id' => $domain['id'], 'status' => $status, 'remove' => true]) ?>">
+ <?= Icon::create('checkbox-checked') ?>
+ </a>
+ <? else : ?>
+ <a href="<?= $controller->url_for('admin/autoinsert/edit/' . $auto_sem['seminar_id'], ['domain_id' => $domain['id'], 'status' => $status]) ?>">
+ <?= Icon::create('checkbox-unchecked') ?>
+ </a>
+ <? endif ?>
+ <?= htmlReady($domain['name']) ?></div>
+ <? endforeach ?>
+
+</td>
diff --git a/app/views/admin/autoinsert/index.php b/app/views/admin/autoinsert/index.php
new file mode 100644
index 0000000..7749329
--- /dev/null
+++ b/app/views/admin/autoinsert/index.php
@@ -0,0 +1,106 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<? if (isset($flash['delete'])): ?>
+ <?= (string)QuestionBox::create(
+ _('Wollen Sie die Zuordnung der Veranstaltung zum automatischen Eintragen wirklich löschen?'),
+ $controller->deleteURL($flash['delete'], ['delete' => 1]),
+ $controller->deleteURL($flash['delete'], ['back' => 1])
+ ) ?>
+<? endif; ?>
+ <form class="default" action="<?= $controller->index() ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial("admin/autoinsert/_search.php", ['semester_data' => $semester_data]) ?>
+ </form>
+
+<? if (is_array($seminar_search) && count($seminar_search) > 0): ?>
+ <br>
+ <form class="default" action="<?= $controller->new() ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Suchergebnisse') ?>
+ </legend>
+
+ <label>
+ <?= _('Veranstaltung') ?>
+ <select name="sem_id" id="sem_id">
+ <? foreach ($seminar_search as $seminar): ?>
+ <option value="<?= $seminar[0] ?>">
+ <?= htmlReady($seminar[1]) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <h2>
+ <?= _('Automatisches Eintragen mit Nutzerstatus:') ?>
+ </h2>
+
+ <?php foreach ($userdomains as $domain): ?>
+ <h3>
+ <?= htmlReady($domain['name']) ?>
+ </h3>
+ <section class="hgroup">
+ <label>
+ <input type="checkbox" name="rechte[<?= $domain['id'] ?>][]" value="dozent">
+ <?= _('Dozent') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="rechte[<?= $domain['id'] ?>][]" value="tutor">
+ <?= _('Tutor') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="rechte[<?= $domain['id'] ?>][]" value="autor">
+ <?= _('Autor') ?>
+ </label>
+ </section>
+ <?php endforeach; ?>
+ </fieldset>
+ <footer>
+ <?= Studip\Button::create(_('Anlegen'), 'anlegen') ?>
+ </footer>
+ </form>
+<? endif; ?>
+
+<? if (!empty($auto_sems)) : ?>
+ <table class="default">
+ <caption><?= _('Vorhandene Zuordnungen') ?></caption>
+ <thead>
+ <tr>
+ <th><?= _('Veranstaltungen') ?></th>
+ <th style="text-align: center;"><?= _('Dozent') ?></th>
+ <th style="text-align: center;"><?= _('Tutor') ?></th>
+ <th style="text-align: center;"><?= _('Autor') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($auto_sems as $auto_sem): ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $auto_sem['seminar_id']]) ?>">
+ <?= htmlReady($auto_sem['Name']) ?>
+ </a>
+ </td>
+
+ <?= $this->render_partial("admin/autoinsert/_status.php", ['status' => 'dozent', 'auto_sem' => $auto_sem, 'domains' => $userdomains]) ?>
+ <?= $this->render_partial("admin/autoinsert/_status.php", ['status' => 'tutor', 'auto_sem' => $auto_sem, 'domains' => $userdomains]) ?>
+ <?= $this->render_partial("admin/autoinsert/_status.php", ['status' => 'autor', 'auto_sem' => $auto_sem, 'domains' => $userdomains]) ?>
+ <td class="actions">
+ <a href="<?= $controller->delete($auto_sem['seminar_id'] ) ?>">
+ <?= Icon::create(
+ 'trash',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Veranstaltung entfernen'), 'class' => 'text-top']
+ ) ?>
+ </a>
+ </td>
+ </tr>
+ <? $i++ ?>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+<? endif ?>
diff --git a/app/views/admin/autoinsert/manual.php b/app/views/admin/autoinsert/manual.php
new file mode 100644
index 0000000..d233ed6
--- /dev/null
+++ b/app/views/admin/autoinsert/manual.php
@@ -0,0 +1,169 @@
+<style type="text/css">
+ .filter_selection select {
+ width: 100%;
+ }
+
+ .filter_selection input[name=remove_filter] {
+ float: right;
+ }
+</style>
+
+<form class="default" action="<?= $controller->manual() ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial("admin/autoinsert/_search.php", compact('semester_data', 'sem_search', 'sem_select')) ?>
+</form>
+
+
+<? if ($seminar_search > 0 && $sem_search && $sem_select): ?>
+ <form class="default" action="<?= $controller->manual() ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="sem_search" value="<?= htmlReady($sem_search) ?>">
+ <input type="hidden" name="sem_select" value="<?= htmlReady($sem_select) ?>">
+ <? foreach ($filtertype as $type): ?>
+ <input type="hidden" name="filtertype[]" value="<?= $type ?>">
+ <? endforeach; ?>
+
+ <table class="default">
+ <colgroup>
+ <col width="17%">
+ <col width="33%">
+ <col width="50%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th colspan="3"><?= _('Suchergebnisse') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <label for="sem_id"><?= _('Veranstaltung') ?></label>
+ </td>
+ <td colspan="2">
+ <select name="sem_id" id="sem_id" style="width: 100%;">
+ <? foreach ($seminar_search as $seminar): ?>
+ <option
+ value="<?= $seminar[0] ?>" <?= ($sem_id == $seminar[0]) ? 'selected="selected"' : '' ?>>
+ <?= htmlReady($seminar[1]) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ <? if (count($filtertype) != count($available_filtertypes)): ?>
+ <tr>
+ <td>
+ <legend for="add_filtertype"><?= _('Filterkriterien') ?></legend>
+ </td>
+ <td colspan="2">
+ <select name="add_filtertype">
+ <? foreach ($available_filtertypes as $key => $value): ?>
+ <? if (!in_array($key, $filtertype)): ?>
+ <option value="<?= $key ?>"><?= $value ?></option>
+ <? endif ?>
+ <? endforeach; ?>
+ </select>
+ <?= Icon::create(
+ 'add',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Filter hinzufügen')]
+ )->asInput(["type" => "image", "class" => "middle", "name" => "add_filter"]) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+
+ <!-- #2 Auswahllisten anzeigen -->
+ <? if (!empty($filtertype)): ?>
+ <tbody class="default filter_selection" style="vertical-align: top;">
+ <tr>
+ <th colspan="3"><?= _('Ausgewählte Filterkriterien') ?></th>
+ </tr>
+ <? $index = 0;
+ foreach ($filtertype
+
+ as $type): ?>
+ <? if ($index % 2 == 0): ?>
+ <? if ($index != 0): ?></tr><? endif ?>
+ <tr>
+ <? endif ?>
+ <td colspan="<?= $index % 2 ? 1 : 2 ?>">
+ <label for="<?= $type ?>"><b><?= $available_filtertypes[$type] ?></b></label>
+ <?= Icon::create(
+ 'remove',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Filter entfernen')]
+ )->asInput(["type" => "image", "class" => "middle", "name" => "remove_filter[" . $type . "]"]) ?>
+ <br>
+
+ <select name="filter[<?= $type ?>][]" multiple size="5" class="nested-select">
+ <? foreach ($values[$type] as $key => $value): ?>
+ <? if (is_array($value)): ?>
+ <option value="<?= $key ?>"
+ class="nested-item-header" <?= in_array($key, (array)@$filter[$type]) ? 'selected="selected"' : '' ?>><?= htmlReady($value['name']) ?></option>
+ <? foreach ($value['values'] as $k => $v): ?>
+ <option value="<?= $k ?>"
+ class="nested-item" <?= in_array($k, (array)@$filter[$type]) ? 'selected="selected"' : '' ?>><?= htmlReady($v) ?></option>
+ <? endforeach; ?>
+ <? else: ?>
+ <option
+ value="<?= $key ?>" <?= in_array($key, (array)@$filter[$type]) ? 'selected="selected"' : '' ?>><?= htmlReady($value) ?></option>
+ <? endif ?>
+ <? endforeach; ?>
+ </select>
+ </td>
+ <? $index++;
+ endforeach; ?>
+ <? if ($index % 2 != 0): ?>
+ <td>&nbsp;</td>
+ <? endif ?>
+ </tr>
+ </tbody>
+ <? endif ?>
+ <tfoot>
+ <tr>
+ <td colspan="3">
+ <?= Studip\Button::create(_('Eintragen'), 'submit') ?>
+ <?= Icon::create(
+ 'question-circle',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Vorschau')]
+ )->asInput(["type" => "image", "style" => "vertical-align: middle;", "name" => "preview"]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+
+
+ </form>
+
+ <script type="text/javascript">
+ jQuery(function ($) {
+ $('input[name=preview]').show().click(function (event) {
+ if (!$(this).next().length || !$(this).next().is('span')) {
+ $(this).after($('<span id="autoinsert_count" style="vertical-align: middle;"/>'));
+ }
+ $.getJSON('<?= $controller->manual_count() ?>',
+ $(this).closest('form').serializeArray(),
+ function (json) {
+ var result = "";
+ if (!json || json.error) {
+ result = "Fehler".toLocaleString() + ": ";
+ result += json.error
+ ? json.error.toLocaleString()
+ : "Fehler bei der Übertragung".toLocaleString();
+ } else {
+ result = "Gefundene Nutzer".toLocaleString() + ": ";
+ result += "<strong>" + json.users + "</strong>";
+ }
+ $('#autoinsert_count').html(result);
+ }
+ );
+ event.preventDefault();
+ });
+ $('input[name^=remove_filter]').click(function (event) {
+ return confirm("Wollen Sie diesen Filter wirklich entfernen?".toLocaleString());
+ });
+ });
+ </script>
+<? endif ?>
diff --git a/app/views/admin/banner/datetime-picker.php b/app/views/admin/banner/datetime-picker.php
new file mode 100644
index 0000000..c8d69d8
--- /dev/null
+++ b/app/views/admin/banner/datetime-picker.php
@@ -0,0 +1,18 @@
+<div class="hgroup">
+ <input size="11" name="<?=$prefix?>date" id="<?=$prefix?>date"
+ value="<?if($timestamp) : ?><?=date('d.m.Y',$timestamp)?><?endif;?>"
+ placeholder ="TT.MM.JJJJ" class="no-hint"
+ <?if($disabled) : ?>disabled<?endif;?>>
+
+ <input type="number" name="<?= $prefix ?>hour" placeholder="<?= _('hh') ?>"
+ value="<? if ($timestamp) echo date('G', $timestamp) ?>"
+ size="2" maxlength="2" style="width: 4em;" class="no-hint"
+ <? if ($disabled) echo 'disabled'; ?>> :
+ <input type="number" name="<?= $prefix ?>minute" placeholder="<?= _('mm') ?>"
+ value="<? if ($timestamp) echo date('i', $timestamp) ?>"
+ size="2" maxlength="2" style="width: 4em;" class="no-hint"
+ <? if ($disabled) echo 'disabled'; ?>>
+ <script>
+ jQuery('#<?=$prefix?>date').datepicker();
+ </script>
+</div>
diff --git a/app/views/admin/banner/edit.php b/app/views/admin/banner/edit.php
new file mode 100644
index 0000000..668fde9
--- /dev/null
+++ b/app/views/admin/banner/edit.php
@@ -0,0 +1,109 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<form action="<?= $controller->edit($banner) ?>" method="post" enctype="multipart/form-data" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <tbody>
+ <tr>
+ <td class="nohover">
+ <? if ($banner['banner_path']): ?>
+ <?= $banner->toImg() ?>
+ <? else: ?>
+ <?= _('Noch kein Bild hochgeladen') ?>
+ <? endif; ?><br>
+
+ <label class="file-upload">
+ <?= _('Bilddatei auswählen') ?>
+ <input id="imgfile" name="imgfile" type="file" accept="image/*"><br>
+ <input type="hidden" name="banner_path" value="<?= $banner['banner_path'] ?>"><br>
+ </label>
+ </td>
+
+ <td class="nohover" style="vertical-align: top">
+ <fieldset>
+ <legend>
+ <?= _('Banner bearbeiten') ?>
+ </legend>
+
+ <label>
+ <?= _('Beschreibung:') ?>
+ <input type="text" id="description" name="description"
+ value="<?= htmlReady($banner['description']) ?>"
+ size="40" maxlen="254">
+ </label>
+
+ <label>
+ <?= _('Alternativtext:') ?>
+
+ <input type="text" id="alttext" name="alttext"
+ value="<?= htmlReady($banner['alttext']) ?>"
+ size="40" maxlen="254">
+ </label>
+
+ <label>
+ <?= _("Verweis-Typ:") ?>
+
+ <input name="target_type" type="hidden" size="8" value="<?=$banner['target_type']?>">
+ <select name="target_type" disabled="disabled">
+ <? foreach ($target_types as $key => $label): ?>
+ <option value="<?= $key ?>" <? if ($banner['target_type'] == $key) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _("Verweis-Ziel:") ?>
+
+ <? if (in_array($banner['target_type'], words('none url'))): ?>
+ <input type="text" name="target" size="40" maxlen="254" value="<?= htmlReady($banner['target']) ?>">
+ <? elseif ($banner['target_type'] == "seminar") :?>
+ <?= $seminar ?>
+ <? elseif ($banner['target_type'] == "inst") :?>
+ <?= $institut ?>
+ <? else: ?>
+ <?= $user ?>
+ <? endif; ?>
+ </label>
+
+ <label>
+ <?= _('Anzeigen ab:') ?>
+
+ <?= $this->render_partial('admin/banner/datetime-picker', [
+ 'prefix' => 'start_',
+ 'timestamp' => $banner['startdate']]) ?>
+ </label>
+
+ <label>
+ <?= _('Anzeigen bis:') ?>
+
+ <?= $this->render_partial('admin/banner/datetime-picker', [
+ 'prefix' => 'end_',
+ 'timestamp' => $banner['enddate']]) ?>
+ </label>
+
+ <label>
+ <?= _('Priorität:')?>
+
+ <select id="priority" name="priority">
+ <? foreach ($priorities as $key => $label): ?>
+ <option value="<?= $key ?>" <? if ($banner['priority'] == $key) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::create(_('Speichern'), 'speichern') ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->index("#banner-{$banner->id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/banner/index.php b/app/views/admin/banner/index.php
new file mode 100644
index 0000000..9c3fb27
--- /dev/null
+++ b/app/views/admin/banner/index.php
@@ -0,0 +1,69 @@
+<? if (isset($flash['delete'])): ?>
+ <?= QuestionBox::create(
+ _('Wollen Sie das Banner wirklich löschen?'),
+ $controller->deleteURL($flash['delete']['banner_id'], ['delete' => 1]),
+ $controller->deleteURL($flash['delete']['banner_id'], ['back' => 1])
+ ) ?>
+<? endif; ?>
+
+<table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Banner') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Ziel') ?></th>
+ <th><?= _('Zeitraum') ?></th>
+ <th><?= _('Klicks') ?></th>
+ <th><?= _('Views') ?></th>
+ <th><?= _('Prio') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($banners as $banner): ?>
+ <tr id="banner-<?= htmlReady($banner->id) ?>">
+ <td style="text-align: center;">
+ <?= $banner->toImg(['style' => 'max-width: 80px']) ?>
+ </td>
+ <td><?= htmlReady($banner->description) ?></td>
+ <td><?= htmlReady($banner->target_type) ?></td>
+ <td>
+ <? if ($banner['target_type'] === 'seminar'): ?>
+ <?= mila(reset(get_object_name($banner->target, 'sem')), 30) ?>
+ <? elseif ($banner['target_type'] === 'inst') :?>
+ <?= mila(reset(get_object_name($banner->target, 'inst')), 30) ?>
+ <? else: ?>
+ <?= htmlReady($banner->target) ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center;">
+ <?= $banner->startdate ? strftime('%x', $banner->startdate) : _('sofort') ?><br>
+ <?= _('bis') ?><br>
+ <?= $banner->enddate ? strftime('%x', $banner->enddate) : _('unbegrenzt') ?>
+ </td>
+ <td align="center">
+ <?= number_format($banner->clicks, 0, ',', '.') ?>
+ </td>
+ <td align="center">
+ <?= number_format($banner->views, 0, ',', '.') ?>
+ </td>
+ <td><?= $banner->priority ?> (<?= $banner->getViewProbability() ?>)</td>
+ <td class="actions">
+ <a class="load-in-new-row" href="<?= $controller->info($banner, ['path' => $banner->banner_path]) ?>">
+ <?= Icon::create('info')->asImg(['title' => _('Eigenschaften')]) ?>
+ </a>
+ <a href="<?= $controller->edit($banner, ['path' => $banner->banner_path]) ?>" data-dialog="size=auto">
+ <?= Icon::create('edit')->asImg(['title' => _('Banner bearbeiten')]) ?>
+ </a>
+ <a href="<?= $controller->reset($banner) ?>">
+ <?= Icon::create('refresh')->asImg(['title' => _('Klicks/Views zurücksetzen')]) ?>
+ </a>
+ <a href="<?= $controller->delete($banner) ?>">
+ <?= Icon::create('trash')->asImg(['title' => _('Banner löschen')]) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+</table>
diff --git a/app/views/admin/banner/info.php b/app/views/admin/banner/info.php
new file mode 100644
index 0000000..2720d5f
--- /dev/null
+++ b/app/views/admin/banner/info.php
@@ -0,0 +1,80 @@
+<table class="default">
+ <tbody>
+ <tr>
+ <td rowspan="9" colspan="2" style="text-align: center;">
+ <? if ($banner['banner_path']): ?>
+ <?= $banner->toImg() ?>
+ <? else: ?>
+ <?= _('noch kein Bild hochgeladen') ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td><?= _("Beschreibung:") ?></td>
+ <td>
+ <input type="text" readonly
+ value="<?= htmlReady($banner['description']) ?>"
+ size="40" maxlen="254">
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Alternativtext:') ?></td>
+ <td>
+ <input type="text" readonly
+ value="<?= htmlReady($banner['alttext']) ?>"
+ size="40" maxlen="254">
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Verweis-Typ:') ?></td>
+ <td>
+ <select disabled>
+ <? foreach ($target_types as $key => $label): ?>
+ <option value="<?= $key ?>" <? if ($banner['target_type'] == $key) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Verweis-Ziel:') ?></td>
+ <td>
+ <input type="text" readonly
+ value="<?= htmlReady($this->edit['target']) ?>"
+ size="40" maxlen="254">
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Anzeigen ab:')?></td>
+ <td>
+ <?= $this->render_partial('admin/banner/datetime-picker', [
+ 'prefix' => 'start_',
+ 'timestamp' => $banner['startdate'],
+ 'disabled' => true]) ?>
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Anzeigen bis:') ?></td>
+ <td>
+ <?= $this->render_partial('admin/banner/datetime-picker', [
+ 'prefix' => 'end_',
+ 'timestamp' => $banner['enddate'],
+ 'disabled' => true]) ?>
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Priorität:') ?></td>
+ <td>
+ <select disabled>
+ <? foreach ($priorities as $key => $label): ?>
+ <option value="<?= $key ?>" <? if ($banner['priority'] == $key) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
diff --git a/app/views/admin/banner/new.php b/app/views/admin/banner/new.php
new file mode 100644
index 0000000..5e27cf0
--- /dev/null
+++ b/app/views/admin/banner/new.php
@@ -0,0 +1,100 @@
+<form action="<?= $controller->new() ?>" method="post" enctype="multipart/form-data" class="default">
+ <fieldset>
+ <legend>
+ <?= _('Neues Banner anlegen') ?>
+ </legend>
+
+ <label class="file-upload">
+ <?= _('Bilddatei auswählen') ?>
+ <input id="imgfile" name="imgfile" type="file" accept="image/*">
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+
+ <input type="text" id="description" name="description"
+ value="<?= htmlReady($this->flash['request']['description']) ?>"
+ style="width: 240px;" maxlen="254">
+ </label>
+
+ <label>
+ <?= _('Alternativtext') ?>
+
+ <input type="text" id="alttext" name="alttext"
+ value="<?= htmlReady($this->flash['request']['alttext']) ?>"
+ style="width: 240px;" maxlen="254">
+ </label>
+
+ <label>
+ <?= _('Verweis-Typ') ?>
+
+ <select id="target_type" name="target_type">
+ <? foreach ($target_types as $key => $label): ?>
+ <option value="<?= $key ?>"><?= $label ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+
+ <label>
+ <?= _('Verweis-Ziel') ?>
+
+ <input type="url" class="target-url" name="target"
+ placeholder="<?= _('URL eingeben') ?>"
+ value="<?= htmlReady($this->flash['request']['target']) ?>"
+ style="width: 240px;" maxlen="254">
+
+ <?= QuickSearch::get('seminar', new StandardSearch('Seminar_id'))
+ ->setInputStyle('width: 240px')
+ ->setInputClass('target-seminar')
+ ->render() ?>
+
+ <?= QuickSearch::get('institut', new StandardSearch('Institut_id'))
+ ->setInputStyle('width: 240px')
+ ->setInputClass('target-inst')
+ ->render() ?>
+
+ <?= QuickSearch::get('user', new StandardSearch('username'))
+ ->setInputStyle('width: 240px')
+ ->setInputClass('target-user')
+ ->render() ?>
+
+ <span class="target-none"><?= _('Kein Verweisziel') ?></span>
+ </label>
+
+ <label>
+ <?= _('Anzeigen ab') ?>
+ <?= $this->render_partial('admin/banner/datetime-picker', ['prefix' => 'start_']) ?>
+ </label>
+
+
+ <label>
+ <?= _('Anzeigen bis')?>
+ <?= $this->render_partial('admin/banner/datetime-picker', ['prefix' => 'end_']) ?>
+ </label>
+
+ <label>
+ <?= _('Priorität')?>
+
+ <select name="priority">
+ <? foreach ($priorities as $key => $label): ?>
+ <option value="<?= $key ?>"><?= $label ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Anlegen'), 'anlegen') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->indexURL()) ?>
+ </footer>
+</form>
+
+<script type="text/javascript">
+jQuery(function ($) {
+ $('#target_type').change(function () {
+ var target = $(this).val();
+ $(this).closest('label').next().find('[class^="target"]').hide().filter('.target-' + target).show();
+ }).change();
+});
+</script>
diff --git a/app/views/admin/cache/_stats_entry.php b/app/views/admin/cache/_stats_entry.php
new file mode 100644
index 0000000..0c85074
--- /dev/null
+++ b/app/views/admin/cache/_stats_entry.php
@@ -0,0 +1,10 @@
+<? if (is_array($entry)) : ?>
+ <dl class="default">
+ <? foreach ($entry as $index => $data) : ?>
+ <dt><?= htmlReady($index) ?></dt>
+ <dd><?= $this->render_partial('admin/cache/_stats_entry', ['entry' => $data]) ?></dd>
+ <? endforeach ?>
+ </dl>
+<? else : ?>
+ <?= htmlReady($entry) ?>
+<? endif; ?>
diff --git a/app/views/admin/cache/settings.php b/app/views/admin/cache/settings.php
new file mode 100644
index 0000000..ad1e544
--- /dev/null
+++ b/app/views/admin/cache/settings.php
@@ -0,0 +1,6 @@
+<? if ($enabled) : ?>
+ <div id="cache-admin-container">
+ <cache-administration :cache-types='<?= htmlReady(json_encode($types)) ?>' current-cache="<?= htmlReady($cache) ?>"
+ :current-config='<?= htmlReady(json_encode($config)) ?>'></cache-administration>
+ </div>
+<? endif;
diff --git a/app/views/admin/cache/stats.php b/app/views/admin/cache/stats.php
new file mode 100644
index 0000000..9de9baf
--- /dev/null
+++ b/app/views/admin/cache/stats.php
@@ -0,0 +1,15 @@
+<section class="contentbox">
+ <header>
+ <h1><?= _('Cache-Statistiken') ?></h1>
+ </header>
+ <br>
+ <ul>
+ <? foreach ($stats as $index => $data) : ?>
+ <li>
+ <strong><?= htmlReady($index) ?></strong>
+ <?= $this->render_partial('admin/cache/_stats_entry', ['entry' => $data]) ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <br>
+</section>
diff --git a/app/views/admin/configuration/configuration.php b/app/views/admin/configuration/configuration.php
new file mode 100644
index 0000000..8b8e6d0
--- /dev/null
+++ b/app/views/admin/configuration/configuration.php
@@ -0,0 +1,31 @@
+<section class="contentbox">
+ <header>
+ <h1>
+ <?= _('Globale Systemkonfigurationen') ?>
+ <? if ($needle): ?>
+ / <?= _('Suchbegriff:') ?> "<em><?= htmlReady($needle) ?></em>"
+ <? endif ?>
+ </h1>
+ </header>
+ <? foreach ($sections as $section => $configs): ?>
+ <?php $id = md5(uniqid($section));?>
+ <article id="<?= $id?>" <? if ($open_section === $section || $only_section || $needle) echo 'class="open"'; ?>>
+ <header>
+ <h1>
+ <a href="<?= URLHelper::getURL("?#{$id}")?>">
+ <?= $section ?: '- ' . _(' Ohne Kategorie ') . ' -' ?>
+ (<?= count($configs) ?>)
+ </a>
+ </h1>
+ </header>
+ <section>
+ <table class="default">
+ <?= $this->render_partial('admin/configuration/table-header.php') ?>
+ <? foreach ($configs as $config): ?>
+ <?= $this->render_partial('admin/configuration/table-row.php', $config) ?>
+ <? endforeach ?>
+ </table>
+ </section>
+ </article>
+ <? endforeach ?>
+</section>
diff --git a/app/views/admin/configuration/edit_configuration.php b/app/views/admin/configuration/edit_configuration.php
new file mode 100644
index 0000000..4818094
--- /dev/null
+++ b/app/views/admin/configuration/edit_configuration.php
@@ -0,0 +1,65 @@
+<form action="<?= $controller->link_for('admin/configuration/edit_configuration', ['field' => $config['field']]) ?>"
+ method="post" data-dialog="size=auto" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Konfigurationsparameter editieren') ?>
+ </legend>
+
+ <? if ($config['description']): ?>
+ <p><?= htmlReady($config['description']) ?></p>
+ <? endif ?>
+
+ <?= $this->render_partial('admin/configuration/type-edit.php', $config) ?>
+
+ <label for="comment">
+ <?= _('Kommentar') ?>
+ <textarea cols="80" rows="2" name="comment" id="comment"><?= htmlReady($config['comment']) ?></textarea>
+ </label>
+ <label>
+ <?= _('Standard') ?>
+
+ <? if ($config['is_default'] === '1'): ?>
+ <?= Icon::create('checkbox-checked', Icon::ROLE_INFO)->asImg(['title' => _('Ja')]) ?>
+ <? elseif ($config['is_default'] === '0'): ?>
+ <?= Icon::create('checkbox-unchecked', Icon::ROLE_INFO)->asImg(['title' => _('Nein')]) ?>
+ <? elseif ($config['is_default'] === null): ?>
+ <em>- <?= _('kein Eintrag vorhanden') ?> -</em>
+ <? endif ?>
+ </label>
+ <div>
+ <label class="col-3">
+ <?= _('Typ') ?>
+ <input name="type" type="text" readonly value="<?= htmlReady($config['type']) ?>">
+ </label>
+ <label class="col-3">
+ <?= _('Bereich') ?>
+ <input type="text" name="range" readonly value="<?= htmlReady($config['range']) ?>">
+ </label>
+ </div>
+ <div>
+ <label class="col-3">
+ <?= _('Kategorie') ?>
+ <select name="section" onchange="jQuery(this).next('input').val( jQuery(this).val() );">
+ <? foreach (array_keys($allconfigs) as $section): ?>
+ <option <? if ($config['section'] === $section) echo 'selected'; ?>>
+ <?= htmlReady($section) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <label class="col-3">
+ (<em><?= _('Bitte die neue Kategorie eingeben') ?></em>)
+ <input type="text" name="section_new" id="section">
+ </label>
+ </div>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Übernehmen')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for("admin/configuration/configuration/{$config['section']}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/configuration/edit_range_config.php b/app/views/admin/configuration/edit_range_config.php
new file mode 100644
index 0000000..32d2d4c
--- /dev/null
+++ b/app/views/admin/configuration/edit_range_config.php
@@ -0,0 +1,22 @@
+<form action="<?= $controller->link_for("admin/configuration/edit_{$range_type}_config", $range, compact('field')) ?>"
+ method="post" data-dialo="size=auto" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= htmlReady($field) ?>
+ </legend>
+ <?= $this->render_partial('admin/configuration/type-edit.php', $config) ?>
+ <label>
+ <?= _('Beschreibung:') ?> (<em>description</em>)
+ <textarea name="description" readonly><?= htmlReady($config['description']) ?></textarea>
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for("admin/configuration/{$range_type}_configuration", ['id' => $range->id])
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/configuration/range_configuration.php b/app/views/admin/configuration/range_configuration.php
new file mode 100644
index 0000000..f32bd0d
--- /dev/null
+++ b/app/views/admin/configuration/range_configuration.php
@@ -0,0 +1,15 @@
+<table class="default">
+ <caption>
+ <?= htmlReady($title) ?>
+ <? if (!empty($subtitle)): ?>
+ <br>
+ <small><?= htmlReady($subtitle) ?></small>
+ <? endif ?>
+ </caption>
+ <?= $this->render_partial('admin/configuration/table-header.php') ?>
+ <tbody>
+ <? foreach ($configs as $config): ?>
+ <?= $this->render_partial('admin/configuration/table-row.php', $config) ?>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/admin/configuration/table-header.php b/app/views/admin/configuration/table-header.php
new file mode 100644
index 0000000..725111c
--- /dev/null
+++ b/app/views/admin/configuration/table-header.php
@@ -0,0 +1,14 @@
+<colgroup>
+ <col style="width: 40%">
+ <col>
+ <col style="width: 100px">
+ <col style="width: 24px">
+</colgroup>
+<thead>
+<tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Wert') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th>&nbsp;</th>
+</tr>
+</thead>
diff --git a/app/views/admin/configuration/table-row.php b/app/views/admin/configuration/table-row.php
new file mode 100644
index 0000000..fd57331
--- /dev/null
+++ b/app/views/admin/configuration/table-row.php
@@ -0,0 +1,29 @@
+<tr>
+ <td>
+ <a data-dialog href="<?= $controller->link_for($linkchunk, compact('field')) ?>">
+ <?= htmlReady($field) ?>
+ </a>
+ <? if (!empty($description)): ?>
+ <br><small><?= htmlReady($description) ?></small>
+ <? endif; ?>
+ </td>
+ <td class="wrap-content">
+ <? if ($type === 'string' || $type === 'i18n'): ?>
+ <em><?= htmlReady($value) ?></em>
+ <? elseif ($type === 'integer'): ?>
+ <?= (int)$value ?>
+ <? elseif ($type === 'boolean'): ?>
+ <? if ($value): ?>
+ <?= Icon::create('accept', Icon::ROLE_STATUS_GREEN, ['title' => _('TRUE')]) ?>
+ <? else : ?>
+ <?= Icon::create('decline', Icon::ROLE_STATUS_RED, ['title' => _('FALSE')]) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ <td><?= htmlReady($type) ?></td>
+ <td class="actions">
+ <a data-dialog="size=auto" href="<?= $controller->link_for($linkchunk, compact('field')) ?>">
+ <?= Icon::create('edit')->asImg(['title' => _('Konfigurationsparameter bearbeiten')]) ?>
+ </a>
+ </td>
+</tr>
diff --git a/app/views/admin/configuration/type-edit.php b/app/views/admin/configuration/type-edit.php
new file mode 100644
index 0000000..ecbbe55
--- /dev/null
+++ b/app/views/admin/configuration/type-edit.php
@@ -0,0 +1,28 @@
+<? if ($type === 'boolean') : ?>
+
+ <input type="hidden" name="value" value="0">
+ <input type="checkbox" name="value" value="1" id="item-value" class="studip-checkbox"
+ <? if ($value) echo 'checked'; ?>>
+ <label for="item-value">
+ <?= _('aktiviert') ?>
+ </label>
+<? else : ?>
+ <label>
+ <?= _('Inhalt') ?>
+ <? if ($type === 'integer'): ?>
+ <input name="value" type="number" id="item-value"
+ value="<?= htmlReady($value) ?>">
+ <? elseif ($type === 'array') : ?>
+ <?php $v = version_compare(PHP_VERSION, '5.4.0', '>=') ? json_encode($value, JSON_UNESCAPED_UNICODE) : json_encode($value) ?>
+ <textarea cols="80" rows="5" name="value" id="item-value"><?= htmlReady($v, true, true) ?></textarea>
+ <? elseif ($type === 'i18n'): ?>
+ <?= I18N::textarea('value', $value, [
+ 'id' => 'item-value',
+ 'cols' => 80,
+ 'rows' => 3,
+ ]) ?>
+ <? else: ?>
+ <textarea cols="80" rows="3" name="value" id="item-value"><?= htmlReady($value) ?></textarea>
+ <? endif; ?>
+ </label>
+<? endif ?>
diff --git a/app/views/admin/content_terms_of_use/delete.php b/app/views/admin/content_terms_of_use/delete.php
new file mode 100644
index 0000000..d7aabd2
--- /dev/null
+++ b/app/views/admin/content_terms_of_use/delete.php
@@ -0,0 +1,42 @@
+
+
+<form class="default" method="post" action="<?= $controller->link_for('admin/content_terms_of_use/delete') ?>">
+ <input type="hidden" name="entry_id" value="<?= htmlReady($entry_id) ?>">
+ <fieldset>
+ <legend>
+ <?= _('Eintrag löschen') ?>
+ </legend>
+
+ <?= MessageBox::warning(sprintf(
+ _('Soll der Eintrag mit der ID "%s" wirklich gelöscht werden?'),
+ htmlReady($entry_id)
+ )) ?>
+ <? if ($dependent_files_count): ?>
+ <p>
+ <?= sprintf(
+ _('Bevor ein Eintrag gelöscht werden kann, müssen Dateien, welche auf ihn verweisen, einem anderen Eintrag zugewiesen werden! Es müssen %u Dateien bearbeitet werden!'),
+ $dependent_files_count
+ ) ?>
+ </p>
+ <label>
+ <?= _('Name des anderen Eintrags:') ?>
+ <select name="other_entry_id">
+ <? foreach ($other_entries as $other_entry): ?>
+ <option value="<?= htmlReady($other_entry->id) ?>" <? if ($other_entry_id === $other_entry->id) echo 'selected'; ?>>
+ <?= htmlReady($other_entry->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? else: ?>
+ <p><?= _('Der Eintrag wird von keiner Datei benutzt!') ?></p>
+ <? endif; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Löschen'), 'confirm') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ URLHelper::getUrl('dispatch.php/admin/content_terms_of_use/index')
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/content_terms_of_use/edit.php b/app/views/admin/content_terms_of_use/edit.php
new file mode 100644
index 0000000..e72a15d
--- /dev/null
+++ b/app/views/admin/content_terms_of_use/edit.php
@@ -0,0 +1,63 @@
+<form class="default" method="post" action="<?= $controller->link_for('admin/content_terms_of_use/store?id=' . $entry->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+
+ <? if ($entry->isNew()): ?>
+ <label>
+ <?= _('ID') ?>
+ <input type="text" name="entry_id" value="<?= htmlReady($entry->id) ?>">
+ </label>
+ <? else: ?>
+ <input type="hidden" name="entry_id" value="<?= htmlReady($entry->id) ?>">
+ <? endif ?>
+ <label>
+ <?= _('Name') ?>
+ <?= I18N::input('name', $entry->name)?>
+ </label>
+ <label>
+ <?= _('Bedingung zum Herunterladen') ?>
+ <select name="download_condition">
+ <? foreach (ContentTermsOfUse::getConditions() as $condition_id => $description): ?>
+ <option value="<?= htmlReady($condition_id) ?>" <? if ($entry->download_condition == $condition_id) echo 'selected'; ?>>
+ <?= htmlReady($description) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Symbol-Name oder URL') ?>
+ <input type="text" name="icon" value="<?= htmlReady($entry->icon) ?>">
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Zusätzliche Angaben') ?></legend>
+
+ <label>
+ <?= _('Position') ?>
+ <input type="number" name="position" value="<?= htmlReady($entry->position) ?>">
+ </label>
+ <label>
+ <input type="checkbox" name="is_default" value="1"
+ <? if ($entry->is_default) echo 'checked'; ?>>
+ <?= _('Standardlizenz bei neuen Dateien') ?>
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <?= I18N::textarea('description', $entry->description)?>
+ </label>
+ <label>
+ <?= _('Hinweise zur Nutzung') ?>
+ <?= I18N::textarea('student_description', $entry->student_description)?>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('admin/content_terms_of_use/index')
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/content_terms_of_use/index.php b/app/views/admin/content_terms_of_use/index.php
new file mode 100644
index 0000000..afaeb81
--- /dev/null
+++ b/app/views/admin/content_terms_of_use/index.php
@@ -0,0 +1,46 @@
+<table class="default">
+ <caption><?= _('Inhalts-Nutzungsbedingungen') ?></caption>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('ID') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Download-Bedingung') ?></th>
+ <th><?= _('Standard')?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($entries) === 0): ?>
+ <tr>
+ <td colspan="6">
+ <?= MessageBox::info(_('Es sind keine Nutzungsbedingungen für Inhalte definiert!')) ?>
+ <?= Studip\LinkButton::create(
+ _('Neue Nutzungsbedingungen definieren'),
+ $controller->url_for('admin/content_terms_of_use/add'),
+ ['data-dialog' => 'reload-on-close;size=auto']
+ ) ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($entries as $entry): ?>
+ <tr>
+ <td><?= Icon::create($entry->icon, Icon::ROLE_INFO) ?></td>
+ <td><?= htmlReady($entry->id) ?></td>
+ <td><?= htmlReady($entry->name) ?></td>
+ <td>
+ <?= htmlReady(ContentTermsOfUse::describeCondition($entry->download_condition)) ?>
+ </td>
+ <td><?= $entry->is_default ? _('Ja') : _('Nein') ?></td>
+ <td class="actions">
+ <a href="<?= $controller->url_for('admin/content_terms_of_use/edit', ['entry_id' => $entry->id]) ?>" data-dialog>
+ <?= Icon::create('edit') ?>
+ </a>
+ <a href="<?= $controller->url_for('admin/content_terms_of_use/delete', ['entry_id' => $entry->id]) ?>" data-dialog="size=auto">
+ <?= Icon::create('trash') ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/admin/course_wizard_steps/edit.php b/app/views/admin/course_wizard_steps/edit.php
new file mode 100644
index 0000000..ab3de24
--- /dev/null
+++ b/app/views/admin/course_wizard_steps/edit.php
@@ -0,0 +1,43 @@
+<form class="default" action="<?= $controller->url_for('admin/coursewizardsteps/save', $step->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= PageLayout::getTitle() ?></legend>
+
+ <label>
+ <span class="required"><?= _('Name des Schrittes') ?></span>
+ <input type="text" name="name" size="50" maxlength="255" value="<?= htmlReady($step->name) ?>" required>
+ </label>
+ <label for="classname">
+ <span class="required"><?= _('PHP-Klasse') ?></span>
+ <input type="text" name="classname" size="50" maxlength="255" value="<?=
+ htmlReady($step->classname) ?>" required>
+ </label>
+ <? if ($availableClasses && count($availableClasses)) : ?>
+ <div>
+ <ul class="clean">
+ <? foreach ($availableClasses as $className) : ?>
+ <li>
+ <a href="#" onClick="jQuery('input[name=classname]').val('<?= htmlReady($className) ?>');">
+ <?= Icon::create('arr_2up', 'info')->asImg(['class' => "text-bottom"]) ?>
+ <?= htmlReady($className) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </div>
+ <? endif ?>
+ <label>
+ <span class="required"> <?= _('Nummer des Schritts im Assistenten') ?></span>
+ <input type="number" name="number" size="4" maxlength="2" value="<?= $step->number ?>" required>
+ </label>
+ <label>
+ <input type="checkbox" name="enabled"<?= $step->enabled ? ' checked="checked"' : '' ?>>
+ <?= _('Schritt ist aktiv') ?>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/course_wizard_steps/index.php b/app/views/admin/course_wizard_steps/index.php
new file mode 100644
index 0000000..963d5da
--- /dev/null
+++ b/app/views/admin/course_wizard_steps/index.php
@@ -0,0 +1,79 @@
+<? if (!$has_enabled) : ?>
+ <?= MessageBox::info(_('Es gibt keine aktiven Schritte für den Anlegeassistenten!')) ?>
+<? endif ?>
+<form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= _('Vorhandene Schritte im Anlegeassistenten für Veranstaltungen') ?>
+ <span class="actions">
+ <a href="<?= $controller->url_for('admin/coursewizardsteps/edit') ?>" data-dialog="size=auto">
+ <?= Icon::create('add')->asImg(tooltip2(_('Neuen Schritt hinzufügen'))) ?>
+ </a>
+ </span>
+ </caption>
+ <colgroup>
+ <col style="width: 30%">
+ <col style="width: 30%">
+ <col style="width: 5%">
+ <col style="width: 5%">
+ <col style="width: 10%">
+ </colgroup>
+ <thead>
+ <th><?= _('Name') ?></th>
+ <th><?= _('PHP-Klasse') ?></th>
+ <th><?= _('Nummer') ?></th>
+ <th><?= _('aktiv?') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </thead>
+ <tbody>
+ <? foreach ($steps as $step) : ?>
+ <tr id="wizard-step-<?= $step->id ?>">
+ <td><?= htmlReady($step->name) ?></td>
+ <td><?= htmlReady($step->classname) ?></td>
+ <td><?= $step->number ?></td>
+ <td>
+ <a href="<?= $controller->link_for("admin/coursewizardsteps/toggle_enabled/{$step->id}") ?>" data-behaviour="ajax-toggle">
+ <? if ($step->enabled): ?>
+ <?= Icon::create('checkbox-checked') ?>
+ <? else: ?>
+ <?= Icon::create('checkbox-unchecked') ?>
+ <? endif; ?>
+ </a>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink(
+ $controller->url_for("admin/coursewizardsteps/edit/{$step->id}"),
+ _('Schritt bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+
+ <? $actionMenu->addButton(
+ 'delete_step',
+ _('Schritt löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Schritt löschen'),
+ 'formaction' => $controller->url_for("admin/coursewizardsteps/delete/{$step->id}"),
+ 'data-confirm' => sprintf(
+ _('Soll der Eintrag "%s" wirklich gelöscht werden?'),
+ htmlReady($step->name)
+ ),
+ ])
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+
+ <? if (!$steps): ?>
+ <tr>
+ <td colspan="5" style="text-align: center">
+ <?= _('Es sind keine Schritte für den Veranstaltungsanlegeassistenten registriert!') ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+</form>
diff --git a/app/views/admin/courseplanning/index.php b/app/views/admin/courseplanning/index.php
new file mode 100644
index 0000000..1b0b5e9
--- /dev/null
+++ b/app/views/admin/courseplanning/index.php
@@ -0,0 +1,53 @@
+<?
+ $min_time = Config::get()->INSTITUTE_COURSE_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->INSTITUTE_COURSE_PLAN_END_HOUR . ':00';
+?>
+
+<?= Studip\Fullcalendar::create($plan_title, [
+ 'editable' => true,
+ 'minTime' => $min_time,
+ 'maxTime' => $max_time,
+ 'allDaySlot' => false,
+ 'nowIndicator' => false,
+ 'slotDuration' => '01:00:00',
+ 'slotLabelInterval' => '01:00',
+ 'slotLabelFormat' => ['hour' => '2-digit', 'minute' => '2-digit'],
+ 'timeZone' => 'UTC',
+ 'header' => [
+ 'left' => '',
+ 'right' => ''
+ ],
+ 'columnHeaderFormat' => ['weekday' => 'long'],
+ 'defaultView' => 'timeGridWeek',
+ 'eventSources' => [compact('events')],
+ 'slotEventOverlap' => false,
+ 'displayEventTime' => false,
+ 'editable' => true,
+ 'droppable' => true, // this allows things to be dropped onto the calendar
+ 'actionCalled' => 'index'
+], [
+ 'class' => 'institute-plan'
+]) ?>
+
+<br>
+
+<? if (count($eventless_courses)) : ?>
+<table class="default" id="external-events">
+ <tr>
+ <th><?= _('Veranstaltungen ohne Termine') ?></th>
+ </tr>
+ <tr>
+ <? foreach ($eventless_courses as $cid => $cname): ?>
+ <td class="fc-event"
+ data-event-course="<?= $cid ?>"
+ data-event-title="<?= htmlReady($cname) ?>"
+ data-event-duration="02:00"
+ data-event-drop-url="<?= $controller->link_for('admin/courseplanning/add_event') ?>"
+ data-event-tooltip=""
+ >
+ <?= htmlReady($cname) ?>
+ </td>
+ <? endforeach; ?>
+ </tr>
+</table>
+<? endif; ?>
diff --git a/app/views/admin/courseplanning/nonconform.php b/app/views/admin/courseplanning/nonconform.php
new file mode 100644
index 0000000..5a7aed4
--- /dev/null
+++ b/app/views/admin/courseplanning/nonconform.php
@@ -0,0 +1,28 @@
+<table class="default">
+ <caption>
+ <?= _('Folgende regelmäßige Termine von Veranstaltungen passen nicht in das vorgegebene Zeitraster:') ?>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Nr.') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Start') ?></th>
+ <th><?= _('Ende') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($non_conform_dates as $ncd): ?>
+ <tr>
+ <td><?= htmlReady($ncd['nr']) ?></td>
+ <td>
+ <?= htmlReady($ncd['name']) ?>
+ <a href="<?= $controller->link_for('course/details/index/' . $ncd['cid']) ?>" data-dialog="size=auto">
+ <?= Icon::create('info-circle')->asImg(['class' => 'text-bottom']) ?>
+ </a>
+ </td>
+ <td><?= htmlReady($ncd['start']) ?></td>
+ <td><?= htmlReady($ncd['end']) ?></td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+</table>
diff --git a/app/views/admin/courseplanning/pick_color.php b/app/views/admin/courseplanning/pick_color.php
new file mode 100644
index 0000000..2606041
--- /dev/null
+++ b/app/views/admin/courseplanning/pick_color.php
@@ -0,0 +1,14 @@
+<form class="default" method="post" action="<?= $controller->pick_color($metadate_id, $from_action, $weekday) ?>" data-dialog="size=auto">
+ <input type="hidden" id="selected-color" name="selected-color" value="<?= $color ?>">
+
+ <div id="event-color-picker"></div>
+
+ <input id="semtype-checkbox" name="event_color_semtype" type="checkbox" class="studip-checkbox" value="1">
+ <label for="semtype-checkbox">
+ <?= sprintf(_('Farbtyp für alle VA dieses Typs (%s) übernehmen'), htmlReady($semtype)) ?>
+ </label>
+
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ </div>
+</form>
diff --git a/app/views/admin/courseplanning/rename_column.php b/app/views/admin/courseplanning/rename_column.php
new file mode 100644
index 0000000..41400ae
--- /dev/null
+++ b/app/views/admin/courseplanning/rename_column.php
@@ -0,0 +1,10 @@
+<form class="default" method="post" action="<?= $controller->link_for('admin/courseplanning/rename_column/' . $column_id . '/' . $week_day) ?>" data-dialog="size=auto">
+ <label>
+ <?= _('Spaltenname') ?>
+ <input name="column_name" type="text" value="<?= htmlReady($column_name) ?>">
+ </label>
+
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ </div>
+</form>
diff --git a/app/views/admin/courseplanning/viewcolumns.php b/app/views/admin/courseplanning/viewcolumns.php
new file mode 100644
index 0000000..da1abfa
--- /dev/null
+++ b/app/views/admin/courseplanning/viewcolumns.php
@@ -0,0 +1,46 @@
+<form class="default" method="POST" action="<?= $controller->url_for('admin/courseplanning/viewcolumns/' . $week_day) ?>" data-dialog="size=auto">
+
+ <table class="default">
+ <caption><?= _('Sichtbarkeit') ?></caption>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th ></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($columns as $col): ?>
+ <? if($col['id'] == '0') continue; ?>
+ <tr>
+ <td>
+ <input id="column_view_<?= $col['id'] ?>" name="column_view[]"
+ class="studip-checkbox" type="checkbox"
+ value="<?= $col['id'] ?>"
+ <?= $col['visible'] ? 'checked' : '' ?>>
+ <label for="column_view_<?= $col['id'] ?>"><?= htmlReady($col['title']) ?></label>
+ </td>
+ <td class="actions">
+ <?= ActionMenu::get()->addLink(
+ $controller->url_for('admin/courseplanning/remove_column', $institute_id, $col['id'], $week_day),
+ _('Spalte löschen'),
+ Icon::create('trash'),
+ [
+ 'data-confirm' => _('Wollen Sie die Spalte wirklich entfernen?'),
+ 'data-dialog' => 'size=auto',
+ ]
+ ) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+
+ <label>
+ <?= _('Zusätzliche Spalte') ?>
+ <input name="column_name" type="text" value="">
+ </label>
+
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ </div>
+</form>
diff --git a/app/views/admin/courseplanning/weekday.php b/app/views/admin/courseplanning/weekday.php
new file mode 100644
index 0000000..a0e15c7
--- /dev/null
+++ b/app/views/admin/courseplanning/weekday.php
@@ -0,0 +1,63 @@
+<?
+ $min_time = Config::get()->INSTITUTE_COURSE_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->INSTITUTE_COURSE_PLAN_END_HOUR . ':00';
+?>
+
+<? $days = ['Sonntag', 'Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag']; ?>
+<div class="calendar-caption">
+ <?= $days[$cal_date->format('w')] ?>
+ <a href="<?= $controller->link_for('admin/courseplanning/index') ?>">
+ (<?= _('zurück zur Übersicht'); ?>)
+ </a>
+</div>
+
+<?= Studip\Fullcalendar::create($plan_title, [
+ 'editable' => true,
+ 'minTime' => $min_time,
+ 'maxTime' => $max_time,
+ 'allDaySlot' => false,
+ 'nowIndicator' => false,
+ 'header' => [
+ 'left' => '',
+ 'right' => ''
+ ],
+ 'slotDuration' => '01:00:00',
+ 'slotLabelInterval' => '01:00',
+ 'slotLabelFormat' => ['hour' => '2-digit', 'minute' => '2-digit'],
+ 'timeZone' => 'UTC',
+ 'defaultDate' => $cal_date->format('Y-m-d'),
+ 'defaultView' => 'resourceTimeGridDay',
+ 'eventSources' => [compact('events')],
+ 'slotEventOverlap' => false,
+ 'displayEventTime' => false,
+ 'editable' => true,
+ 'droppable' => true, // this allows things to be dropped onto the calendar
+ 'resources' => $columns,
+ 'actionCalled' => 'weekday/' . $cal_date->format('w')
+], [
+ 'class' => 'institute-plan'
+]) ?>
+
+<br>
+
+<? if (count($eventless_courses)) : ?>
+<table class="default" id="external-events">
+ <tr>
+ <th><?= _('Veranstaltungen ohne Termine') ?></th>
+ </tr>
+ <tr>
+ <? foreach ($eventless_courses as $cid => $cname): ?>
+ <td
+ class="fc-event"
+ data-event-course="<?= $cid ?>"
+ data-event-title="<?= htmlReady($cname) ?>"
+ data-event-duration="02:00"
+ data-event-drop-url="<?= $controller->link_for('admin/courseplanning/add_event') ?>"
+ data-event-tooltip=""
+ >
+ <?= htmlReady($cname) ?>
+ </td>
+ <? endforeach; ?>
+ </tr>
+</table>
+<? endif; ?>
diff --git a/app/views/admin/courses/_course.php b/app/views/admin/courses/_course.php
new file mode 100644
index 0000000..590fc3b
--- /dev/null
+++ b/app/views/admin/courses/_course.php
@@ -0,0 +1,207 @@
+<?php
+/*
+ * Show course only if it has no parent course or the parent course is not
+ * part of the current view. Otherwise the current course will be listed
+ * as subcourse under its parent.
+ */
+if (!$values['parent_course'] || !in_array($values['parent_course'], array_keys($courses))) : ?>
+ <?php
+ $course = Course::find($semid);
+ $children = [];
+ if ($GLOBALS['SEM_CLASS'][$GLOBALS['SEM_TYPE'][$values['status']]['class']]['is_group']) {
+ $children = Course::findbyParent_Course($semid);
+ }
+ ?>
+ <tr id="course-<?= $semid ?>"<?= $parent ? ' class="subcourses subcourse-' . $parent . '"' : '' ?> data-course-id="<?= $semid ?>">
+ <td>
+ <? if (Config::get()->ADMIN_COURSES_SHOW_COMPLETE): ?>
+ <? if ($GLOBALS['perm']->have_studip_perm('tutor', $semid)) : ?>
+ <a href="<?= $controller->url_for('admin/courses/toggle_complete/' . $semid) ?>"
+ class="course-completion"
+ data-course-completion="<?= $values['completion'] ?>"
+ title="<?= _('Bearbeitungsstatus ändern') ?>">
+ <?= _('Bearbeitungsstatus ändern') ?>
+ </a>
+ <? else : ?>
+ <?= $course->getCompletionIcon()->asImg(['title' => _('Bearbeitungsstatus kann nicht von Ihnen geändert werden.')]) ?>
+ <? endif ?>
+ <? else: ?>
+ <?= CourseAvatar::getAvatar($semid)->getImageTag(Avatar::SMALL, ['title' => trim($values['Name'])]) ?>
+ <? endif; ?>
+ </td>
+ <? if (in_array('number', $view_filter)) : ?>
+ <td>
+ <? if ($GLOBALS['perm']->have_studip_perm('autor', $semid)) : ?>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $semid]) ?>">
+ <? endif ?>
+ <?= htmlReady($values["VeranstaltungsNummer"]) ?>
+ <? if ($GLOBALS['perm']->have_studip_perm('autor', $semid)) : ?>
+ </a>
+ <? endif ?>
+ </td>
+ <? endif ?>
+ <? if (in_array('name', $view_filter)) : ?>
+ <td>
+ <? if ($GLOBALS['perm']->have_studip_perm("autor", $semid)) : ?>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $semid]) ?>">
+ <? endif ?>
+ <?= htmlReady(trim($values['Name'])) ?>
+ <? if ($GLOBALS['perm']->have_studip_perm("autor", $semid)) : ?>
+ </a>
+ <? endif ?>
+ <a data-dialog="buttons=false" href="<?= $controller->url_for(sprintf('course/details/index/%s', $semid)) ?>">
+ <? $params = tooltip2(_("Veranstaltungsdetails anzeigen")); ?>
+ <? $params['style'] = 'cursor: pointer'; ?>
+ <?= Icon::create('info-circle', 'inactive')->asImg($params) ?>
+ </a>
+ <? if ($values["visible"] == 0) : ?>
+ <?= _("(versteckt)") ?>
+ <? endif ?>
+ <?php if (count($children) > 0) : ?>
+ <br>
+ <a href="" class="toggle-subcourses" data-get-subcourses-url="<?= $controller->url_for('admin/courses/get_subcourses', $semid) ?>">
+ <?= Icon::create('add', 'clickable')->asImg(12) ?>
+ <?= Icon::create('remove', 'clickable', ['class' => 'hidden-js'])->asImg(12) ?>
+ <?= sprintf(
+ ngettext('%u Unterveranstaltung', '%u Unterveranstaltungen',
+ count($children)),
+ count($children)) ?>
+ </a>
+ <?php endif ?>
+ </td>
+ <? endif ?>
+ <? if (in_array('type', $view_filter)) : ?>
+ <td>
+ <?= htmlReady($GLOBALS['SEM_CLASS'][$GLOBALS['SEM_TYPE'][$values["status"]]["class"]]['name']) ?>:
+ <strong><?= htmlReady($GLOBALS['SEM_TYPE'][$values["status"]]["name"]) ?></strong>
+ </td>
+ <? endif ?>
+ <? if (in_array('room_time', $view_filter)) : ?>
+ <td class="raumzeit">
+ <?= Seminar::GetInstance($semid)->getDatesHTML([
+ 'semester_id' => $semester ? $semester->id : null,
+ 'show_room' => true,
+ ]) ?: _('nicht angegeben') ?>
+ </td>
+ <? endif ?>
+ <? if (in_array('semester', $view_filter)) : ?>
+ <td>
+ <?= htmlReady($course->semester_text) ?>
+ </td>
+ <? endif?>
+ <? if (in_array('requests', $view_filter)) : ?>
+ <td style="text-align: center;">
+ <a title="<?=_('Raumanfragen')?>" href="<?= URLHelper::getLink('dispatch.php/course/room_requests', ['cid' => $semid])?>">
+ <?= $values['requests'] ?>
+ </a>
+ </td>
+ <? endif ?>
+ <? if (in_array('teachers', $view_filter)) : ?>
+ <td>
+ <?= $this->render_partial_collection('my_courses/_dozent', $values['dozenten']) ?>
+
+ </td>
+ <? endif ?>
+ <? if (in_array('members', $view_filter)) : ?>
+ <td style="text-align: center;">
+ <a title="<?=_('Teilnehmende')?>" href="<?= URLHelper::getLink('dispatch.php/course/members', ['cid' => $semid])?>">
+ <?= $values["teilnehmer"] ?>
+ </a>
+ </td>
+ <? endif ?>
+ <? if (in_array('waiting', $view_filter)) : ?>
+ <td style="text-align: center;">
+ <a title="<?=_('Teilnehmende auf der Warteliste')?>" href="<?= URLHelper::getLink('dispatch.php/course/members', ['cid' => $semid])?>">
+ <?= $values["waiting"] ?>
+ </a>
+ </td>
+ <? endif ?>
+ <? if (in_array('preliminary', $view_filter)) : ?>
+ <td style="text-align: center;">
+ <a title="<?=_('Vorläufige Anmeldungen') ?>" href="<?= URLHelper::getLink('dispatch.php/course/members', ['cid' => $semid])?>">
+ <?= $values['prelim'] ?>
+ </a>
+ </td>
+ <? endif ?>
+ <? if (in_array('contents', $view_filter)) : ?>
+ <td style="text-align: left; white-space: nowrap;">
+ <? if (!empty($values['navigation'])) : ?>
+ <? foreach (MyRealmModel::array_rtrim($values['navigation']) as $key => $nav) : ?>
+ <? if ($nav instanceof Navigation && $nav->isVisible(true)) : ?>
+ <a href="<?=
+ UrlHelper::getLink('seminar_main.php',
+ ['auswahl' => $semid,
+ 'redirect_to' => strtr($nav->getURL(), '?', '&')]) ?>" <?= $nav->hasBadgeNumber() ? 'class="badge" data-badge-number="' . intval($nav->getBadgeNumber()) . '"' : '' ?>>
+ <?= $nav->getImage()->asImg(20, $nav->getLinkAttributes()) ?>
+ </a>
+ <? elseif (is_string($key)) : ?>
+ <?=
+ Assets::img('blank.gif', ['width' => 20,
+ 'height' => 20]); ?>
+ <? endif ?>
+ <? echo ' ' ?>
+ <? endforeach ?>
+ <? endif ?>
+ </td>
+ <? endif ?>
+ <? if (in_array('last_activity', $view_filter)) : ?>
+ <td style="text-align: center;">
+ <span title="<?=_('Datum der letzten Aktivität in dieser Veranstaltung')?>">
+ <?= htmlReady(date('d.m.Y', $values['last_activity'])); ?>
+ </span>
+ </td>
+ <? endif ?>
+ <? foreach (PluginManager::getInstance()->getPlugins("AdminCourseContents") as $plugin) : ?>
+ <? foreach ($plugin->adminAvailableContents() as $index => $label) : ?>
+ <? if (in_array($plugin->getPluginId()."_".$index, $view_filter)) : ?>
+ <td style="text-align: center;">
+ <? $content = $plugin->adminAreaGetCourseContent($course, $index) ?>
+ <?= is_a($content, "Flexi_Template") ? $content->render() : $content ?>
+ </td>
+ <? endif ?>
+ <? endforeach ?>
+ <? endforeach ?>
+ <td class="actions">
+ <? if (isset($actions[$selected_action]['partial']) && is_numeric($selected_action) && $GLOBALS['perm']->have_studip_perm('tutor', $semid)) : ?>
+ <?= $this->render_partial("admin/courses/{$actions[$selected_action]['partial']}", [
+ 'course' => $course,
+ 'values' => $values,
+ 'action' => $actions[$selected_action],
+ ]) ?>
+ <? elseif (!is_numeric($selected_action)) : ?>
+ <? $plugin = PluginManager::getInstance()->getPlugin($selected_action) ?>
+ <? $template = $plugin->getAdminCourseActionTemplate($semid, $values) ?>
+ <? if ($template) : ?>
+ <?= $template->render() ?>
+ <? elseif ($GLOBALS['perm']->have_studip_perm('tutor', $semid)) : ?>
+ <?=
+ \Studip\LinkButton::create(
+ $actions[$selected_action]['title'],
+ URLHelper::getURL(sprintf($actions[$selected_action]['url'], $semid),
+ ($actions[$selected_action]['params'] ? $actions[$selected_action]['params'] : [])),
+ ($actions[$selected_action]['attributes'] ? $actions[$selected_action]['attributes'] : [])
+ ) ?>
+ <? endif ?>
+ <? elseif ($GLOBALS['perm']->have_studip_perm('tutor', $semid)) : ?>
+ <? $lockrules = [
+ '2' => "sem_tree",
+ '3' => "room_time",
+ '11' => "seminar_copy",
+ '14' => "admission_type",
+ '16' => "seminar_archive",
+ '17' => "admission_type",
+ '18' => 'room_time'
+ ] ?>
+ <? if ($GLOBALS['perm']->have_studip_perm("admin", $semid) || !isset($lockrules[$selected_action]) || !LockRules::Check($semid, $lockrules[$selected_action])) : ?>
+ <?=
+ \Studip\LinkButton::create(
+ $actions[$selected_action]['title'],
+ URLHelper::getURL(sprintf($actions[$selected_action]['url'], $semid),
+ ($actions[$selected_action]['params'] ? $actions[$selected_action]['params'] : [])),
+ ($actions[$selected_action]['attributes'] ? $actions[$selected_action]['attributes'] : [])
+ ) ?>
+ <? endif ?>
+ <? endif ?>
+ </td>
+ </tr>
+<?php endif ?>
diff --git a/app/views/admin/courses/add_to_archive.php b/app/views/admin/courses/add_to_archive.php
new file mode 100644
index 0000000..1d96f98
--- /dev/null
+++ b/app/views/admin/courses/add_to_archive.php
@@ -0,0 +1,3 @@
+<label>
+ <input name="archiv_sem[]" type="checkbox" value="<?= htmlReady($course->id) ?>">
+</label>
diff --git a/app/views/admin/courses/additional_inputs.php b/app/views/admin/courses/additional_inputs.php
new file mode 100644
index 0000000..5d84f69
--- /dev/null
+++ b/app/views/admin/courses/additional_inputs.php
@@ -0,0 +1,28 @@
+<tr>
+ <th colspan="<?= $colspan ?>" style="text-align: right">
+ <? switch ($selected_action) {
+ case 8 :
+ echo $this->render_partial('admin/courses/lock_preselect.php', compact('values', 'semid'));
+ break;
+ default:
+ case 9:
+ echo '<label>', _('Alle auswählen'), '<input title="', _('Alle auswählen'), '"
+ type="checkbox" name="all" value="1" data-proxyfor=".course-admin td:last-child :checkbox" aria-label="',
+ _('Alle auswählen'), '"/></label>';
+ break;
+ case 10:
+ echo $this->render_partial('admin/courses/aux_preselect.php', compact('values', 'semid'));
+ break;
+ case 16:
+ echo '<label>', _('Alle auswählen'), '<input title="', _('Alle auswählen'), '"
+ type="checkbox" name="all" value="1" data-proxyfor=":checkbox[name^=archiv_sem]" aria-label="',
+ _('Alle auswählen'), '"/></label>';
+ break;
+ case 17:
+ echo '<label>', _('Alle auswählen'), '<input title="', _('Alle auswählen'), '"
+ type="checkbox" name="all" value="1" data-proxyfor=":checkbox[name^=admission_locked]" aria-label="',
+ _('Alle auswählen'), '"/></label>';
+ break;
+ }?>
+ </th>
+</tr> \ No newline at end of file
diff --git a/app/views/admin/courses/admission_locked.php b/app/views/admin/courses/admission_locked.php
new file mode 100644
index 0000000..20e6f0a
--- /dev/null
+++ b/app/views/admin/courses/admission_locked.php
@@ -0,0 +1,6 @@
+<input type="hidden" name="all_sem[]" value="<?= htmlReady($course->id) ?>">
+<label>
+ <input type="checkbox" <?= $values['admission_locked'] == 'disable' ? 'disabled' : '' ?>
+ name="admission_locked[<?= htmlReady($course->id) ?>]"
+ value="1" <?= $values['admission_locked'] ? 'checked' : '' ?>>
+</label>
diff --git a/app/views/admin/courses/aux-select.php b/app/views/admin/courses/aux-select.php
new file mode 100644
index 0000000..9088902
--- /dev/null
+++ b/app/views/admin/courses/aux-select.php
@@ -0,0 +1,13 @@
+<select name="lock_sem[<?= htmlReady($course->id) ?>]" style="max-width: 200px">
+<? foreach ($aux_lock_rules as $id => $rule) : ?>
+ <option value="<?= $id ?>" <?= $values['aux_lock_rule'] == $id ? 'selected' : '' ?>>
+ <?= htmlReady($rule['name']) ?>
+ </option>
+<? endforeach ?>
+</select>
+<br>
+<label>
+ <input type="checkbox" value="1" name="lock_sem_forced[<?= htmlReady($course->id) ?>]"
+ <?= $values['aux_lock_rule_forced'] ? 'checked' : '' ?>>
+ <?=_('Erzwungen')?>
+</label>
diff --git a/app/views/admin/courses/aux_preselect.php b/app/views/admin/courses/aux_preselect.php
new file mode 100644
index 0000000..86e88be
--- /dev/null
+++ b/app/views/admin/courses/aux_preselect.php
@@ -0,0 +1,15 @@
+<label><?= _('Für alle Veranstaltungen') ?>
+ <select name="lock_sem_all" style="max-width: 200px">
+ <? foreach ($aux_lock_rules as $id => $rule) : ?>
+ <option value="<?= $id ?>"
+ <?= ($values['aux_lock_rule'] == $id) ? 'selected' : '' ?>>
+ <?= htmlReady($rule["name"]) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+</label>
+<label>
+<input type="checkbox" value="1" name="aux_all_forced">
+<?=_("Erzwungen")?>
+</label>
+<?= \Studip\Button::createAccept(_('Speichern'), 'all'); ?> \ No newline at end of file
diff --git a/app/views/admin/courses/courses.php b/app/views/admin/courses/courses.php
new file mode 100644
index 0000000..ca851d0
--- /dev/null
+++ b/app/views/admin/courses/courses.php
@@ -0,0 +1,235 @@
+<? $colspan = 2 ?>
+<? if ($actions[$selected_action]['multimode']) : ?>
+ <form action="<?= URLHelper::getLink($actions[$selected_action]['url']) ?>" method="post">
+<? endif ?>
+<?= CSRFProtection::tokenTag() ?>
+<table class="default course-admin">
+ <colgroup>
+ <col width="2%">
+ <? if (in_array('number', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="8%">
+ <? endif ?>
+ <? if (in_array('name', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col>
+ <? endif ?>
+ <? if (in_array('type', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="10%">
+ <? endif ?>
+ <? if (in_array('room_time', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="30%">
+ <? endif ?>
+ <? if (in_array('semester', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="10%">
+ <? endif ?>
+ <? if (in_array('requests', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="5%">
+ <? endif ?>
+ <? if (in_array('teachers', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="10%">
+ <? endif ?>
+ <? if (in_array('members', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="3%">
+ <? endif ?>
+ <? if (in_array('waiting', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="5%">
+ <? endif ?>
+ <? if (in_array('preliminary', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="5%">
+ <? endif ?>
+ <? if (in_array('contents', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="8%">
+ <? endif ?>
+ <? if (in_array('last_activity', $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="8%">
+ <? endif ?>
+ <? foreach (PluginManager::getInstance()->getPlugins("AdminCourseContents") as $plugin) : ?>
+ <? foreach ($plugin->adminAvailableContents() as $index => $label) : ?>
+ <? if (in_array($plugin->getPluginId()."_".$index, $view_filter)) : ?>
+ <? $colspan++ ?>
+ <col width="8%">
+ <? endif ?>
+ <? endforeach ?>
+ <? endforeach ?>
+ <col width="15%">
+
+ </colgroup>
+ <caption>
+ <? if (!$GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE || ($GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE === "all")) : ?>
+ <?= _('Veranstaltungen') ?>
+ <? else : ?>
+ <?= htmlReady(sprintf(_('Veranstaltungen im %s'), $semester->name)) ?>
+ <? endif ?>
+ <span class="actions">
+ <?= sprintf('%u %s', $count_courses, $count_courses > 1 ? _('Veranstaltungen') : _('Veranstaltung')) ?>
+ </span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <? if (Config::get()->ADMIN_COURSES_SHOW_COMPLETE): ?>
+ <th <? if ($sortby === 'completion') printf('class="sort%s"', mb_strtolower($sortFlag)) ?>>
+ <a href="<?= URLHelper::getLink('', ['sortby' => 'completion', 'sortFlag' => mb_strtolower($sortFlag)]) ?>" class="course-completion" title="<?= _('Bearbeitungsstatus') ?>">
+ <?= _('Bearbeitungsstatus') ?>
+ </a>
+ </th>
+ <? else: ?>
+ <th>
+ &nbsp;
+ </th>
+ <? endif; ?>
+ <? if (in_array('number', $view_filter)) : ?>
+ <th <?= ($sortby == 'VeranstaltungsNummer') ? sprintf('class="sort%s"', mb_strtolower($sortFlag)) : '' ?>>
+ <a href="<?=
+ URLHelper::getLink('', ['sortby' => 'VeranstaltungsNummer',
+ 'sortFlag' => mb_strtolower($sortFlag)]) ?>">
+ <?= _('Nr.') ?>
+ </a>
+ </th>
+ <? endif ?>
+ <? if (in_array('name', $view_filter)) : ?>
+ <th <?= ($sortby == 'Name') ? sprintf('class="sort%s"', mb_strtolower($sortFlag)) : '' ?>>
+ <a href="<?=
+ URLHelper::getLink('', ['sortby' => 'Name',
+ 'sortFlag' => mb_strtolower($sortFlag)]) ?>">
+ <?= _('Name') ?>
+ </a>
+ </th>
+ <? endif ?>
+ <? if (in_array('type', $view_filter)) : ?>
+ <th <?= ($sortby == 'status') ? sprintf('class="sort%s"', mb_strtolower($sortFlag)) : '' ?>>
+ <a href="<?=
+ URLHelper::getLink('', ['sortby' => 'status',
+ 'sortFlag' => mb_strtolower($sortFlag)]) ?>">
+ <?= _("VA-Typ") ?>
+ </a>
+ </th>
+ <? endif ?>
+ <? if (in_array('room_time', $view_filter)) : ?>
+ <th><?= _('Raum/Zeit') ?></th>
+ <? endif ?>
+ <? if (in_array('semester', $view_filter)) : ?>
+ <th <?= ($sortby == 'start_time') ? sprintf('class="sort%s"', mb_strtolower($sortFlag)) : '' ?>>
+ <a href="<?= URLHelper::getLink('', ['sortby' => 'start_time', 'sortFlag' => mb_strtolower($sortFlag)]) ?>">
+ <?= _('Semester') ?>
+ </a>
+ </th>
+ <? endif ?>
+ <? if (in_array('requests', $view_filter)) : ?>
+ <th <?= ($sortby == 'requests') ? sprintf('class="sort%s"', mb_strtolower($sortFlag)) : '' ?>>
+ <a href="<?=
+ URLHelper::getLink('', ['sortby' => 'requests',
+ 'sortFlag' => mb_strtolower($sortFlag)]) ?>">
+ <abbr title="<?= _('Raumanfragen') ?>">
+ <?= _('RA') ?>
+ </abbr>
+ </a>
+ </th>
+ <? endif ?>
+ <? if (in_array('teachers', $view_filter)) : ?>
+ <th><?= _('Lehrende') ?></th>
+ <? endif ?>
+ <? if (in_array('members', $view_filter)) : ?>
+ <th <?= ($sortby == 'teilnehmer') ? sprintf('class="sort%s"', mb_strtolower($sortFlag)) : '' ?>>
+ <a href="<?=
+ URLHelper::getLink('', ['sortby' => 'teilnehmer',
+ 'sortFlag' => mb_strtolower($sortFlag)]) ?>">
+ <abbr title="<?= _('Teilnehmende') ?>">
+ <?= _('TN') ?>
+ </abbr>
+ </a>
+ </th>
+ <? endif ?>
+ <? if (in_array('waiting', $view_filter)) : ?>
+ <th <? if ($sortby == 'waiting') printf('class="sort%s"', mb_strtolower($sortFlag)); ?>>
+ <a href="<?= URLHelper::getLink('', ['sortby' => 'waiting',
+ 'sortFlag' => mb_strtolower($sortFlag)]) ?>">
+ <?= _('Warteliste') ?>
+ </a>
+ </th>
+ <? endif ?>
+ <? if (in_array('preliminary', $view_filter)) : ?>
+ <th <?= ($sortby == 'prelim') ? sprintf('class="sort%s"', mb_strtolower($sortFlag)) : '' ?>>
+ <a href="<?=
+ URLHelper::getLink('', ['sortby' => 'prelim',
+ 'sortFlag' => mb_strtolower($sortFlag)]) ?>"><?= _('Vorläufig') ?></a>
+ </th>
+ <? endif ?>
+ <? if (in_array('contents', $view_filter)) : ?>
+ <th style="width: <?= $nav_elements * 27 ?>px">
+ <?= _('Inhalt') ?>
+ </th>
+ <? endif ?>
+ <? if (in_array('last_activity', $view_filter)) : ?>
+ <th style="width: <?= $nav_elements * 27 ?>px">
+ <?= _('letzte Aktivität') ?>
+ </th>
+ <? endif ?>
+ <? foreach (PluginManager::getInstance()->getPlugins("AdminCourseContents") as $plugin) : ?>
+ <? foreach ($plugin->adminAvailableContents() as $index => $label) : ?>
+ <? if (in_array($plugin->getPluginId()."_".$index, $view_filter)) : ?>
+ <th style="width: <?= $nav_elements * 27 ?>px"><?= htmlReady($label) ?></th>
+ <? endif ?>
+ <? endforeach ?>
+ <? endforeach ?>
+ <th style="text-align: center" class="actions">
+ <?= _('Aktion') ?>
+ </th>
+ </tr>
+ <? if ($actions[$selected_action]['multimode']) : ?>
+ <?= $this->render_partial('admin/courses/additional_inputs.php', compact('colspan')) ?>
+ <? if (count($courses) > 10): ?>
+ <tr>
+ <th colspan="<?= $colspan ?>" style="text-align: right">
+ <? if (is_a($actions[$selected_action]['multimode'], "\\Studip\\Button")) : ?>
+ <?= $actions[$selected_action]['multimode'] ?>
+ <? else : ?>
+ <?= Studip\Button::createAccept(
+ is_string($actions[$selected_action]['multimode'])
+ ? $actions[$selected_action]['multimode']
+ : $actions[$selected_action]['title'],
+ 'save_action',
+ $selected_action == 16 ? ['data-dialog' => 1] : null) ?>
+ <? endif ?>
+ </th>
+ </tr>
+ <? endif; ?>
+ <? endif ?>
+ </thead>
+ <tbody>
+ <? foreach ($courses as $semid => $values) : ?>
+ <?= $this->render_partial('admin/courses/_course', compact('semid', 'values', 'view_filter', 'actions', 'selected_action', 'courses')) ?>
+ <? endforeach ?>
+ </tbody>
+<? if ($actions[$selected_action]['multimode']) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="<?= $colspan ?>" style="text-align: right">
+ <? if (is_a($actions[$selected_action]['multimode'], "\\Studip\\Button")) : ?>
+ <?= $actions[$selected_action]['multimode'] ?>
+ <? else : ?>
+ <?= Studip\Button::createAccept(
+ is_string($actions[$selected_action]['multimode'])
+ ? $actions[$selected_action]['multimode']
+ : $actions[$selected_action]['title'],
+ $actions[$selected_action]['name'],
+ $selected_action == 16 ? ['data-dialog' => 1] : null) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+</table>
+<? if ($actions[$selected_action]['multimode']) : ?>
+</form>
+<? endif ?>
diff --git a/app/views/admin/courses/export_csv.php b/app/views/admin/courses/export_csv.php
new file mode 100644
index 0000000..795c300
--- /dev/null
+++ b/app/views/admin/courses/export_csv.php
@@ -0,0 +1,16 @@
+<form action="<?= $controller->link_for('admin/courses/export_csv') ?>" method="get" class="default">
+ <fieldset>
+ <? foreach ($fields as $index => $name) : ?>
+ <? if ($index !== 'contents') : ?>
+ <label>
+ <input type="checkbox" name="fields[]" value="<?= htmlReady($index) ?>"
+ <?= in_array($index, $selection) ? ' checked' : "" ?>>
+ <?= htmlReady($name) ?>
+ </label>
+ <? endif ?>
+ <? endforeach ?>
+ </fieldset>
+ <div data-dialog-button>
+ <?= Studip\Button::create(_('Auswahl exportieren')) ?>
+ </div>
+</form>
diff --git a/app/views/admin/courses/get_subcourses.php b/app/views/admin/courses/get_subcourses.php
new file mode 100644
index 0000000..dfa0d21
--- /dev/null
+++ b/app/views/admin/courses/get_subcourses.php
@@ -0,0 +1,3 @@
+<?php foreach ($courses as $semid => $values) : ?>
+ <?= $this->render_partial('admin/courses/_course', compact('semid', 'values', 'view_filter', 'actions', 'selected_action', 'parent', 'courses')) ?>
+<?php endforeach;
diff --git a/app/views/admin/courses/index.php b/app/views/admin/courses/index.php
new file mode 100644
index 0000000..c5a17c8
--- /dev/null
+++ b/app/views/admin/courses/index.php
@@ -0,0 +1,14 @@
+<? if (empty($insts)): ?>
+ <?= MessageBox::info(sprintf(_('Sie wurden noch keinen Einrichtungen zugeordnet. Bitte wenden Sie sich an einen der zuständigen %sAdministratoren%s.'), '<a href="' . URLHelper::getLink('dispatch.php/siteinfo/show') . '">', '</a>')) ?>
+<? elseif (!empty($courses)): ?>
+ <?= $this->render_partial('admin/courses/courses.php', compact('courses')) ?>
+<? elseif ($count_courses): ?>
+ <?= MessageBox::info(sprintf(
+ _('Es wurden %u Veranstaltungen gefunden. Grenzen Sie das Suchergebnis mit den Filtermöglichkeiten weiter ein, oder %slassen Sie sich alle Veranstaltungen anzeigen%s.'),
+ $count_courses,
+ '<a href="' . $controller->url_for('admin/courses', ['display' => 'all']) . '">',
+ '</a>'
+ )) ?>
+<? else: ?>
+ <?= MessageBox::info(_('Ihre Suche ergab keine Treffer')) ?>
+<? endif; ?>
diff --git a/app/views/admin/courses/lock.php b/app/views/admin/courses/lock.php
new file mode 100644
index 0000000..83d2c11
--- /dev/null
+++ b/app/views/admin/courses/lock.php
@@ -0,0 +1,12 @@
+<? $current_lock_rule = $all_lock_rules->findOneBy('lock_id', $values['lock_rule']); ?>
+<? if (!$GLOBALS['perm']->have_perm('root') && ($current_lock_rule['permission'] == 'admin' || $current_lock_rule['permission'] == 'root')) : ?>
+ <?= htmlReady($current_lock_rule['name'])?>
+<? else : ?>
+ <select name="lock_sem[<?= htmlReady($course->id) ?>]" style="max-width: 200px">
+ <? foreach ($all_lock_rules as $lock_rule): ?>
+ <option value="<?= $lock_rule['lock_id'] ?>" <?= $lock_rule['lock_id'] == $values['lock_rule'] ? 'selected' : '' ?>>
+ <?= htmlReady($lock_rule['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+<? endif ?>
diff --git a/app/views/admin/courses/lock_preselect.php b/app/views/admin/courses/lock_preselect.php
new file mode 100644
index 0000000..ced1499
--- /dev/null
+++ b/app/views/admin/courses/lock_preselect.php
@@ -0,0 +1,12 @@
+<label><?= _('Für alle Veranstaltungen') ?>
+ <select name="lock_sem_all" style="max-width: 200px">
+ <? for ($i = 0; $i < count($all_lock_rules); $i++) : ?>
+ <option value="<?= $all_lock_rules[$i]["lock_id"] ?>"
+ <?= ($all_lock_rules[$i]["lock_id"] == $values['lock_rule']) ? 'selected' : '' ?>>
+ <?= htmlReady($all_lock_rules[$i]["name"]) ?>
+ </option>
+ <? endfor ?>
+ </select>
+</label>
+
+<?= \Studip\Button::createAccept(_('Zuweisen'), 'all'); ?> \ No newline at end of file
diff --git a/app/views/admin/courses/notice-action.php b/app/views/admin/courses/notice-action.php
new file mode 100644
index 0000000..c9866e1
--- /dev/null
+++ b/app/views/admin/courses/notice-action.php
@@ -0,0 +1,16 @@
+<?php
+ $notice = $course->config->COURSE_ADMIN_NOTICE;
+ $method = $notice ? 'createHasNotice' : 'createHasNoNotice';
+?>
+
+<?= Studip\LinkButton::$method(
+ _('Notiz'),
+ URLHelper::getURL(
+ sprintf($action['url'], $course->id),
+ $action['params'] ?? []
+ ),
+ array_merge($action['attributes'] ?? [], [
+ 'class' => 'admin-courses-action-button',
+ 'title' => $notice,
+ ])
+) ?>
diff --git a/app/views/admin/courses/notice.php b/app/views/admin/courses/notice.php
new file mode 100644
index 0000000..00e6f57
--- /dev/null
+++ b/app/views/admin/courses/notice.php
@@ -0,0 +1,20 @@
+<form action="<?= $controller->notice($course) ?>" method="post" data-dialog class="default">
+ <fieldset>
+ <legend>
+ <?= sprintf(_('Notiz für "%s"'), htmlReady($course->getFullName())) ?>
+ </legend>
+
+ <label>
+ <?= _('Notiz') ?>
+ <textarea name="notice"><?= htmlReady($notice) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ URLHelper::getLink("dispatch.php/admin/course/index#course-{$course->id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/courses/sidebar.php b/app/views/admin/courses/sidebar.php
new file mode 100644
index 0000000..a2a1d2c
--- /dev/null
+++ b/app/views/admin/courses/sidebar.php
@@ -0,0 +1,68 @@
+<form class="default" method="post"
+ action="<?= URLHelper::getLink('dispatch.php/admin/courses/sidebar'); ?>" >
+ <input type="hidden" name="updateConfig" value="1">
+ <fieldset>
+ <legend><?= _('Standardfelder') ?></legend>
+ <label>
+ <input name="searchActive" type="checkbox" value="1"
+ <?= ($userSelectedElements['search']) ? 'checked="checked"' : '' ?>
+ >
+ <?= _('Freie Suche'); ?>
+ </label>
+
+ <label>
+ <input name="instituteActive" type="checkbox" value="1"
+ <?= ($userSelectedElements['institute']) ? 'checked="checked"' : '' ?>
+ >
+ <?= _('Einrichtung'); ?>
+ </label>
+ <label>
+ <input name="semesterActive" type="checkbox" value="1"
+ <?= ($userSelectedElements['semester']) ? 'checked="checked"' : '' ?>
+ >
+ <?= _('Semester'); ?>
+ </label>
+ <label>
+ <input name="stgteilActive" type="checkbox" value="1"
+ <?= ($userSelectedElements['stgteil']) ? 'checked="checked"' : '' ?>
+ >
+ <?= _('Studiengangteil'); ?>
+ </label>
+ <label>
+ <input name="courseTypeActive" type="checkbox" value="1"
+ <?= ($userSelectedElements['courseType']) ? 'checked="checked"' : '' ?>
+ >
+ <?= _('Veranstaltungstypfilter'); ?>
+ </label>
+ <label>
+ <input name="teacherActive" type="checkbox" value="1"
+ <?= ($userSelectedElements['teacher']) ? 'checked="checked"' : '' ?>
+ >
+ <?= _('Lehrperson'); ?>
+ </label>
+ <label>
+ <input name="viewFilterActive" type="checkbox" value="1"
+ <?= ($userSelectedElements['viewFilter']) ? 'checked="checked"' : '' ?>
+ >
+ <?= _('Darstellungsfilter'); ?>
+ </label>
+ </fieldset>
+ <? if ($datafields): ?>
+ <fieldset>
+ <legend><?= _('Datenfelder') ?></legend>
+ <? foreach ($datafields as $datafield): ?>
+ <label>
+ <input name="activeDatafields[]" type="checkbox" value="<?= htmlReady($datafield->id) ?>"
+ <? if ($userSelectedElements['datafields']) : ?>
+ <?= in_array($datafield->id, $userSelectedElements['datafields']) ? 'checked="checked"' : '' ?>
+ <? endif ?>
+ >
+ <?= $datafield->name ?>
+ </label>
+ <? endforeach ?>
+ </fieldset>
+ <? endif ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern')); ?>
+ </div>
+</form>
diff --git a/app/views/admin/courses/visibility.php b/app/views/admin/courses/visibility.php
new file mode 100644
index 0000000..90447f9
--- /dev/null
+++ b/app/views/admin/courses/visibility.php
@@ -0,0 +1,6 @@
+<? if ($GLOBALS['perm']->have_perm("admin") || !LockRules::Check($course->id, "seminar_visibility")) : ?>
+ <label>
+ <input type="hidden" name="all_sem[]" value="<?= htmlReady($course->id) ?>">
+ <input name="visibility[<?= htmlReady($course->id) ?>]" type="checkbox" value="1" <?= $values['visible'] ? 'checked' : '' ?>>
+ </label>
+<? endif ?>
diff --git a/app/views/admin/cronjobs/logs/display.php b/app/views/admin/cronjobs/logs/display.php
new file mode 100644
index 0000000..6a0e0bc
--- /dev/null
+++ b/app/views/admin/cronjobs/logs/display.php
@@ -0,0 +1,34 @@
+<dl class="cronlog">
+ <dt><?= _('Cronjob') ?></dt>
+ <dd><?= htmlReady($log->schedule->title) ?></dd>
+
+ <dt><?= _('Aufgabe') ?></dt>
+ <dd><?= htmlReady($log->schedule->task->name) ?></dd>
+
+ <dt><?= _('Geplante Ausführung') ?></dt>
+ <dd><?= date('d.m.Y H:i:s', $log->scheduled) ?></dd>
+
+ <dt><?= _('Tatsächliche Ausführung') ?></dt>
+ <dd><?= date('d.m.Y H:i:s', $log->executed) ?></dd>
+
+ <dt><?= _('Ausführungsdauer') ?></dt>
+ <dd>
+ <? if ($log->duration == -1): ?>
+ <?= _('Cronjob läuft noch oder wurde durch einen Fehler abgebrochen') ?>
+ <? else: ?>
+ <?= number_format($log->duration, 6, ',', '.') ?> <?= _('Sekunden') ?>
+ <? endif; ?>
+ </dd>
+
+<? if (!empty($log->output)): ?>
+ <dt><?= _('Ausgabe') ?></dt>
+ <dd><pre><?= htmlReady($log->output) ?></pre></dd>
+<? endif; ?>
+
+<? if ($log->exception !== null): ?>
+ <dt><?= _('Fehler') ?></dt>
+ <dd>
+ <?= nl2br(htmlReady($log->exception)) ?>
+ </dd>
+<? endif; ?>
+</dl>
diff --git a/app/views/admin/cronjobs/logs/index.php b/app/views/admin/cronjobs/logs/index.php
new file mode 100644
index 0000000..6f05112
--- /dev/null
+++ b/app/views/admin/cronjobs/logs/index.php
@@ -0,0 +1,142 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<form action="<?= $controller->filter() ?>" method="post" class="cronjob-filters default">
+ <fieldset>
+ <legend>
+ <?= _('Darstellung einschränken') ?>
+
+ <? if ($pagination->getTotal() != $total): ?>
+ <small>
+ <?= sprintf(_('Passend: %u von %u Logeinträgen'), $pagination->getTotal(), $total) ?>
+ </small>
+ <? endif; ?>
+ </legend>
+
+ <label class="col-2">
+ <?= _('Status') ?>
+ <select name="filter[status]" id="status" class="submit-upon-select">
+ <option value=""><?= _('Alle Logeinträge anzeigen') ?></option>
+ <option value="passed" <? if ($filter['status'] === 'passed') echo 'selected'; ?>>
+ <?= _('Nur fehlerfreie Logeinträge anzeigen') ?>
+ </option>
+ <option value="failed" <? if ($filter['status'] === 'failed') echo 'selected'; ?>>
+ <?= _('Nur fehlerhafte Logeinträge anzeigen') ?>
+ </option>
+ </select>
+ </label>
+
+ <label class="col-2">
+ <?= _('Cronjob') ?>
+ <select name="filter[schedule_id]" id="schedule_id" class="submit-upon-select">
+ <option value=""><?= _('Alle Logeinträge anzeigen') ?></option>
+ <? foreach ($schedules as $schedule): ?>
+ <option value="<?= $schedule->schedule_id ?>" <? if ($filter['schedule_id'] === $schedule->schedule_id) echo 'selected'; ?>>
+ <?= htmlReady($schedule->title) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label class="col-2">
+ <?= _('Aufgabe') ?>
+ <select name="filter[task_id]" id="task_id" class="submit-upon-select">
+ <option value=""><?= _('Alle Aufgaben anzeigen') ?></option>
+ <? foreach ($tasks as $task): ?>
+ <option value="<?= $task->task_id ?>" <? if ($filter['task_id'] === $task->task_id) echo 'selected'; ?>>
+ <?= htmlReady($task->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+ <? if (!empty($filter)): ?>
+ <footer>
+ <?= LinkButton::createCancel(
+ _('Zurücksetzen'),
+ $controller->url_for('admin/cronjobs/logs/filter'),
+ ['title' => _('Filter zurücksetzen')]
+ ) ?>
+ </footer>
+ <? endif ?>
+</form>
+
+
+<form action="<?= $controller->bulk($pagination->getCurrentPage()) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default cronjobs">
+ <colgroup>
+ <col style="width: 20px">
+ <col style="width: 150px">
+ <col style="width: 150px">
+ <col>
+ <col style="width: 50px">
+ <col style="width: 50px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" name="all" value="1"
+ data-proxyfor=":checkbox[name='ids[]']"
+ data-activates=".cronjobs select[name=action]">
+ </th>
+ <th><?= _('Ausgeführt') ?></th>
+ <th><?= _('Geplant') ?></th>
+ <th><?= _('Cronjob') ?></th>
+ <th><?= _('Ok?') ?></th>
+ <th><?= _('Optionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($logs) === 0): ?>
+ <tr class="empty">
+ <td colspan="6"><?= _('Keine Einträge vorhanden') ?></td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($logs as $log): ?>
+ <tr id="log-<?= htmlReady($log->id) ?>">
+ <td style="text-align: center">
+ <input type="checkbox" name="ids[]" value="<?= htmlReady($log->id) ?>">
+ </td>
+ <td><?= strftime('%x %X', $log->executed) ?></td>
+ <td><?= strftime('%x %X', $log->scheduled) ?></td>
+ <td><?= htmlReady($log->schedule->title ?: $log->schedule->task->name) ?></td>
+ <td>
+ <? if ($log->duration == -1): ?>
+ <?= Icon::create('question', Icon::ROLE_INACTIVE)->asImg(['title' => _('Läuft noch')]) ?>
+ <? elseif ($log->exception === null): ?>
+ <?= Icon::create('accept', Icon::ROLE_STATUS_GREEN)->asImg(['title' => _('Ja')]) ?>
+ <? else: ?>
+ <?= Icon::create('decline', Icon::ROLE_STATUS_RED)->asImg(['title' => _('Nein')]) ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: right">
+ <a data-dialog href="<?= $controller->display($log, $pagination->getCurrentPage()) ?>">
+ <?= Icon::create('admin')->asImg(['title' => _('Logeintrag anzeigen')]) ?>
+ </a>
+ <a href="<?= $controller->delete($log, $pagination->getCurrentPage()) ?>">
+ <?= Icon::create('trash')->asImg(['title' => _('Logeintrag löschen')]) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <select name="action" data-activates="button[name=bulk]">
+ <option value="">- <?= _('Aktion auswählen') ?></option>
+ <option value="delete"><?= _('Löschen') ?></option>
+ </select>
+ <?= Button::createAccept(_('Ausführen'), 'bulk') ?>
+
+ <section style="float: right">
+ <?= $pagination->asLinks(function ($page) use ($controller) {
+ return $controller->index($page);
+ }) ?>
+ </section>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form> \ No newline at end of file
diff --git a/app/views/admin/cronjobs/schedules/display.php b/app/views/admin/cronjobs/schedules/display.php
new file mode 100644
index 0000000..7d49b2d
--- /dev/null
+++ b/app/views/admin/cronjobs/schedules/display.php
@@ -0,0 +1,78 @@
+<dl class="cronjob">
+ <dt><?= _('Titel') ?></dt>
+ <dd><?= htmlReady($schedule->title) ?></dd>
+
+<? if ($schedule->description): ?>
+ <dt><?= _('Beschreibung') ?></dt>
+ <dd><?= htmlReady($schedule->description) ?></dd>
+<? endif; ?>
+
+ <dt><?= _('Aktiv') ?></dt>
+ <dd><?= $schedule->active ? _('Ja') : _('Nein') ?></dd>
+
+ <dt><?= _('Priorität') ?></dt>
+ <dd><?= CronjobSchedule::describePriority($schedule->priority) ?></dd>
+
+<? if (count($schedule->parameters) > 0): ?>
+ <dt><?= _('Parameter') ?></dt>
+ <dd>
+ <ul>
+ <? foreach ($schedule->parameters as $key => $value): ?>
+ <li><?= htmlReady($key) ?>: <?= htmlReady($value) ?></li>
+ <? endforeach; ?>
+ </ul>
+ </dd>
+<? endif; ?>
+
+ <dt><?= _('Aufgabe') ?></dt>
+ <dd><?= htmlReady($schedule->task->name) ?></dd>
+
+ <dt><?= _('Typ') ?></dt>
+<? if ($schedule->type === 'once'): ?>
+ <dd>
+ <?= sprintf(_('Einmalig am %s um %s'), date('d.m.Y', $schedule->next_execution), date('H:i', $schedule->next_execution)) ?>
+ </dd>
+
+ <dt><?= _('Ausgeführt') ?>?</dt>
+ <dd>
+ <? if ($schedule->execution_count > 0): ?>
+ <?= _('Ja') ?>, <?= sprintf(_('am %s um %s'), date('d.m.Y', $schedule->last_execution), date('H:i:s', $schedule->last_execution)) ?>
+ <? else: ?>
+ <?= _('Nein') ?>
+ <? endif; ?>
+ </dd>
+<? else: ?>
+ <dd>
+ <?= _('Regelmässig') ?>
+ <?= $this->render_partial('admin/cronjobs/schedules/periodic-schedule', $schedule->toArray()) ?>
+ </dd>
+
+ <dt><?= _('Ausführungen') ?></dt>
+ <dd><?= number_format($schedule->execution_count, 0, ',', '.') ?></dd>
+
+ <? if ($schedule->active): ?>
+ <dt><?= _('Nächste Ausführung') ?></dt>
+ <dd><?= date('d.m.Y H:i:s', $schedule->next_execution) ?></dd>
+ <? endif; ?>
+
+ <? if ($schedule->execution_count > 0): ?>
+ <dt><?= _('Letzte Ausführung') ?></dt>
+ <dd><?= $schedule->last_execution ? date('d.m.Y H:i:s', $schedule->last_execution) : _('nie') ?></dd>
+
+ <dt><?= _('Letztes Ergebnis') ?></dt>
+ <dd><code><?= htmlReady($schedule->last_result) ?></code></dd>
+ <? endif; ?>
+
+<? endif; ?>
+</dl>
+
+<div data-dialog-button>
+ <?= Studip\LinkButton::create(
+ _('Log anzeigen'),
+ $controller->url_for('admin/cronjobs/logs/schedule', $schedule)
+ ) ?>
+ <?= Studip\LinkButton::create(
+ _('Cronjob bearbeiten'),
+ $controller->editURL($schedule)
+ ) ?>
+</div>
diff --git a/app/views/admin/cronjobs/schedules/edit.php b/app/views/admin/cronjobs/schedules/edit.php
new file mode 100644
index 0000000..4b5b3df
--- /dev/null
+++ b/app/views/admin/cronjobs/schedules/edit.php
@@ -0,0 +1,241 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<?php
+ $days_of_week = [
+ 1 => _('Montag'),
+ 2 => _('Dienstag'),
+ 3 => _('Mittwoch'),
+ 4 => _('Donnerstag'),
+ 5 => _('Freitag'),
+ 6 => _('Samstag'),
+ 7 => _('Sonntag'),
+ ];
+?>
+
+<form action="<?= $controller->edit($schedule, $page) ?>" method="post" class="cronjobs-edit default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <h1>
+ <? if ($schedule->isNew()): ?>
+ <?= _('Neuen Cronjob anlegen') ?>
+ <? else: ?>
+ <?= htmlReady(sprintf(_('Cronjob "%s" bearbeiten'), $schedule->title)) ?>
+ <? endif; ?>
+ </h1>
+
+ <fieldset>
+ <legend>
+ <?= _('Details') ?>
+ </legend>
+
+ <label>
+ <input type="hidden" name="active" value="0">
+ <input type="checkbox" name="active" id="active" value="1"
+ <? if ($schedule->active) echo 'checked'; ?>>
+ <?= _('Aktiv') ?>
+ </label>
+
+ <label>
+ <?= _('Priorität') ?>
+ <select name="priority" id="priority">
+ <? foreach (CronjobSchedule::getPriorities() as $priority => $label): ?>
+ <option value="<?= $priority ?>" <? if ((!$schedule->priority && $priority === CronjobSchedule::PRIORITY_NORMAL) || $schedule->priority === $priority) echo 'selected'; ?>>
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Titel') ?>
+ <input type="text" name="title" id="title" value="<?= htmlReady($schedule->title ?: '') ?>">
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description"><?= htmlReady($schedule->description ?: '') ?></textarea>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Aufgabe') ?></legend>
+ <table class="default cron-task">
+ <colgroup>
+ <col style="width: 300px">
+ <col style="width: 150px">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Klassenname') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($tasks as $task): ?>
+ <? if (!$schedule->isNew() && $task->task_id != $schedule->task_id) continue; ?>
+ <tbody <? if (!$schedule->isNew() && $task->task_id === $schedule->task_id) echo 'class="selected"'; ?>>
+ <tr>
+ <td>
+ <label for="task-<?= $task->task_id ?>">
+ <? if ($schedule->isNew()): ?>
+ <input required type="radio" name="task_id"
+ id="task-<?= $task->task_id ?>"
+ value="<?= $task->task_id ?>"
+ <? if ($task->task_id === $schedule->task_id) echo 'checked'; ?>>
+ <? endif; ?>
+
+ <?= htmlReady($task->class) ?>
+ </label>
+ </td>
+ <td>
+ <label for="task-<?= $task->task_id ?>"><?= htmlReady($task->name) ?: '&nbsp;' ?></label>
+ </td>
+ <td>
+ <label for="task-<?= $task->task_id ?>"><?= htmlReady($task->description) ?: '&nbsp;' ?></label>
+ </td>
+ </tr>
+ <? if (count($task->parameters) > 0): ?>
+ <tr>
+ <td colspan="3">
+ <div class="parameters">
+ <?= $this->render_partial('admin/cronjobs/schedules/parameters', compact('task', 'schedule')) ?>
+ </div>
+ </td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+ </table>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Zeitplan') ?></legend>
+
+ <label>
+ <input type="radio" name="type" value="periodic"
+ data-activates="[name^='periodic']"
+ data-deactivates="[name^='once']"
+ <? if ($schedule->type === 'periodic') echo 'checked'; ?>>
+ <?= _('Wiederholt') ?>
+ </label>
+
+ <section>
+ <table class="default">
+ <colgroup>
+ <col style="width: 20%">
+ <col style="width: 20%">
+ <col style="width: 20%">
+ <col style="width: 20%">
+ <col style="width: 20%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <?= _('Minute') ?>
+ </th>
+ <th>
+ <?= _('Stunde') ?>
+ </th>
+ <th>
+ <?= _('Tag') ?>
+ </th>
+ <th>
+ <?= _('Monat') ?>
+ </th>
+ <th>
+ <?= _('Wochentag') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="cron-item">
+ <select name="periodic[minute][type]" id="minute" class="size-s">
+ <option value="" title="<?= _('beliebig') ?>">*</option>
+ <option value="once" <? if ($schedule->minute !== null && $schedule->minute >= 0) echo 'selected'; ?>>
+ min
+ </option>
+ <option value="periodic" <? if ($schedule->minute < 0) echo 'selected'; ?>>
+ */min
+ </option>
+ </select>
+ <input type="number" name="periodic[minute][value]" value="<?= abs($schedule->minute) ?>">
+ </td>
+ <td class="cron-item">
+ <select name="periodic[hour][type]" id="hour" class="size-s">
+ <option value="" title="<?= _('beliebig') ?>">*</option>
+ <option value="once" <? if ($schedule->hour !== null && $schedule->hour >= 0) echo 'selected'; ?>>
+ hour
+ </option>
+ <option value="periodic" <? if ($schedule->hour < 0) echo 'selected'; ?>>
+ */hour
+ </option>
+ </select>
+ <input type="number" name="periodic[hour][value]" value="<?= abs($schedule->hour) ?>">
+ </td>
+ <td class="cron-item">
+ <select name="periodic[day][type]" id="day" class="size-s">
+ <option value="" title="<?= _('beliebig') ?>">*</option>
+ <option value="once" <? if ($schedule->day !== null && $schedule->day >= 0) echo 'selected'; ?>>
+ day
+ </option>
+ <option value="periodic" <? if ($schedule->day < 0) echo 'selected'; ?>>
+ */day
+ </option>
+ </select>
+ <input type="number" name="periodic[day][value]" value="<?= abs($schedule->day) ?>">
+ </td>
+ <td class="cron-item">
+ <select name="periodic[month][type]" id="month" class="size-s">
+ <option value="" title="<?= _('beliebig') ?>">*</option>
+ <option value="once" <? if ($schedule->month !== null && $schedule->month >= 0) echo 'selected'; ?>>
+ month
+ </option>
+ <option value="periodic" <? if ($schedule->month < 0) echo 'selected'; ?>>
+ */month
+ </option>
+ </select>
+ <input type="number" name="periodic[month][value]" value="<?= abs($schedule->month) ?>" class="size-s">
+ </td>
+ <td>
+ <select name="periodic[day_of_week][value]" id="day_of_week" class="size-s">
+ <option value=""><?= _('*') ?></option>
+ <? foreach ($days_of_week as $index => $label): ?>
+ <option value="<?= $index ?>" <? if ($schedule->day_of_week === $index) echo 'selected'; ?>>
+ <?= $index ?> (<?= $label ?>)
+ </option>
+ <? endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </section>
+
+ <label>
+ <input type="radio" name="type" value="once"
+ data-activates="input[name^='once']"
+ data-deactivates="[name^='periodic']"
+ <? if ($schedule->type === 'once') echo 'checked'; ?>>
+ <?= _('Einmalig') ?>
+ </label>
+
+ <label class="col-1">
+ <?= _('Datum') ?>
+ <input type="text" name="once[date]" data-date-picker class="size-s"
+ value="<? if ($schedule->type === 'once' && $schedule->next_execution) echo date('d.m.Y', $schedule->next_execution); ?>">
+ </label>
+
+ <label class="col-1">
+ <?= _('Uhrzeit') ?>
+ <input type="text" name="once[time]" data-time-picker class="size-s"
+ value="<? if ($schedule->type === 'once' && $schedule->next_execution) echo date('H:i', $schedule->next_execution) ?>">
+ </label>
+ </fieldset>
+
+ <footer class="buttons">
+ <?= Button::createAccept(_('Speichern'), 'store') ?>
+ <?= LinkButton::createCancel('Abbrechen', $controller->indexURL($page)) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/admin/cronjobs/schedules/index.php b/app/views/admin/cronjobs/schedules/index.php
new file mode 100644
index 0000000..4a188dd
--- /dev/null
+++ b/app/views/admin/cronjobs/schedules/index.php
@@ -0,0 +1,163 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<form action="<?= $controller->filter() ?>" method="post" class="default cronjob-filters">
+ <fieldset>
+ <legend>
+ <?= _('Darstellung einschränken') ?>
+ <? if ($pagination->getTotal() != $total): ?>
+ <?= sprintf(_('Passend: %u von %u Cronjobs'), $pagination->getTotal(), $total) ?>
+ <? endif; ?>
+ </legend>
+ <label class="col-2">
+ <?= _('Typ') ?>
+ <select name="filter[type]" id="type" class="submit-upon-select">
+ <option value=""><?= _('Alle Cronjobs anzeigen') ?></option>
+ <option value="once" <? if ($filter['type'] === 'once') echo 'selected'; ?>>
+ <?= _('Nur einmalige Cronjobs anzeigen') ?>
+ </option>
+ <option value="periodic" <? if ($filter['type'] === 'periodic') echo 'selected'; ?>>
+ <?= _('Nur regelmässige Cronjobs anzeigen') ?>
+ </option>
+ </select>
+ </label>
+ <label class="col-2">
+ <?= _('Aufgabe') ?>
+ <select name="filter[task_id]" id="task_id" class="submit-upon-select">
+ <option value=""><?= _('Alle Cronjobs anzeigen') ?></option>
+ <? foreach ($tasks as $task): ?>
+ <option value="<?= $task->task_id ?>" <? if ($filter['task_id'] === $task->task_id) echo 'selected'; ?>>
+ <?= htmlReady($task->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <label class="col-2">
+ <?= _('Status') ?>
+ <select name="filter[status]" id="status" class="submit-upon-select">
+ <option value=""><?= _('Alle Cronjobs anzeigen') ?></option>
+ <option value="active" <? if ($filter['status'] === 'active') echo 'selected'; ?>>
+ <?= _('Nur aktive Cronjobs anzeigen') ?>
+ </option>
+ <option value="inactive" <? if ($filter['status'] === 'inactive') echo 'selected'; ?>>
+ <?= _('Nur deaktivierte Cronjobs anzeigen') ?>
+ </option>
+ </select>
+ </label>
+ </fieldset>
+ <? if (!empty($filter)): ?>
+ <footer>
+ <?= LinkButton::createCancel(
+ _('Zurücksetzen'),
+ $controller->filterURL(),
+ ['title' => _('Filter zurücksetzen')]
+ ) ?>
+ </footer>
+ <? endif ?>
+</form>
+
+
+<form class="cronjobs" action="<?= $controller->bulk($pagination->getCurrentPage()) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default cronjobs sortable-table" data-sortlist="[[1, 0]]">
+ <colgroup>
+ <col style="width: 20px">
+ <col>
+ <col style="width: 40px">
+ <col style="width: 100px">
+ <col style="width: 30px">
+ <col style="width: 30px">
+ <col style="width: 30px">
+ <col style="width: 30px">
+ <col style="width: 30px">
+ <col style="width: 90px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th data-sort="false">
+ <input type="checkbox" name="all" value="1"
+ data-proxyfor=":checkbox[name='ids[]']"
+ data-activates=".cronjobs select[name=action]">
+ </th>
+ <th data-sort="text"><?= _('Cronjob') ?></th>
+ <th data-sort="htmldata"><?= _('Aktiv') ?></th>
+ <th data-sort="text"><?= _('Typ') ?></th>
+ <th colspan="5" data-sort="false"><?= _('Ausführung') ?></th>
+ <th data-sort="false"><?= _('Optionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($schedules) === 0): ?>
+ <tr class="empty">
+ <td colspan="10"><?= _('Keine Einträge vorhanden') ?></td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($schedules as $schedule): ?>
+ <tr id="job-<?= htmlReady($schedule->id) ?>" <? if (!$schedule->task->active) echo 'class="inactivatible"'; ?>>
+ <td style="text-align: center">
+ <input type="checkbox" name="ids[]" value="<?= htmlReady($schedule->id) ?>">
+ </td>
+ <td><?= htmlReady($schedule->title ?: $schedule->task->name) ?></td>
+ <td style="text-align: center;"
+ data-sort-value="'<?= (int)($schedule->active && $schedule->task->active) ?>'">
+ <? if (!$schedule->task->active): ?>
+ <?= Icon::create('checkbox-unchecked', Icon::ROLE_INACTIVE)->asImg(['title' => _('Cronjob kann nicht aktiviert werden, da die zugehörige ' . 'Aufgabe deaktiviert ist.')]) ?>
+ <? elseif ($schedule->active): ?>
+ <a href="<?= $controller->deactivate($schedule, $pagination->getCurrentPage()) ?>"
+ data-behaviour="ajax-toggle">
+ <?= Icon::create('checkbox-checked')->asImg(['title' => _('Cronjob deaktivieren')]) ?>
+ </a>
+ <? else: ?>
+ <a href="<?= $controller->activate($schedule, $pagination->getCurrentPage()) ?>"
+ data-behaviour="ajax-toggle">
+ <?= Icon::create('checkbox-unchecked')->asImg(['title' => _('Cronjob aktivieren')]) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <td><?= $schedule->type === 'once' ? _('Einmalig') : _('Regelmässig') ?></td>
+ <? if ($schedule->type === 'once'): ?>
+ <td colspan="5">
+ <?= strftime('%x %R', $schedule->next_execution) ?>
+ </td>
+ <? else: ?>
+ <?= $this->render_partial('admin/cronjobs/schedules/periodic-schedule', $schedule->toArray() + ['display' => 'table-cells']) ?>
+ <? endif; ?>
+ <td style="text-align: right">
+ <a data-dialog href="<?= $controller->display($schedule) ?>">
+ <?= Icon::create('admin')->asImg(['title' => _('Cronjob anzeigen')]) ?>
+ </a>
+ <a href="<?= $controller->edit($schedule, $pagination->getCurrentPage()) ?>">
+ <?= Icon::create('edit')->asImg(['title' => _('Cronjob bearbeiten')]) ?>
+ </a>
+ <a href="<?= $controller->link_for('admin/cronjobs/logs/schedule', $schedule) ?>">
+ <?= Icon::create('log')->asImg(['title' => _('Log anzeigen')]) ?>
+ </a>
+ <?= Icon::create('trash')->asInput([
+ 'data-confirm' => _('Wollen Sie den ausgewählten Cronjob wirklich löschen?'),
+ 'formaction' => $controller->cancelURL($schedule, $pagination->getCurrentPage()),
+ ]) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="10">
+ <select name="action" data-activates=".cronjobs button[name=bulk]" aria-label="<?= _('Aktion auswählen')?>">
+ <option value="">- <?= _('Aktion auswählen') ?> -</option>
+ <option value="activate"><?= _('Aktivieren') ?></option>
+ <option value="deactivate"><?= _('Deaktivieren') ?></option>
+ <option value="cancel"><?= _('Löschen') ?></option>
+ </select>
+ <?= Button::createAccept(_('Ausführen'), 'bulk') ?>
+
+ <section style="float: right">
+ <?= $pagination->asLinks(function ($page) use ($controller) {
+ return $controller->index($page);
+ }) ?>
+ </section>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form> \ No newline at end of file
diff --git a/app/views/admin/cronjobs/schedules/parameters.php b/app/views/admin/cronjobs/schedules/parameters.php
new file mode 100644
index 0000000..e4ffefd
--- /dev/null
+++ b/app/views/admin/cronjobs/schedules/parameters.php
@@ -0,0 +1,69 @@
+<?php
+ $selected = !$schedule->isNew() && $schedule->task_id === $task->task_id;
+ $parameters = $schedule->parameters;
+?>
+
+<h3><?= _('Parameter') ?></h3>
+<ul class="clean">
+<? foreach ($task->parameters as $key => $data): ?>
+ <li class="parameter">
+ <? if ($data['type'] === 'boolean'): ?>
+ <input type="hidden" name="parameters[<?= $task->task_id ?>][<?= htmlReady($key) ?>]" value="0">
+ <label>
+ <input type="checkbox" name="parameters[<?= $task->task_id ?>][<?= htmlReady($key) ?>]" value="1"
+ id="parameter-<?= htmlReady($key) ?>"
+ <? if ($selected ? $parameters[$key] : $data['default']) echo 'checked'; ?>>
+ <? if ($data['status'] === 'mandatory'): ?>
+ <span class="required">
+ <?= htmlReady($data['description']) ?>
+ </span>
+ <? else: ?>
+ <?= htmlReady($data['description']) ?>
+ <? endif; ?>
+ </label>
+ <? else: ?>
+ <label for="parameter-<?= htmlReady($key) ?>">
+ <? if ($data['status'] === 'mandatory'): ?>
+ <span class="required">
+ <?= htmlReady($data['description']) ?>
+ </span>
+ <? else: ?>
+ <?= htmlReady($data['description']) ?>
+ <? endif; ?>
+
+ <? endif; ?>
+ <? if ($data['type'] === 'string'): ?>
+ <input type="text" name="parameters[<?= $task->task_id ?>][<?= htmlReady($key) ?>]"
+ id="parameter-<?= htmlReady($key) ?>"
+ value="<?= htmlReady($selected ? $parameters[$key] : ($data['default'] ?: '')) ?>"
+ placeholder="<?= $data['default'] ?: '' ?>"
+ <? if ($data['status'] === 'mandatory') echo 'required'; ?>>
+ <? elseif ($data['type'] === 'text'): ?>
+ <textarea name="parameters[<?= $task->task_id ?>][<?= htmlReady($key) ?>]"
+ id="parameter-<?= htmlReady($key) ?>"
+ placeholder="<?= $data['default'] ?: '' ?>"
+ <? if ($data['status'] === 'mandatory') echo 'required'; ?>
+ ><?= htmlReady($selected ? $parameters[$key] : ($data['default'] ?: '')); ?></textarea>
+ <? elseif ($data['type'] === 'integer'): ?>
+ <input type="number" name="parameters[<?= $task->task_id ?>][<?= htmlReady($key) ?>]"
+ id="parameter-<?= htmlReady($key) ?>"
+ placeholder="<?= $data['default'] ?: '' ?>"
+ value="<?= (int)($selected ? $parameters[$key] : ($data['default'] ?: 0)) ?>"
+ <? if ($data['status'] === 'mandatory') echo 'required'; ?>>
+ <? elseif ($data['type'] === 'select'): ?>
+ <select name="parameters[<?= $task->task_id ?>][<?= htmlReady($key) ?>]">
+ <? if ($data['status'] === 'optional'): ?>
+ <option value=""><?= _('Bitte wählen Sie einen Wert aus') ?></option>
+ <? endif; ?>
+ <? foreach ($data['values'] as $k => $l): ?>
+ <option value="<?= htmlReady($k) ?>"
+ <? if (($parameters[$key] ?: $data['default'] ?: null) === $k) echo 'selected'; ?>>
+ <?= htmlReady($l) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? endif; ?>
+ </label>
+ </li>
+<? endforeach; ?>
+</ul>
diff --git a/app/views/admin/cronjobs/schedules/periodic-schedule.php b/app/views/admin/cronjobs/schedules/periodic-schedule.php
new file mode 100644
index 0000000..b482efd
--- /dev/null
+++ b/app/views/admin/cronjobs/schedules/periodic-schedule.php
@@ -0,0 +1,41 @@
+<?php
+$cronify = function ($n) {
+ if ($n === null) {
+ return '*';
+ }
+ if ($n < 0) {
+ return '*/' . abs($n);
+ }
+ return $n;
+}
+?>
+<? if ($display === 'table-cells'): ?>
+ <td><?= $cronify($minute) ?></td>
+ <td><?= $cronify($hour) ?></td>
+ <td><?= $cronify($day) ?></td>
+ <td><?= $cronify($month) ?></td>
+ <td><?= $cronify($day_of_week) ?></td>
+<? else: ?>
+ <ul class="crontab">
+ <li class="crontab-minute">
+ <span class="label"><?= _('Minute') ?></span>
+ <?= $cronify($minute) ?>
+ </li>
+ <li class="crontab-hour">
+ <span class="label"><?= _('Stunde') ?></span>
+ <?= $cronify($hour) ?>
+ </li>
+ <li class="crontab-day">
+ <span class="label"><?= _('Tag') ?></span>
+ <?= $cronify($day) ?>
+ </li>
+ <li class="crontab-month">
+ <span class="label"><?= _('Monat') ?></span>
+ <?= $cronify($month) ?>
+ </li>
+ <li class="crontab-day-of-week">
+ <span class="label"><?= _('Wochentag') ?></span>
+ <?= $cronify($day_of_week) ?>
+ </li>
+ </ul>
+<? endif ?> \ No newline at end of file
diff --git a/app/views/admin/cronjobs/tasks/execute.php b/app/views/admin/cronjobs/tasks/execute.php
new file mode 100644
index 0000000..e0c1e03
--- /dev/null
+++ b/app/views/admin/cronjobs/tasks/execute.php
@@ -0,0 +1,14 @@
+<h2><?= sprintf(_('Cronjob-Aufgabe "%s" ausführen'), htmlReady($task->name)) ?></h2>
+<? if (isset($result)): ?>
+ <pre><code><?= htmlReady($result ?: _('- Keine Ausgabe -')) ?></code></pre>
+<? else: ?>
+ <p><?= htmlReady($task->description) ?></p>
+ <form class="default" action="<?= $controller->execute($task) ?>" method="post" data-dialog="size=auto">
+ <? if (count($task->parameters)): ?>
+ <?= $this->render_partial('admin/cronjobs/schedules/parameters') ?>
+ <? endif; ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Ausführen'), 'submit') ?>
+ </div>
+ </form>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/admin/cronjobs/tasks/index.php b/app/views/admin/cronjobs/tasks/index.php
new file mode 100644
index 0000000..0169bb7
--- /dev/null
+++ b/app/views/admin/cronjobs/tasks/index.php
@@ -0,0 +1,91 @@
+<? use Studip\Button; ?>
+
+<form action="<?= $controller->bulk($pagination->getCurrentPage()) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default cronjobs sortable-table" data-sortlist="[[1,0]]">
+ <colgroup>
+ <col style="width: 20px">
+ <col style="width: 200px">
+ <col>
+ <col style="width: 100px">
+ <col style="width: 40px">
+ <col style="width: 70px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th data-sort="false">
+ <input type="checkbox" name="all" value="1"
+ data-proxyfor=":checkbox[name='ids[]']"
+ data-activates=".cronjobs select[name=action]">
+ </th>
+ <th data-sort="text"><?= _('Aufgabe') ?></th>
+ <th data-sort="text"><?= _('Beschreibung') ?></th>
+ <th data-sort="text"><?= _('Herkunft') ?></th>
+ <th data-sort="htmldata"><?= _('Aktiv') ?></th>
+ <th data-sort="false"><?= _('Optionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($tasks) === 0): ?>
+ <tr class="empty">
+ <td colspan="6"><?= _('Keine Einträge vorhanden') ?></td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($tasks as $task): ?>
+ <tr id="job-<?= htmlReady($task->id) ?>">
+ <td style="text-align: center">
+ <input type="checkbox" name="ids[]" value="<?= htmlReady($task->id) ?>">
+ </td>
+ <td><?= htmlReady($task->name) ?></td>
+ <td><?= htmlReady($task->description) ?></td>
+ <td><?= $task->isCore() ? _('Kern') : _('Plugin') ?></td>
+ <td style="text-align: center;" data-sort-value="'<?= (int) $task->active ?>'">
+ <? if ($task->active): ?>
+ <a href="<?= $controller->deactivate($task, $pagination->getCurrentPage()) ?>" data-behaviour="ajax-toggle">
+ <?= Icon::create('checkbox-checked')->asImg(['title' => _('Aufgabe deaktivieren')]) ?>
+ </a>
+ <? else: ?>
+ <a href="<?= $controller->activate($task, $pagination->getCurrentPage()) ?>" data-behaviour="ajax-toggle">
+ <?= Icon::create('checkbox-unchecked')->asImg(['title' => _('Aufgabe aktivieren')]) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <td style="text-align: right">
+ <? if ($task->valid): ?>
+ <a data-dialog href="<?= $controller->execute($task) ?>">
+ <?= Icon::create('play')->asImg(['title' => _('Aufgabe ausführen')]) ?>
+ </a>
+ <? endif; ?>
+ <a href="<?= $controller->link_for('admin/cronjobs/logs/task', $task) ?>">
+ <?= Icon::create('log')->asImg(['title' => _('Log anzeigen')]) ?>
+ </a>
+ <?= Icon::create('trash')->asInput([
+ 'data-confirm' => _('Wollen Sie die ausgewählte Aufgabe wirklich löschen?'),
+ 'formaction' => $controller->deleteURL($task, $pagination->getCurrentPage()),
+ ]) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <select name="action" data-activates=".cronjobs button[name=bulk]">
+ <option value="">- <?= _('Aktion auswählen') ?></option>
+ <option value="activate"><?= _('Aktivieren') ?></option>
+ <option value="deactivate"><?= _('Deaktivieren') ?></option>
+ <option value="delete"><?= _('Löschen') ?></option>
+ </select>
+ <?= Button::createAccept(_('Ausführen'), 'bulk') ?>
+
+ <section style="float: right">
+ <?= $pagination->asLinks(function ($page) use ($controller) {
+ return $controller->index($page);
+ }) ?>
+ </section>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
diff --git a/app/views/admin/datafields/config.php b/app/views/admin/datafields/config.php
new file mode 100644
index 0000000..417996f
--- /dev/null
+++ b/app/views/admin/datafields/config.php
@@ -0,0 +1,18 @@
+<form action="<?= $controller->url_for('admin/datafields/config/' . $struct->getID()) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Datenfeld konfigurieren') ?></legend>
+
+ <label>
+ <?= _('Inhalte') ?>
+ <textarea name="typeparam"><?="\n"?><?= htmlReady(rtrim($struct->getTypeParam()), false) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
+ <?= Studip\Button::create(_('Vorschau'), 'preview', ['data-dialog' => 'size=auto']) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/datafields/index/' . $struct->getObjectType() . '#' . $struct->getObjectType())) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/datafields/edit.php b/app/views/admin/datafields/edit.php
new file mode 100644
index 0000000..5d8116a
--- /dev/null
+++ b/app/views/admin/datafields/edit.php
@@ -0,0 +1,201 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+?>
+
+<form action="<?= $controller->url_for('admin/datafields/edit/' . $item->id) ?>" method="post"
+ class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Bearbeiten der Parameter') ?></legend>
+
+ <label>
+ <span class="required"><?= _('Name') ?></span>
+
+ <?= I18N::input('datafield_name', $item->name, [
+ 'id' => 'datafield_name',
+ 'required' => '',
+ 'size' => 60,
+ 'maxlength' => 254,
+ ]) ?>
+ </label>
+
+ <label>
+ <?= _('Feldtyp') ?>
+
+ <select name="datafield_type" id="datafield_type">
+ <? foreach (DataFieldEntry::getSupportedTypes($item->object_type) as $param): ?>
+ <option <? if ($item->type === $param) echo 'selected'; ?>>
+ <?= htmlReady($param) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? if (!$datafield_entry instanceof DataFieldI18NEntry): ?>
+ <?= str_replace('['.$datafield_id.']', '', $datafield_entry->getHTML('default_value')) ?>
+ <? endif ?>
+ <label>
+ <? if ($item->object_type === 'sem'): ?>
+ <?= _('Veranstaltungskategorie') ?>:
+
+ <select name="object_class[]" id="object_class">
+ <option value="NULL"><?= _('alle') ?></option>
+ <? foreach (SemClass::getClasses() as $key => $val): ?>
+ <option value="<?= $key ?>" <? if ($item->object_class == $key) echo 'selected'; ?>>
+ <?= htmlReady($val['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? elseif ($item->object_type === 'inst'): ?>
+ <?= _('Einrichtungstyp') ?>:
+
+ <select name="object_class[]" id="object_class">
+ <option value="NULL"><?= _('alle') ?></option>
+ <? foreach ($GLOBALS['INST_TYPE'] as $key => $val): ?>
+ <option value="<?= $key ?>" <? if ($item->object_class == $key) echo 'selected'; ?>>
+ <?= htmlReady($val['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? elseif ($item->object_type === 'moduldeskriptor'): ?>
+ <?= _('Sprache') ?>:
+
+ <select multiple name="object_class[]" id="object_class" required>
+ <option value="NULL" <? if ($item->object_class === null) echo 'selected'; ?>><?= _('alle (mehrsprachige Eingabe bei Feldtyp textline, textarea, textmarkup)') ?></option>
+ <? foreach ((array) $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'] as $key => $value) : ?>
+ <option value="<?= htmlReady($key) ?>" <? if (mb_strpos($item->object_class, $key) !== false) echo 'selected'; ?>>
+ <?= htmlReady($value['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? elseif ($item->object_type === 'modulteildeskriptor'): ?>
+ <?= _('Sprache') ?>:
+
+ <select multiple name="object_class[]" id="object_class" required>
+ <option value="NULL" <? if ($item->object_class === null) echo 'selected'; ?>><?= _('alle (mehrsprachige Eingabe)') ?></option>
+ <? foreach ((array) $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'] as $key => $value) : ?>
+ <option value="<?= htmlReady($key) ?>" <? if (mb_strpos($item->object_class, $key) !== false) echo 'selected'; ?>>
+ <?= htmlReady($value['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? elseif ($item->object_type === 'studycourse'): ?>
+ <?= _('Typ/Abschnitt') ?>
+
+ <select name="object_class" required>
+ <option value="all_settings"<?= mb_strpos($item->object_class, 'all_settings') !== false ? ' selected' : '' ?>><?= _('alle (Abschnitt "Einstellungen")') ?></option>
+ <option value="all_info"<?= mb_strpos($item->object_class, 'all_info') !== false ? ' selected' : '' ?>><?= _('alle (Abschnitt "Inhalte und Informationen")') ?></option>
+ <option value="einfach_settings"<?= mb_strpos($item->object_class, 'einfach_settings') !== false ? ' selected' : '' ?>><?= _('Einfach-Studiengänge (Abschnitt "Einstellungen")') ?></option>
+ <option value="einfach_info"<?= mb_strpos($item->object_class, 'einfach_info') !== false ? ' selected' : '' ?>><?= _('Einfach-Studiengänge (Abschnitt "Inhalte und Informationen")') ?></option>
+ <option value="mehrfach_settings"<?= mb_strpos($item->object_class, 'mehrfach_settings') !== false ? ' selected' : '' ?>><?= _('Mehrfach-Studiengänge (Abschnitt "Einstellungen")') ?></option>
+ <option value="mehrfach_info"<?= mb_strpos($item->object_class, 'mehrfach_info') !== false ? ' selected' : '' ?>><?= _('Mehrfach-Studiengänge (Abschnitt "Inhalte und Informationen")') ?></option>
+ </select>
+ <? else : ?>
+ <?= _('Nutzerstatus') ?>:
+
+ <select multiple size="<?= count($controller->user_status) ?>" name="object_class[]" id="object_class" required>
+ <option value="0" <? if ($item->object_class === null) echo 'selected'; ?>>
+ <?= _('alle') ?>
+ </option>
+ <? foreach ($controller->user_status as $key => $value): ?>
+ <option value="<?= $value ?>" <? if ($item->object_class & DataField::permMask($key)) echo 'selected'; ?>>
+ <?= $key ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? endif; ?>
+ </label>
+
+ <label>
+ <?= _('Benötigter Status zum Bearbeiten') ?>
+
+ <select name="edit_perms" id="edit_perms">
+ <? foreach (array_keys($controller->user_status) as $key): ?>
+ <option <? if ($item->edit_perms === $key) echo 'selected'; ?>>
+ <?= $key ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Sichtbarkeit') ?> (<?= _('für andere') ?>)
+
+ <select name="visibility_perms" id="visibility_perms">
+ <option value="all" <? if ($item->view_perms == 'all') echo 'selected'; ?>>
+ <?= _('alle') ?>
+ </option>
+ <? foreach (array_keys($controller->user_status) as $key): ?>
+ <option <? if ($item->view_perms === $key) echo 'selected'; ?>>
+ <?= $key ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <? if ($item->object_type === 'user'): ?>
+ <label>
+ <?= _('Systemfeld') ?>
+ <?= tooltipIcon(_('Nur für die Person selbst sichtbar, wenn der '
+ . 'benötigte Status zum Bearbeiten oder die '
+ . 'Sichtbarkeit ausreichend ist')) ?>
+
+ <input type="hidden" name="system" value="0">
+ <input type="checkbox" name="system" value="1"
+ <? if ($item->system) echo 'checked'; ?>>
+ </label>
+ <? endif; ?>
+ <label>
+ <?= _('Einrichtung') ?>
+ <select name="institut_id" class="nested-select">
+ <option value="" class="is-placeholder"></option>
+ <? foreach ($institutes as $institute): ?>
+ <option value="<?= htmlReady($institute['Institut_id']) ?>"
+ class="<?= $institute['is_fak'] ? 'nested-item-header' : 'nested-item' ?>"
+ <?= $item->institut_id === $institute['Institut_id'] ? 'selected' : ''?>>
+ <?= htmlReady(my_substr($institute['Name'],0,80)) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+
+ <label>
+ <?= _('Position') ?>
+
+ <input type="text" name="priority" id="priority"
+ maxlength="10" size="5"
+ value="<?= $item->priority ?>">
+ </td>
+ </label>
+
+ <? if ($item->object_type === 'sem') : ?>
+ <label>
+ <input type="checkbox" name="is_required" id="is_required" value="1"
+ <? if ($item->is_required) echo 'checked'; ?>>
+ <?= _('Eintrag verpflichtend') ?>
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>:
+
+ <textarea name="description" id="description"><?= htmlReady($item->description) ?></textarea>
+ </label>
+ <? endif; ?>
+
+ <? if ($item->object_type === 'user'): ?>
+ <label>
+ <?= _('Mögliche Bedingung für Anmelderegel') ?>:
+
+ <input type="checkbox" name="is_userfilter" id="is_userfilter" value="1"
+ <? if ($item->is_userfilter) echo 'checked'; ?>>
+ </label>
+ <? endif; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Übernehmen'), 'uebernehmen', ['title' => _('Änderungen übernehmen')])?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/datafields/index/'.$item->type.'#'.$item->type), ['title' => _('Zurück zur Übersicht')])?>
+ </footer>
+</form>
diff --git a/app/views/admin/datafields/index.php b/app/views/admin/datafields/index.php
new file mode 100644
index 0000000..a10dba7
--- /dev/null
+++ b/app/views/admin/datafields/index.php
@@ -0,0 +1,173 @@
+<!-- Alle Datenfelder -->
+<table class="collapsable default">
+ <colgroup>
+ <col>
+ <col width="20%">
+ <col width="10%">
+ <col width="10%">
+ <col width="10%">
+ <col width="10%">
+ <col width="10%">
+ <col width="6%">
+ <col width="6%">
+ <col width="2%">
+ <col width="48px">
+ </colgroup>
+ <caption>
+ <?= _('Verwaltung von generischen Datenfeldern') ?>
+ </caption>
+ <thead style="vertical-align: bottom">
+ <tr>
+ <th rowspan="2"><?= _('Name') ?></th>
+ <th rowspan="2"><?= _('Feldtyp') ?></th>
+ <th rowspan="2" style="word-wrap: nowrap">
+ <?= _('Typ') ?>
+ <?= tooltipIcon(_('Veranstaltungskategorie, Einrichtungstyp, Sprache bzw. Nutzerstatus')) ?>
+ </th>
+ <th rowspan="2">
+ <?= _('Institution') ?>
+ </th>
+ <th colspan="2" style="text-align: center">
+ <?= _('benötigter Status') ?>
+ </th>
+ <th colspan="2" rowspan="2"></th>
+ <th rowspan="2"><?= _('Position') ?></th>
+ <th rowspan="2">
+ <abbr title="<?= _('Einträge') ?>">#</abbr>
+ </th>
+ <th rowspan="2" class="actions"></th>
+ </tr>
+ <tr>
+ <th style="white-space: nowrap">
+ <?= _('Änderbar') ?>
+ <?= tooltipIcon(_('Gibt den Status an, ab dem das Datenfeld änderbar ist')) ?>
+ </th>
+ <th style="white-space: nowrap">
+ <?= _('Öffentlich') ?>
+ <?= tooltipIcon(_('Gibt den Status an, ab dem das Datenfeld für andere sichtbar ist')) ?>
+ </th>
+ </tr>
+ </thead>
+<? foreach ($datafields_list as $key => $data): ?>
+ <tbody class="<? if ($current_class !== $key && !$class_filter) echo 'collapsed'; ?> <? if (empty($datafields_list[$key])) echo 'empty'; ?>">
+ <tr class="table_header header-row">
+ <? if (in_array($key, words('sem user'))): ?>
+ <th class="toggle-indicator" colspan="6">
+ <? else: ?>
+ <th class="toggle-indicator" colspan="11">
+ <? endif; ?>
+ <? if (empty($datafields_list[$key])): ?>
+ <?= sprintf(_('Datenfelder für %s'), $allclasses[$key]) ?>
+ <? else: ?>
+ <a name="<?= $key ?>" class="toggler" href="<?= $controller->url_for('admin/datafields/index/' . $key) ?>">
+ <?= sprintf(_('Datenfelder für %s'), $allclasses[$key]) ?>
+ </a>
+ <? endif; ?>
+ </th>
+ <? if ($key === 'sem'): ?>
+ <th><?= _('Pflichtfeld') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ <th colspan="3"></th>
+ <? elseif ($key === 'user'): ?>
+ <th style="white-space: nowrap;">
+ <?= _('System') ?>
+ <?= tooltipIcon(_('Für die Person nur sichtbar, wenn der Status zum Bearbeiten '
+ . ' oder für die Sichtbarkeit ausreichend ist')) ?>
+ </th>
+ <th><?= _('Anmelderegel') ?></th>
+ <th colspan="3"></th>
+ <? endif; ?>
+ </tr>
+ <? foreach ($data as $input => $val): ?>
+ <tr>
+ <td>
+ <a name="item_<?= $val->id ?>"></a>
+ <?= htmlReady($val->name) ?>
+ </td>
+ <td>
+ <? if (in_array($val->type, words('selectbox selectboxmultiple radio combo'))): ?>
+ <a data-dialog="size=auto" href="<?= $controller->url_for('admin/datafields/config/'. $val->id) ?>">
+ <?= Icon::create('edit')->asImg(['class'=> 'text-top', 'title' => 'Einträge bearbeiten']) ?>
+ </a>
+ <? endif; ?>
+ <span><?= htmlReady($val->type) ?></span>
+ </td>
+ <td>
+ <? if ($key === 'sem'): ?>
+ <?= $val->object_class !== null ? htmlReady($GLOBALS['SEM_CLASS'][$val->object_class]['name']) : _('alle')?>
+ <? elseif ($key == 'inst'): ?>
+ <?= $val->object_class !== null ? htmlReady($GLOBALS['INST_TYPE'][$val->object_class]['name']) : _('alle')?>
+ <? elseif ($key === 'moduldeskriptor' || $key === 'modulteildeskriptor') : ?>
+ <?= $val->object_class !== null ? htmlReady(implode(', ', array_map(function ($class) {
+ return $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'][$class]['name'];
+ }, explode(',', $val->object_class)))) : _('alle')?>
+ <? elseif ($key === 'studycourse'): ?>
+ <? $object_classes =
+ [
+ 'all_settings' => _('alle (Abschnitt "Einstellungen")'),
+ 'all_info' => _('alle (Abschnitt "Inhalte und Informationen")'),
+ 'einfach_settings' => _('Einfach-Studiengänge (Abschnitt "Einstellungen")'),
+ 'einfach_info' => _('Einfach-Studiengänge (Abschnitt "Inhalte und Informationen")'),
+ 'mehrfach_settings' => _('Mehrfach-Studiengänge (Abschnitt "Einstellungen")'),
+ 'mehrfach_info' => _('Mehrfach-Studiengänge (Abschnitt "Inhalte und Informationen")')
+ ];?>
+ <?= $object_classes[$val->object_class] ?>
+ <? else: ?>
+ <?= $val->object_class !== null ? DataField::getReadableUserClass($val->object_class) : _('alle')?>
+ <? endif; ?>
+ </td>
+ <td>
+ <? if ($val->institution) : ?>
+ <?= htmlReady($val->institution->name)?>
+ <? endif; ?>
+ </td>
+ <td><?= $val->edit_perms ?></td>
+ <td><?= $val->view_perms ?></td>
+ <? if ($key === 'user'): ?>
+ <td>
+ <? if ($val->system): ?>
+ <?= Icon::create('checkbox-checked', Icon::ROLE_INACTIVE, ['title' => _('Ja')])->asImg() ?>
+ <? else: ?>
+ <?= Icon::create('checkbox-unchecked', Icon::ROLE_INACTIVE, ['title' => _('Nein')])->asImg() ?>
+ <? endif; ?>
+ </td>
+ <td>
+ <? if ($val->is_userfilter): ?>
+ <?= Icon::create('checkbox-checked', Icon::ROLE_INACTIVE, ['title' => _('Ja')])->asImg() ?>
+ <? else: ?>
+ <?= Icon::create('checkbox-unchecked', Icon::ROLE_INACTIVE, ['title' => _('Nein')])->asImg() ?>
+ <? endif; ?>
+ </td>
+ <? elseif ($key === 'sem'): ?>
+ <td>
+ <? if ($val->is_required): ?>
+ <?= Icon::create('checkbox-checked', Icon::ROLE_INACTIVE, ['title' => _('Ja')])->asImg() ?>
+ <? else: ?>
+ <?= Icon::create('checkbox-unchecked', Icon::ROLE_INACTIVE, ['title' => _('Nein')])->asImg() ?>
+ <? endif; ?>
+ </td>
+ <td>
+ <? if (trim($val->description)): ?>
+ <?= Icon::create('checkbox-checked', Icon::ROLE_INACTIVE, ['title' => _('Ja')])->asImg() ?>
+ <? else: ?>
+ <?= Icon::create('checkbox-unchecked', Icon::ROLE_INACTIVE, ['title' => _('Nein')])->asImg() ?>
+ <? endif; ?>
+ </td>
+ <? else: ?>
+ <td colspan="2"></td>
+ <? endif; ?>
+ <td><?= $val->priority ?></td>
+ <td><?= count($val) ?></td>
+ <td class="actions">
+ <a href="<?=$controller->url_for('admin/datafields/edit/' . $val->id)?>" data-dialog>
+ <?= Icon::create('edit')->asImg(['title' => 'Datenfeld ändern']) ?>
+ </a>
+ <a href="<?=$controller->url_for('admin/datafields/delete/' . $val->id)?>">
+ <?= Icon::create('trash')->asImg(['title' => 'Datenfeld löschen']) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+<? endforeach; ?>
+</table>
diff --git a/app/views/admin/datafields/new.php b/app/views/admin/datafields/new.php
new file mode 100644
index 0000000..3b33efe
--- /dev/null
+++ b/app/views/admin/datafields/new.php
@@ -0,0 +1,172 @@
+<?php
+use Studip\Button, Studip\LinkButton;
+?>
+
+<form action="<?= $controller->url_for('admin/datafields/new/' . $object_typ) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= sprintf(_('Einen neuen Datentyp für die Kategorie "%s" erstellen'), $type_name) ?>
+ </legend>
+
+ <label>
+ <span class="required"><?= _('Name') ?></span>
+
+ <?= I18N::input('datafield_name', $datafield->name, [
+ 'required' => '',
+ 'size' => 60,
+ 'maxlength' => 254,
+ ]) ?>
+ </label>
+
+ <label>
+ <?= _('Feldtyp') ?>
+
+ <select name="datafield_type">
+ <? foreach (DataFieldEntry::getSupportedTypes($object_typ) as $param): ?>
+ <option><?= htmlReady($param) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label for="object_class">
+ <? if ($object_typ === 'sem'): ?>
+ <?= _('Veranstaltungskategorie') ?>
+ <? elseif ($object_typ === 'inst'): ?>
+ <?= _('Einrichtungstyp') ?>
+ <? elseif ($object_typ === 'moduldeskriptor' || $object_type === 'modulteildeskriptor') : ?>
+ <?= _('Sprache') ?>
+ <? elseif ($object_typ === 'studycourse'): ?>
+ <?= _('Typ/Abschnitt') ?>
+ <? else: ?>
+ <?= _('Nutzerstatus') ?>
+ <? endif; ?>
+
+ <? if ($object_typ === 'sem'): ?>
+ <select name="object_class[]">
+ <option value="NULL"><?= _('alle') ?></option>
+ <? foreach (SemClass::getClasses() as $key => $val): ?>
+ <option value="<?= $key ?>">
+ <?= htmlReady($val['name']) ?>
+ </option>
+ <? endforeach; ?>
+ <? elseif ($object_typ === 'inst'): ?>
+ <select name="object_class[]">
+ <option value="NULL"><?= _('alle') ?></option>
+ <? foreach ($GLOBALS['INST_TYPE'] as $key => $val): ?>
+ <option value="<?= $key ?>">
+ <?= htmlReady($val['name']) ?>
+ </option>
+ <? endforeach; ?>
+ <? elseif ($object_typ === 'moduldeskriptor') : ?>
+ <select multiple name="object_class[]" required>
+ <option value="NULL" selected><?= _('alle (mehrsprachige Eingabe bei Feldtyp textline, textarea, textmarkup)') ?></option>
+ <? foreach ((array) $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'] as $key => $value) : ?>
+ <option value="<?= htmlReady($key) ?>"><?= htmlReady($value['name']) ?></option>
+ <? endforeach; ?>
+ <? elseif ($object_typ === 'modulteildeskriptor') : ?>
+ <select multiple name="object_class[]" required>
+ <option value="NULL" selected><?= _('alle (mehrsprachige Eingabe bei Feldtyp textline, textarea, textmarkup)') ?></option>
+ <? foreach ((array) $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'] as $key => $value) : ?>
+ <option value="<?= htmlReady($key) ?>"><?= htmlReady($value['name']) ?></option>
+ <? endforeach; ?>
+ <? elseif ($object_typ === 'studycourse') : ?>
+ <select name="object_class" required>
+ <option value="all_settings" selected><?= _('alle (Abschnitt "Einstellungen")') ?></option>
+ <option value="all_info"><?= _('alle (Abschnitt "Inhalte und Informationen")') ?></option>
+ <option value="einfach_settings"><?= _('Einfach-Studiengänge (Abschnitt "Einstellungen")') ?></option>
+ <option value="einfach_info"><?= _('Einfach-Studiengänge (Abschnitt "Inhalte und Informationen")') ?></option>
+ <option value="mehrfach_settings"><?= _('Mehrfach-Studiengänge (Abschnitt "Einstellungen")') ?></option>
+ <option value="mehrfach_info"><?= _('Mehrfach-Studiengänge (Abschnitt "Inhalte und Informationen")') ?></option>
+ <? else: ?>
+ <select multiple size="7" name="object_class[]" required>
+ <option value="NULL" selected><?= _('alle') ?></option>
+ <? foreach ($controller->user_status as $perm => $value): ?>
+ <option value="<?= $value ?>"><?= $perm ?></option>
+ <? endforeach; ?>
+ <? endif; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('benötigter Status') ?>
+
+ <select name="edit_perms">
+ <? foreach (array_keys($controller->user_status) as $perm): ?>
+ <option><?= $perm ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Sichtbarkeit') ?>
+
+ <select name="visibility_perms">
+ <? foreach (array_keys($controller->user_status) as $perm): ?>
+ <option><?= $perm ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Einrichtung') ?>
+ <select name="institut_id" class="nested-select">
+ <option value="" class="is-placeholder"></option>
+ <? foreach ($institutes as $institute): ?>
+ <option value="<?= htmlReady($institute['Institut_id']) ?>"
+ class="<?= $institute['is_fak'] ? 'nested-item-header' : 'nested-item' ?>"
+ <?= $item->institut_id === $institute['Institut_id'] ? 'selected' : ''?>>
+ <?= htmlReady(my_substr($institute['Name'],0,80)) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <? if ($object_typ === 'user') :?>
+ <label>
+ <input type="hidden" name="system" value="0">
+ <input type="checkbox" name="system" value="1">
+
+ <?= _('Systemfeld') ?>
+ <?= tooltipIcon(_('Nur für die Person selbst sichtbar, wenn der '
+ . 'benötigte Status zum Bearbeiten oder die '
+ . 'Sichtbarkeit ausreichend ist')) ?>
+ </label>
+ <? endif; ?>
+
+ <label>
+ <?= _('Position') ?>
+
+ <input type="text" name="priority"
+ maxlength="10" size="2" class="size-s">
+ </label>
+
+ <? if ($object_typ === 'sem'): ?>
+ <label>
+ <input type="checkbox" name="is_required" value="true">
+
+ <?= _('Pflichtfeld') ?>
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+
+ <textarea name="description"></textarea>
+ </label>
+
+ <? endif; ?>
+ <? if ($object_typ === 'user'): ?>
+ <label>
+ <input type="checkbox" name="is_userfilter" value="1">
+
+ <?= _('Mögliche Bedingung für Anmelderegel') ?>
+ </label>
+ <? endif; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Anlegen'), 'anlegen', ['title' => _('Neues Datenfeld anlegen')]) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/datafields'), ['title' => _('Zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/datafields/preview.php b/app/views/admin/datafields/preview.php
new file mode 100644
index 0000000..27792fe
--- /dev/null
+++ b/app/views/admin/datafields/preview.php
@@ -0,0 +1,17 @@
+<form action="<?= $controller->url_for('admin/datafields/config/' . $struct->getID()) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <input type="hidden" name="typeparam" value="<?= htmlReady(rtrim($struct->getTypeParam()), false) ?>">
+
+ <fieldset>
+ <legend><?= _('Vorschau') ?></legend>
+
+ <?= $preview->getHTML('dummy') ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
+ <?= Studip\Button::create(_('Bearbeiten'), 'edit', ['data-dialog' => 'size=auto']) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/datafields/index/' . $struct->getObjectType() . '#' . $struct->getObjectType())) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/datafields/type_select.php b/app/views/admin/datafields/type_select.php
new file mode 100644
index 0000000..e430a75
--- /dev/null
+++ b/app/views/admin/datafields/type_select.php
@@ -0,0 +1,30 @@
+<?php
+use Studip\Button, Studip\LinkButton;
+?>
+
+<form action="<?= $controller->url_for('admin/datafields/new/') ?>" method="post"
+ class="default" <? if (Request::isXhr()) echo 'data-dialog'; ?>>
+
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Verwaltung von generischen Datenfeldern') ?></legend>
+
+ <label>
+ <?= _('Datenfeldtyp:') ?>
+
+ <select name="datafield_typ">
+ <? foreach ($allclasses as $key => $class): ?>
+ <option value="<?= $key ?>" <? if ($key === $class_filter) echo 'selected'; ?>>
+ <?= htmlReady($class) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::create(_('Auswählen'), 'auswaehlen', ['title' => _('Datenfeld auswählen')])?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/datafields', compact('class_filter'))) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/domain/edit.php b/app/views/admin/domain/edit.php
new file mode 100644
index 0000000..d63172c
--- /dev/null
+++ b/app/views/admin/domain/edit.php
@@ -0,0 +1,48 @@
+<form action="<?= $controller->link_for("admin/domain/save/{$domain->id}") ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend class="hide-in-dialog">
+ <? if ($domain->isNew()): ?>
+ <?= _('Neue Nutzerdomäne anlegen') ?>
+ <? else: ?>
+ <?= _('Nutzerdomäne bearbeiten') ?>
+ <? endif; ?>
+ </legend>
+
+ <label>
+ <span class="required"><?= _('ID der Domäne') ?></span>
+ <input required type="text" name="id" pattern="<?= UserDomain::REGEXP ?>"
+ maxlength="32" value="<?= htmlReady($domain->id) ?>">
+ </label>
+
+ <label>
+ <span class="required"><?= _('Name der Domäne') ?></span>
+ <input required type="text" name="name"
+ value="<?= htmlReady($domain->name) ?>">
+ </label>
+
+ <label>
+ <?= _('Sichtbarkeit innerhalb der Domäne') ?>
+ </label>
+
+ <label class="undecorated" style="display: block;">
+ <input type="radio" name="restricted_access" value="1"
+ <? if ($domain->restricted_access) echo 'checked'; ?>>
+ <?= _('Nutzer bleiben innerhalb der Domäne und können keine Nutzer ausserhalb sehen') ?>
+ </label>
+
+ <label class="undecorated" style="display: block;">
+ <input type="radio" name="restricted_access" value="0"
+ <? if (!$domain->restricted_access) echo 'checked'; ?>>
+ <?= _('Nutzer der Domäne können das System uneingeschränkt nutzen') ?>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'), $controller->url_for('admin/domain')
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/domain/index.php b/app/views/admin/domain/index.php
new file mode 100644
index 0000000..9b37517
--- /dev/null
+++ b/app/views/admin/domain/index.php
@@ -0,0 +1,52 @@
+<? if (count($domains) == 0) : ?>
+ <?= MessageBox::info(_('Es sind keine Nutzerdomänen vorhanden.')) ?>
+<? else : ?>
+ <form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <colgroup>
+ <col style="width: 40%">
+ <col style="width: 20%">
+ <col style="width: 15%">
+ <col style="width: 15%">
+ <col style="width: 10%">
+ </colgroup>
+ <caption>
+ <?= _('Liste der Nutzerdomänen') ?>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('ID') ?></th>
+ <th><?= _('Nutzer/-innen') ?></th>
+ <th><?= _('Veranstaltungen') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($domains as $domain): ?>
+ <tr>
+ <td><?= htmlReady($domain->name) ?></td>
+ <td><?= htmlReady($domain->id) ?></td>
+ <td><?= count($domain->users) ?></td>
+ <td><?= count($domain->courses) ?></td>
+ <td class="actions">
+ <a href="<?= $controller->link_for("admin/domain/edit/{$domain->id}") ?>" data-dialog="size=auto">
+ <?= Icon::create('edit')->asImg(tooltip2(_('bearbeiten'))) ?>
+ </a>
+ <? if (count($domain->users) === 0): ?>
+ <?= Icon::create('trash')->asInput(tooltip2(_('löschen')) + [
+ 'class' => 'text-top',
+ 'formaction' => $controller->url_for("admin/domain/delete/{$domain->id}"),
+ 'data-confirm' => _('Wollen Sie die Nutzerdomäne wirklich löschen?')
+ ]) ?>
+ <? else: ?>
+ <?= Icon::create('trash', Icon::ROLE_INACTIVE)->asImg(['title' => _('Domänen, denen noch Personen zugewiesen sind, können nicht gelöscht werden.')]) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </form>
+<? endif ?>
diff --git a/app/views/admin/holidays/edit.php b/app/views/admin/holidays/edit.php
new file mode 100644
index 0000000..4cdd3c2
--- /dev/null
+++ b/app/views/admin/holidays/edit.php
@@ -0,0 +1,36 @@
+<form method="post" class="default" action="<?= $controller->url_for('admin/holidays/edit/' . $holiday->id) ?>" data-dialog="size=auto">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Ferien bearbeiten') ?></legend>
+ <label>
+ <?= _('Name der Ferien') ?>
+ <input required type="text" name="name" id="name" value="<?= htmlReady($holiday->name) ?>">
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description" id="description"><?= htmlReady($holiday->description) ?></textarea>
+ </label>
+
+ <label class="col-3">
+ <?= _('Ferienbeginn') ?>:
+ <input required type="text" id="beginn" name="beginn"
+ data-date-picker
+ value="<? if ($holiday->beginn) echo date('d.m.Y', $holiday->beginn) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Ferienende') ?>:
+ <input required type="text" id="ende" name="ende"
+ data-date-picker='{">=":"#beginn"}'
+ value="<? if ($holiday->ende) echo date('d.m.Y', $holiday->ende) ?>">
+ </label>
+ </fieldset>
+
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/holidays')) ?>
+ </div>
+
+</form>
diff --git a/app/views/admin/holidays/index.php b/app/views/admin/holidays/index.php
new file mode 100644
index 0000000..23f720f
--- /dev/null
+++ b/app/views/admin/holidays/index.php
@@ -0,0 +1,77 @@
+<form action="<?= $controller->url_for('admin/holidays/delete/bulk') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+<table class="default" id="holidays">
+ <caption><?= _('Ferien') ?></caption>
+ <colgroup>
+ <col width="20px">
+ <col>
+ <col width="50%">
+ <col width="48px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="#holidays tbody :checkbox"
+ data-activates="#holidays tfoot button">
+ </th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Zeitraum') ?></th>
+ <th>&nbsp;</th>
+ </tr>
+ </thead>
+ <tbody>
+<? if (empty($holidays)): ?>
+ <tr>
+ <td colspan="4" style="text-align: center;">
+ <? if ($filter): ?>
+ <?= _('In der gewählten Ansicht gibt es keine Einträge.') ?>
+ <? else: ?>
+ <?= _('Es wurden noch keine Ferien angelegt.') ?><br>
+ <?= Studip\LinkButton::create(_('Neue Ferien anlegen'),
+ $controller->url_for('admin/holidays/edit'),
+ ['data-dialog' => 'size=auto']) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+<? else: ?>
+ <? foreach ($holidays as $holiday): ?>
+ <tr <? if ($holiday->current) echo 'style="font-weight: bold;"'; ?>>
+ <td>
+ <input type="checkbox" name="ids[]" value="<?= $holiday->id ?>">
+ </td>
+ <td title="<?= htmlReady($holiday->description) ?>">
+ <?= htmlReady($holiday->name) ?>
+ </td>
+ <td>
+ <?= strftime('%x', $holiday->beginn) ?>
+ -
+ <?= strftime('%x', $holiday->ende) ?>
+ </td>
+ <td class="actions">
+ <a data-dialog="size=auto" href="<?= $controller->url_for('admin/holidays/edit/' . $holiday->id) ?>">
+ <?= Icon::create('edit', 'clickable', ['title' => _('Ferienangaben bearbeiten')])->asImg() ?>
+ </a>
+ <?= Icon::create('trash', 'clickable', ['title' => _('Ferien löschen')])->asInput([
+ 'formaction' => $controller->url_for('admin/holidays/delete/' . $holiday->id),
+ 'data-confirm' => _('Sollen die Ferien wirklich gelöscht werden?'),
+ 'class' => 'text-bottom',
+ ]) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+<? endif; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="4">
+ <?= _('Markierte Einträge') ?>
+ <?= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Sollen die Ferien wirklich gelöscht werden?'),
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+</form>
diff --git a/app/views/admin/ilias_interface/add_ilias.php b/app/views/admin/ilias_interface/add_ilias.php
new file mode 100755
index 0000000..f209700
--- /dev/null
+++ b/app/views/admin/ilias_interface/add_ilias.php
@@ -0,0 +1,26 @@
+<form class="default" action="<?= $controller->url_for('admin/ilias_interface/save/'.$ilias_index) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if (count($existing_indices)) : ?>
+ <label>
+ <span class="required"><?= _('Art der Verknüpfung') ?></span>
+ <select name="ilias_index">
+ <option selected><?=_('Neue Verknüpfung')?></option>
+ <? foreach ($existing_indices as $existing_index => $data) : ?>
+ <option><?=sprintf(_('ILIAS-Installation (Index %s) aus vorheriger Verknüpfung'), $existing_index)?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif ?>
+ <label>
+ <span class="required"><?= _('Name der Installation') ?></span>
+ <input type="text" name="ilias_name" size="50" maxlength="255" value="<?= htmlReady($ilias_config['name']) ?>" required>
+ </label>
+ <label>
+ <span class="required"> <?= _('URL') ?></span>
+ <input type="text" name="ilias_url" size="50" maxlength="255" value="<?= $ilias_config['url'] ?>" required>
+ </label>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/admin/ilias_interface/edit_content.php b/app/views/admin/ilias_interface/edit_content.php
new file mode 100755
index 0000000..4e0c51b
--- /dev/null
+++ b/app/views/admin/ilias_interface/edit_content.php
@@ -0,0 +1,99 @@
+<form class="default" action="<?= $controller->url_for('admin/ilias_interface/save/'.$ilias_index) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="ilias_content_settings" size="50" maxlength="255" value="1">
+ <label>
+ <span class="required"><?= _('Wurzelkategorie für Stud.IP-Daten') ?></span>
+ <? if ($ilias_config['root_category']) : ?>
+ <div><?=htmlReady($ilias_config['root_category_name']).' (ID '.htmlReady($ilias_config['root_category']).')'?></div>
+ <? else : ?>
+ <input type="text" name="ilias_root_category_name" size="50" maxlength="255" value="<?= htmlReady($ilias_config['root_category_name']) ?>" required>
+ <? endif ?>
+ </label>
+ <? if ($ilias_config['user_data_category']) : ?>
+ <label>
+ <span class="required"><?= _('Kategorie mit User-Daten') ?></span>
+ <div><?= _('User_daten').' (ID '.htmlReady($ilias_config['user_data_category']).')'?></div>
+ </label>
+ <? endif ?>
+ <label>
+ <input type="checkbox" name="ilias_category_create_on_add_module" value="1" <?= $ilias_config['category_create_on_add_module'] ? 'checked' : '' ?>>
+ <span><?= _('Persönliche ILIAS-Kategorie erst erzeugen, wenn Lernobjekte angelegt werden') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_category_to_desktop" value="1" <?= $ilias_config['category_to_desktop'] ? 'checked' : '' ?>>
+ <span><?= _('Persönliche ILIAS-Kategorie auf den Schreibtisch legen') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_delete_ilias_users" value="1" <?= $ilias_config['delete_ilias_users'] ? 'checked' : '' ?>>
+ <span><?= _('Beim Löschen von Stud.IP-Accounts ILIAS-Accounts ebenfalls löschen (alle zugehörigen Objekte werden gelöscht!)') ?></span>
+ </label>
+ <label>
+ <span class="required"><?= _('Prefix für automatisch angelegte Usernamen') ?></span>
+ <? if ($ilias_config['is_active']) : ?>
+ <div><?=$ilias_config['user_prefix'] ? htmlReady($ilias_config['user_prefix']) : _('Kein Präfix')?></div>
+ <? else : ?>
+ <input type="text" name="ilias_user_prefix" size="50" maxlength="255" value="<?= htmlReady($ilias_config['user_prefix']) ?>">
+ <? endif ?>
+ </label>
+ <label>
+ <span><?= _('Datenfeld (Name) mit Matrikelnummer (wenn leer, wird keine Matrikelnummer übergeben)') ?></span>
+ <input type="text" name="ilias_matriculation" size="50" maxlength="255" value="<?= htmlReady($ilias_config['matriculation']) ?>">
+ </label>
+ <label>
+ <span class="required"><?= _('Struktur für angelegte Kurse') ?></span>
+ </label>
+ <label>
+ <input type="radio" name="ilias_cat_semester" value="none" required <?=$ilias_config['cat_semester'] == "none" ? ' checked' : ''?>>
+ <span><?= _('Keine Semester-Kategorien') ?></span>
+ </label>
+ <label>
+ <input type="radio" name="ilias_cat_semester" value="outer" required <?=$ilias_config['cat_semester'] == "outer" ? ' checked' : ''?>>
+ <span><?= _('Semester als Kategorie oberhalb der Einrichtung') ?></span>
+ </label>
+ <label>
+ <input type="radio" name="ilias_cat_semester" value="inner" required <?=$ilias_config['cat_semester'] == "inner" ? ' checked' : ''?>>
+ <span><?= _('Semester als Kategorie innerhalb der Einrichtung') ?></span>
+ </label>
+ <label>
+ <span class="required"><?= _('Kurstitel') ?></span>
+ </label>
+ <label>
+ <input type="radio" name="ilias_course_semester" value="old" required <?=$ilias_config['course_semester'] == "old" ? ' checked' : ''?>>
+ <span><?= _('Stud.IP-Veranstaltung "Veranstaltungsname"') ?></span>
+ </label>
+ <label>
+ <input type="radio" name="ilias_course_semester" value="old_bracket" required <?=$ilias_config['course_semester'] == "old_bracket" ? ' checked' : ''?>>
+ <span><?= _('Stud.IP-Veranstaltung "Veranstaltungsname" (Semester)') ?></span>
+ </label>
+ <label>
+ <input type="radio" name="ilias_course_semester" value="none" required <?=$ilias_config['course_semester'] == "none" ? ' checked' : ''?>>
+ <span><?= _('Veranstaltungsname') ?></span>
+ </label>
+ <label>
+ <input type="radio" name="ilias_course_semester" value="bracket" required <?=$ilias_config['course_semester'] == "bracket" ? ' checked' : ''?>>
+ <span><?= _('Veranstaltungsname (Semester)') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_course_veranstaltungsnummer" value="1" <?= $ilias_config['course_veranstaltungsnummer'] ? 'checked' : '' ?>>
+ <span><?= _('Stud.IP-Veranstaltungsnummer im ILIAS-Kurstitel anzeigen') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_delete_ilias_courses" value="1" <?= $ilias_config['delete_ilias_courses'] ? 'checked' : '' ?>>
+ <span><?= _('Beim Löschen von Stud.IP-Veranstaltungen ILIAS-Kurse ebenfalls löschen (alle untergeordneten Objekte werden gelöscht!)') ?></span>
+ </label>
+ <label>
+ <span> <?= _('Module') ?></span>
+ </label>
+ <label>
+ <? foreach ($modules_available as $module_index => $module_name) : ?>
+ <label>
+ <input type="checkbox" name="ilias_modules_<?=$module_index?>" value="1" <?=$ilias_config['modules'][$module_index] ? ' checked':''?>>
+ <?=htmlReady($module_name)?>
+ </label>
+ <? endforeach ?>
+ </label>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/ilias_interface/edit_interface_settings.php b/app/views/admin/ilias_interface/edit_interface_settings.php
new file mode 100755
index 0000000..5143cd0
--- /dev/null
+++ b/app/views/admin/ilias_interface/edit_interface_settings.php
@@ -0,0 +1,54 @@
+<form class="default" action="<?= $controller->url_for('admin/ilias_interface/save_interface_settings/') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <label>
+ <span class="required"><?= _('Name des Moduls "ILIAS-Schnittstelle" in Veranstaltungen') ?></span>
+ <input type="text" name="ilias_interface_moduletitle" size="50" maxlength="255" value="<?= htmlReady($ilias_interface_moduletitle) ?>" required>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_interface_edit_moduletitle" value="1" <?= $ilias_interface_config['edit_moduletitle'] ? 'checked' : '' ?>>
+ <span><?= _('Lehrende können den Seitennamen der ILIAS-Schnittstelle in Veranstaltungen anpassen') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_interface_show_offline" value="1" <?= $ilias_interface_config['show_offline'] ? 'checked' : '' ?>>
+ <span><?= _('Namen von Lernobjekten und Kursen, die in ILIAS offline sind, sind in Stud.IP sichtbar') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_interface_add_statusgroups" value="1" <?= $ilias_interface_config['add_statusgroups'] ? 'checked' : '' ?>>
+ <span><?= _('Lehrende können Statusgruppen nach ILIAS übertragen') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_interface_allow_change_course" value="1" <?= $ilias_interface_config['allow_change_course'] ? 'checked' : '' ?>>
+ <span><?= _('Lehrende können die Kursverknüpfung einer Veranstaltung ändern') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_interface_allow_add_own_course" value="1" <?= $ilias_interface_config['allow_add_own_course'] ? 'checked' : '' ?>>
+ <span><?= _('Lehrende können einen eigenen ILIAS-Kurs verknüpfen, der noch nicht mit Stud.IP verbunden ist') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_interface_show_tools_page" value="1" <?= $ilias_interface_config['show_tools_page'] ? 'checked' : '' ?>>
+ <span><?= _('Account-Seite im Tools-Bereich ist für alle Nutzenden (auch für Studierende ohne Berechtigung zum Anlegen von Lernobjekten) sichtbar') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_interface_search_active" value="1" <?= $ilias_interface_config['search_active'] ? 'checked' : '' ?>>
+ <span><?= _('Suche nach Lernobjekten verfügbar') ?></span>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_interface_cache" value="1" <?= $ilias_interface_config['cache'] ? 'checked' : '' ?>>
+ <span><?= _('SOAP-Cache') ?></span>
+ </label>
+ <? if (!empty($existing_indices)) : ?>
+ <label>
+ <span class="required"><?= _('Art der Verknüpfung') ?></span>
+ <select name="ilias_index">
+ <option value="new" selected><?=_('Neue Verknüpfung')?></option>
+ <? foreach ($existing_indices as $existing_index => $data) : ?>
+ <option value="<?=$existing_index?>"><?=sprintf(_('ILIAS-Installation (Index %s) aus vorheriger Verknüpfung'), $existing_index)?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/ilias_interface/edit_permissions.php b/app/views/admin/ilias_interface/edit_permissions.php
new file mode 100755
index 0000000..81b53e9
--- /dev/null
+++ b/app/views/admin/ilias_interface/edit_permissions.php
@@ -0,0 +1,25 @@
+<form class="default" action="<?= $controller->url_for('admin/ilias_interface/save/'.$ilias_index) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <label>
+ <span class="required"><?= _('Rollen-Template zum Erstellen von Lernobjekten') ?></span>
+ <input type="text" name="ilias_author_role_name" size="50" maxlength="255" value="<?= $ilias_config['author_role_name'] ? htmlReady($ilias_config['author_role_name']) : 'Author' ?>" required>
+ </label>
+ <label>
+ <span class="required"><?= _('Erforderliche Rechtestufe zum Erstellen von Lernobjekten') ?></span>
+ <select name="ilias_author_perm">
+ <option value="autor" <?=$ilias_config['author_perm'] == 'autor' ? 'selected' : ''?>><?=_('autor')?></option>
+ <option value="tutor" <?=$ilias_config['author_perm'] == 'tutor' ? 'selected' : ''?>><?=_('tutor')?></option>
+ <option value="dozent" <?=(($ilias_config['author_perm'] == 'dozent') OR ! $ilias_config['author_perm']) ? 'selected' : ''?>><?=_('dozent')?></option>
+ <option value="admin" <?=$ilias_config['author_perm'] == 'admin' ? 'selected' : ''?>><?=_('admin')?></option>
+ <option value="root" <?=$ilias_config['author_perm'] == 'root' ? 'selected' : ''?>><?=_('root')?></option>
+ </select>
+ </label>
+ <label>
+ <input type="checkbox" name="ilias_allow_change_account" value="1" <?= $ilias_config['allow_change_account'] ? 'checked' : '' ?>>
+ <span><?= _('Stud.IP-User können sich bestehende ILIAS-Accounts manuell zuordnen') ?></span>
+ </label>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/admin/ilias_interface/edit_server.php b/app/views/admin/ilias_interface/edit_server.php
new file mode 100755
index 0000000..50c859a
--- /dev/null
+++ b/app/views/admin/ilias_interface/edit_server.php
@@ -0,0 +1,87 @@
+<? if (!$valid_url) : ?>
+<form class="default" action="<?= $controller->url_for('admin/ilias_interface/edit_server/'.$ilias_index) ?>" method="post">
+<? else : ?>
+<form class="default" action="<?= $controller->url_for('admin/ilias_interface/save/'.$ilias_index) ?>" method="post">
+<? endif ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <? if (count($existing_indices) && ($ilias_index == 'new')) : ?>
+ <label>
+ <span class="required"><?= _('Art der Verknüpfung') ?></span>
+ <select name="ilias_index">
+ <option value="new" selected><?=_('Neue Verknüpfung')?></option>
+ <? foreach ($existing_indices as $existing_index => $data) : ?>
+ <option value="<?=$existing_index?>"><?=sprintf(_('ILIAS-Installation (Index %s) aus vorheriger Verknüpfung'), $existing_index)?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? else : ?>
+ <label>
+ <span class="required"><?= _('Kennung der Verknüpfung') ?></span>
+ <input type="hidden" name="ilias_index" value="<?=$ilias_index?>">
+ <input type="text" size="50" maxlength="255" value="<?=$ilias_index == 'new' ? _('Neue Verknüpfung') : $ilias_index?>" disabled>
+ </label>
+ <? endif ?>
+ <label>
+ <span class="required"><?= _('Name der Installation') ?></span>
+ <input type="text" name="ilias_name" size="50" maxlength="255" value="<?= htmlReady($ilias_config['name']) ?>" required>
+ </label>
+ <label>
+ <span class="required"> <?= _('URL') ?></span>
+ <input type="text" name="ilias_url" size="50" maxlength="255" value="<?= $ilias_config['url'] ?>" required>
+ </label>
+ <? if ($valid_url) : ?>
+ <label for="ilias_version">
+ <span class="required"><?= _('ILIAS Version') ?></span>
+ <? if ($ilias_version) : ?>
+ <input type="hidden" name="ilias_version" value="<?=htmlReady($ilias_version)?>">
+ <div><?=htmlReady($ilias_version).' ('.htmlReady($ilias_version_date).')'?></div>
+ <? else : ?>
+ <input type="text" name="ilias_version" size="8" maxlength="8" value="<?=htmlReady($ilias_config['version']) ?>" required>
+ <? endif ?>
+ </label>
+ <label>
+ <span class="required"> <?= _('Name des ILIAS-Mandanten') ?></span>
+ <? if (count($ilias_clients) == 1) : ?>
+ <input type="hidden" name="ilias_client" value="<?=htmlReady($ilias_clients[0])?>">
+ <div><?=htmlReady($ilias_clients[0])?></div>
+ <? elseif (count($ilias_clients) > 1) : ?>
+ <select name="ilias_client">
+ <? foreach ($ilias_clients as $client_name) : ?>
+ <option value="<?=htmlReady($client_name)?>" <?= $client_name == $ilias_config['client'] ? ' selected' : ''?>><?=htmlReady($client_name)?></option>
+ <? endforeach ?>
+ </select>
+ <? else : ?>
+ <input type="text" name="ilias_client" size="50" maxlength="255" value="<?= $ilias_config['client'] ?>" required>
+ <? endif ?>
+ </label>
+ <label>
+ <span><?= _('LDAP-Einstellung') ?></span>
+ <? if ($ldap_options) : ?>
+ <select name="ilias_ldap_enable">
+ <?=$ldap_options;?>
+ </select><br>
+ <?=_("Authentifizierungsplugin (nur LDAP) beim Anlegen von externen Accounts übernehmen.");?>
+ <?=Icon::create('info-circle', 'inactive', ['title' => _("Wählen Sie hier ein Authentifizierungsplugin, damit neu angelegte ILIAS-Accounts den Authentifizierungsmodus LDAP erhalten, wenn dieser Modus auch für den vorhandenen Stud.IP-Account gilt. Andernfalls erhalten alle ILIAS-Accounts den default-Modus")])->asImg(16);?>
+ <? else : ?>
+ <br><?=_("(Um diese Einstellung zu nutzen muss zumindest ein LDAP Authentifizierungsplugin aktiviert sein.)");?>
+ <input type="hidden" name="ilias_ldap_enable" value="">
+ <? endif ?>
+ </label>
+ <label>
+ <span class="required"> <?= _('Admin-Account') ?></span>
+ <input type="text" name="ilias_admin" size="50" maxlength="255" value="<?= $ilias_config['admin'] ?>" required>
+ </label>
+ <label>
+ <span class="required"> <?= _('Admin-Passwort') ?></span>
+ <input type="password" name="ilias_admin_pw" size="50" maxlength="255" value="<?= $ilias_config['admin_pw'] ?>" required>
+ </label>
+ <? endif ?>
+ <footer data-dialog-button>
+ <? if (!$valid_url) : ?>
+ <?= Studip\Button::createAccept(_('Weiter'), 'submit', ['data-dialog' => 'size=auto']) ?>
+ <? else : ?>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <? endif ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/admin/ilias_interface/index.php b/app/views/admin/ilias_interface/index.php
new file mode 100755
index 0000000..b9e1ff7
--- /dev/null
+++ b/app/views/admin/ilias_interface/index.php
@@ -0,0 +1,94 @@
+ <form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= _('Angebundene ILIAS-Installationen') ?>
+ <span class="actions">
+ <a href="<?= $controller->url_for('admin/ilias_interface/edit_server/new') ?>" data-dialog="size=auto">
+ <?= Icon::create('add')->asImg(tooltip2(_('Neue ILIAS-Installation hinzufügen'))) ?>
+ </a>
+ </span>
+ </caption>
+ <colgroup>
+ <col style="width: 10%">
+ <col style="width: 60%">
+ <col style="width: 10%">
+ <col style="width: 10%">
+ <col style="width: 10%">
+ </colgroup>
+ <thead>
+ <th><?= _('Aktiv') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Index') ?></th>
+ <th><?= _('Version') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </thead>
+ <tbody>
+ <? foreach ($ilias_configs as $ilias_index => $ilias_config) : ?>
+ <tr id="ilias-<?= htmlReady($ilias_index)?>">
+ <td>
+ <? if ($ilias_config['is_active']) {
+ $text = _('Diese ILIAS-Installation ist aktiv. Klicken Sie hier, um sie zu deaktivieren.');
+ $img = 'checkbox-checked';
+ $cmd = 'deactivate';
+ } else {
+ $text = _('Diese ILIAS-Installation ist inaktiv. Klicken Sie hier, um sie zu aktivieren.');
+ $img = 'checkbox-unchecked';
+ $cmd = 'activate';
+ }
+ ?>
+ <a href="<?= $controller->url_for('admin/ilias_interface/'.$cmd.'/'.$ilias_index) ?>">
+ <?= Icon::create($img, 'clickable', ['title' => $text])->asImg() ?>
+ </a>
+ </td>
+ <td><?= htmlReady($ilias_config['name']) ?></td>
+ <td><?= htmlReady($ilias_index) ?></td>
+ <td><?= htmlReady($ilias_config['version']) ?></td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink(
+ $controller->url_for("admin/ilias_interface/edit_server/$ilias_index"),
+ _('Servereinstellungen bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? $actionMenu->addLink(
+ $controller->url_for("admin/ilias_interface/edit_content/$ilias_index"),
+ _('Inhaltseinstellungen bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? $actionMenu->addLink(
+ $controller->url_for("admin/ilias_interface/edit_permissions/$ilias_index"),
+ _('Berechtigungen bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+
+ <? $actionMenu->addButton(
+ 'delete_config',
+ _('Konfiguration löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Konfiguration löschen'),
+ 'formaction' => $controller->url_for("admin/ilias_interface/delete/$ilias_index"),
+ 'data-confirm' => sprintf(
+ sprintf(_('Soll die ILIAS-Installation "%s" wirklich entfernt werden?'),
+ htmlReady($ilias_config['name']))
+ ),
+ ])
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+
+ <? if (!$ilias_configs): ?>
+ <tr>
+ <td colspan="5" style="text-align: center">
+ <?= _('Es ist keine ILIAS-Installation eingerichtet.') ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+</form> \ No newline at end of file
diff --git a/app/views/admin/ilias_interface/soap_methods.php b/app/views/admin/ilias_interface/soap_methods.php
new file mode 100755
index 0000000..a6c6dc8
--- /dev/null
+++ b/app/views/admin/ilias_interface/soap_methods.php
@@ -0,0 +1,40 @@
+<form class="default" action="<?= $controller->url_for('admin/ilias_interface/soap_methods/'.$ilias_index) ?>" method="post">
+ <? if ($result) : ?>
+ <article class="studip">
+ <section><?=_('Ergebnis')?></section>
+ <? if (is_array($result)) : ?>
+ <pre>
+ <? print_r($result)?>
+ </pre>
+ <? else : ?>
+ <?=htmlReady($result)?>
+ <? endif ?>
+ </article>
+ <? endif ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <? if (!$ilias_soap_method) : ?>
+ <label>
+ <span class="required"><?= _('SOAP-Methode') ?></span>
+ <select name="ilias_soap_method">
+ <? foreach ($soap_methods as $method => $params) : ?>
+ <option value="<?=htmlReady($method)?>"><?=htmlReady($method)?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? else : ?>
+ <input type="hidden" name="ilias_call" value="<?= $ilias_soap_method ?>">
+ <? foreach ($soap_methods[$ilias_soap_method] as $param) : ?>
+ <label>
+ <span> <?= $param ?></span>
+ <input type="text" name="ilias_soap_param_<?=$param?>" size="50" value="<?=$params[$param]?>">
+ </label>
+ <? endforeach ?>
+ <? endif ?>
+ <footer>
+ <? if (!$ilias_soap_method) : ?>
+ <?= Studip\Button::createAccept(_('Weiter'), 'submit') ?>
+ <? else : ?>
+ <?= Studip\Button::createAccept(_('Ausführen'), 'submit') ?>
+ <? endif ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/admin/install/finish.php b/app/views/admin/install/finish.php
new file mode 100644
index 0000000..0829aec
--- /dev/null
+++ b/app/views/admin/install/finish.php
@@ -0,0 +1,19 @@
+<h2><?= _('Stud.IP ist auf Ihrem Server nun vollständig installiert!') ?></h2>
+
+<p>
+ <?= _('Der Klick auf den Button „Zum neuen Stud.IP“ schließt diesen Assistenten '
+ . 'und führt Sie zur Anmeldung in Ihrem neuen Stud.IP. Melden Sie sich mit '
+ . ' Ihren root-Zugangsdaten an.') ?>
+</p>
+<p>
+ <?= _('Dort werden Sie ggf. aufgefordert, zunächst weitere notwendige '
+ . 'Migrationsschritte durchzuführen!') ?>
+</p>
+<p>
+ <?= sprintf(
+ _('Haben Sie Fragen, Anregungen oder benötigen Unterstützung, helfen wir '
+ . 'Ihnen gerne weiter! Sie finden uns auf %sdevelop.studip.de%s.'),
+ '<a href="https://develop.studip.de" target="_blank">',
+ '</a>'
+ ) ?>
+</p>
diff --git a/app/views/admin/install/index.php b/app/views/admin/install/index.php
new file mode 100644
index 0000000..d6156d8
--- /dev/null
+++ b/app/views/admin/install/index.php
@@ -0,0 +1,51 @@
+<h2><?= _('Willkommen beim Installationsassistenten für Stud.IP!') ?></h2>
+
+<p>
+ <?= sprintf(
+ _('Dieser Assistent führt Sie in %u Schritten durch die Installation '
+ . 'von Stud.IP. Nach dem letzten Schritt haben Sie eine voll '
+ . 'funktionsfähige Stud.IP-Installation mit Datenbank und von Ihnen '
+ . 'ausgewählten Beispiel-Inhalten für den ersten Testbetrieb.'),
+ count($steps)
+ ) ?>
+
+ <?= _('Die Installation dauert ca. 10 Minuten.') ?>
+</p>
+
+<p>
+ <?= _('Sie benötigen für die Installation') ?>
+ <ul>
+ <li><?= _('eine Datenbank (MySQL/MariaDB)') ?></li>
+ <li>
+ <?= _('Zugriff auf den Server (als Server-Administrator oder über '
+ . 'Ihren Hoster)') ?>
+ </li>
+ </ul>
+</p>
+
+<p>
+ <?= _('Bitte halten Sie folgende Informationen bereit:') ?>
+
+ <ul>
+ <li><?= _('Datenbank-Host') ?></li>
+ <li><?= _('Datenbank-Name') ?></li>
+ <li><?= _('Datenbank-Nutzername') ?></li>
+ <li><?= _('Datenbank-Passwort') ?></li>
+ </ul>
+</p>
+
+
+<p>
+ <?= sprintf(
+ _('Eine ausführliche Installationsanleitung und weiterführende Hilfen '
+ . 'finden Sie auf den %sHilfe-Seiten von Stud.IP%s und über die Fußleiste '
+ . 'des Assistenten.'),
+ '<a href="https://hilfe.studip.de/admin/Admins/Installationsanleitung" class="link-extern" target="_blank">',
+ '</a>'
+ ) ?>
+</p>
+
+<p>
+ <?= _('Klicken Sie auf „Assistent starten“, wenn Sie mit der Installation '
+ . 'beginnen wollen!') ?>
+</p>
diff --git a/app/views/admin/install/install-basic.php b/app/views/admin/install/install-basic.php
new file mode 100644
index 0000000..688a86c
--- /dev/null
+++ b/app/views/admin/install/install-basic.php
@@ -0,0 +1,42 @@
+<h3><?= _('Installation') ?></h3>
+<dl>
+ <dt><?= _('Datenbank') ?></dt>
+ <dd class="success">
+ <?= _('Datenbanktabellen wurden erzeugt und ausgewählte Beispieldaten '
+ . 'eingetragen') ?>
+ </dd>
+
+ <dt><?= _('Root-Konto') ?></dt>
+ <dd class="success">
+ <?= _('Das Konto für das Haupt-Administrator-Konto wurde eingerichtet') ?>
+ </dd>
+
+ <dt><?= _('Konfiguration') ?></dt>
+<?php if ($local_inc === true): ?>
+ <dd class="success">
+ <?= sprintf(
+ _('Konfiguration wurde in die Datenbank und die Dateien '
+ . '%sconfig/config_local.inc.php%s sowie '
+ . '%sconfig/config.inc.php%s geschrieben'),
+ '<code>',
+ '</code>',
+ '<code>',
+ '</code>'
+ ) ?>
+ </dd>
+<?php else: ?>
+ <dd class="failed">
+ <?= _('Konnte nicht gespeichert werden. Bitte erzeugen Sie die beiden '
+ . 'folgenden Dateien mit dem jeweiligen Inhalt:') ?>
+ <br>
+
+ <code>config/config_local.inc.php</code>:<br>
+ <textarea onclick="this.select()"><?= htmlReady($local_inc) ?></textarea>
+
+ <br>
+
+ <code>config/config.inc.php</code>:<br>
+ <textarea onclick="this.select()"><?= htmlReady($config_inc) ?></textarea>
+ </dd>
+<?php endif; ?>
+</dl>
diff --git a/app/views/admin/install/install.php b/app/views/admin/install/install.php
new file mode 100644
index 0000000..f56a30b
--- /dev/null
+++ b/app/views/admin/install/install.php
@@ -0,0 +1,54 @@
+<h3><?= _('Installation') ?></h3>
+<dl class="requests">
+ <dt data-request-url="<?= $controller->link_for('install/sql') ?>" data-event-source="1">
+ <?= _('Datenbank') ?>
+ </dt>
+ <dd class="success">
+ <?= _('Datenbanktabellen wurden erzeugt und ausgewählte Beispieldaten '
+ . 'eingetragen') ?>
+ </dd>
+ <dd class="failed">
+ <?= _('Fehler beim Installieren') ?>
+ <div class="response"></div>
+ </dd>
+ <progress class="event-sourced" max="1" value="0"></progress>
+
+ <dt data-request-url="<?= $controller->link_for('install/root') ?>">
+ <?= _('Root-Konto') ?>
+ </dt>
+ <dd class="success">
+ <?= _('Das Konto für das Haupt-Administrator-Konto wurde eingerichtet') ?>
+ </dd>
+ <dd class="failed">
+ <?= _('Fehler beim Einrichten') ?>
+ <div class="response"></div>
+ </dd>
+
+ <dt data-request-url="<?= $controller->link_for('install/config') ?>">
+ <?= _('Konfiguration') ?>
+ </dt>
+ <dd class="success">
+ <?= sprintf(
+ _('Konfiguration wurde in die Datenbank und die Dateien '
+ . '%sconfig/config_local.inc.php%s sowie '
+ . '%sconfig/config.inc.php%s geschrieben'),
+ '<code>',
+ '</code>',
+ '<code>',
+ '</code>'
+ ) ?>
+ </dd>
+ <dd class="failed">
+ <?= _('Konnte nicht gespeichert werden. Bitte erzeugen Sie die beiden '
+ . 'folgenden Dateien mit dem jeweiligen Inhalt:') ?>
+ <br>
+
+ <code>config/config_local.inc.php</code>:<br>
+ <textarea onclick="this.select()" class="response" data-key="local_inc"></textarea>
+
+ <br>
+
+ <code>config/config.inc.php</code>:<br>
+ <textarea onclick="this.select()" class="response" data-key="config_inc"></textarea>
+ </dd>
+</dl>
diff --git a/app/views/admin/install/layout.php b/app/views/admin/install/layout.php
new file mode 100644
index 0000000..8a0f993
--- /dev/null
+++ b/app/views/admin/install/layout.php
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <base href="<?= rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') ?>/">
+ <title>Stud.IP - <?= _('Installation') ?> - <?= htmlReady($steps[$step]) ?></title>
+ <link rel="icon" type="image/svg+xml" href="<?= URLHelper::getLink('assets/images/favicon.svg') ?>">
+ <link href="<?= URLHelper::getLink('assets/stylesheets/studip-installer.css') ?>" rel="stylesheet" type="text/css">
+ <link href="<?= URLHelper::getLink('assets/stylesheets/studip-base.css') ?>" rel="stylesheet" type="text/css">
+</head>
+<body id="install">
+ <form action="<?= $controller->link_for($step) ?>" method="post" class="stage ui-dialog ui-corner-all ui-widget ui-widget-content ui-front studip-dialog ui-dialog-buttons">
+ <noscript>
+ <input type="hidden" name="basic" value="1">
+ </noscript>
+ <div class="ui-dialog-titlebar ui-corner-all ui-widget-header ui-helper-clearfix">
+ <div><?= _('Installationsassistent') ?></div>
+ <div>
+ <?= sprintf('Schritt %u/%u:', $current_step, $total_steps) ?>
+ <?= htmlReady($steps[$step]) ?>
+ </div>
+ </div>
+ <div class="ui-dialog-content ui-widget-content">
+ <?php if ($error): ?>
+ <?= MessageBox::error($error, (array) @$error_details) ?>
+ <?php endif; ?>
+ <?= $content_for_layout ?>
+ </div>
+ <progress id="progress" value="<?= $current_step ?>" max="<?= $total_steps ?>"></progress>
+ <div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
+ <div class="ui-dialog-buttonset">
+ <?php if (!$hide_back_button && $previous_step): ?>
+ <?= Studip\LinkButton::create(
+ '<< ' . _('zurück'),
+ $controller->url_for($previous_step)
+ ) ?>
+ <?php elseif ($hide_back_button): ?>
+ <?= Studip\LinkButton::create(
+ '<< ' . _('zurück'),
+ $controller->url_for($step),
+ ['style' => 'visibility: hidden;']
+ ) ?>
+ <?php endif; ?>
+
+ <?php if (!$valid && $button_label): ?>
+ <?= Studip\Button::create($button_label, 'continue') ?>
+ <?php elseif (!$valid): ?>
+ <?= Studip\Button::create(_('Erneut prüfen'), 'check') ?>
+ <?php elseif ($next_step): ?>
+ <?= Studip\Button::create($button_label ?: (_('Weiter') . ' >>'), 'continue') ?>
+ <?php else: ?>
+ <?= Studip\Button::create($button_label, 'continue', ['style' => 'visibility: hidden;']) ?>
+ <?php endif; ?>
+ </div>
+ </div>
+ <footer>
+ <ul>
+ <li>
+ <a href="https://hilfe.studip.de/admin/Admins/Installationsanleitung" target="_blank">
+ <?= _('Hilfe') ?>
+ </a>
+ </li>
+ <li>
+ <a href="https://develop.studip.de" target="_blank">
+ <?= _('Stud.IP Entwicklungs- und Anwendungsforum') ?>
+ </a>
+ </li>
+ </ul>
+ </footer>
+ </form>
+
+ <script src="<?= URLHelper::getLink('assets/javascripts/studip-installer.js') ?>"></script>
+</body>
+</html>
diff --git a/app/views/admin/install/mysql.php b/app/views/admin/install/mysql.php
new file mode 100644
index 0000000..2e8f654
--- /dev/null
+++ b/app/views/admin/install/mysql.php
@@ -0,0 +1,35 @@
+<p>
+ <?= _('In diesem Schritt verbinden Sie Ihre Stud.IP-Installation mit Ihrer '
+ . 'bestehenden Datenbank.') ?>
+</p>
+
+<h3><?= _('Verbindungsdaten für die Datenbank') ?></h3>
+<div class="type-text required">
+ <label for="host"><?= _('Datenbank-Host') ?></label>
+ <input required type="text" id="host" name="host" value="<?= htmlReady(Request::get('host', $_SESSION['STUDIP_INSTALLATION']['database']['host'])) ?>">
+</div>
+
+<div class="type-text required">
+ <label for="user"><?= _('Datenbank-Nutzer') ?></label>
+ <input type="text" id="user" name="user" value="<?= htmlReady(Request::get('user', $_SESSION['STUDIP_INSTALLATION']['database']['user'])) ?>">
+</div>
+
+<div class="type-text">
+ <label for="password"><?= _('Datenbank-Passwort') ?></label>
+ <input type="password" id="password" name="password" value="<?= htmlReady(Request::get('password', $_SESSION['STUDIP_INSTALLATION']['database']['password'])) ?>">
+</div>
+
+<div class="type-text required">
+ <label for="database"><?= _('Name der Datenbank') ?></label>
+ <input required type="text" id="database" name="database" value="<?= htmlReady(Request::get('database', $_SESSION['STUDIP_INSTALLATION']['database']['database'])) ?>">
+</div>
+
+<div class="type-checkbox">
+ <input type="checkbox" name="create" id="create" value="1" checked
+ class="studip-checkbox">
+ <label for="create">
+ <?= _('Versuche Datenbank anzulegen, falls sie noch nicht existiert') ?>
+ </label>
+</div>
+
+<?php $button_label = $valid ? '' : _('Verbindung prüfen'); ?>
diff --git a/app/views/admin/install/mysql_check.php b/app/views/admin/install/mysql_check.php
new file mode 100644
index 0000000..1b38f8b
--- /dev/null
+++ b/app/views/admin/install/mysql_check.php
@@ -0,0 +1,66 @@
+<p>
+ <?= _('In diesem Schritt wird geprüft, ob die Konfiguration der Datenbank '
+ . 'korrekt ist.') ?>
+ <?= _('Wenn alle Häkchen grün sind, können Sie fortfahren!') ?>
+</p>
+
+<h3><?= _('Datenbank-Version') ?></h3>
+<dl>
+ <dt><?= htmlReady($result['version']['present']) ?></dt>
+<?php if ($result['version']['valid']): ?>
+ <dd class="success"><?= _('Ok') ?></dd>
+<?php else: ?>
+ <dd class="failed">
+ <?= sprintf(
+ _('Fehler, mindestens MySQL/MariaDB %s benötigt'),
+ htmlReady($result['version']['required'])
+ ) ?>
+ </dd>
+<?php endif; ?>
+</dl>
+
+<?php if (!$result['version']['valid']): ?>
+<p>
+ <?= sprintf(
+ _('Stud.IP benötigt eine MySQL/MariaDB-Datenbank ab mindestens Version %s.'),
+ htmlReady($result['version']['required'])
+ ) ?>
+</p>
+<?php endif; ?>
+
+<h3><?= _('Einstellungen') ?></h3>
+<dl>
+<?php foreach ($result['settings']['settings'] as $setting => $state): ?>
+ <dt><?= htmlReady($setting) ?></dt>
+ <?php if ($state['valid']): ?>
+ <dd class="success">
+ <?= _('Ok') ?>
+ (<?= htmlReady($state['present']) ?> <?= htmlReady($state['cmp']) ?> <?= htmlReady($state['required']) ?>)
+ </dd>
+ <?php else: ?>
+ <dd class="failed">
+ <?php if ($state['cmp'] === '!~=') : ?>
+ <?= sprintf(
+ _('Fehler, Wert ist %s und darf nicht %s sein'),
+ htmlReady($state['present']),
+ htmlReady($state['required'])
+ ) ?>
+ <?php else : ?>
+ <?= sprintf(
+ _('Fehler, Wert ist %s und muss %s sein'),
+ htmlReady($state['present']) ?: _('(leer)'),
+ htmlReady($state['required'])
+ ) ?>
+ <?php endif ?>
+ </dd>
+ <?php endif; ?>
+<?php endforeach; ?>
+</dl>
+
+<?php if (!$result['settings']['valid']): ?>
+<p>
+ <?= _('Bitte ändern Sie die Einstellungen in Ihrer Datenbankkonfiguration '
+ . 'oder wenden Sie sich an Ihren Hoster.') ?>
+ <?= _('Klicken Sie anschließend auf „Erneut prüfen“.') ?>
+</p>
+<?php endif; ?>
diff --git a/app/views/admin/install/permissions.php b/app/views/admin/install/permissions.php
new file mode 100644
index 0000000..03c2b57
--- /dev/null
+++ b/app/views/admin/install/permissions.php
@@ -0,0 +1,34 @@
+<p>
+ <?= _('In diesem Schritt wird geprüft, ob ausgewählte Datenverzeichnisse '
+ . 'beschreibbar sind.') ?>
+ <?= _('Sie können fortfahren, wenn sichergestellt ist, dass die '
+ . 'notwendigen Verzeichnisse schreibbar sind!') ?>
+</p>
+<p>
+ <?= _('Sollte der Ordner "config" nicht schreibbar sein, wird die '
+ . 'erzeugte Konfiguration am Ende der Installation angezeigt und '
+ . 'muss von Hand in die entsprechenden Dateien kopiert werden.') ?>
+</p>
+
+<h3><?= _('Schreibbare Dateien/Ordner') ?></h3>
+<dl>
+<?php foreach ($writable['paths'] as $f => $is_writable): ?>
+ <dt><?= htmlReady($f) ?></dt>
+ <?php if ($is_writable): ?>
+ <dd class="success"><?= _('Ok') ?></dd>
+ <?php elseif ($requirements[$f]): ?>
+ <dd class="failed"><?= _('Fehler, nicht schreibbar') ?></dd>
+ <?php else: ?>
+ <dd class="notice"><?= _('Nicht schreibbar (unproblematisch)') ?></dd>
+ <?php endif; ?>
+<?php endforeach; ?>
+</dl>
+
+<?php if (!$valid): ?>
+<p>
+ <?= _('Mindestens ein Verzeichnis kann nicht von der Anwendung beschrieben '
+ . 'werden.') ?>
+ <?= _('Ändern Sie die Berechtigungen für das Verzeichnis und klicken Sie '
+ . 'auf „Erneut prüfen“.') ?>
+</p>
+<?php endif; ?>
diff --git a/app/views/admin/install/php_check.php b/app/views/admin/install/php_check.php
new file mode 100644
index 0000000..ea337f3
--- /dev/null
+++ b/app/views/admin/install/php_check.php
@@ -0,0 +1,97 @@
+<p>
+ <?= _('In diesem Schritt wird geprüft, ob die PHP-Konfiguration auf dem '
+ . 'Server den Anforderungen von Stud.IP entspricht.') ?>
+ <?= _('Wenn alle Häkchen grün sind, können Sie fortfahren!') ?>
+</p>
+
+<h3><?= _('PHP-Version') ?></h3>
+<dl>
+ <dt><?= htmlReady($result['version']['present']) ?></dt>
+<?php if ($result['version']['valid']): ?>
+ <dd class="success"><?= _('Ok') ?></dd>
+<?php else: ?>
+ <dd class="failed">
+ <?= sprintf(
+ _('Fehler, mindestens PHP %s benötigt'),
+ htmlReady($result['version']['required'])
+ ) ?>
+ </dd>
+<?php endif; ?>
+</dl>
+
+<?php if (!$result['version']['valid']): ?>
+<p>
+ <?= sprintf(
+ _('Bevor Sie mit der Installation fortfahren können, müssen Sie die '
+ . 'PHP-Version Ihres Servers auf mind. Version %s aktualisieren.'),
+ htmlReady($result['version']['required'])
+ ) ?>
+ <?= _('Bei Problemen mit dem Aktualisieren Ihrer PHP-Version wenden Sie '
+ . 'sich an Ihren Hoster.') ?>
+</p>
+<?php endif; ?>
+
+<h3><?= _('PHP-Module') ?></h3>
+<dl>
+<?php foreach ($result['modules']['required'] as $module => $requirement): ?>
+ <dt><?= htmlReady($module) ?></dt>
+ <?php if (!$result['modules']['present'][$module] && $requirement === true): ?>
+ <dd class="failed"><?= _('Nicht installiert') ?></dd>
+ <?php elseif (!$result['modules']['present'][$module] && $requirement): ?>
+ <dd>
+ <?= sprintf(
+ _('Optional benötigt für "%s"'),
+ htmlReady($requirement)
+ ) ?>
+ </dd>
+ <?php else: ?>
+ <dd class="success"><?= _('Ok') ?></dd>
+ <?php endif; ?>
+<?php endforeach; ?>
+</dl>
+
+<?php if (!$result['modules']['valid']): ?>
+<p>
+ <?= _('Mindestens ein PHP-Modul muss noch installiert werden, bevor Sie '
+ . 'mit der Installation von Stud.IP fortfahren können.') ?>
+ <?= _('Bei Problemen mit der Installation von Modulen wenden Sie sich an '
+ . 'Ihren Hoster.') ?>
+</p>
+<?php endif; ?>
+
+<h3><?= _('PHP-Einstellungen') ?></h3>
+<dl>
+<?php foreach ($result['settings']['settings'] as $setting => $state): ?>
+ <dt><?= htmlReady($setting) ?></dt>
+ <?php if ($state['valid']): ?>
+ <dd class="success">
+ <?= _('Ok') ?>
+ (<?= htmlReady($state['present']) ?> <?= htmlReady($state['cmp']) ?> <?= htmlReady($state['required']) ?>)
+ </dd>
+ <?php else: ?>
+ <dd class="failed">
+ <?= sprintf(
+ _('Fehler, Wert ist %s und muss %s sein'),
+ htmlReady($state['present']) ?: _('(leer)'),
+ htmlReady($state['required'])
+ ) ?>
+ </dd>
+ <?php endif; ?>
+<?php endforeach; ?>
+</dl>
+
+<?php if (!$result['settings']['valid']): ?>
+<p>
+ <?= sprintf(
+ _('Die rot markierten Einstellungen müssen in der Datei %s%s%s '
+ . 'auf den angegebenen Wert gesetzt werden.'),
+ '<code>',
+ htmlReady(php_ini_loaded_file()),
+ '</code>'
+ ) ?>
+
+ <?= _('Denken Sie daran, dass nach einer Änderung der Server neu gestartet '
+ . 'werden muss!') ?>
+ <?= _('Wenn Sie dazu keine Berechtigung haben, wenden Sie sich an Ihren Hoster.') ?>
+</p>
+<?php endif; ?>
diff --git a/app/views/admin/install/prepare.php b/app/views/admin/install/prepare.php
new file mode 100644
index 0000000..ea93b07
--- /dev/null
+++ b/app/views/admin/install/prepare.php
@@ -0,0 +1,88 @@
+<p>
+ <?= _('In diesem Schritt wählen Sie aus, welche Beispieldaten in Ihre '
+ . 'Datenbank eingespielt werden und geben einige Grunddaten zur '
+ . 'Installation an, die in der Datenbank gespeichert werden.') ?>
+ <?= _('Die Grunddaten können Sie nach der Installation weiterhin bearbeiten.') ?>
+</p>
+
+<h3><?= _('SQL-Daten einspielen') ?></h3>
+<ul class="list-unstyled">
+<?php $i = 0; foreach ($files as $file => $description): ?>
+ <li>
+ <?php if (in_array($file, $required)): ?>
+ <input type="hidden" name="files[]" value="<?= htmlReady($file) ?>">
+ <input type="checkbox" checked disabled class="studip-checkbox">
+ <?php else: ?>
+ <input type="checkbox" name="files[]" value="<?= htmlReady($file) ?>"
+ class="studip-checkbox" id="option-<?= $i ?>">
+ <?php endif; ?>
+ <label for="option-<?= $i ?>">
+ <strong <?php if (in_array($file, $required)): ?>class="required"<?php endif; ?>>
+ <?= htmlReady($description) ?>
+ </strong>
+ (<?= htmlReady($file) ?>)
+ </label>
+ </li>
+<?php $i += 1; endforeach; ?>
+</ul>
+
+<h3><?= _('Daten zum System') ?></h3>
+<div class="type-text required">
+ <label for="system-name" class="vertical">
+ <?= _('Name der Stud.IP-Installation') ?>
+ </label>
+ <input required type="text" id="system-name" name="system_name"
+ value="<?= htmlReady(Request::get('system_name', $_SESSION['STUDIP_INSTALLATION']['system']['UNI_NAME_CLEAN'])) ?>">
+</div>
+
+<div class="type-text required">
+ <label for="system-id" class="vertical">
+ <?= _('Id der Stud.IP-Installation') ?>
+ </label>
+ <input required type="text" id="system-id" name="system_id"
+ value="<?= htmlReady(Request::get('system_id', $_SESSION['STUDIP_INSTALLATION']['system']['STUDIP_INSTALLATION_ID'])) ?>"
+ placeholder="<?= _('Eindeutiges, gängiges Kürzel Ihrer Einrichtung') ?>">
+</div>
+
+<div class="type-text required">
+ <label for="system-url" class="vertical">
+ <?= _('E-Mail-Adresse für Kontakt') ?>
+ </label>
+ <input required type="email" id="system-email" name="system_email"
+ value="<?= htmlReady(Request::get('system_email', $_SESSION['STUDIP_INSTALLATION']['system']['UNI_CONTACT'])) ?>">
+</div>
+
+<div class="type-text required">
+ <label for="system-url" class="vertical">
+ <?= _('URL der Stud.IP-Installation') ?>
+ </label>
+ <input required type="url" id="system-url" name="system_url"
+ value="<?= htmlReady(Request::get('system_url', $_SESSION['STUDIP_INSTALLATION']['system']['ABSOLUTE_URI_STUDIP'] ?: $defaults['system_url'])) ?>"
+ placeholder="https://">
+</div>
+
+<div class="type-text">
+ <label for="system-host-url" class="vertical">
+ <?= _('URL der betreibenden Einrichtung') ?>
+ </label>
+ <input type="url" id="system-host-url" name="system_host_url"
+ value="<?= htmlReady(Request::get('system_host_url', $_SESSION['STUDIP_INSTALLATION']['system']['UNI_URL'])) ?>"
+ placeholder="https://">
+</div>
+
+<h3><?= _('Diese Stud.IP-Installation läuft im') ?></h3>
+<div class="type-text">
+ <label class="plain">
+ <input type="radio" name="env" value="development"
+ <?php if ($_SESSION['STUDIP_INSTALLATION']['env'] === 'development') echo 'checked'; ?>>
+ <?= _('Entwicklungsmodus') ?>
+ </label>
+</div>
+
+<div class="type-text">
+ <label class="plain">
+ <input type="radio" name="env" value="production"
+ <?php if ($_SESSION['STUDIP_INSTALLATION']['env'] === 'production') echo 'checked'; ?>>
+ <?= _('Produktivmodus') ?>
+ </label>
+</div>
diff --git a/app/views/admin/install/root.php b/app/views/admin/install/root.php
new file mode 100644
index 0000000..46cffe4
--- /dev/null
+++ b/app/views/admin/install/root.php
@@ -0,0 +1,49 @@
+<p>
+ <?= _('In diesem Schritt legen Sie die Benutzerdaten für ein '
+ . 'Haupt-Administrator-Konto (root) in Stud.IP fest.') ?>
+ <?= _('Bitte merken Sie sich die Zugangsdaten!') ?>
+</p>
+
+<h3><?= _('Konto für Root einrichten') ?></h3>
+<div class="type-text required">
+ <label for="username" class="vertical"><?= _('Nutzername') ?></label>
+ <input required type="text" id="username" name="username" minlength="4"
+ value="<?= htmlReady(Request::get('username', $_SESSION['STUDIP_INSTALLATION']['root']['username'])) ?>">
+</div>
+
+<div class="type-text required">
+ <label for="password" class="vertical"><?= _('Passwort') ?></label>
+ <input required type="password" id="password" name="password" minlength="8">
+</div>
+
+<div class="type-text required">
+ <label for="password_confirm" class="vertical"><?= _('Passwort bestätigen') ?></label>
+ <input required type="password" id="password_confirm" name="password_confirm" minlength="8">
+</div>
+
+<div class="type-text required">
+ <label for="first_name" class="vertical"><?= _('Vorname') ?></label>
+ <input required type="text" id="first_name" name="first_name"
+ value="<?= htmlReady(Request::get('first_name', $_SESSION['STUDIP_INSTALLATION']['root']['first_name'])) ?>">
+</div>
+
+<div class="type-text required">
+ <label for="last_name" class="vertical"><?= _('Nachname') ?></label>
+ <input required type="text" id="last_name" name="last_name"
+ value="<?= htmlReady(Request::get('last_name', $_SESSION['STUDIP_INSTALLATION']['root']['last_name'])) ?>">
+</div>
+
+<div class="type-text required">
+ <label for="email" class="vertical"><?= _('E-Mail-Adresse') ?></label>
+ <input required type="email" id="email" name="email" value="<?= htmlReady(Request::get('user', $_SESSION['STUDIP_INSTALLATION']['root']['email'])) ?>">
+</div>
+
+<p style="margin-top: 1em;">
+ <?= _('Wenn Sie jetzt auf installieren klicken,') ?>
+ <ul>
+ <li><?= _('werden die notwendigen Datenbanktabellen erzeugt') ?></li>
+ <li><?= _('werden die ausgewählten Beispieldaten eingetragen') ?></li>
+ <li><?= _('wird die Grundkonfiguration für das System in der Datenbank gespeichert') ?></li>
+ <li><?= _('wird ein Root-Konto für Sie eingerichtet.') ?></li>
+ </ul>
+</p>
diff --git a/app/views/admin/install/session_error.php b/app/views/admin/install/session_error.php
new file mode 100644
index 0000000..0264e0d
--- /dev/null
+++ b/app/views/admin/install/session_error.php
@@ -0,0 +1,4 @@
+<div class="messagebox messagebox_error">
+ <?= _('Ihre PHP-Konfiguration bezüglich Sessions ist fehlerhaft oder Sie '
+ . 'haben den Installationsassistenten nicht korrekt gestartet.') ?>
+</div>
diff --git a/app/views/admin/licenses/edit.php b/app/views/admin/licenses/edit.php
new file mode 100644
index 0000000..6943a53
--- /dev/null
+++ b/app/views/admin/licenses/edit.php
@@ -0,0 +1,45 @@
+<form action="<?= $controller->link_for("admin/licenses/store", ['identifier' => $license->getId()]) ?>"
+ method="post"
+ enctype="multipart/form-data"
+ class="default">
+
+ <label>
+ <?= _("Lizenzkürzel (nach SPDX wenn möglich)") ?>
+ <input type="text" name="data[identifier]" value="<?= htmlReady($license['identifier']) ?>" required>
+ </label>
+
+ <label>
+ <?= _("Name") ?>
+ <input type="text" name="data[name]" value="<?= htmlReady($license['name']) ?>" required>
+ </label>
+
+ <input type="hidden" name="data[default]" value="0">
+ <label>
+ <input type="checkbox" name="data[default]" value="1"<?= $license['default'] ? " checked" : "" ?>>
+ <?= _("Standardlizenz") ?>
+ </label>
+
+ <label>
+ <?= _("Link zur Lizenz") ?>
+ <input type="text" name="data[link]" value="<?= htmlReady($license['link']) ?>" required>
+ </label>
+
+ <label>
+ <?= _("Beschreibung") ?>
+ <textarea name="data[description]"><?= htmlReady($license['description']) ?></textarea>
+ </label>
+
+ <label class="file-upload">
+ <?= _('Bild hochladen (PNG, JPG, GIF)') ?>
+ <input type="file" name="avatar" accept=".jpg,.png,.jpeg,.gif">
+ </label>
+
+ <label>
+ <input type="checkbox" name="delete_avatar" value="1">
+ <?= _("Bild löschen") ?>
+ </label>
+
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_("Speichern")) ?>
+ </div>
+</form>
diff --git a/app/views/admin/licenses/index.php b/app/views/admin/licenses/index.php
new file mode 100644
index 0000000..ee545ce
--- /dev/null
+++ b/app/views/admin/licenses/index.php
@@ -0,0 +1,54 @@
+<table class="default">
+ <caption>
+ <?= _("Lizenzen") ?>
+ </caption>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _("SPDX-Lizenzkürzel") ?></th>
+ <th><?= _("Name") ?></th>
+ <th class="actions"><?= _("Aktion") ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($licenses as $license) : ?>
+ <tr>
+ <td>
+ <?= LicenseAvatar::getAvatar($license['identifier'])->getImageTag(Avatar::MEDIUM) ?>
+ </td>
+ <td><?= htmlReady($license['identifier']) ?></td>
+ <td>
+ <? if ($license['link']) : ?>
+ <a href="<?= htmlReady($license['link']) ?>">
+ <? endif ?>
+ <?= htmlReady($license['name']) ?>
+ <? if ($license['link']) : ?>
+ </a>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->link_for("admin/licenses/edit", ['identifier' => $license['identifier']]) ?>" data-dialog>
+ <?= Icon::create("edit", "clickable")->asImg(20, ['class' => "text-bottom"]) ?>
+ </a>
+ <form action="<?= $controller->link_for("admin/licenses/delete", ['identifier' => $license->getId()]) ?>"
+ method="post"
+ data-confirm="<?= _("Wirklich löschen?") ?>"
+ class="inline">
+ <?= Icon::create("trash", "clickable")->asInput(20) ?>
+ </form>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+
+<?
+
+$actions = new ActionsWidget();
+$actions->addLink(
+ _("Lizenz erzeugen"),
+ $controller->url_for("admin/licenses/edit"),
+ Icon::create("add", "clickable"),
+ ['data-dialog' => 1]
+);
+Sidebar::Get()->addWidget($actions);
diff --git a/app/views/admin/lockrules/_form.php b/app/views/admin/lockrules/_form.php
new file mode 100644
index 0000000..319ecdc
--- /dev/null
+++ b/app/views/admin/lockrules/_form.php
@@ -0,0 +1,98 @@
+<?
+# Lifter010:
+use Studip\Button, Studip\LinkButton;
+
+?>
+<form action="<?= $action ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag(); ?>
+ <fieldset>
+ <legend>
+ <? if ($lock_rule->name) : ?>
+ <?= sprintf(_('Sperrebene "%s" ändern'), htmlready($lock_rule["name"])) ?>
+ <? else : ?>
+ <?= _('Neue Sperrebene eingeben für den Bereich:') ?> <?= $rule_type_names[$lock_rule_type]; ?>
+ <? endif ?>
+ </legend>
+
+ <label>
+ <?= _("Name") ?>
+
+ <input type="text" style="width:90%" required name="lockdata_name"
+ value="<?= htmlReady($lock_rule['name']) ?>">
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <?= tooltipIcon(_('Dieser Text wird auf allen Seiten mit gesperrtem Inhalt angezeigt')) ?>
+
+ <textarea name="lockdata_description" rows="5"
+ style="width:90%"><?= htmlReady($lock_rule["description"]) ?></textarea>
+ </label>
+
+ <label>
+ <?= _('Nutzerstatus') ?>
+ <?= tooltipIcon(_('Die Einstellungen dieser Sperrebene gelten für Nutzer bis zu dieser Berechtigung')) ?>
+
+ <select name="lockdata_permission">
+ <? foreach ($lock_rule_permissions as $p) : ?>
+ <option <?= ($lock_rule['permission'] == $p ? 'selected' : '') ?>><?= $p ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'ok', ['title' => _('Einstellungen übernehmen')]) ?>
+ </footer>
+
+
+ <? foreach ($lock_config['groups'] as $group => $group_title) : ?>
+ <? $attributes = array_filter(array_map(function ($a) use ($group) {
+ return $a['group'] == $group ? $a['name'] : null;
+ }, $lock_config['attributes'])); ?>
+ <? if (count($attributes)) : ?>
+ <br>
+ <table class="default">
+ <caption>
+ <?= htmlready($group_title) ?>
+ </caption>
+ <colgroup>
+ <col width="70%">
+ <col width="15%">
+ <col width="15%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('gesperrt') ?></th>
+ <th><?= _('nicht gesperrt') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($attributes as $attr => $attr_name) : ?>
+ <tr>
+ <td>
+ <?= htmlready($attr_name) ?>
+ </td>
+ <td>
+ <input type="radio"
+ name="lockdata_attributes[<?= $attr ?>]" <?= ($lock_rule['attributes'][$attr] ? 'checked' : '') ?>
+ value="1"/>
+ </td>
+ <td>
+ <input type="radio"
+ name="lockdata_attributes[<?= $attr ?>]" <?= (!$lock_rule['attributes'][$attr] ? 'checked' : '') ?>
+ value="0"/>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'ok', ['title' => _('Einstellungen übernehmen')]) ?>
+ </footer>
+ <? endif ?>
+
+ <? endforeach ?>
+</form>
diff --git a/app/views/admin/lockrules/edit.php b/app/views/admin/lockrules/edit.php
new file mode 100644
index 0000000..87d0c89
--- /dev/null
+++ b/app/views/admin/lockrules/edit.php
@@ -0,0 +1,4 @@
+<?
+# Lifter010: TODO
+?>
+<?= $this->render_partial('admin/lockrules/_form.php', ['action' => $this->controller->url_for('admin/lockrules/edit/' . $lock_rule->getId())]); \ No newline at end of file
diff --git a/app/views/admin/lockrules/index.php b/app/views/admin/lockrules/index.php
new file mode 100644
index 0000000..9835b3b
--- /dev/null
+++ b/app/views/admin/lockrules/index.php
@@ -0,0 +1,65 @@
+<?php
+# Lifter010: TODO
+?>
+
+<form method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= _('Sperrebenen für den Bereich:') ?> <?= $rule_type_names[$lock_rule_type]; ?>
+ </caption>
+ <colgroup>
+ <col width="30%">
+ <col width="50%">
+ <col width="20%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ <th><?= _('Besitzer') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if(count($lock_rules) > 0) : ?>
+ <? foreach ($lock_rules as $rule): ?>
+ <tr>
+ <td>
+ <?= htmlReady($rule->name) ?>
+ </td>
+ <td>
+ <?= htmlReady(my_substr($rule->description, 0, 100)) ?>
+ </td>
+ <td>
+ <?= htmlReady($rule->user_id ? get_fullname($rule->user_id) : '') ?>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->url_for('admin/lockrules/edit/' . $rule->lock_id) ?>">
+ <?= Icon::create('edit', 'clickable', ['title' => _('Diese Regel bearbeiten')])->asImg() ?>
+ </a>
+
+ <?
+ if ($rule->getUsage()) :?>
+ <? $msg = sprintf(_('Sie beabsichtigen die Ebene %s zu löschen. Diese Ebene wird von %s Objekten benutzt. Soll sie trotzdem gelöscht werden?'),
+ htmlReady($rule->name), htmlReady($rule->getUsage())) ?>
+ <? else : ?>
+ <? $msg = sprintf(_('Möchten Sie die Ebene %s löschen?'), $rule->name) ?>
+ <? endif ?>
+ <?= Icon::create('trash', 'clickable', [
+ 'title' => _('Diese Regel löschen'),
+ 'style' => 'vertical-align: middle'
+ ])->asInput(['data-confirm'=>$msg,'formaction'=>$controller->url_for('admin/lockrules/delete/'.$rule->lock_id)]) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? else :?>
+ <tr>
+ <td colspan="4" style="text-align: center">
+ <?=_('Keine Sperrebenen vorhanden')?>
+ </td>
+ </tr>
+ <? endif?>
+ </tbody>
+ </table>
+</form>
diff --git a/app/views/admin/lockrules/new.php b/app/views/admin/lockrules/new.php
new file mode 100644
index 0000000..b40667d
--- /dev/null
+++ b/app/views/admin/lockrules/new.php
@@ -0,0 +1,5 @@
+<?
+# Lifter010: TODO
+?>
+<?= $this->render_partial('admin/lockrules/_form.php', ['action' => $this->controller->url_for('admin/lockrules/new')]);
+
diff --git a/app/views/admin/login_style/index.php b/app/views/admin/login_style/index.php
new file mode 100644
index 0000000..aa0c74a
--- /dev/null
+++ b/app/views/admin/login_style/index.php
@@ -0,0 +1,64 @@
+<? if (count($pictures) > 0) : ?>
+ <table class="default">
+ <caption>
+ <?= _('Hintergrundbilder für den Startbildschirm') ?>
+ </caption>
+ <colgroup>
+ <col>
+ <col width="400">
+ <col width="100">
+ <col width="25">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Info') ?></th>
+ <th><?= _('Vorschau') ?></th>
+ <th><?= _('Aktiviert für') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($pictures as $pic) :
+ $dim = $pic->getDimensions();
+ ?>
+ <tr>
+ <td>
+ <?= htmlReady($pic->filename) ?>
+ <br>
+ (<?= $dim[0] ?> x <?= $dim[1] ?>,
+ <?= relsize($pic->getFilesize(), false) ?>)
+ </td>
+ <td>
+ <img src="<?= $pic->getURL() ?>" width="400">
+ </td>
+ <td>
+ <a href="<?= $controller->link_for("admin/loginstyle/activation/{$pic->id}/desktop", (int) !$pic->desktop) ?>">
+ <?= Icon::create('computer', $pic->desktop ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(32, [
+ 'title' => $pic->desktop
+ ? _('Bild nicht mehr für die Desktopansicht verwenden')
+ : _('Bild für die Desktopansicht verwenden')
+ ]) ?>
+ </a>
+ <a href="<?= $controller->link_for("admin/loginstyle/activation/{$pic->id}/mobile", (int) !$pic->mobile) ?>">
+ <?= Icon::create('cellphone', $pic->mobile ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(32, [
+ 'title' => $pic->mobile
+ ? _('Bild nicht mehr für die Mobilansicht verwenden')
+ : _('Bild für die Mobilansicht verwenden')
+ ]) ?>
+ </a>
+ </td>
+ <td class="actions">
+ <? if (!$pic->in_release): ?>
+ <a href="<?= $controller->link_for("admin/loginstyle/delete/{$pic->id}") ?>">
+ <?= Icon::create('trash')->asImg([
+ 'title' => _('Bild löschen'),
+ 'data-confirm' => _('Soll das Bild wirklich gelöscht werden?'),
+ ]) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </table>
+<? else : ?>
+ <?= PageLayout::postInfo(_('In Ihrem System sind leider keine Bilder für den Startbildschirm hinterlegt.')) ?>
+<? endif ?>
diff --git a/app/views/admin/login_style/newpic.php b/app/views/admin/login_style/newpic.php
new file mode 100644
index 0000000..d2c9250
--- /dev/null
+++ b/app/views/admin/login_style/newpic.php
@@ -0,0 +1,33 @@
+<form class="default" action="<?= $controller->link_for('admin/loginstyle/add') ?>" method="post" enctype="multipart/form-data">
+ <fieldset>
+ <legend>
+ <?= _('Bild(er) hinzufügen') ?>
+ </legend>
+ <label>
+ <?= _('Bild(er) hochladen') ?>
+ <input type="file"
+ name="pictures[]"
+ style="display: none;"
+ accept="image/gif,image/jpeg,image/png"
+ required
+ multiple>
+ <?= Icon::create('upload')->asImg(['class' => 'text-bottom upload']) ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="desktop" value="1" checked>
+ <?= _('aktiv in Desktopansicht') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="mobile" value="1" checked>
+ <?= _('aktiv in Mobilansicht') ?>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('loginstyle/index')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/lti/edit.php b/app/views/admin/lti/edit.php
new file mode 100644
index 0000000..996b9f2
--- /dev/null
+++ b/app/views/admin/lti/edit.php
@@ -0,0 +1,71 @@
+<form class="default" action="<?= $controller->link_for('admin/lti/save/' . $tool->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Konfiguration des LTI-Tools') ?>
+ </legend>
+
+ <label>
+ <span class="required">
+ <?= _('Name der Anwendung') ?>
+ </span>
+ <input type="text" name="name" value="<?= htmlReady($tool->name) ?>" required>
+ </label>
+
+ <label>
+ <span class="required">
+ <?= _('URL der Anwendung') ?>
+ </span>
+ <input type="text" name="launch_url" value="<?= htmlReady($tool->launch_url) ?>" required>
+ </label>
+
+ <label>
+ <span class="required">
+ <?= _('Consumer-Key') ?>
+ </span>
+ <input type="text" name="consumer_key" value="<?= htmlReady($tool->consumer_key) ?>" required>
+ </label>
+
+ <label>
+ <span class="required">
+ <?= _('Consumer-Secret') ?>
+ </span>
+ <input type="text" name="consumer_secret" value="<?= htmlReady($tool->consumer_secret) ?>" required>
+ </label>
+
+ <label>
+ <?= _('OAuth Signatur Methode') ?>
+ <select name="oauth_signature_method">
+ <option value="sha1">HMAC-SHA1</option>
+ <option value="sha256" <?=$tool->oauth_signature_method === 'sha256' ? 'selected' : '' ?>>HMAC-SHA256</option>
+ </select>
+ </label>
+
+ <label>
+ <input type="checkbox" name="allow_custom_url" value="1" <?= $tool->allow_custom_url ? ' checked' : '' ?>>
+ <?= _('Eingabe einer abweichenden URL im Kurs erlauben') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="deep_linking" value="1" <?= $tool->deep_linking ? ' checked' : '' ?>>
+ <?= _('Auswahl von Inhalten über LTI Deep Linking (Content Item)') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="send_lis_person" value="1" <?= $tool->send_lis_person ? ' checked' : '' ?>>
+ <?= _('Nutzerdaten an LTI-Tool senden') ?>
+ <?= tooltipIcon(_('Nutzerdaten dürfen nur an das externe Tool gesendet werden, wenn es keine Datenschutzbedenken gibt. Mit Setzen des Hakens bestätigen Sie, dass die Übermittlung der Daten zulässig ist.')) ?>
+ </label>
+
+ <label>
+ <?= _('Zusätzliche LTI-Parameter') ?>
+ <?= tooltipIcon(_('Ein Wert pro Zeile, Beispiel: Review:Chapter=1.2.56')) ?>
+ <textarea name="custom_parameters"><?= htmlReady($tool->custom_parameters) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/lti')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/lti/index.php b/app/views/admin/lti/index.php
new file mode 100644
index 0000000..919aae8
--- /dev/null
+++ b/app/views/admin/lti/index.php
@@ -0,0 +1,59 @@
+<form action="" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= _('Aktuell konfigurierte LTI-Tools') ?>
+ </caption>
+
+ <colgroup>
+ <col style="width: 30%;">
+ <col style="width: 40%;">
+ <col style="width: 20%;">
+ <col style="width: 5%;">
+ <col style="width: 5%;">
+ </colgroup>
+
+ <thead>
+ <th><?= _('Name der Anwendung') ?></th>
+ <th><?= _('URL der Anwendung') ?></th>
+ <th><?= _('Consumer-Key') ?></th>
+ <th><?= _('Links') ?></th>
+ <th class="actions">
+ <?= _('Aktionen') ?>
+ </th>
+ </thead>
+
+ <tbody>
+ <? foreach ($tools as $tool): ?>
+ <tr>
+ <td>
+ <a href="<?= $controller->link_for('admin/lti/edit/' . $tool->id) ?>" title="<?= _('LTI-Tool konfigurieren') ?>" data-dialog>
+ <?= htmlReady($tool->name) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= htmlReady($tool->launch_url) ?>" target="_blank" class="link-extern">
+ <?= htmlReady($tool->launch_url) ?>
+ </a>
+ </td>
+ <td>
+ <?= htmlReady($tool->consumer_key) ?>
+ </td>
+ <td>
+ <?= count($tool->links) ?>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->link_for('admin/lti/edit/' . $tool->id) ?>" title="<?= _('LTI-Tool konfigurieren') ?>" data-dialog>
+ <?= Icon::create('edit') ?>
+ </a>
+ <?= Icon::create('trash')->asInput([
+ 'formaction' => $controller->url_for('admin/lti/delete/' . $tool->id),
+ 'title' => _('LTI-Tool löschen'),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich das LTI-Tool "%s" löschen?'), htmlReady($tool->name))
+ ]) ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+</form>
diff --git a/app/views/admin/overlapping/admin_info.php b/app/views/admin/overlapping/admin_info.php
new file mode 100644
index 0000000..be3d68e
--- /dev/null
+++ b/app/views/admin/overlapping/admin_info.php
@@ -0,0 +1,27 @@
+<section class="contentbox">
+ <header>
+ <h1>
+ <?= _('Zuständige Administratoren') ?>
+ </h1>
+ </header>
+ <section>
+ <dl>
+ <dt>
+ <?= _('Heimateinrichtung') ?>
+ </dt>
+ <dd>
+ <?= htmlReady($course->home_institut->getFullname()) ?>
+ </dd>
+ <dt>
+ <?= _('Zuständige Administratoren') ?>
+ </dt>
+ <? foreach ($admins as $admin) : ?>
+ <dd>
+ <a href="<?= $controller->url_for('profile', ['username' => $admin->username]) ?>">
+ <?= htmlReady($admin->user->getFullname()) ?>
+ </a>
+ </dd>
+ <? endforeach; ?>
+ </dl>
+ </section>
+</section>
diff --git a/app/views/admin/overlapping/conflicts.php b/app/views/admin/overlapping/conflicts.php
new file mode 100644
index 0000000..f12588f
--- /dev/null
+++ b/app/views/admin/overlapping/conflicts.php
@@ -0,0 +1,96 @@
+<? $comp_abs = $conflicts->findBy('base_metadate_id', $cycle->id)->pluck('comp_abschnitt_id') ?>
+<? $comp_versions = StgteilVersion::findBySQL('INNER JOIN `mvv_stgteilabschnitt` USING (`version_id`) WHERE `abschnitt_id` IN (?) GROUP BY `version_id`', [$comp_abs]); ?>
+<? foreach ($comp_versions as $comp_version) : ?>
+<li>
+ <?= Icon::create('category', Icon::ROLE_INFO); ?>
+ <a class="mvv-ovl-version" href="<?= $controller->url_for('admin/overlapping/version_info', $comp_version->id) ?>" data-dialog="size=auto">
+ <?= htmlReady($comp_version->getDisplayName()); ?>
+ </a>
+ <? $comp_abschnitte = $comp_version->abschnitte->findBy('abschnitt_id', $conflicts->findBy('base_metadate_id', $cycle->id)->pluck('comp_abschnitt_id'))->orderBy('position', SORT_NUMERIC) ?>
+ <ul>
+ <? foreach ($comp_abschnitte as $comp_abschnitt) : ?>
+ <li>
+ <?= htmlReady($comp_abschnitt->getDisplayName()) ?>
+ <? $modul_ids = Modulteil::findAndMapMany(function ($mt) {
+ return $mt->modul_id;
+ }, $conflicts->findBy('base_metadate_id', $cycle->id)->pluck('comp_modulteil_id')) ?>
+ <? $module = StgteilabschnittModul::findBySQL(
+ '`abschnitt_id` = ? AND `modul_id` IN (?) ORDER BY `position`',
+ [$comp_abschnitt->id, $modul_ids]
+ ) ?>
+ <ul>
+ <? foreach ($module as $modul) : ?>
+ <li>
+ <?= Icon::create('log', Icon::ROLE_INFO); ?>
+ <?= htmlReady($modul->getDisplayName()) ?>
+ <? $conflicts_modulteile = $conflicts->filter(function ($c) use ($cycle, $comp_abschnitt) {
+ return $c->base_metadate_id == $cycle->id && $c->comp_abschnitt_id == $comp_abschnitt->id;
+ }) ?>
+ <? $comp_modulteile = $modul->modul->modulteile->findBy('modulteil_id', $conflicts_modulteile->pluck('comp_modulteil_id')) ?>
+ <ul>
+ <? foreach ($comp_modulteile as $comp_modulteil) : ?>
+ <li class="mvv-ovl-comp-modulteil">
+ <? $id = md5($base_modul->abschnitt_id . $comp_abschnitt->id . $comp_modulteil->id) ?>
+ <input id="<?= $id ?>" type="checkbox" checked>
+ <label for="<?= $id ?>"></label>
+ <div>
+ <?= htmlReady($comp_modulteil->getDisplayName()) ?>
+ </div>
+ <div>
+ <? foreach (range(1, 6) as $fachsem_nr) : ?>
+ <? $fachsems = $comp_modulteil->abschnitt_assignments->findBy('abschnitt_id', $comp_abschnitt->id); ?>
+ <? $fachsem = $fachsems->findOneBy('fachsemester', $fachsem_nr); ?>
+ <? if ($fachsem) : ?>
+ <div <?= tooltip($GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'][$fachsem->differenzierung]['name']) ?>>
+ <?= $GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'][$fachsem->differenzierung]['icon']; ?>
+ <? else : ?>
+ <div>
+ <? endif; ?>
+ </div>
+ <? endforeach; ?>
+ </div>
+ <? $comp_cycles = $conflicts->filter(function ($c) use ($comp_abschnitt, $comp_modulteil, $cycle, $base_modul, $modulteil) {
+ return ($c->base_abschnitt_id == $base_modul->abschnitt_id
+ && $c->base_modulteil_id == $modulteil->id
+ && $c->base_metadate_id == $cycle->id
+ && $c->comp_abschnitt_id == $comp_abschnitt->id
+ && $c->comp_modulteil_id == $comp_modulteil->id);
+ }); ?>
+ <ul class="mvv-overlapping-conflicts">
+ <? foreach ($comp_cycles as $comp_cycle) : ?>
+ <li>
+ <?= htmlReady($comp_cycle->comp_course->VeranstaltungsNummer) ?>
+ <a href="<?= $controller->url_for('admin/overlapping/course_info', $comp_cycle->comp_course_id) ?>" data-dialog="">
+ <?= Icon::create('info-circle', Icon::ROLE_INFO, ['style' => 'vertical-align: text-bottom;', 'title' => _('Veranstaltungsdetails')]) ?>
+ </a>
+ <?= htmlReady($comp_cycle->comp_course->getFullname('type-name')) ?>
+ <? if ($comp_cycle->comp_course->admission_turnout) : ?>
+ <?= sprintf(_('(erw. TN %s)'), htmlReady($comp_cycle->comp_course->admission_turnout)) ?>
+ <? endif; ?>
+ <? $dates = $comp_cycle->comp_cycle->dates->filter(function ($c) use ($selected_semester) {
+ return ($selected_semester->beginn <= $c->date && $selected_semester->ende >= $c->date);
+ }); ?>
+ <?= Icon::create('date-cycle', Icon::ROLE_INFO, ['style' => 'vertical-align: text-bottom;']) ?>
+ <?= sprintf('%s (%sx)', $comp_cycle->comp_cycle->toString('short'), count($dates)); ?>
+ <a href="<?= $controller->url_for('admin/overlapping/admin_info', $comp_cycle->comp_course->id) ?>" data-dialog="size=auto;title='<?= htmlReady($comp_cycle->comp_course->getFullname()) ?>';">
+ <?= Icon::create('person-online', Icon::ROLE_INFO, ['style' => 'vertical-align: text-bottom;', 'title' => _('Zuständige Administratoren')]) ?>
+ </a>
+ <span title="<?= $comp_cycle->isExcluded() ? _('Veranstaltung nicht berücksichtigen') : _('Veranstaltung berücksichtigen') ?>"
+ data-mvv-ovl-course="<?= $comp_cycle->comp_course_id ?>"
+ data-mvv-ovl-selection="<?= $comp_cycle->selection_id ?>"
+ class="mvv-overlapping-exclude<?= $comp_cycle->isExcluded() ? ' mvv-overlapping-invisible' : '' ?>">
+ </span>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </li>
+ <? endforeach; ?>
+ </ul>
+</li>
+<? endforeach; ?> \ No newline at end of file
diff --git a/app/views/admin/overlapping/courses.php b/app/views/admin/overlapping/courses.php
new file mode 100644
index 0000000..fe1e5a8
--- /dev/null
+++ b/app/views/admin/overlapping/courses.php
@@ -0,0 +1,32 @@
+<? foreach ($modulteil->lvgruppen as $lvgruppe) : ?>
+ <? foreach ($lvgruppe->getAssignedCoursesBySemester($selected_semester->id, false) as $course) : ?>
+ <? $course_obj = Course::find($course['seminar_id']) ?>
+ <? foreach ($course_obj->cycles->findBy('metadate_id', $conflicts->pluck('base_metadate_id')) as $cycle) : ?>
+ <? $dates = $cycle->dates->filter(function ($c) use ($selected_semester) {
+ return ($selected_semester->beginn <= $c->date && $selected_semester->ende >= $c->date);
+ }); ?>
+ <li>
+ <div class="mvv-ovl-base-course">!</div>
+ <? $id = md5($modul->abschnitt_id . $modulteil->id . $course['seminar_id']) ?>
+ <input id="<?= $id ?>" type="checkbox" checked>
+ <label for="<?= $id ?>"></label>
+ <?= htmlReady($course_obj->VeranstaltungsNummer) ?>
+ <a href="<?= $controller->url_for('admin/overlapping/course_info', $course_obj->id) ?>" data-dialog="">
+ <?= Icon::create('info-circle', Icon::ROLE_INFO, [
+ 'class' => 'text-bottom',
+ 'title' => _('Veranstaltungsdetails')
+ ]) ?>
+ </a>
+ <?= htmlReady($course_obj->getFullname('type-name')) ?>
+ <? if ($course_obj->admission_turnout) : ?>
+ <?= sprintf(_('(erw. TN %s)'), htmlReady($course_obj->admission_turnout)) ?>
+ <? endif; ?>
+ <?= Icon::create('date-cycle', Icon::ROLE_INFO, ['class' => 'text-bottom']) ?>
+ <?= sprintf('%s (%sx)', $cycle->toString('short'), count($dates)); ?>
+ <ul>
+ <?= $this->render_partial('admin/overlapping/conflicts', ['cycle' => $cycle, 'base_modul' => $modul, 'selected_semester' => $selected_semester]) ?>
+ </ul>
+ </li>
+ <? endforeach; ?>
+ <? endforeach; ?>
+<? endforeach; ?>
diff --git a/app/views/admin/overlapping/index.php b/app/views/admin/overlapping/index.php
new file mode 100644
index 0000000..821268f
--- /dev/null
+++ b/app/views/admin/overlapping/index.php
@@ -0,0 +1,7 @@
+<?= $this->render_partial('admin/overlapping/selection', ['fachsems' => $fachsems, 'semtypes' => $semtypes]) ?>
+<? if (count($conflicts)) : ?>
+ <?= $this->render_partial('admin/overlapping/overlapping') ?>
+<? endif; ?>
+<script>
+ STUDIP.Overlapping.init();
+</script> \ No newline at end of file
diff --git a/app/views/admin/overlapping/modul.php b/app/views/admin/overlapping/modul.php
new file mode 100644
index 0000000..e075b83
--- /dev/null
+++ b/app/views/admin/overlapping/modul.php
@@ -0,0 +1,29 @@
+<?= Icon::create('log', Icon::ROLE_INFO); ?> <?= htmlReady($modul->getDisplayName()); ?>
+<ul>
+ <? foreach ($modul->modul->modulteile->findBy('id', $conflicts->pluck('base_modulteil_id')) as $modulteil) : ?>
+ <li class="mvv-ovl-base-modulteil">
+ <? $id = md5($modul->abschnitt_id . $modulteil->id) ?>
+ <input id="<?= $id ?>" type="checkbox" checked>
+ <label for="<?= $id ?>"></label>
+ <div>
+ <?= htmlReady($modulteil->getDisplayName()); ?>
+ </div>
+ <? $fachsems = $modulteil->abschnitt_assignments->findBy('abschnitt_id', $abschnitt->id); ?>
+ <div>
+ <? foreach (range(1, 6) as $fachsem_nr) : ?>
+ <? $fachsem = $fachsems->findOneBy('fachsemester', $fachsem_nr); ?>
+ <? if ($fachsem) : ?>
+ <div <?= tooltip($GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'][$fachsem->differenzierung]['name']) ?>>
+ <?= $GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'][$fachsem->differenzierung]['icon']; ?>
+ </div>
+ <? else : ?>
+ <div></div>
+ <? endif; ?>
+ <? endforeach; ?>
+ </div>
+ <ul>
+ <?= $this->render_partial('admin/overlapping/courses', ['modulteil' => $modulteil, 'modul' => $modul]); ?>
+ </ul>
+ </li>
+ <? endforeach; ?>
+</ul>
diff --git a/app/views/admin/overlapping/overlapping.php b/app/views/admin/overlapping/overlapping.php
new file mode 100644
index 0000000..03b35e1
--- /dev/null
+++ b/app/views/admin/overlapping/overlapping.php
@@ -0,0 +1,31 @@
+<h1>
+ <?= Icon::create('category', Icon::ROLE_INFO)->asImg() ?>
+ <?= htmlReady($base_version->getDisplayName()); ?>
+</h1>
+<section>
+ <? foreach ($base_version->abschnitte->findBy('id', $conflicts->pluck('base_abschnitt_id')) as $abschnitt) : ?>
+ <article>
+ <header class="mvv-ovl-base-abschnitt">
+ <h2>
+ <?= htmlReady($abschnitt->getDisplayName()); ?>
+ </h2>
+ <div>
+ <? foreach (range(1, 6) as $fachsem_nr) : ?>
+ <div>
+ <?= $fachsem_nr ?>
+ </div>
+ <? endforeach; ?>
+ </div>
+ </header>
+ <? foreach ($abschnitt->modul_zuordnungen as $modul) : ?>
+ <? if (count(array_intersect($modul->modul->modulteile->pluck('id'), $conflicts->pluck('base_modulteil_id')))) : ?>
+ <ul class="collapsable css-tree mvv-ovl-conflict">
+ <li>
+ <?= $this->render_partial('admin/overlapping/modul', ['abschnitt' => $abschnitt, 'modul' => $modul]); ?>
+ </li>
+ </ul>
+ <? endif; ?>
+ <? endforeach; ?>
+ </article>
+ <? endforeach; ?>
+</section> \ No newline at end of file
diff --git a/app/views/admin/overlapping/selection.php b/app/views/admin/overlapping/selection.php
new file mode 100644
index 0000000..2fbdce1
--- /dev/null
+++ b/app/views/admin/overlapping/selection.php
@@ -0,0 +1,69 @@
+<form method="post" class="default collapsable mvv-ovl-selection" action="<?= $controller->url_for('admin/overlapping/check') ?>">
+ <fieldset>
+ <legend>
+ <?= _('Auswahl') ?>
+ </legend>
+
+ <label for="base-version-select">
+ <span><?= _('Studiengangteil') ?></span>
+ <select id="base-version-select" class="nested-select" name="base_version">
+ <? if ($base_version) : ?>
+ <option value="<?= $base_version->id ?>" selected><?= htmlReady($base_version->getDisplayName()) ?></option>
+ <? endif; ?>
+ </select>
+ </label>
+
+
+ <label for="comp-versions-select">
+ <span><?= _('Vergleichs-Studiengangteile') ?></span>
+ <select id="comp-versions-select" class="nested-select" name="comp_versions[]" multiple>
+ <? if (count($comp_versions)) : ?>
+ <? foreach($comp_versions as $comp_version) : ?>
+ <option value="<?= $comp_version->id ?>" selected><?= htmlReady($comp_version->getDisplayName()) ?></option>
+ <? endforeach; ?>
+ <? endif; ?>
+ </select>
+ </label>
+
+
+ <label for="fachsem-select">
+ <span><?= _('Fachsemester') ?></span>
+ <select id="fachsem-select" class="nested-select" name="fachsems[]" multiple>
+ <? foreach (range(1, 6) as $fsem) : ?>
+ <option value="<?= $fsem ?>"<?= in_array($fsem, (array) $fachsems) ? ' selected' : '' ?>>
+ <?= $fsem . ModuleManagementModel::getLocaleOrdinalNumberSuffix($fsem) . ' ' . _('Fachsemester') ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label for="semtype-select">
+ <span><?= _('Veranstaltungstyp-Filter') ?></span>
+ <select id="semtype-select" class="nested-select" name="semtypes[]" multiple>
+ <? foreach ($GLOBALS['SEM_CLASS'] as $class_id => $class) : ?>
+ <? if ($class['studygroup_mode']) : continue;
+ endif; ?>
+ <optgroup class="nested-item-header" label="<?= htmlReady($class['name']) ?>">
+ <? foreach ($class->getSemTypes() as $id => $type) : ?>
+ <option class="nested-item nested-item-level-2"
+ value="<?= $id ?>"<?= in_array($id, (array) $semtypes) ? ' selected' : '' ?>>
+ <?= htmlReady($type['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </optgroup>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <input type="checkbox"
+ name="show_hidden"
+ value="1" <?= $_SESSION['MVV_OVL_HIDDEN'] ? ' checked' : '' ?>>
+ <?= _('ausgeblendete Veranstaltungen anzeigen') ?>
+ </label>
+ </fieldset>
+ <footer>
+ <?= \Studip\Button::createAccept(_('Vergleichen'), 'compare') ?>
+ <?= \Studip\Button::createCancel(_('Zurücksetzen'), 'index', ['formaction' => $controller->url_for('/reset')]) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/plugin/activation-error-form.php b/app/views/admin/plugin/activation-error-form.php
new file mode 100644
index 0000000..cd9b8b9
--- /dev/null
+++ b/app/views/admin/plugin/activation-error-form.php
@@ -0,0 +1,32 @@
+<?php
+$aggregated = array_sum($memory);
+if (!$aggregated) {
+ $question = _('Markierte Plugins dennoch deaktivieren');
+} elseif ($aggregated === count($memory)) {
+ $question = _('Markierte Plugins dennoch aktivieren');
+} else {
+ $question = _('Markierte Plugins dennoch aktivieren bzw. deaktivieren');
+}
+?>
+
+<form action="<?= $controller->url_for('admin/plugin/save') ?>" method="post">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <input type="hidden" name="force" value="1">
+
+ <?= _('Die folgenden Fehler sind aufgetreten:') ?>
+ <div class="messagebox_details">
+ <ul>
+ <? foreach ($errors as $plugin_id => $error): ?>
+ <li>
+ <label>
+ <input type="checkbox" name="enabled_<?= $plugin_id ?>"
+ value="<?= (int) $memory[$plugin_id] ?>">
+ <?= htmlReady($error) ?>
+ </label>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+
+ <?= Studip\Button::create($question) ?>
+</form>
diff --git a/app/views/admin/plugin/default_activation.php b/app/views/admin/plugin/default_activation.php
new file mode 100644
index 0000000..5ac8d16
--- /dev/null
+++ b/app/views/admin/plugin/default_activation.php
@@ -0,0 +1,45 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<? if (isset($flash['message'])): ?>
+ <?= MessageBox::success($flash['message']) ?>
+<? endif ?>
+
+<form action="<?= $controller->url_for('admin/plugin/save_default_activation', $plugin_id) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+
+ <fieldset>
+ <legend>
+ <?= _('Standard-Aktivierung in Veranstaltungen') ?>: <?= htmlReady($plugin_name) ?>
+ </legend>
+
+
+ <label>
+ <?= _('Einrichtung') ?>
+ <select name="selected_inst[]" multiple size="20" class="nested-select" style="width: 100%">
+ <? foreach ($institutes as $id => $institute): ?>
+ <option class="nested-item-header" value="<?= $id ?>" <?= in_array($id, $selected_inst) ? 'selected' : '' ?>>
+ <?= htmlReady($institute['name']) ?>
+ </option>
+
+ <? if (isset($institute['children'])): ?>
+ <? foreach ($institute['children'] as $id => $child): ?>
+ <option class="nested-item" value="<?= $id ?>" <?= in_array($id, $selected_inst) ? 'selected' : '' ?>>
+ <?= htmlReady($child['name']) ?>
+ </option>
+ <? endforeach ?>
+ <? endif ?>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Übernehmen'),'save', ['title' => _('Einstellungen speichern')])?>
+ &nbsp;
+ <?= LinkButton::create('<< ' . _("Zurück"), $controller->url_for('admin/plugin'), ['title' => _('Zurück zur Plugin-Verwaltung')])?>
+ </footer>
+</form>
diff --git a/app/views/admin/plugin/edit_automaticupdate.php b/app/views/admin/plugin/edit_automaticupdate.php
new file mode 100644
index 0000000..066b1b3
--- /dev/null
+++ b/app/views/admin/plugin/edit_automaticupdate.php
@@ -0,0 +1,64 @@
+<?
+if (mb_strpos($_SERVER['SERVER_NAME'], ':') !== false) {
+ list($_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT']) =
+ explode(':', $_SERVER['SERVER_NAME']);
+}
+if ($_SERVER['SERVER_NAME'] === "localhost" || $_SERVER['SERVER_NAME'] = "127.0.0.1") {
+ $domain_warning = sprintf(_("Achtung, mit %s als Domain kann der Webhook-Aufruf von github nicht funktionieren."), $_SERVER['SERVER_NAME']);
+}
+$DOMAIN_STUDIP = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
+$DOMAIN_STUDIP .= '://'.$_SERVER['SERVER_NAME'];
+
+if ($_SERVER['HTTPS'] == 'on' && $_SERVER['SERVER_PORT'] != 443 ||
+ $_SERVER['HTTPS'] != 'on' && $_SERVER['SERVER_PORT'] != 80) {
+ $DOMAIN_STUDIP .= ':'.$_SERVER['SERVER_PORT'];
+}
+?>
+
+<div>
+ <? foreach (PageLayout::getMessages() as $m) : ?>
+ <?= $m ?>
+ <? endforeach ?>
+</div>
+<form action="<?= $controller->url_for('admin/plugin/edit_automaticupdate/'.$plugin['id']) ?>" method="post" class="default" data-dialog="size=auto;reload-on-close">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= MessageBox::info(_("Sie können gitlab, github.com oder dem neuen Stud.IP-Plugin-Marktplatz mitteilen, dass Ihr Stud.IP per Webhook über Änderungen im Code des Plugins benachrichtigt werden soll.")) ?>
+ <fieldset>
+ <legend><?= _("Einstellungen von Stud.IP") ?></legend>
+ <label>
+ <?= _("URL, von der das Plugin als ZIP-Datei bezogen werden soll") ?>
+ <input type="url" name="automatic_update_url" value="<?= htmlReady($plugin['automatic_update_url']) ?>">
+ </label>
+ <label>
+ <?= _("Automatisches Update absichern über Sicherheitstoken (optional)") ?>
+ <input type="checkbox" name="use_security_token" value="1"<?= $plugin['automatic_update_secret'] || !$plugin['automatic_update_url'] ? " checked" : "" ?>>
+ </label>
+ </fieldset>
+
+ <? if ($plugin['automatic_update_url']) : ?>
+ <fieldset>
+ <legend><?= _("Daten für das bereitstellende System") ?></legend>
+ <p class="info">
+ <?= _("Tragen Sie bei gitlab, github.com oder dem Pluginmarktplatz untenstehende URL ein, die der Webhook aufrufen soll.") ?>
+ <? if ($plugin['automatic_update_secret']) : ?>
+ <?= _("Dieser Aufruf muss noch mit dem Sicherheitstoken abgesichert werden.") ?>
+ <? endif ?>
+ </p>
+ <label>
+ <?= _("URL") ?>
+ <input type="text" readonly value="<?= htmlReady(URLHelper::getURL("dispatch.php/plugins/trigger_automaticupdate/".$plugin['class'], ['s' => md5(Config::get()->STUDIP_INSTALLATION_ID.$plugin['id'])], true)) ?>">
+ </label>
+ <? if ($plugin['automatic_update_secret']) : ?>
+ <label>
+ <?= _("Sicherheitstoken für das andere System (schreibgeschützt)") ?>
+ <input type="text" readonly value="<?= htmlReady($plugin['automatic_update_secret']) ?>">
+ </label>
+ <? endif ?>
+ </fieldset>
+ <? endif ?>
+
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern')) ?>
+ </div>
+</form>
diff --git a/app/views/admin/plugin/index.php b/app/views/admin/plugin/index.php
new file mode 100644
index 0000000..7187a77
--- /dev/null
+++ b/app/views/admin/plugin/index.php
@@ -0,0 +1,200 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<? if ($num_updates): ?>
+ <?= MessageBox::info($this->render_partial('admin/plugin/update_info')) ?>
+<? endif ?>
+
+<? if (count($plugins) == 0): ?>
+ <?= MessageBox::info(_('Es sind noch keine Plugins in diesem Stud.IP vorhanden.'), [
+ _('Sie können Plugins aus dem Marktplatz installieren oder manuell hochladen.'),
+ sprintf(
+ _('Benutzen Sie dafür die Funktion "%sweitere Plugins installieren%s" in der Info-Box.'),
+ '<a href="' . $controller->url_for('admin/plugin/search') . '">',
+ '</a>'
+ )
+ ]) ?>
+<? else: ?>
+ <form action="<?= $controller->url_for('admin/plugin/save') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <input type="hidden" name="plugin_filter" value="<?= $plugin_filter ?>">
+
+ <table class="default">
+ <caption>
+ <div class="actions" title="<?= _('Gesamt (aktiv/inaktiv)') ?>">
+ <?= sprintf(
+ _('%u Plugins (%u/%u)'),
+ count($plugins),
+ count(array_filter($plugins, function ($p) { return $p['enabled']; })),
+ count(array_filter($plugins, function ($p) { return !$p['enabled']; }))
+ ) ?>
+ </div>
+ <?= _('Verwaltung von Plugins') ?>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Aktiv') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Version') ?></th>
+ <th><?= _('Schema') ?></th>
+ <th><?= _('Position') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($plugins as $plugin): ?>
+ <? $pluginid = $plugin['id'] ?>
+ <tr>
+ <td style="padding-left: 1ex;" width="30">
+ <input type="checkbox" name="enabled_<?= $pluginid ?>"
+ value="1" <? if ($plugin['enabled']) echo 'checked'; ?>>
+ </td>
+ <td>
+ <a data-dialog="size=auto" href="<?= $controller->url_for('admin/plugin/manifest/' . $pluginid) ?>">
+ <?= htmlReady($plugin['name']) ?>
+ <? if ($plugin['core']): ?>
+ <em>(<?= _('Kern-Plugin') ?>)</em>
+ <? endif; ?>
+ </a>
+ </td>
+ <td <? if (!$plugin['enabled']) echo 'class="quiet"'; ?>>
+ <?= join(', ', $plugin['type']) ?>
+ </td>
+ <td <? if (!$plugin['enabled']) echo 'class="quiet"'; ?>>
+ <?= htmlReady($update_info[$pluginid]['version']) ?>
+ <? if ($plugin['automatic_update_url']): ?>
+ <?= Icon::create('plugin+move_down', Icon::ROLE_STATUS_RED)->asImg([
+ 'title' => _('Automatische Updates sind eingerichtet'),
+ 'style' => 'vertical-align: text-bottom',
+ ]) ?>
+ <? endif; ?>
+ </td>
+ <td <? if (!$plugin['enabled']) echo 'class="quiet"'; ?>>
+ <? if (!$plugin['depends']) : ?>
+ <?= htmlReady($migrations[$pluginid]['schema_version']) ?>
+ <? if ($migrations[$pluginid]['schema_version'] < $migrations[$pluginid]['migration_top_version']): ?>
+ <a href="<?= $controller->url_for('admin/plugin/migrate/' . $pluginid) ?>"
+ title="<?= sprintf(_('Update auf Version %d verfügbar'), $migrations[$pluginid]['migration_top_version']) ?>">
+ <?= Icon::create('plugin+new') ?>
+ </a>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ <td>
+ <input name="position_<?= $pluginid ?>" type="text" size="2"
+ value="<?= $plugin['position'] ?>" <? if (!$plugin['enabled']) echo 'disabled'; ?>>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (in_array('StandardPlugin', $plugin['type'])): ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('admin/plugin/default_activation/' . $pluginid),
+ _('In Veranstaltungen aktivieren'),
+ Icon::create('seminar+add', 'clickable', ['title' => _('In Veranstaltungen aktivieren')])
+ ) ?>
+ <? endif ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('admin/role/assign_plugin_role/' . $pluginid),
+ _('Zugriffsrechte bearbeiten'),
+ Icon::create('edit', 'clickable', ['title' => _('Zugriffsrechte bearbeiten')])
+ ) ?>
+
+ <? if (!$plugin['depends'] && isset($update_info[$pluginid]['version']) && !$plugin['core']): ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('admin/plugin/edit_automaticupdate/' . $pluginid),
+ $plugin['automatic_update_url'] ? _('Automatisches Update verwalten (eingerichtet)') : _('Automatisches Update verwalten'),
+ Icon::create('plugin+move_down', $plugin['automatic_update_url'] ? 'attention' : 'clickable', [
+ 'title' => $plugin['automatic_update_url']
+ ? _('Automatisches Update verwalten (eingerichtet)')
+ : _('Automatisches Update verwalten')
+ ]),
+ ['data-dialog' => 'size=auto;reload-on-close']
+ ) ?>
+ <? endif ?>
+ <? if (!$plugin['depends'] && isset($update_info[$pluginid]['version']) && !$plugin['core']): ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('admin/plugin/download/' . $pluginid),
+ _('Herunterladen'),
+ Icon::create('download', 'clickable', ['title' => _('Herunterladen')])
+ ) ?>
+ <? endif ?>
+ <? if (!$plugin['depends'] && !$plugin['core']): ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('admin/plugin/ask_delete/' . $pluginid),
+ _('Deinstallieren'),
+ Icon::create('trash', 'clickable', ['title' => _('Deinstallieren')])
+ ) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td style="text-align: center;" colspan="7">
+ <?= Button::createAccept(_('Speichern'), 'save', ['title' => _('Einstellungen speichern')]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </form>
+<? endif ?>
+
+<?
+$sidebar = Sidebar::Get();
+
+if (Config::get()->PLUGINS_UPLOAD_ENABLE) {
+ $uploadArea = $sidebar->addWidget(new LinksWidget());
+ $uploadArea->setTitle(_('Plugin als ZIP-Datei hochladen'));
+ $uploadArea->addElement(new WidgetElement(
+ $this->render_partial('admin/plugin/upload-drag-and-drop'))
+ );
+
+ $sidebar->addWidget(new ActionsWidget())->addLink(
+ _('Plugin von URL installieren'),
+ $controller->url_for('admin/plugin/edit_automaticupdate'),
+ Icon::create('download')
+ )->asDialog();
+}
+
+$widget = $sidebar->addWidget(new OptionsWidget());
+$widget->setTitle(_('Darstellungseinstellungen'));
+$widget->addSelect(
+ _('Darstellung einschränken'),
+ $controller->url_for('admin/plugin'),
+ 'plugin_filter',
+ array_merge(
+ ['' => _('Alle Plugin-Typen anzeigen')],
+ array_combine($plugin_types, $plugin_types)
+ ),
+ $plugin_filter
+);
+$widget->addRadioButton(
+ _('Alle Plugins anzeigen'),
+ $controller->url_for('admin/plugin?core_filter=yes'),
+ ($core_filter ?: 'yes') === 'yes'
+);
+$widget->addRadioButton(
+ _('Kern-Plugins ausblenden'),
+ $controller->url_for('admin/plugin?core_filter=no'),
+ $core_filter === 'no'
+);
+$widget->addRadioButton(
+ _('Nur Kern-Plugins anzeigen'),
+ $controller->url_for('admin/plugin?core_filter=only'),
+ $core_filter === 'only'
+);
+if ($plugin_filter || ($core_filter ?: 'yes') !== 'yes') {
+ $widget->addElement(new WidgetElement('<hr>'));
+ $widget->addElement(new LinkElement(
+ _('Zurücksetzen'),
+ $controller->url_for('admin/plugin?reset_filter=1'),
+ Icon::create('refresh'),
+ ['class' => 'options-radio']
+ ));
+}
diff --git a/app/views/admin/plugin/manifest.php b/app/views/admin/plugin/manifest.php
new file mode 100644
index 0000000..2c9c72d
--- /dev/null
+++ b/app/views/admin/plugin/manifest.php
@@ -0,0 +1,25 @@
+<dl>
+ <dt><?= _('Name') ?></dt>
+ <dd><?= htmlReady($plugin['name']) ?></dd>
+
+ <dt><?= _('Klasse') ?></dt>
+ <dd><?= htmlReady($plugin['class']) ?></dd>
+
+ <dt><?= _('Typ') ?></dt>
+ <dd><?= join(', ', $plugin['type']) ?></dd>
+
+ <dt><?= _('Origin') ?></dt>
+ <dd><?= htmlReady($manifest['origin']) ?></dd>
+
+ <dt><?= _('Version') ?></dt>
+ <dd><?= htmlReady($manifest['version']) ?></dd>
+
+ <dt><?= _('Beschreibung') ?></dt>
+ <dd>
+ <? if ($manifest['description']): ?>
+ <?= htmlReady($manifest['description']) ?>
+ <? else: ?>
+ (<?= _('keine Beschreibung vorhanden') ?>)
+ <? endif; ?>
+ </dd>
+</dl>
diff --git a/app/views/admin/plugin/search.php b/app/views/admin/plugin/search.php
new file mode 100644
index 0000000..413cd68
--- /dev/null
+++ b/app/views/admin/plugin/search.php
@@ -0,0 +1,91 @@
+<? if (!$search_results): ?>
+ <?= MessageBox::info(_('Es wurden keine Plugins gefunden.')) ?>
+<? else: ?>
+ <table class="default nohover">
+ <caption>
+ <? if ($search === null): ?>
+ <?= _('Empfohlene Plugins') ?>
+ <? else: ?>
+ <?= _('Suchergebnisse') ?>
+ <? endif ?>
+ </caption>
+ <thead>
+ <tr>
+ <th class="plugin_image"><?= _('Bild')?></th>
+ <th><?= _('Name und Beschreibung')?></th>
+ <th><?= _('Version') ?></th>
+ <th><?= _('Bewertung') ?></th>
+ <th class="plugin_install actions"><?= _('Installieren') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($search_results as $name => $plugin): ?>
+ <tr style="vertical-align: top">
+ <td class="plugin_image">
+ <? if ($plugin['image']): ?>
+ <a href="<?= htmlReady($plugin['image']) ?>"
+ data-lightbox="<?= htmlReady($plugin['displayname']) ?>"
+ data-title="<?= htmlReady($name) ?>">
+ <img src="<?= htmlReady($plugin['image']) ?>" class="plugin_preview">
+ </a>
+ <? endif ?>
+ </td>
+ <td>
+ <a href="<?= htmlReady($plugin['marketplace_url']) ?>" target="_blank" rel="noopener noreferrer" title="<?= _('Zum Marktplatz') ?>">
+ <strong><?= htmlReady($name) ?></strong>
+ </a>
+ <? if (mb_strlen($plugin['description']) > 500) : ?>
+ <span class="plugin_description short">
+ <div>
+ <p>
+ <?= htmlReady($plugin['description'], true, true) ?>
+ </p>
+ <? if ($plugin['plugin_url'] && $plugin['plugin_url'] !== $plugin['marketplace_url']): ?>
+ <a href="<?= htmlReady($plugin['plugin_url']) ?>" target="_blank" rel="noopener noreferrer" class="link-extern">
+ <?= _('Plugin-Homepage') ?>
+ </a>
+ <? endif ?>
+
+ <p class="read_more"></p>
+ </div>
+
+ <a href="" class="read_more_link" onClick="jQuery(this).parent().toggleClass('short');return false;">
+ <span><?= _('Weiterlesen') ?></span>
+ </a>
+ </span>
+ <? else: ?>
+ <p>
+ <?= htmlReady($plugin['description'], true, true) ?>
+ </p>
+ <? if ($plugin['plugin_url'] && $plugin['plugin_url'] !== $plugin['marketplace_url']): ?>
+ <a href="<?= htmlReady($plugin['plugin_url']) ?>" target="_blank" rel="noopener noreferrer" class="link-extern">
+ <?= _('Plugin-Homepage') ?>
+ </a>
+ <? endif ?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= htmlReady($plugin['version']) ?>
+ </td>
+ <td class="plugin_score" <? if ($plugin['score']) printf('title="%s"', round($plugin['score'] / 2, 1)) ?>>
+ <? for ($i = 0; $i < $plugin['score'] / 2; ++$i): ?>
+ <?= Icon::create('star', Icon::ROLE_INACTIVE) ?>
+ <? endfor ?>
+ </td>
+ <td class="plugin_install actions">
+ <form action="<?= $controller->link_for('admin/plugin/install') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="plugin_url" value="<?= htmlReady($plugin['url']) ?>">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= Icon::create('install')->asInput([
+ 'title' => _('Plugin installieren'),
+ 'class' => 'middle',
+ 'name' => 'install',
+ ]) ?>
+ </form>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? endif ?>
diff --git a/app/views/admin/plugin/unregistered.php b/app/views/admin/plugin/unregistered.php
new file mode 100644
index 0000000..3600ee1
--- /dev/null
+++ b/app/views/admin/plugin/unregistered.php
@@ -0,0 +1,41 @@
+<table class="default">
+ <caption>
+ <?= _('Im Pluginverzeichnis vorhandene Plugins registrieren') ?>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Pluginklasse') ?></th>
+ <th><?= _('Version') ?></th>
+ <th><?= _('Ursprung') ?></th>
+ <th><?= _('Registrieren') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (!$unknown_plugins): ?>
+ <tr>
+ <td colspan="5">
+ <?= _('Es sind keine nicht registrierten Plugins vorhanden') ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($unknown_plugins as $n => $plugin): ?>
+ <tr>
+ <td><?= htmlReady($plugin['pluginname']) ?></td>
+ <td><?= htmlReady($plugin['pluginclassname']) ?></td>
+ <td><?= htmlReady($plugin['version']) ?></td>
+ <td><?= htmlReady($plugin['origin']) ?></td>
+ <td class="actions">
+ <form action="<?= $controller->link_for('admin/plugin/register/' . $n) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= Icon::create('install')->asInput([
+ 'title' => _('Plugin registrieren'),
+ 'class' => 'middle',
+ 'name' => 'install',
+ ]) ?>
+ </form>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/admin/plugin/update_info.php b/app/views/admin/plugin/update_info.php
new file mode 100644
index 0000000..fba0403
--- /dev/null
+++ b/app/views/admin/plugin/update_info.php
@@ -0,0 +1,26 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<?= sprintf(ngettext('Es ist ein Update für ein Plugin verfügbar', 'Es sind Updates für %d Plugins verfügbar', $num_updates), $num_updates) ?>
+
+<form action="<?= $controller->url_for('admin/plugin/install_updates') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <div style="margin: 1ex;">
+ <? foreach ($plugins as $plugin): ?>
+ <? $pluginid = $plugin['id'] ?>
+ <? if (isset($update_info[$pluginid]['update']) && !$plugin['depends']): ?>
+ <div>
+ <label>
+ <input type="checkbox" name="update[]" value="<?= $pluginid ?>" checked>
+ <?= htmlReady(sprintf(_('%s: Version %s installieren'), $plugin['name'], $update_info[$pluginid]['update']['version'])) ?>
+ </label>
+ </div>
+ <? endif ?>
+ <? endforeach ?>
+ </div>
+
+ <?= Button::createAccept(_('Starten'), 'doUpdate', ['title' => _('Updates installieren')])?>
+ </form>
diff --git a/app/views/admin/plugin/upload-drag-and-drop.php b/app/views/admin/plugin/upload-drag-and-drop.php
new file mode 100644
index 0000000..35ab11b
--- /dev/null
+++ b/app/views/admin/plugin/upload-drag-and-drop.php
@@ -0,0 +1,8 @@
+<form action="<?= $controller->url_for('admin/plugin/install') ?>"
+ method="post" enctype="multipart/form-data" class="drag-and-drop">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+
+ <?= _('Plugin auswählen oder via Drag and Drop installieren') ?>
+ <input type="file" name="upload_file">
+</form>
diff --git a/app/views/admin/role/add.php b/app/views/admin/role/add.php
new file mode 100644
index 0000000..e03c8c4
--- /dev/null
+++ b/app/views/admin/role/add.php
@@ -0,0 +1,21 @@
+<form action="<?= $controller->url_for('admin/role/add') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+
+ <fieldset>
+ <legend>
+ <?= _('Neue Rolle anlegen') ?>
+ </legend>
+
+ <label for="name">
+ <?= _('Name') ?>:
+ <input type="text" name="name" id="name">
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Anlegen'), 'createrolebtn') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('admin/role')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/role/add_plugin.php b/app/views/admin/role/add_plugin.php
new file mode 100644
index 0000000..084b4fc
--- /dev/null
+++ b/app/views/admin/role/add_plugin.php
@@ -0,0 +1,32 @@
+<?php
+use Studip\Button;
+use Studip\LinkButton;
+?>
+
+<form action="<?= $controller->url_for('admin/role/add_plugin/' . $role_id) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Plugins zur Rolle hinzufügen') ?>
+ </legend>
+
+ <label>
+ <?= _('Plugins auswählen') ?>
+
+ <select name="plugin_ids[]" multiple>
+ <? foreach ($plugins as $plugin): ?>
+ <option value="<?= $plugin['id'] ?>">
+ <?= htmlReady($plugin['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Hinzufügen')) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('admin/role/show_role/' . $role_id)) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/role/assign_plugin_role.php b/app/views/admin/role/assign_plugin_role.php
new file mode 100644
index 0000000..779511b
--- /dev/null
+++ b/app/views/admin/role/assign_plugin_role.php
@@ -0,0 +1,70 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+?>
+
+<form action="<?= $controller->url_for('admin/role/assign_plugin_role') ?>" method="POST" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Rollenverwaltung für Plugins') ?>
+ </legend>
+
+ <label>
+ <select name="pluginid" style="min-width: 300px;">
+ <? foreach ($plugins as $plugin): ?>
+ <option value="<?= $plugin['id'] ?>" <?= $plugin['id'] == $pluginid ? 'selected' : '' ?>>
+ <?= htmlReady($plugin['name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Auswählen'), 'select', ['title' => _('Plugin auswählen')]) ?>
+ </footer>
+</form>
+
+<? if ($pluginid): ?>
+ <br>
+ <form action="<?= $controller->url_for('admin/role/save_plugin_role', $pluginid) ?>" method="POST" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <table class="default nohover">
+ <tr>
+ <th style="text-align: center;"><?= _('Gegenwärtig zugewiesene Rollen') ?></th>
+ <th></th>
+ <th><?= _('Verfügbare Rollen') ?></th>
+ </tr>
+ <tr class="table_row_even">
+ <td style="text-align: right;">
+ <select multiple name="assignedroles[]" size="10" style="width: 300px;">
+ <? foreach ($assigned as $assignedrole): ?>
+ <option value="<?= $assignedrole->getRoleid() ?>">
+ <?= htmlReady($assignedrole->getRolename()) ?>
+ <? if ($assignedrole->getSystemtype()): ?>[<?= _('Systemrolle') ?>]<? endif ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </td>
+ <td style="text-align: center;">
+ <?= Icon::create('arr_2left', 'sort', ['title' => _('Markierte Rollen dem Plugin zuweisen')])->asInput(["type" => "image", "class" => "middle", "name" => "assign_role"]) ?>
+ <br>
+ <br>
+ <?= Icon::create('arr_2right', 'sort', ['title' => _('Markierte Rollen entfernen')])->asInput(["type" => "image", "class" => "middle", "name" => "remove_role"]) ?>
+ </td>
+ <td>
+ <select multiple name="rolesel[]" size="10" style="width: 300px;">
+ <? foreach ($roles as $role): ?>
+ <option value="<?= $role->getRoleid() ?>">
+ <?= htmlReady($role->getRolename()) ?>
+ <? if ($role->getSystemtype()): ?>[<?= _('Systemrolle') ?>]<? endif ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </form>
+<? endif ?>
diff --git a/app/views/admin/role/assign_role.php b/app/views/admin/role/assign_role.php
new file mode 100644
index 0000000..cf4b05d
--- /dev/null
+++ b/app/views/admin/role/assign_role.php
@@ -0,0 +1,134 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+?>
+
+<form action="<?= $controller->url_for('admin/role/assign_role') ?>" class="default" method="POST">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Rollen für Benutzer verwalten') ?>
+ </legend>
+
+ <? if (empty($users)): ?>
+ <label>
+ <?= _('Benutzer') ?>
+ <input type="text" name="username" value="<?= htmlReady($username) ?>" placeholder="<?= _('Name der Person') ?>">
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Suchen'), 'search', ['title' => _('Benutzer suchen')])?>
+ </footer>
+ <? else: ?>
+ <label>
+ <?= _('Benutzer') ?>
+ <select name="usersel" style="min-width: 300px;">
+ <? foreach ($users as $user): ?>
+ <option value="<?= $user->id ?>" <? if ($currentuser && $currentuser->id === $user->id) echo 'selected'; ?>>
+ <?= htmlReady(sprintf('%s (%s)', $user->getFullName(), $user->username)) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Auswählen'), 'select', ['title' => _('Benutzer auswählen')])?>
+ <?= LinkButton::create(_('Zurücksetzen'), $controller->url_for('admin/role/assign_role'), ['title' => _('Suche zurücksetzen')])?>
+ </footer>
+ <? endif ?>
+</form>
+
+<? if (isset($currentuser)): ?>
+ <br>
+ <form action="<?= $controller->url_for('admin/role/save_role', $currentuser->id) ?>" method="POST">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <table class="default nohover">
+ <tr>
+ <th style="text-align: center;">
+ <? printf(_('Rollen für %s'), htmlReady($currentuser->vorname . ' ' . $currentuser->nachname)) ?>
+ </th>
+ <th></th>
+ <th><?= _('Verfügbare Rollen') ?></th>
+ </tr>
+ <tr class="table_row_even">
+ <td style="text-align: right;">
+ <select multiple name="assignedroles[]" size="10" style="width: 300px;">
+ <? foreach ($assignedroles as $assignedrole): ?>
+ <option value="<?= $assignedrole->getRoleid() ?>">
+ <?= htmlReady($assignedrole->getRolename()) ?>
+ <? if ($assignedrole->getSystemtype()): ?>[<?= _('Systemrolle') ?>]<? endif ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </td>
+ <td style="text-align: center;">
+ <?= Icon::create('arr_2left', 'sort', ['title' => _('Markierte Rollen dem Benutzer zuweisen')])->asInput(["type" => "image", "class" => "middle", "name" => "assign_role"]) ?>
+ <br>
+ <br>
+ <?= Icon::create('arr_2right', 'sort', ['title' => _('Markierte Rollen entfernen')])->asInput(["type" => "image", "class" => "middle", "name" => "remove_role"]) ?>
+ </td>
+ <td>
+ <select size="10" name="rolesel[]" multiple style="width: 300px;">
+ <? foreach ($roles as $role): ?>
+ <option value="<?= $role->getRoleid() ?>">
+ <?= htmlReady($role->getRolename()) ?>
+ <? if ($role->getSystemtype()): ?>[<?= _('Systemrolle') ?>]<? endif ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </form>
+
+ <h3>
+ <?= _('Einrichtungszuordnungen') ?>
+ </h3>
+
+ <table class="default">
+ <colgroup>
+ <col width="50%">
+ <col>
+ <col width="24px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Rolle')?> </th>
+ <th><?= _('Einrichtungen')?> </th>
+ <th class="actions"><?= _('Aktionen')?> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($assignedroles as $assignedrole): ?>
+ <? if (!$assignedrole->getSystemtype()): ?>
+ <tr>
+ <td>
+ <?= htmlReady($assignedrole->getRolename()) ?>
+ </td>
+ <td>
+ <?= htmlReady(implode(",\n", $assignedroles_institutes[$assignedrole->getRoleid()]))?>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->link_for('/assign_role_institutes/' . $assignedrole->getRoleid() . '/' . $currentuser->id) ?>" data-dialog="size=auto;reload-on-close">
+ <?= Icon::create('edit', 'clickable')->asImg(['title' => _('Einrichtungszuordnung bearbeiten')]) ?>
+ </a>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+
+ <h3>
+ <?= _('Implizit zugewiesene Systemrollen') ?>
+ </h3>
+
+ <? foreach ($all_userroles as $role): ?>
+ <? if (!in_array($role, $assignedroles)): ?>
+ <?= htmlReady($role->getRolename()) ?><br>
+ <? endif ?>
+ <? endforeach ?>
+<? endif ?>
diff --git a/app/views/admin/role/assign_role_institutes.php b/app/views/admin/role/assign_role_institutes.php
new file mode 100644
index 0000000..b3be22d
--- /dev/null
+++ b/app/views/admin/role/assign_role_institutes.php
@@ -0,0 +1,39 @@
+<? foreach(PageLayout::getMessages() as $pm) : ?>
+ <?= $pm ?>
+<? endforeach; ?>
+
+<form action="<?= $controller->link_for('/assign_role_institutes/' . $role->getRoleid() . '/' . $user->id) ?>" method="post" class="default" data-dialog="size=auto;reload-on-close">
+ <fieldset>
+ <legend>
+ <?= _('Einrichtungszuordnung anpassen') ?>
+ </legend>
+
+ <label>
+ <?= sprintf(_("Einrichtungszuordnung für %s in der Rolle %s"), htmlReady($user->getFullname()), htmlready($role->getRoleName()))?>
+ <div class="hgroup">
+ <?= $qsearch->render() ?>
+
+ </div>
+ </label>
+
+ <h4><?= _('Vorhandene Zuordnungen') ?></h4>
+ <ul>
+ <? foreach ($institutes as $institute): ?>
+ <li>
+ <?= htmlReady($institute->name) ?>
+ <a href="<?= $controller->link_for("/assign_role_institutes/{$role->getRoleid()}/{$user->id}", ['remove_institute' => $institute->id]) ?>" data-dialog="size=auto;reload-on-close">
+ <?= Icon::create('trash') ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::create(_('Einrichtung hinzufügen'), "add_institute", ["rel" => "lightbox"]) ?>
+ <?= Studip\LinkButton::createCancel(_('Schließen'), $controller->url_for('/assign_role/' . $user->id), [
+ 'data-dialog-button' => '',
+ 'data-dialog' => 'size=auto;reload-on-close'
+ ]) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/role/index.php b/app/views/admin/role/index.php
new file mode 100644
index 0000000..4ebd0c4
--- /dev/null
+++ b/app/views/admin/role/index.php
@@ -0,0 +1,58 @@
+<table class="default">
+ <caption>
+ <?= _('Vorhandene Rollen') ?>
+ </caption>
+ <thead>
+ <tr>
+ <th rowspan="2"><?= _('Name') ?></th>
+ <th colspan="2" style="text-align: right;">
+ <?= _('Benutzer') ?>
+ </th>
+ <th style="text-align: right;" rowspan="2"><?= _('Plugins') ?></th>
+ <th rowspan="2"></th>
+ </tr>
+ <tr>
+ <th style="text-align: right;">
+ <abbr title="<?= _('Direkte Zuweisung') ?>">
+ <?= _('explizit') ?>
+ </abbr>
+ </th>
+ <th style="text-align: right;">
+ <abbr title="<?= _('Indirekte Zuweisung durch Berechtigungsstufe') ?>">
+ <?= _('implizit') ?>
+ </abbr>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($roles as $role): ?>
+ <? $role_id = $role->getRoleid() ?>
+ <tr>
+ <td>
+ <a href="<?= $controller->link_for("admin/role/show_role/{$role_id}") ?>">
+ <?= htmlReady($role->getRolename()) ?>
+ <? if ($role->getSystemtype()): ?>
+ [<?= _('Systemrolle') ?>]
+ <? endif ?>
+ </a>
+ </td>
+ <td style="text-align: right;">
+ <?= $stats[$role_id]['explicit'] ?>
+ </td>
+ <td style="text-align: right;">
+ <?= $stats[$role_id]['implicit'] ?>
+ </td>
+ <td style="text-align: right;">
+ <?= $stats[$role_id]['plugins'] ?>
+ </td>
+ <td class="actions">
+ <? if (!$role->getSystemtype()): ?>
+ <a href="<?= $controller->link_for('admin/role/ask_remove_role', $role_id) ?>">
+ <?= Icon::create('trash')->asImg(tooltip2(_('Rolle löschen'))) ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/admin/role/show_role.php b/app/views/admin/role/show_role.php
new file mode 100644
index 0000000..161296f
--- /dev/null
+++ b/app/views/admin/role/show_role.php
@@ -0,0 +1,216 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+?>
+
+<form action="<?= $controller->url_for('admin/role/show_role') ?>" method="get" class="default inline">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Rollenzuweisungen anzeigen') ?>
+ </legend>
+
+ <label>
+ <?= _('Rolle wählen') ?>
+
+ <select name="role">
+ <? foreach ($roles as $one_role): ?>
+ <option value="<?= $one_role->getRoleid() ?>" <? if ($one_role->getRoleid() == $roleid) echo 'selected'; ?>>
+ <?= htmlReady($one_role->getRolename()) ?>
+ <? if ($one_role->getSystemtype()): ?>
+ [<?= _('Systemrolle') ?>]
+ <? endif; ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Auswählen'), 'selectrole', ['title' => _('Rolle auswählen')])?>
+ </footer>
+</form>
+
+<? if (isset($role)): ?>
+<br>
+<form action="<?= $controller->url_for('admin/role/remove_user/' . $role->getRoleId() . '/bulk') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default" id="role-users">
+ <colgroup>
+ <col width="20px">
+ <col width="3%">
+ <col width="33%">
+ <col width="5%">
+ <col>
+ <col width="24px">
+ </colgroup>
+ <caption>
+ <?= sprintf(
+ _('Liste der Personen mit der Rolle "%s"'),
+ htmlReady($role->getRolename())
+ ) ?>
+ <? if (!$role->getSystemtype()): ?>
+ <div class="actions">
+ <?= $mps->render() ?>
+ </div>
+ <? endif; ?>
+ </caption>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="#role-users tbody :checkbox"
+ data-activates="#role-users tfoot button">
+ </th>
+ <th>&nbsp;</th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Status') ?></th>
+ <th><?= _('Einrichtungszuordnung') ?></th>
+ <th>&nbsp;</th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($users) === 0): ?>
+ <tr>
+ <td colspan="6" style="text-align: center;">
+ <?= _('Es wurden keine Benutzer gefunden.') ?>
+ </td>
+ </tr>
+ <? else: ?>
+ <? foreach (array_values($users) as $index => $user): ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="ids[]" value="<?= $user['user_id'] ?>">
+ </td>
+ <td style="text-align: right;">
+ <?= $index + 1 ?>.
+ </td>
+ <td>
+ <a href="<?= $controller->url_for('admin/role/assign_role', $user['user_id']) ?>">
+ <?= htmlReady(sprintf('%s %s (%s)', $user['Vorname'], $user['Nachname'], $user['username'])) ?>
+ </a>
+ </td>
+ <td><?= $user['perms'] ?></td>
+ <td>
+ <? $institutes = join(', ', $user['institutes']); ?>
+ <?= htmlReady(mb_substr($institutes, 0, 60)) ?>
+ <? if (mb_strlen($institutes) > 60): ?>
+ ...<?= tooltipIcon(join("\n", $user['institutes']))?>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <?= Icon::create('trash', 'clickable', ['title' => _('Rolle entziehen')])
+ ->asInput([
+ "data-confirm" => _('Soll dieser Person wirklich die Rolle entzogen werden?'),
+ "formaction" => $controller->url_for('admin/role/remove_user/'.$roleid.'/'.$user['user_id'])]) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+ <? if ($implicit_count > 0): ?>
+ <tr>
+ <td></td>
+ <td colspan="5">
+ <?= sprintf(
+ _('+%u weitere, implizit zugewiesene Person(en)'),
+ $implicit_count
+ ) ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <?= _('Alle markierten Einträge') ?>
+ <?= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Sollen den markierten Personen wirklich die Rolle entzogen werden?'),
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
+
+<br>
+
+<form action="<?= $controller->url_for('admin/role/remove_plugin/' . $role->getRoleId() . '/bulk') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default" id="role-plugins">
+ <caption>
+ <?= sprintf(_('Liste der Plugins mit der Rolle "%s"'),
+ htmlReady($role->getRolename())) ?>
+ <div class="actions">
+ <a href="<?= $controller->url_for('admin/role/add_plugin/' . $roleid) ?>" data-dialog="size=auto">
+ <?= Icon::create('plugin+add', 'clickable') ?>
+ <?= _('Plugins hinzufügen') ?>
+ </a>
+ </div>
+ </caption>
+ <colgroup>
+ <col width="20px">
+ <col width="3%">
+ <col width="38%">
+ <col>
+ <col width="24px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="#role-plugins tbody :checkbox"
+ data-activates="#role-plugins tfoot button">
+ </th>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($plugins) === 0): ?>
+ <tr>
+ <td colspan="5" style="text-align: center;">
+ <?= _('Es wurden keine Plugins gefunden.') ?>
+ </td>
+ </tr>
+ <? else: ?>
+ <? foreach (array_values($plugins) as $index => $plugin): ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="ids[]" value="<?= $plugin['id'] ?>">
+ </td>
+ <td style="text-align: right;">
+ <?= $index + 1 ?>.
+ </td>
+ <td>
+ <a href="<?= $controller->url_for('admin/role/assign_plugin_role', $plugin['id']) ?>">
+ <?= htmlReady($plugin['name']) ?>
+ </a>
+ </td>
+ <td><?= implode(', ', $plugin['type']) ?></td>
+ <td class="actions">
+ <?= Icon::create('trash', 'clickable', ['title' => _('Rolle entziehen')])
+ ->asInput([
+ "data-confirm" => _('Soll diesem Plugin wirklich die Rolle entzogen werden?'),
+ "formaction" => $controller->url_for('admin/role/remove_plugin/'.$roleid.'/'.$plugin['id'])]) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <?= _('Alle markierten Einträge') ?>
+ <?= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Sollen den markierten Plugins wirklich die Rolle entzogen werden?'),
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
+<? endif; ?>
diff --git a/app/views/admin/sem_classes/_sem_type.php b/app/views/admin/sem_classes/_sem_type.php
new file mode 100644
index 0000000..6928df1
--- /dev/null
+++ b/app/views/admin/sem_classes/_sem_type.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * Copyright (c) 2012 Rasmus Fuhse <fuhse@data-quest.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+$number_of_seminars = $sem_type->countSeminars();
+$id = $sem_type['id'];
+?>
+<li id="sem_type_<?= htmlReady($id) ?>">
+ <span class="name_container">
+ <span class="id" title="<?= _("ID des Veranstaltungstyps") ?>">
+ [<?= htmlReady($sem_type['id']) ?>]
+ </span>
+ <span class="name_html">
+ <?= htmlReady($sem_type['name']) ?>
+ </span>
+ <span class="name_input" style="display: none;">
+ <input type="text" value="<?= htmlReady($sem_type['name']) ?>">
+ </span>
+ </span>
+ (<?= sprintf(_("%s Veranstaltungen"), $number_of_seminars ? $number_of_seminars : _("keine")) ?>)
+ <a href="#" class="sem_type_edit" onClick="jQuery(this).closest('li').find('.name_container').children().toggle().find('input').focus(); return false;" title="<?= _("Veranstaltungstyp umbenennen") ?>"><?= Icon::create('edit', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ <? if ($number_of_seminars == 0) : ?>
+ <a href="#" class="sem_type_delete" onClick="return false;" title="<?= _("Veranstaltungstyp löschen") ?>"><?= Icon::create('trash', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ <? endif ?>
+</li> \ No newline at end of file
diff --git a/app/views/admin/sem_classes/add_sem_type.php b/app/views/admin/sem_classes/add_sem_type.php
new file mode 100644
index 0000000..c842f99
--- /dev/null
+++ b/app/views/admin/sem_classes/add_sem_type.php
@@ -0,0 +1,28 @@
+<form action="?" method="post" class="default" id="add_sem_class_window" data-dialog>
+ <fieldset>
+ <legend>
+ <?= _('Veranstaltungskategorie anlegen') ?>
+ </legend>
+
+ <label>
+ <span class="required">
+ <?= _("Name") ?>
+ </span>
+ <input type="text" name="add_name" id="add_name" required>
+ </label>
+
+ <label>
+ <?= _("Attribute kopieren von Veranstaltungskategorie") ?>
+ <select name="add_like" id="add_like">
+ <option value=""><?= _("keine") ?></option>
+ <? foreach ($GLOBALS['SEM_CLASS'] as $id => $sem_class) : ?>
+ <option value="<?= $id ?>"><?= htmlReady($sem_class['name']) ?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::create(_("Erstellen")) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/sem_classes/content_plugin.php b/app/views/admin/sem_classes/content_plugin.php
new file mode 100644
index 0000000..7a9cffe
--- /dev/null
+++ b/app/views/admin/sem_classes/content_plugin.php
@@ -0,0 +1,19 @@
+<?php
+
+/*
+ * Copyright (c) 2012 Rasmus Fuhse <fuhse@data-quest.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+?>
+<div class="plugin<?= ($plugin['enabled'] ? "" : " deactivated").(is_numeric($plugin['id']) ? "" : " core").($sticky ? " sticky" : "") ?>" id="plugin_<?= $plugin_id ?>" <?= $plugin['enabled'] ? "" : ' title="'._("Plugin ist momentan global deaktiviert.").'"' ?>>
+ <h2><?= $plugin['name'] ?></h2>
+ <div>
+ <label><input type="checkbox" value="1" name="nonsticky"<?= !$sticky ? " checked" : "" ?>><?= _("Wählbar") ?></label>
+ <br>
+ <label><input type="checkbox" value="1" name="active"<?= $activated ? " checked" : "" ?>><?= _("Standard Aktiv") ?></label>
+ </div>
+</div>
diff --git a/app/views/admin/sem_classes/details.php b/app/views/admin/sem_classes/details.php
new file mode 100644
index 0000000..a0693a7
--- /dev/null
+++ b/app/views/admin/sem_classes/details.php
@@ -0,0 +1,267 @@
+<?php
+
+/*
+ * Copyright (c) 2012 Rasmus Fuhse <fuhse@data-quest.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+?>
+<form action="<?= URLHelper::getLink($overview_url) ?>" method="post" class="default attribute_table collapsable">
+ <input type="hidden" id="sem_class_id" value="<?= Request::int("id") ?>">
+ <fieldset>
+ <legend>
+ <?= _('Veranstaltungskategorie bearbeiten') ?>
+ </legend>
+
+ <label class="sem_class_name">
+ <span><?= _("Name der Veranstaltungskategorie") ?></span>
+ <div>
+ <span class="name"><?= htmlReady($sem_class['name']) ?></span>
+ <a href="#" class="sem_class_edit" onClick="jQuery(this).closest('label').children().toggle().find('input:visible').focus(); return false;"><?= Icon::create('edit', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ </div>
+
+ <div class="name_input" style="display: none;">
+ <input id="sem_class_name" type="text" value="<?= htmlReady($sem_class['name']) ?>" onBlur="jQuery(this).closest('label').children().toggle().find('.name').text(this.value);">
+ </div>
+ </label>
+
+
+ <label class="sem_class_name">
+ <span><?= _('Beschreibungstext für die Suche') ?></span>
+
+ <div>
+ <span class="description"><?= htmlReady($sem_class['description']) ?></span>
+ <a href="#" class="sem_class_edit" onClick="jQuery(this).closest('label').children().toggle().find('input:visible').focus(); return false;">
+ <?= Icon::create('edit', 'clickable')->asImg(['class' => 'text-bottom']) ?></a>
+ </div>
+ <div class="description_input" style="display: none;">
+ <input id="sem_class_description" type="text" value="<?= htmlReady($sem_class['description']) ?>" onBlur="jQuery(this).closest('label.sem_class_name').children().toggle().find('.description').text(this.value);" style="width: 80%;">
+ </div>
+ </label>
+
+ <section class="sem_type_list">
+ <span><?= _("Veranstaltungstypen") ?></span>
+
+ <ul id="sem_type_list">
+ <? foreach ($sem_class->getSemTypes() as $id => $sem_type) : ?>
+ <?= $this->render_partial("admin/sem_classes/_sem_type.php", ['sem_type' => $sem_type]) ?>
+ <? endforeach ?>
+ </ul>
+ <div class="add">
+ <div style="display: none; margin-left: 37px;">
+ <input type="text" id="new_sem_type" onBlur="if (!this.value) jQuery(this).closest('.add').children().toggle();">
+ <a href="" onClick="STUDIP.admin_sem_class.add_sem_type(); return false;"><?= Icon::create('arr_2up', 'sort')->asImg(['class' => "text-bottom", "title" => _("hinzufügen")]) ?></a>
+ </div>
+ <div style="margin-left: 21px;">
+ <a href="#" onClick="jQuery(this).closest('.add').children().toggle(); jQuery('#new_sem_type').focus(); return false;">
+ <?= Icon::create('add', 'clickable')->asImg(['class' => "text-bottom", "title" => _("Veranstaltungstyp hinzufügen")]) ?>
+ </a>
+ </div>
+ </div>
+ </section>
+
+
+
+ <? foreach (["dozent","tutor","autor"] as $role) : ?>
+ <section>
+ <?= sprintf(_("Titel der %s"), $GLOBALS['DEFAULT_TITLE_FOR_STATUS'][$role][1]) ?>
+
+ <label>
+ <input type="radio" id="title_<?= $role ?>_isnull" name="title_<?= $role ?>_isnull" value="1"<?= !$sem_class['title_'.$role] && !$sem_class['title_'.$role.'_plural'] ? " checked" : ""?>>
+ <?= sprintf(_("Systemdefault (%s)"), htmlReady(implode("/", $GLOBALS['DEFAULT_TITLE_FOR_STATUS'][$role]))) ?>
+ </label>
+
+ <div class="hgroup">
+ <label>
+ <input type="radio" name="title_<?= $role ?>_isnull" value="0"<?= $sem_class['title_'.$role] || $sem_class['title_'.$role.'_plural'] ? " checked" : ""?>>
+ <input placeholder="<?= htmlReady($GLOBALS['DEFAULT_TITLE_FOR_STATUS'][$role][0]) ?>" title="<?= _("Singular") ?>" type="text" id="title_<?= $role ?>" name="title_<?= $role ?>" value="<?= htmlReady($sem_class['title_'.$role]) ?>">
+ <input placeholder="<?= htmlReady($GLOBALS['DEFAULT_TITLE_FOR_STATUS'][$role][1]) ?>" title="<?= _("Plural") ?>" type="text" id="title_<?= $role ?>_plural" name="title_<?= $role ?>_plural" value="<?= htmlReady($sem_class['title_'.$role.'_plural']) ?>">
+ </label>
+ </div>
+ </section>
+ <? endforeach ?>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _("Voreinstellungen beim Anlegen einer Veranstaltung") ?>
+ </legend>
+
+ <label>
+ <?= _("Lesbar für Nutzer") ?>
+ <select id="default_read_level">
+ <option value="0"<?= $sem_class['default_read_level'] == 0 ? " selected" : "" ?>><?= _("Unangemeldet an Veranstaltung") ?></option>
+ <option value="1"<?= $sem_class['default_read_level'] == 1 ? " selected" : "" ?>><?= _("Angemeldet an Veranstaltung") ?></option>
+ </select>
+ </label>
+
+ <label>
+ <?= _("Schreibbar für Nutzer") ?>
+ <select id="default_write_level">
+ <option value="0"<?= $sem_class['default_write_level'] == 0 ? " selected" : "" ?>><?= _("Unangemeldet an Veranstaltung") ?></option>
+ <option value="1"<?= $sem_class['default_write_level'] == 1 ? " selected" : "" ?>><?= _("Angemeldet an Veranstaltung") ?></option>
+ </select>
+ </label>
+
+ <label>
+ <?= _("Anmeldemodus") ?>
+ <select id="admission_prelim_default">
+ <option value="0"<?= $sem_class['admission_prelim_default'] == 0 ? " selected" : "" ?>><?= _("direkter Eintrag") ?></option>
+ <option value="1"<?= $sem_class['admission_prelim_default'] == 1 ? " selected" : "" ?>><?= _("vorläufiger Eintrag") ?></option>
+ </select>
+ </label>
+
+ <label>
+ <?= _("Anmeldung gesperrt") ?>
+ <select id="admission_type_default">
+ <option value="0"<?= $sem_class['admission_type_default'] == 0 ? " selected" : "" ?>><?= _("Nein") ?></option>
+ <option value="3"<?= $sem_class['admission_type_default'] == 3 ? " selected" : "" ?>><?= _("Ja") ?></option>
+ </select>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _("Forum") ?>
+ </legend>
+
+ <label>
+ <input type="checkbox" id="topic_create_autor" value="1"<?= $sem_class['topic_create_autor'] ? " checked" : "" ?>>
+ <?= _("Autoren dürfen Themen anlegen.") ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="write_access_nobody" value="1"<?= $sem_class['write_access_nobody'] ? " checked" : "" ?>>
+ <?= _("Unangemeldete Nutzer (nobody) dürfen posten.") ?>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _("Anzeige") ?>
+ </legend>
+
+ <label>
+ <input type="checkbox" id="visible" value="1"<?= $sem_class['visible'] ? " checked" : "" ?>>
+ <?= _("Sichtbar") ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="show_browse" value="1"<?= $sem_class['show_browse'] ? " checked" : "" ?>>
+ <?= _("Zeige im Veranstaltungsbaum an.") ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="show_raumzeit" value="1"<?= $sem_class['show_raumzeit'] ? " checked" : "" ?>>
+ <?= _("Zeige Raum-Zeit-Seite an.") ?>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _("Sonstiges") ?>
+ </legend>
+
+ <label>
+ <input type="checkbox" id="studygroup_mode" value="1"<?= $sem_class['studygroup_mode'] ? " checked" : "" ?>>
+ <?= _("Studentische Arbeitsgruppe") ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="only_inst_user" value="1"<?= $sem_class['only_inst_user'] ? " checked" : "" ?>>
+ <?= _("Nur Nutzer der Einrichtungen sind erlaubt.") ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="bereiche" value="1"<?= $sem_class['bereiche'] ? " checked" : "" ?>>
+ <?= _("Muss Studienbereiche haben (falls nein, darf es keine haben)") ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="module" value="1"<?= $sem_class['module'] ? " checked" : "" ?>>
+ <?= _("Kann Modulen zugeordnet werden.") ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="course_creation_forbidden" value="1"<?= $sem_class['course_creation_forbidden'] ? " checked" : "" ?>>
+ <?= _("Anlegeassistent für diesen Typ sperren.") ?>
+ </label>
+
+ <label>
+ <?= _("Kurzer Beschreibungstext zum Anlegen einer Veranstaltung") ?>
+ <textarea id="create_description" maxlength="200" style="width: 100%"><?= htmlReady($sem_class['create_description']) ?></textarea>
+ </label>
+
+ <label>
+ <input type="checkbox" id="is_group" value="1"<?= $sem_class['is_group'] ? " checked" : "" ?>>
+ <?= _("Kann Unterveranstaltungen haben") ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsed attribute_table">
+ <legend>
+ <?= _("Inhaltselemente") ?>
+ </legend>
+
+
+ <div container="plugins" id="plugins" class="core_module_slot">
+ <h2 title="<?= _("Diese Inhaltselemente sind standardmäßig bei den Veranstaltungen dieser Klasse aktiviert.") ?>"><?= _("Aktivierte Inhaltselemente") ?></h2>
+ <div class="droparea">
+ <? foreach ($modules as $module_name => $module_info) : ?>
+ <? if ($module_info['activated']) : ?>
+ <?= $this->render_partial("admin/sem_classes/content_plugin.php",
+ [
+ 'plugin' => $module_info,
+ 'sem_class' => $sem_class,
+ 'plugin_id' => $module_name,
+ 'activated' => $sem_class['modules'][$module_name]['activated'],
+ 'sticky' => $sem_class['modules'][$module_name]['sticky']
+ ]
+ )?>
+ <? endif ?>
+ <? endforeach ?>
+ </div>
+ </div>
+ <hr>
+ <div container="deactivated" id="deactivated_modules">
+ <h2 title="<?= _("Diese Module sind standardmäßig nicht aktiviert.") ?>"><?= _("Nichtaktivierte Inhaltselemente") ?></h2>
+ <div class="droparea">
+ <? foreach ($modules as $module_name => $module_info) {
+ if (!$module_info['activated']) {
+ echo $this->render_partial("admin/sem_classes/content_plugin.php",
+ [
+ 'plugin' => $module_info,
+ 'sem_class' => $sem_class,
+ 'plugin_id' => $module_name,
+ 'activated' => $sem_class['modules'][$module_id]['activated'],
+ 'sticky' => $sem_class['modules'][$module_id]['sticky']
+ ]
+ );
+ }
+ } ?>
+ </div>
+ </div>
+ </fieldset>
+
+ <footer>
+ <div id="message_below"></div>
+
+ <?= Studip\Button::create(_("Speichern"), "save", ['onClick' => "STUDIP.admin_sem_class.saveData(); return false;"])?>
+ <? if ($sem_class->countSeminars() === 0) : ?>
+ <input type="hidden" name="delete_sem_class" value="<?= Request::int("id") ?>">
+ <?= Studip\Button::create(_("Löschen"), "delete", ['onClick' => "return window.confirm('"._("Wirklich löschen?")."');"])?>
+ <? endif ?>
+ </footer>
+</form>
+
+<div id="sem_type_delete_question_title" style="display: none;"><?= _("Sicherheitsabfrage") ?></div>
+<div id="sem_type_delete_question" style="display: none;">
+ <p class="info"><?= _("Wirklich den Veranstaltungstyp löschen?") ?></p>
+ <input type="hidden" id="sem_type_for_deletion">
+ <?= Studip\LinkButton::create(_("Löschen"), ['onclick' => "STUDIP.admin_sem_class.delete_sem_type(); return false;"]) ?>
+ <?= Studip\LinkButton::create(_("Abbrechen"), ['onclick' => "jQuery(this).closest('#sem_type_delete_question').dialog('close'); return false;"]) ?>
+</div>
diff --git a/app/views/admin/sem_classes/overview.php b/app/views/admin/sem_classes/overview.php
new file mode 100644
index 0000000..20c5efc
--- /dev/null
+++ b/app/views/admin/sem_classes/overview.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * Copyright (c) 2012 Rasmus Fuhse <fuhse@data-quest.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+?>
+<table class="default">
+ <thead>
+ <tr>
+ <th><?= _("ID") ?></th>
+ <th><?= _("Veranstaltungskategorie") ?></th>
+ <th><?= _("Anzahl Veranstaltungstypen") ?></th>
+ <th><?= _("Anzahl Veranstaltungen") ?></th>
+ <th><?= _("Zuletzt geändert") ?></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($GLOBALS['SEM_CLASS'] as $id => $sem_class) : ?>
+ <tr>
+ <td class="id"><?= htmlReady($id) ?></td>
+ <td><?= htmlReady($sem_class['name']) ?></td>
+ <td><?= count($sem_class->getSemTypes()) ?></td>
+ <td><?= $sem_class->countSeminars() ?></td>
+ <td><?= date("j.n.Y H:i", $sem_class['chdate']) ?> <?= _("Uhr") ?></td>
+ <td class="actions">
+ <a href="<?= URLHelper::getLink("dispatch.php/admin/sem_classes/details", ['id' => $id]) ?>" title="<?= _("Editieren dieser Veranstaltungskategorie") ?>">
+ <?= Icon::create('edit', 'clickable')->asImg(['class' => "text-bottom"]) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+
+<?
+$sidebar = Sidebar::Get();
+$links = new ActionsWidget();
+$links->addLink(
+ _('Neue Kategorie anlegen'),
+ $controller->url_for('admin/sem_classes/add_sem_type'),
+ Icon::create('add', 'clickable'),
+ [
+ 'onClick' => 'STUDIP.sem_classes.add(); return false;',
+ 'data-dialog' => 'size=auto'
+ ]
+);
+$sidebar->addWidget($links);
diff --git a/app/views/admin/semester/edit.php b/app/views/admin/semester/edit.php
new file mode 100644
index 0000000..ded488d
--- /dev/null
+++ b/app/views/admin/semester/edit.php
@@ -0,0 +1,103 @@
+<form method="post" action="<?= $controller->url_for('admin/semester/edit/' . $semester->id) ?>" data-dialog="size=auto" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= PageLayout::getTitle() ?>
+ </legend>
+
+ <label>
+ <?= _('Name des Semesters') ?>
+
+ <?= I18N::input('name', $semester->name, [
+ 'id' => 'name',
+ 'class' => isset($errors['name']) ? 'invalid' : '',
+ ]) ?>
+ </label>
+
+ <label>
+ <?= _('Kürzel') ?>
+
+ <?= I18N::input('token', $semester->semester_token, [
+ 'id' => 'token',
+ ]) ?>
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+
+ <?= I18N::textarea('description', $semester->description, [
+ 'id' => 'description',
+ ]) ?>
+ </label>
+
+ <label>
+ <?= _('Externe ID') ?>
+
+ <input type="text" name="external_id" value="<?= htmlReady($semester->external_id) ?>" maxlength="50">
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Semesterzeitraum') ?>
+ </legend>
+
+ <label class="col-3">
+ <?= _('Beginn') ?>
+
+ <? if ($semester->absolute_seminars_count > 0): ?>
+ <?= tooltipIcon(_('Das Startdatum kann nur bei Semestern geändert werden, in denen keine Veranstaltungen liegen!'), true) ?>
+ <? endif; ?>
+
+ <? if ($semester->absolute_seminars_count > 0): ?>
+ <input type="text" name="beginn" value="<?= date('d.m.Y', $semester->beginn) ?>" readonly>
+ <? else: ?>
+ <input required type="text" id="beginn" name="beginn"
+ <? if (isset($errors['beginn'])) echo 'class="invalid"'; ?>
+ data-date-picker
+ value="<? if ($semester->beginn) echo date('d.m.Y', $semester->beginn) ?>">
+ <? endif; ?>
+ </label>
+
+ <label class="col-3">
+ <?= _('Ende') ?>
+
+ <input required type="text" id="ende" name="ende"
+ <? if (isset($errors['ende'])) echo 'class="invalid"'; ?>
+ data-date-picker='{">":"#beginn"}'
+ value="<? if ($semester->ende) echo date('d.m.Y', $semester->ende); ?>">
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Vorlesungszeitraum') ?>
+ </legend>
+
+ <label class="col-3">
+ <?= _('Beginn') ?>
+
+ <input required type="text" id="vorles_beginn" name="vorles_beginn"
+ <? if (isset($errors['vorles_beginn'])) echo 'class="invalid"'; ?>
+ data-date-picker='{"<":"#vorles_ende",">=":"#beginn"}'
+ value="<? if ($semester->vorles_beginn) echo date('d.m.Y', $semester->vorles_beginn); ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Ende') ?>
+
+ <input required type="text" id="vorles_ende" name="vorles_ende"
+ <? if (isset($errors['vorles_ende'])) echo 'class="invalid"'; ?>
+ data-date-picker='{">":"#vorles_beginn","<=":"#ende"}'
+ value="<? if ($semester->vorles_ende) echo date('d.m.Y', $semester->vorles_ende); ?>">
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('admin/semester'))?>
+ </footer>
+</table>
+</form>
diff --git a/app/views/admin/semester/index.php b/app/views/admin/semester/index.php
new file mode 100644
index 0000000..bae4737
--- /dev/null
+++ b/app/views/admin/semester/index.php
@@ -0,0 +1,155 @@
+<form action="<?= $controller->url_for('admin/semester/delete/bulk') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+<table class="default" id="semesters">
+ <caption><?= _('Semester') ?></caption>
+ <colgroup>
+ <col width="20px">
+ <col>
+ <col width="10%">
+ <col width="15%">
+ <col width="15%">
+ <col width="20%">
+ <col width="48px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="#semesters tbody :checkbox"
+ data-activates="#semesters tfoot button">
+ </th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Kürzel') ?></th>
+ <th><?= _('Zeitraum') ?></th>
+ <th><?= _('Veranstaltungszeitraum') ?></th>
+ <th><?= _('Veranstaltungen') ?></th>
+ <th>&nbsp;</th>
+ </tr>
+ </thead>
+ <tbody>
+<? if (empty($semesters)): ?>
+ <tr>
+ <td colspan="7" style="text-align: center;">
+ <? if ($filter): ?>
+ <?= _('In der gewählten Ansicht gibt es keine Einträge.') ?>
+ <? else: ?>
+ <?= _('Es wurden noch keine Semester angelegt.') ?><br>
+ <?= Studip\LinkButton::create(_('Neues Semester anlegen'),
+ $controller->url_for('admin/semester/edit'),
+ ['data-dialog' => 'size=auto']) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+<? else: ?>
+ <? foreach ($semesters as $semester): ?>
+ <tr <? if ($semester->current) echo 'style="font-weight: bold;"'; ?>>
+ <td>
+ <input type="checkbox" name="ids[]" value="<?= $semester->id ?>"
+ <? if ($semester->absolute_seminars_count): ?>
+ <?= 'disabled' ?>
+ <?= tooltip(_('Das Semester kann nicht gelöscht werden, weil Veranstaltungen zugeordnet sind.')); ?>
+ <? endif; ?>
+ >
+ </td>
+ <td title="<?= htmlReady($semester->description) ?>">
+ <?= htmlReady($semester->name) ?>
+ <? if (!$semester->visible): ?>
+ <?= '(' . _('gesperrt') . ')'; ?>
+ <? endif; ?>
+ </td>
+ <td>
+ <?= htmlReady($semester->semester_token ?: '- ' . _('keins') . ' -') ?>
+ </td>
+ <td>
+ <?= strftime('%x', $semester->beginn) ?>
+ -
+ <?= strftime('%x', $semester->ende) ?>
+ </td>
+ <td>
+ <?= strftime('%x', $semester->vorles_beginn) ?>
+ -
+ <?= strftime('%x', $semester->vorles_ende) ?>
+ </td>
+ <td>
+ <?= $semester->absolute_seminars_count ?>
+ <?= sprintf(_('(+%u implizit)'),
+ $semester->continuous_seminars_count + $semester->duration_seminars_count) ?>
+ </td>
+ <td class="actions" nowrap>
+
+ <?
+ $actionMenu = ActionMenu::get();
+
+ $actionMenu->addLink(
+ $controller->url_for("admin/semester/edit/{$semester->id}"),
+ _('Semesterangaben bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ );
+
+ if ($semester->visible) {
+ $actionMenu->addLink(
+ $controller->url_for("admin/semester/lock/{$semester->id}"),
+ _('Semester sperren'),
+ Icon::create('lock-unlocked'),
+ ['data-dialog' => 'size=auto']
+ );
+ } else {
+ $actionMenu->addButton(
+ 'unlock',
+ _('Semester entsperren'),
+ Icon::create('lock-locked', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Semester entsperren'),
+ 'formaction' => $controller->url_for("admin/semester/unlock/{$semester->id}"),
+ 'data-confirm' => _('Soll das Semester wirklich entsperrt werden? Anmelderegeln und Sperrebenen werden nicht verändert.'),
+ 'style' => 'vertical-align: text-bottom'
+ ])
+ );
+ }
+
+ if ($semester->absolute_seminars_count) {
+ $actionMenu->addLink(
+ $controller->url_for("admin/semester"),
+ _('Semester löschen'),
+ Icon::create('trash', Icon::ROLE_INACTIVE),
+ array_merge(
+ tooltip2(_('Das Semester kann nicht gelöscht werden, weil Veranstaltungen zugeordnet sind.')),
+ [
+ 'disabled' => FALSE,
+ 'onclick' => 'return false;'
+ ]
+ )
+ );
+ } else {
+ $actionMenu->addButton(
+ 'delete',
+ _('Semester löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Semester löschen'),
+ 'formaction' => $controller->url_for("admin/semester/delete/{$semester->id}"),
+ 'data-confirm' => _('Soll das Semester wirklich gelöscht werden?'),
+ 'style' => 'vertical-align: text-bottom'
+ ])
+ );
+ }
+
+ echo $actionMenu;
+ ?>
+
+ </td>
+ </tr>
+ <? endforeach; ?>
+<? endif; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="7">
+ <?= Studip\Button::create(_('Markierte Einträge löschen'), 'delete', [
+ 'data-confirm' => _('Sollen die Semester wirklich gelöscht werden?')
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+</form>
diff --git a/app/views/admin/semester/lock.php b/app/views/admin/semester/lock.php
new file mode 100644
index 0000000..7f0109f
--- /dev/null
+++ b/app/views/admin/semester/lock.php
@@ -0,0 +1,44 @@
+<form class="default" action="<?= $controller->link_for("admin/semester/lock/{$id}") ?>" method="post" data-dialog="size=auto" class="default">
+
+ <fieldset>
+ <legend><?= _('Berechtigungen') ?></legend>
+
+ <label>
+ <input name ="degrade_users" type="checkbox" value="1" checked>
+ <?= _('Teilnehmende zu Lesern herabstufen') ?>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Anmelderegeln') ?></legend>
+
+ <label>
+ <input name ="lock_enroll" type="checkbox" value="1">
+ <?= _('Anmeldung gesperrt') ?>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Zusätzliche optionale Sperrebene') ?></legend>
+
+ <label>
+ <?= _('Für alle Veranstaltungen') ?>
+ <select name="lock_sem_all">
+ <option value="">
+ -- <?= _('keine Sperrebene') ?> --
+ </option>
+ <? foreach ($all_lock_rules as $lock_rule): ?>
+ <option value="<?= htmlReady($lock_rule->id) ?>">
+ <?= htmlReady($lock_rule->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Sperren'), 'confirm_lock'); ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('admin/semester'))?>
+ </footer>
+</form>
diff --git a/app/views/admin/smileys/edit.php b/app/views/admin/smileys/edit.php
new file mode 100644
index 0000000..32c21e7
--- /dev/null
+++ b/app/views/admin/smileys/edit.php
@@ -0,0 +1,58 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<form action="<?= $controller->url_for('admin/smileys/edit', $smiley->id, $view) ?>"
+ method="post" enctype="multipart/form-data">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table align="center" cellpadding="2" cellspacing="0">
+ <thead class="hide-in-dialog">
+ <tr>
+ <th colspan="2"><b><?= _('Smiley bearbeiten') ?></b></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="table_row_even">
+ <td><?= _('Smiley:')?></td>
+ <td align="center"><?= $smiley->getImageTag() ?></td>
+ </tr>
+ <tr class="table_row_odd">
+ <td>
+ <label for="name"><?= _('Name')?></label>
+ </td>
+ <td>
+ <input type="text" name="name" id="name" required pattern="[A-Za-z0-9-_]+"
+ value="<?= Request::option('name', $smiley->name) ?>">
+ <br>
+ <small><?= _('Erlaubte Zeichen:') ?> a-z 0-9 &ndash; _</small>
+ </td>
+ </tr>
+ <tr class="table_row_even">
+ <td>
+ <label for="short"><?= _('Kürzel')?></label>
+ </td>
+ <td>
+ <input type="text" name="short" id="short"
+ value="<?= Request::option('short', $smiley->short) ?>">
+ </td>
+ </tr>
+ <tr class="table_row_odd">
+ <td><?= _('Erstellt') ?></td>
+ <td><?= date('d.m.Y H:i:s', $smiley->mkdate) ?></td>
+ </tr>
+ <tr class="table_row_even">
+ <td><?= _('Geändert') ?></td>
+ <td><?= date('d.m.Y H:i:s', $smiley->chdate) ?></td>
+ </tr>
+ </tbody>
+ <tfoot data-dialog-button>
+ <tr>
+ <td colspan="2">
+ <?= Button::createAccept(_('Speichern'), 'edit') ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/smileys?view=' . $view))?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+
+ <br>
+</form>
diff --git a/app/views/admin/smileys/index.php b/app/views/admin/smileys/index.php
new file mode 100644
index 0000000..e5e3012
--- /dev/null
+++ b/app/views/admin/smileys/index.php
@@ -0,0 +1,86 @@
+<? use Studip\Button; ?>
+
+<form action="<?= $controller->url_for('/admin/smileys/delete/bulk', $view) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default">
+ <colgroup>
+ <col width="20px">
+ <col>
+ <col>
+ <col width="50px">
+ <col>
+ <col width="50px">
+ <? if ($favorites_enabled): ?>
+ <col width="50px">
+ <? endif; ?>
+ <col width="50px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>&nbsp;</th>
+ <th><?= _('Smiley') ?></th>
+ <th><?= _('Smileyname') ?></th>
+ <th>&Sigma;</th>
+ <th><?= _('Kürzel') ?></th>
+ <th>&Sigma;</th>
+ <? if ($favorites_enabled): ?>
+ <th><?= _('Favoriten') ?></th>
+ <? endif; ?>
+ <th>&nbsp;</th>
+ </tr>
+ </thead>
+ <? if (empty($smileys)): ?>
+ <tbody>
+ <tr>
+ <td align="center" class="blank" colspan="<?= $favorites_enabled ? 8 : 7 ?>">
+ <?= _('Keine Smileys vorhanden.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? else: ?>
+ <tbody>
+ <? foreach ($smileys as $smiley): ?>
+ <tr id="smiley<?= $smiley->id ?>">
+ <td><input type="checkbox" name="smiley_id[]" value="<?= $smiley->id ?>"></td>
+ <td><?= $smiley->getImageTag() ?></td>
+ <td><?= htmlReady($smiley->name) ?></td>
+ <td><?= $smiley->count ?></td>
+ <? if ($smiley->short): ?>
+ <td class="separator"><?= htmlReady($smiley->short) ?></td>
+ <td><?= $smiley->short_count ?></td>
+ <? else: ?>
+ <td class="separator" colspan="2" align="center">-</td>
+ <? endif; ?>
+ <? if ($favorites_enabled): ?>
+ <td class="separator"><?= $smiley->fav_count ?></td>
+ <? endif; ?>
+ <td align="right">
+ <a href="<?= $controller->url_for('admin/smileys/edit', $smiley->id, $view) ?>"
+ title="<?= htmlReady(sprintf(_('Smiley "%s" bearbeiten'), $smiley->name)) ?>"
+ data-dialog="size=auto">
+ <?= Icon::create('edit', 'clickable')->asImg() ?>
+ </a>
+ <a href="<?= $controller->url_for('admin/smileys/delete', $smiley->id, $view) ?>"
+ title="<?= htmlReady(sprintf(_('Smiley "%s" löschen'), $smiley->name)) ?>">
+ <?= Icon::create('trash', 'clickable')->asImg() ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td>
+ <input class="middle" type="checkbox" data-proxyfor=":checkbox[name^=smiley_id]"
+ data-activates="button[name=bulk-delete]"
+ name="check_all" title="<?= _('Alle Benutzer auswählen') ?>">
+ </td>
+ <td colspan="<?= $favorites_enabled ? 7 : 6 ?>">
+ <?= Studip\Button::createCancel(_('Markierte löschen'), 'bulk-delete') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</form>
diff --git a/app/views/admin/smileys/statistics.php b/app/views/admin/smileys/statistics.php
new file mode 100644
index 0000000..e134b49
--- /dev/null
+++ b/app/views/admin/smileys/statistics.php
@@ -0,0 +1,13 @@
+<dl class="smiley-statistics">
+ <dt><?= _('Vorhanden') ?></dt>
+ <dd><?= $count_all ?></dd>
+
+ <dt><?= _('Davon benutzt') ?></dt>
+ <dd><?= $count_used ?></dd>
+
+ <dt><?= _('Smiley-Vorkommen') ?></dt>
+ <dd><?= $sum ?></dd>
+
+ <dt><?= _('Letzte Änderung') ?></dt>
+ <dd><?= (!is_null($last_change) ? date('d.m.Y H:i:s', $last_change) : '')?></dd>
+</dl>
diff --git a/app/views/admin/smileys/upload.php b/app/views/admin/smileys/upload.php
new file mode 100644
index 0000000..5dc2c13
--- /dev/null
+++ b/app/views/admin/smileys/upload.php
@@ -0,0 +1,40 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<form action="<?= $controller->url_for('admin/smileys/upload', $view) ?>"
+ method="post" enctype="multipart/form-data">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table align="center" cellpadding="2" cellspacing="0">
+ <thead class="hide-in-dialog">
+ <tr>
+ <th colspan="2"><b><?= _('Neues Smiley hochladen') ?></b></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="table_row_odd">
+ <td>
+ <label for="replace"><?= _('existierende Datei überschreiben') ?></label>
+ </td>
+ <td>
+ <input type="checkbox" id="replace" name="replace" value="1">
+ </td>
+ </tr>
+ <tr class="table_row_even">
+ <td>
+ <label for="file"><?= _('Bilddatei auswählen') ?></label>
+ </td>
+ <td>
+ <input type="file" id="file" name="smiley_file" required>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot data-dialog-button>
+ <tr>
+ <td colspan="2" align="center">
+ <?= Button::createAccept(_('Hochladen'), 'upload') ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/smileys?view=' . $view))?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
diff --git a/app/views/admin/specification/_field.php b/app/views/admin/specification/_field.php
new file mode 100644
index 0000000..30a01ff
--- /dev/null
+++ b/app/views/admin/specification/_field.php
@@ -0,0 +1,36 @@
+<?php
+$fields = Request::getArray('fields');
+$order = Request::getArray('order');
+?>
+
+<section>
+ <? if ($required) : ?>
+ <span class="required">
+ <?= htmlReady($name) ?>
+ </span>
+ <? else : ?>
+ <?= htmlReady($name) ?>
+ <? endif ?>
+
+
+ <div class="hgroup">
+ <label class="col-2">
+ <?= _('Sortierung') ?>
+ <input id="order_<?= $id ?>" min="0" type="number" size="3" name="order[<?= $id ?>]"
+ value="<?= (int)(($order && isset($order[$id])) ? $order[$id] : @$rule['order'][$id]) ?>">
+ <input type="hidden" name="fields[<?= $id ?>]" value="0">
+ </label>
+ <label class="col-2">
+ <input type="checkbox"
+ name="fields[<?= $id ?>]"
+ value="1"
+ <?= (($fields && isset($fields[$id])) ? $fields[$id] : @$rule['attributes'][$id]) ? 'checked="checked"' : '' ?>>
+ <?= _('Aktivieren') ?>
+ </label>
+ <label class="col-1">
+ <? if ($institution) : ?>
+ <?= htmlReady($institution->name)?>
+ <? endif; ?>
+ </label>
+ </div>
+</section>
diff --git a/app/views/admin/specification/edit.php b/app/views/admin/specification/edit.php
new file mode 100644
index 0000000..de868a4
--- /dev/null
+++ b/app/views/admin/specification/edit.php
@@ -0,0 +1,90 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<? if (isset($flash['error'])) : ?>
+ <?= MessageBox::error($flash['error'], $flash['error_detail']) ?>
+<? elseif (isset($flash['info'])): ?>
+ <?= MessageBox::info($flash['info']) ?>
+<? endif ?>
+
+<form action="<?= $controller->url_for('admin/specification/store' . ($rule ? '/' . $rule['lock_id'] : '')) ?>"
+ method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <? if ($rule) : ?>
+ <?= sprintf(_('Regel "%s" editieren'), htmlReady($rule['name'])) ?>
+ <? else : ?>
+ <?= _('Eine neue Regel definieren') ?>
+ <? endif ?>
+ </legend>
+ <label>
+ <span class="required">
+ <?= _('Name der Regel:') ?>
+ </span>
+ <input type="text" name="rulename" value="<?= htmlReady(Request::get('rulename', $rule['name'])) ?>"
+ required="required">
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea cols="60" rows="5"
+ name="description"><?= htmlReady(Request::get('description', $rule['description'])) ?></textarea>
+ </label>
+ </fieldset>
+ <? if (count($entries_semdata) > 0) : ?>
+ <fieldset>
+ <legend>
+ <?= _('Zusatzinformationen') ?>
+ </legend>
+ <? foreach ($entries_semdata as $id => $entry) : ?>
+ <?= $this->render_partial('admin/specification/_field', array_merge(
+ compact('rule'),
+ ['id' => $entry->datafield_id, 'name' => $entry->name],
+ ['required' => true, 'institution' => $entry->institution]
+ )) ?>
+ <? endforeach ?>
+ </fieldset>
+ <? endif ?>
+
+ <? if (count($semFields) > 0) : ?>
+ <fieldset>
+ <legend>
+ <?= _('Veranstaltungsinformationen') ?>
+ </legend>
+ <? foreach ($semFields as $id => $name) : ?>
+ <?= $this->render_partial('admin/specification/_field', compact('rule', 'id', 'name')) ?>
+ <? endforeach ?>
+ </fieldset>
+ <? endif ?>
+
+ <? if (count($entries_user) > 0) : ?>
+ <fieldset>
+ <legend>
+ <?= _('Personenbezogene Informationen') ?>
+ </legend>
+ <? foreach ($entries_user as $id => $entry) : ?>
+ <?= $this->render_partial('admin/specification/_field',
+ array_merge(compact('rule'), ['id' => $entry->datafield_id, 'name' => $entry->name])) ?>
+ <? endforeach ?>
+ </fieldset>
+ <? endif ?>
+ <footer>
+ <? if ($rule) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'uebernehmen', ['title' => _('Änderungen übernehmen')]) ?>
+ <? else : ?>
+ <?= Button::createAccept(_('Erstellen'), 'erstellen', ['title' => _('Neue Regel erstellen')]) ?>
+ <? endif ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/specification'), ['title' => _('Zurück zur Übersicht')]) ?>
+ </footer>
+</form>
+
+<?
+$sidebar = Sidebar::Get();
+if ($GLOBALS['perm']->have_perm('root')) {
+ $actions = new ActionsWidget();
+ $actions->addLink(_('Datenfelder bearbeiten'), URLHelper::getLink('dispatch.php/admin/datafields'), Icon::create('add', 'clickable'));
+ $sidebar->addWidget($actions);
+}
+?>
diff --git a/app/views/admin/specification/index.php b/app/views/admin/specification/index.php
new file mode 100644
index 0000000..6fbf711
--- /dev/null
+++ b/app/views/admin/specification/index.php
@@ -0,0 +1,56 @@
+<form method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= _('Verwaltung von Zusatzangaben') ?>
+ </caption>
+ <colgroup>
+ <col width="45%">
+ <col width="45%">
+ <col width="10%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (!empty($allrules)): ?>
+ <? foreach ($allrules as $index => $rule) : ?>
+ <tr>
+ <td>
+ <?= htmlReady($rule['name']) ?>
+ </td>
+ <td>
+ <?= htmlReady($rule['description']) ?>
+ </td>
+ <td class="actions">
+ <a href="<?=$controller->url_for('admin/specification/edit/'.$rule['lock_id']) ?>" style="vertical-align: bottom">
+ <?= Icon::create('edit', 'clickable', ['title' => _('Regel bearbeiten')])->asImg() ?>
+ </a>
+ <?=Icon::create('trash', 'clickable', tooltip2(_('Regel löschen')))->asInput([
+ 'formaction' => $controller->url_for('admin/specification/delete/' . $rule['lock_id']),
+ 'data-confirm' => sprintf(_('Wollen Sie die Regel "%s" wirklich löschen?'), htmlReady($rule['name'])),
+ 'style' => 'vertical-align: bottom'
+ ])?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? else : ?>
+ <tr>
+ <td colspan="3" style="text-align: center">
+ <?= _('Es wurden noch keine Zusatzangaben definiert.') ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+</form>
+<?
+
+$sidebar = Sidebar::Get();
+$actions = new ActionsWidget();
+$actions->addLink(_('Neue Regel anlegen'), $controller->url_for('admin/specification/edit'), Icon::create('add', 'clickable'));
+$sidebar->addWidget($actions);
diff --git a/app/views/admin/statusgroups/_edit_subgroupselect.php b/app/views/admin/statusgroups/_edit_subgroupselect.php
new file mode 100644
index 0000000..2968896
--- /dev/null
+++ b/app/views/admin/statusgroups/_edit_subgroupselect.php
@@ -0,0 +1,9 @@
+<? foreach ($groups as $group): ?>
+ <? if ($selected->id == $group->id) continue; ?>
+ <option value="<?= $group->id ?>" <? if ($group->id == $selected->range_id) echo 'selected'; ?> <? if ($level > 0): ?> class="nested-item nested-item-level-<?= $level ?>"<? endif; ?>>
+ <?= $preset ?><?= htmlReady($group->name) ?>
+ </option>
+ <? if($group->children): ?>
+ <?= $this->render_partial("admin/statusgroups/_edit_subgroupselect.php", ['groups' => $group->children, 'selected' => $selected, 'level' => $level + 1]) ?>
+ <? endif; ?>
+<? endforeach; ?> \ No newline at end of file
diff --git a/app/views/admin/statusgroups/_group-nestable.php b/app/views/admin/statusgroups/_group-nestable.php
new file mode 100644
index 0000000..982447e
--- /dev/null
+++ b/app/views/admin/statusgroups/_group-nestable.php
@@ -0,0 +1,10 @@
+<? if ($groups): ?>
+ <ol class="dd-list">
+ <? foreach ($groups as $group): ?>
+ <li class="dd-item" data-id="<?= $group->id ?>">
+ <div class="dd-handle"><?= formatReady($group->name) ?></div>
+ <?= $this->render_partial('admin/statusgroups/_group-nestable', ['groups' => $group->children]) ?>
+ </li>
+ <? endforeach; ?>
+ </ol>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/admin/statusgroups/_group.php b/app/views/admin/statusgroups/_group.php
new file mode 100644
index 0000000..237254e
--- /dev/null
+++ b/app/views/admin/statusgroups/_group.php
@@ -0,0 +1,61 @@
+<a name="group-<?= $group->id ?>"></a>
+<table id="<?= $group->id ?>" class="default movable">
+ <colgroup>
+ <col width="1">
+ <col width="1">
+ <col width="10">
+ <col>
+ <col width="10%">
+ </colgroup>
+ <caption>
+ <?= htmlReady($group->name) ?>
+ <? if ($tutor): ?>
+ <span class="actions">
+ <? $menu = ActionMenu::get() ?>
+ <? $menu->addLink($controller->url_for("admin/statusgroups/editGroup/{$group->id}"),
+ _('Gruppe bearbeiten'), Icon::create('edit'), ['data-dialog' => 'size=auto']) ?>
+ <? $menu->addMultiPersonSearch(
+ MultiPersonSearch::get("add_statusgroup" . $group->id)
+ ->setLinkText(_('Personen hinzufügen'))
+ ->setDefaultSelectedUser($group->members->pluck('user_id'))
+ ->setExecuteURL($controller->url_for("admin/statusgroups/memberAdd/{$group->id}"))
+ ->setSearchObject($searchType)
+ ->addQuickfilter(_("aktuelle Einrichtung"), $membersOfInstitute)
+ ->addQuickfilter(_('Nicht zugeordnet'), $not_assigned)
+ ) ?>
+ <? $menu->addLink($controller->url_for("admin/statusgroups/deleteGroup/{$group->id}"),
+ _('Gruppe löschen'), Icon::create('trash'), ['data-dialog' => 'size=auto']) ?>
+ <? $menu->addLink($controller->url_for("admin/statusgroups/sortAlphabetic/{$group->id}"),
+ _('Gruppe alphabetisch sortieren'), Icon::create('arr_2down'), ['data-dialog' => 'size=auto']) ?>
+ <? if ($group->children): ?>
+ <? $menu->addLink($controller->link_for("admin/statusgroups/sortGroupsAlphabetical/{$group->id}"),
+ _('Untergruppen alphabetisch sortieren'), Icon::create('filter2'),
+ ['data-confirm' => _('Sollen die Untergruppen dieser Gruppe alphabetisch sortiert werden?')]) ?>
+ <? endif ?>
+ <?= $menu->render() ?>
+ </span>
+ <? endif; ?>
+ </caption>
+ <thead>
+ <tr>
+ <th colspan="4">
+ <?= sprintf(ngettext('%u Mitglied', '%u Mitglieder', count($group->members)),
+ count($group->members)) ?>
+ </th>
+ <th class="actions"></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?= $this->render_partial('admin/statusgroups/_members.php', ['group' => $group]) ?>
+ </tbody>
+</table>
+
+<? if ($group->children): ?>
+<ul class='tree-seperator'>
+ <li>
+ <? foreach ($group->children as $child): ?>
+ <?= $this->render_partial('admin/statusgroups/_group.php', ['group' => $child]) ?>
+ <? endforeach ?>
+ </li>
+</ul>
+<? endif; ?>
diff --git a/app/views/admin/statusgroups/_members.php b/app/views/admin/statusgroups/_members.php
new file mode 100644
index 0000000..a4e8bf7
--- /dev/null
+++ b/app/views/admin/statusgroups/_members.php
@@ -0,0 +1,21 @@
+<? foreach ($group->members as $user): ?>
+ <tr data-userid="<?= $user->user_id ?>">
+ <td <?= ($tutor ? 'class="dragHandle"' : '') ?>></td>
+ <td><?= $user->position + 1 ?></td>
+ <td><?= $user->avatar() ?></td>
+ <td><?= htmlReady($user->name()) ?></td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink($controller->url_for('settings/statusgruppen/', ['open' => $group->id, 'type' => 'role', 'username' => $user->user->username]),
+ _('Benutzer in dieser Rolle bearbeiten'),
+ Icon::create('edit', 'clickable')) ?>
+ <? if ($tutor) : ?>
+ <? $actionMenu->addLink($controller->url_for('admin/statusgroups/delete/' . $group->id . '/' . $user->user_id),
+ _('Person aus Gruppe austragen'),
+ Icon::create('trash', 'clickable'),
+ ['data-dialog' => 'size=auto']) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+<? endforeach; ?>
diff --git a/app/views/admin/statusgroups/delete.php b/app/views/admin/statusgroups/delete.php
new file mode 100644
index 0000000..e4173b6
--- /dev/null
+++ b/app/views/admin/statusgroups/delete.php
@@ -0,0 +1,17 @@
+<form method="post" action="<?= $controller->url_for("admin/statusgroups/delete/{$group->id}/{$user->user_id}") ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Nutzer aus Gruppe austragen') ?>
+ </legend>
+
+ <section>
+ <?= sprintf(_('%s wirklich aus %s austragen?'), htmlReady($user->getFullname()), htmlReady($group->name)) ?>
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Entfernen'), 'confirm') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/statusgroups/index')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/statusgroups/deleteGroup.php b/app/views/admin/statusgroups/deleteGroup.php
new file mode 100644
index 0000000..e843318
--- /dev/null
+++ b/app/views/admin/statusgroups/deleteGroup.php
@@ -0,0 +1,17 @@
+<form method="post" action="<?= $controller->url_for("admin/statusgroups/deleteGroup/{$group->id}") ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Gruppe löschen') ?>
+ </legend>
+
+ <section>
+ <?= sprintf(_('Gruppe %s wirklich löschen?'), htmlReady($group->name)) ?>
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Löschen'), 'confirm', ['data-dialog-button' => '']) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/statusgroups/index'), ['data-dialog-button' => '', 'data-dialog' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/statusgroups/editGroup.php b/app/views/admin/statusgroups/editGroup.php
new file mode 100644
index 0000000..87bdfd7
--- /dev/null
+++ b/app/views/admin/statusgroups/editGroup.php
@@ -0,0 +1,76 @@
+<form class="default" action="<?= $controller->url_for('admin/statusgroups/editGroup/' . $group->id) ?>#group-<?= $group->id ?>" method="post">
+ <fieldset>
+ <legend>
+ <?= _('Gruppe bearbeiten') ?>
+ </legend>
+
+ <label>
+ <span class="required"><?= _('Gruppenname') ?></span>
+ <?= I18N::input('name', $group->name, [
+ 'required' => '',
+ 'class' => 'groupname',
+ 'size' => 50,
+ 'placeholder' => _('Mitarbeiterinnen und Mitarbeiter'),
+ ]) ?>
+ </label>
+ <label>
+ <?= _('Weibliche Bezeichnung') ?>
+ <?= I18N::input('name_w', $group->name_w, [
+ 'size' => 50,
+ 'placeholder' => _('Mitarbeiterin'),
+ ]) ?>
+ </label>
+ <label>
+ <?= _('Männliche Bezeichnung') ?>
+ <?= I18N::input('name_m', $group->name_m, [
+ 'size' => 50,
+ 'placeholder' => _('Mitarbeiter'),
+ ]) ?>
+ </label>
+
+ <? if ($type['needs_size']): ?>
+ <label>
+ <?= _('Größe') ?>
+ <input name="size" type="text" size="10"
+ value="<?= htmlReady($group->size) ?>"
+ placeholder="<?= _('Unbegrenzt') ?>">
+ </label>
+ <? endif; ?>
+
+ <? foreach ($group->getDatafields() as $field): ?>
+ <?= $field->getHTML('datafields') ?>
+ <? endforeach; ?>
+
+ <? if ($type['needs_self_assign']): ?>
+ <label>
+ <?= _('Selbsteintrag') ?>
+ <input name="selfassign" type="checkbox" value="1"
+ <? if ($group->selfassign) echo 'checked'; ?>>
+ </label>
+ <? endif; ?>
+
+ <noscript>
+ <label>
+ <?= _('Position') ?>
+ <input name="size" type="text" size="10"
+ value="<?= htmlReady($group->position) ?>"
+ placeholder="0">
+ </label>
+ </noscript>
+
+ <label>
+ <?= _('Einordnen unter') ?>
+ <select name="range_id" class="nested-select">
+ <option value="<?= htmlReady(Context::getId()) ?>">
+ - <?= _('Hauptebene') ?> -
+ </option>
+ <?= $this->render_partial("admin/statusgroups/_edit_subgroupselect.php", ['groups' => $groups, 'selected' => $group, 'level' => 0]) ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/statusgroups/index.php b/app/views/admin/statusgroups/index.php
new file mode 100644
index 0000000..f9dc6b8
--- /dev/null
+++ b/app/views/admin/statusgroups/index.php
@@ -0,0 +1,6 @@
+<? if (!$groups): ?>
+ <?= MessageBox::info(_('Es wurden noch keine Gruppen angelegt')) ?>
+<? endif; ?>
+<? foreach ($groups as $group): ?>
+ <?= $this->render_partial('admin/statusgroups/_group.php', compact('group')) ?>
+<? endforeach; ?> \ No newline at end of file
diff --git a/app/views/admin/statusgroups/sortAlphabetic.php b/app/views/admin/statusgroups/sortAlphabetic.php
new file mode 100644
index 0000000..a73ce27
--- /dev/null
+++ b/app/views/admin/statusgroups/sortAlphabetic.php
@@ -0,0 +1,17 @@
+<form method="post" action="<?= $controller->url_for("admin/statusgroups/sortAlphabetic/{$group->id}") ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Gruppe alphabetisch sortieren') ?>
+ </legend>
+
+ <section>
+ <?= sprintf(_('Gruppe %s wirklich alphabetisch sortieren? Die vorherige Sortierung kann nicht wiederhergestellt werden.'), htmlReady($group->name)) ?>
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Sortieren'), 'confirm') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/statusgroups/sortGroups.php b/app/views/admin/statusgroups/sortGroups.php
new file mode 100644
index 0000000..0f367e4
--- /dev/null
+++ b/app/views/admin/statusgroups/sortGroups.php
@@ -0,0 +1,20 @@
+<noscript>
+ <?= MessageBox::info(_('Leider ist es aus technischen Gründen nicht möglich ein vernünftiges Interface '
+ . 'ohne Javascript zu liefern. Nutzen sie bitte die Gruppierung unter den '
+ . 'Einstellungen der Gruppen oder aktivieren sie Javascript.')) ?>
+</noscript>
+
+<div class="ordering" title="<?= _('Gruppenreihenfolge ändern') ?>">
+ <div class="nestable">
+ <?= $this->render_partial('admin/statusgroups/_group-nestable.php', compact('groups')) ?>
+ </div>
+</div>
+
+<form class="default" id="order_form" action="<?= $controller->url_for('admin/statusgroups/sortGroups') ?>" method="POST">
+ <input type="hidden" name="ordering" id="ordering">
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'order') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/statusgroups/index')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/user/_activities_no_courses.php b/app/views/admin/user/_activities_no_courses.php
new file mode 100644
index 0000000..6f71e48
--- /dev/null
+++ b/app/views/admin/user/_activities_no_courses.php
@@ -0,0 +1,3 @@
+<section>
+ <?= MessageBox::info(_('Keine Veranstaltungen gefunden')) ?>
+</section> \ No newline at end of file
diff --git a/app/views/admin/user/_course_files.php b/app/views/admin/user/_course_files.php
new file mode 100644
index 0000000..c427619
--- /dev/null
+++ b/app/views/admin/user/_course_files.php
@@ -0,0 +1,76 @@
+<section class="contentbox">
+ <header>
+ <h1>
+ <?= _('Dateiübersicht Veranstaltungen') ?>
+ </h1>
+ </header>
+ <? foreach ($course_files as $semester_name => $file_date) : ?>
+ <article id="<?= $semester_name ?>" class="<?= ContentBoxHelper::classes($semester_name) ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($semester_name) ?>">
+ <?= htmlReady($semester_name) ?>
+ </a>
+ </h1>
+ </header>
+ <section>
+ <table class="default">
+ <colgroup>
+ <col style="width: 200px">
+ <col>
+ <col style="width: 120px">
+ <col style="width: 120px">
+ <col style="width: 20px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Veranstaltungsnummer') ?></th>
+ <th><?= _('Veranstaltung') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Anzahl') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($file_date as $data): ?>
+ <tr>
+ <td><?= htmlReady($data['course']->veranstaltungsnummer) ?></td>
+ <td>
+ <?= htmlReady($data['course']->name) ?>
+ </td>
+ <td>
+ <?= htmlReady($data['course']->getSemType()['name'])?>
+ </td>
+ <td>
+ <? if ($data['files']) : ?>
+ <?= sprintf('%u %s', $data['files'], _('Dokumente')) ?>
+ <? else : ?>
+ -
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <? if ($data['files']) : ?>
+ <?
+ $actionMenu = ActionMenu::get();
+ $actionMenu->addLink($controller->url_for('admin/user/list_files/' . $user['user_id'] . '/' . $data['course']->id, $params),
+ _('Dateien auflisten'),
+ Icon::create('folder-full', 'clickable'),
+ ['data-dialog' => 'size=50%']);
+ $actionMenu->addLink($controller->url_for('admin/user/download_user_files/' . $user['user_id'] . '/' . $data['course']->id),
+ _('Dateien als ZIP herunterladen'),
+ Icon::create('download', 'clickable'));
+
+ ?>
+
+ <?= $actionMenu->render() ?>
+ <? endif ?>
+ </td>
+
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ </section>
+ </article>
+ <? endforeach; ?>
+</section> \ No newline at end of file
diff --git a/app/views/admin/user/_course_list.php b/app/views/admin/user/_course_list.php
new file mode 100644
index 0000000..6f66277
--- /dev/null
+++ b/app/views/admin/user/_course_list.php
@@ -0,0 +1,60 @@
+<section class="contentbox">
+ <header>
+ <h1><?= $headline ?></h1>
+ </header>
+ <? if (!empty($memberships)) : ?>
+ <? foreach ($memberships as $semester_name => $_memberships) : ?>
+ <article id="<?= $semester_name ?>" class="<?= ContentBoxHelper::classes($semester_name) ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($semester_name) ?>">
+ <?= $semester_name ?>
+ </a>
+ </h1>
+ </header>
+ <section>
+ <table class="default">
+ <colgroup>
+ <col style="width: 200px">
+ <col>
+ <col style="width: 15%">
+ <col style="width: 15%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Veranstaltungsnummer') ?></th>
+ <th><?= _('Veranstaltung') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Status') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($_memberships as $membership): ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $membership->course->id]) ?>">
+ <?= htmlReady($membership->course->veranstaltungsnummer) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $membership->course->id]) ?>">
+ <?= htmlReady($membership->course->name) ?>
+ </a>
+ </td>
+ <td>
+ <?= htmlReady($membership->course->getSemType()['name'])?>
+ </td>
+ <td>
+ <?= htmlReady($membership->status) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ </section>
+ </article>
+ <? endforeach ?>
+ <? else : ?>
+ <?= $this->render_partial('admin/user/_activities_no_courses.php') ?>
+ <? endif ?>
+</section>
diff --git a/app/views/admin/user/_delete.php b/app/views/admin/user/_delete.php
new file mode 100644
index 0000000..db4b221
--- /dev/null
+++ b/app/views/admin/user/_delete.php
@@ -0,0 +1,70 @@
+<form action="<?= $controller->link_for('admin/user/delete') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+<? if ($users) : ?>
+ <? $details = [] ?>
+ <? foreach ($users as $user) : ?>
+ <? $details[] = htmlReady(sprintf('%s (%s)', $user->getFullName(), $user->username)) ?>
+ <input type="hidden" name="user_ids[]" value="<?= $user['user_id'] ?>">
+ <? endforeach ?>
+<? endif ?>
+ <?= MessageBox::warning(_('Wollen Sie die folgenden Nutzer wirklich löschen?'), $details) ?>
+
+ <fieldset>
+ <legend><?= _('Personenbezogene Daten') ?></legend>
+
+ <label>
+ <input type="checkbox" id="personaldocuments" name="personaldocuments"
+ value="1" checked>
+ <?= _('Dokumente löschen?') ?>
+ <?= tooltipHtmlIcon(_('persönlicher Dateibereich')) ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="personalcontent" name="personalcontent"
+ value="1" checked>
+ <?= _('Andere Inhalte löschen?') ?>
+ <?= tooltipHtmlIcon(_('Inhalte der Profilseite, persöhnliche Blubber, Nachrichten')) ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="personalnames" name="personalnames"
+ value="1" checked>
+ <?= _('Namen löschen?') ?>
+ <?= tooltipHtmlIcon(_('Vor-/ Nachname, Username, E-Mail')) ?>
+ </label>
+
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Veranstaltungsbezogene Daten') ?></legend>
+
+ <label>
+ <input type="checkbox" id="documents" name="documents" value="1" checked>
+ <?= _('Dokumente löschen?') ?>
+ <?= tooltipHtmlIcon(_('Dateien in Veranstaltungen und Einrichtungen')) ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="coursecontent" name="coursecontent" value="1" checked>
+ <?= _('Andere Inhalte löschen?') ?>
+ <?= tooltipHtmlIcon(_('veranstaltungsbezogene Inhalte, bis auf Wiki und Forum Einträge')) ?>
+ </label>
+
+ <label>
+ <input type="checkbox" id="memberships" name="memberships" value="1" checked>
+ <?= _('Veranstaltungs-/Einrichtungszuordnungen löschen?') ?>
+ <?= tooltipHtmlIcon(_('Zuordnungen zu Veranstaltungen, Einrichtungen, Studiengruppen')) ?>
+ </label>
+
+ </fieldset>
+
+ <label>
+ <input type="checkbox" id="mail" name="mail" value="1" checked>
+ <?= _('E-Mail-Benachrichtigung verschicken?') ?>
+ </label>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Ja!'), 'delete', ['title' => _('Benutzer löschen')]) ?>
+ <?= Studip\Button::createCancel(_('Nein!'), 'back', ['title' => _('Abbrechen')]) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/user/_institute_files.php b/app/views/admin/user/_institute_files.php
new file mode 100644
index 0000000..9f17a08
--- /dev/null
+++ b/app/views/admin/user/_institute_files.php
@@ -0,0 +1,58 @@
+<section class="contentbox">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href('institutes') ?>">
+ <?= _('Dateiübersicht Einrichtungen') ?>
+ </a>
+ </h1>
+ </header>
+ <section>
+ <table class="default">
+ <colgroup>
+ <col>
+ <col style="width: 120px">
+ <col style="width: 20px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Dateiname') ?></th>
+ <th><?= _('Anzahl') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($institutes as $institute): ?>
+ <tr>
+ <td>
+ <?= htmlReady($institute['Name']) ?>
+ </td>
+ <td>
+ <? if ((int)$institute['files']) : ?>
+ <?= sprintf('%u %s', $institute['files'], _('Dokumente')) ?>
+ <? else : ?>
+ -
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <? if ($institute['files']) : ?>
+ <?
+ $actionMenu = ActionMenu::get();
+ $actionMenu->addLink($controller->url_for('admin/user/list_files/' . $user['user_id'] . '/' . $institute['Institut_id'] , $params),
+ _('Dateien auflisten'),
+ Icon::create('folder-full', 'clickable'),
+ ['data-dialog' => 'size=50%']);
+ $actionMenu->addLink($controller->url_for('admin/user/download_user_files/' . $user['user_id'] . '/' . $institute['Institut_id']),
+ _('Dateien als ZIP herunterladen'),
+ Icon::create('download', 'clickable'));
+
+ ?>
+ <?= $actionMenu->render() ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ </section>
+</section>
+
diff --git a/app/views/admin/user/_priority_list.php b/app/views/admin/user/_priority_list.php
new file mode 100644
index 0000000..1727e7f
--- /dev/null
+++ b/app/views/admin/user/_priority_list.php
@@ -0,0 +1,47 @@
+<section class="contentbox">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href('priorities') ?>">
+ <?= _('Übersicht Anmeldelisten von Veranstaltungen mit automatischer Platzvergabe') ?>
+ </a>
+ </h1>
+ </header>
+ <? if (!empty($priorities)) : ?>
+ <section>
+ <table class="default">
+ <colgroup>
+ <col style="width: 200px">
+ <col>
+ <col style="width: 15%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Veranstaltungsnummer') ?></th>
+ <th><?= _('Veranstaltung') ?></th>
+ <th style="text-align: center"><?= _('Priorität') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($priorities as $priority): ?>
+ <? $course = Course::find($priority['seminar_id']) ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $course->id]) ?>">
+ <?= htmlReady($course->veranstaltungsnummer) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $course->id]) ?>">
+ <?= sprintf('%s (%s)', htmlReady($course->getFullName('type-name')), htmlReady($course->getFullName('sem-duration-name'))) ?>
+ </a>
+ </td>
+ <td style="text-align: center"><?= htmlReady($priority['priority']) ?></td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ </section>
+ <? else : ?>
+ <?= $this->render_partial('admin/user/_activities_no_courses.php') ?>
+ <? endif ?>
+</section> \ No newline at end of file
diff --git a/app/views/admin/user/_results.php b/app/views/admin/user/_results.php
new file mode 100644
index 0000000..1d02f19
--- /dev/null
+++ b/app/views/admin/user/_results.php
@@ -0,0 +1,241 @@
+<br>
+
+<form action="<?= $controller->link_for('admin/user/bulk') ?>" method="post" data-dialog="size=auto" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= sprintf(_('Suchergebnis: es wurden %s Personen gefunden'), count($users)) ?>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <th colspan="2" <?= $sortby === 'username' ? 'class="sort' . $order . '"' : '' ?>>
+ <a href="<?= $controller->link_for('admin/user', ['sortby' => 'username', 'order' => $order, 'toggle' => $sortby === 'username']) ?>">
+ <?= _('Benutzername') ?>
+ </a>
+ </th>
+ <th>&nbsp;</th>
+ <th <?= $sortby === 'perms' ? 'class="sort' . $order . '"' : '' ?>>
+ <a href="<?= $controller->link_for('admin/user',['sortby' =>'perms', 'order'=> $order ,'toggle' => $sortby === 'perms']) ?>">
+ <?= _('Status') ?>
+ </a>
+ </th>
+ <th <?= $sortby === 'Vorname' ? 'class="sort' . $order . '"' : '' ?>>
+ <a href="<?= $controller->link_for('admin/user', ['sortby' => 'Vorname', 'order' => $order, 'toggle' => $sortby === 'Vorname']) ?>">
+ <?= _('Vorname') ?>
+ </a>
+ </th>
+ <th <?= $sortby === 'Nachname' ? 'class="sort' . $order . '"' : '' ?>>
+ <a href="<?= $controller->link_for('admin/user', ['sortby' => 'Nachname' , 'order' => $order, 'toggle' => $sortby === 'Nachname']) ?>">
+ <?= _('Nachname') ?>
+ </a>
+ </th>
+ <th <?= $sortby === 'Email' ? 'class="sort' . $order . '"' : '' ?>>
+ <a href="<?= $controller->link_for('admin/user', ['sortby' => 'Email', 'order' => $order, 'toggle' => $sortby === 'Email']) ?>">
+ <?= _('E-Mail') ?>
+ </a>
+ </th>
+ <th <?= $sortby === 'changed' ? 'class="sort' . $order . '"' : '' ?>>
+ <a href="<?= $controller->link_for('admin/user', ['sortby' => 'changed', 'order' => $order, 'toggle' => $sortby === 'changed']) ?>">
+ <?= _('inaktiv') ?>
+ </a>
+ </th>
+ <th <?= $sortby === 'mkdate' ? 'class="sort' . $order . '"' : '' ?>>
+ <a href="<?= $controller->link_for('admin/user', ['sortby' => 'mkdate', 'order' => $order , 'toggle' => $sortby === 'mkdate']) ?>">
+ <?= _('registriert seit') ?>
+ </a>
+ </th>
+ <th colspan="2" <?= $sortby === 'auth_plugin' ? 'class="sort' . $order . '"' : '' ?>>
+ <a href="<?= $controller->link_for('admin/user', ['sortby'=> 'auth_plugin', 'order' => $order ,'toggle' => $sortby === 'auth_plugin']) ?>">
+ <?= _('Authentifizierung') ?>
+ </a>
+ </th>
+ </tr>
+ </thead>
+
+ <tbody>
+
+ <? foreach ($users as $user) : ?>
+ <tr>
+ <td style="white-space:nowrap;">
+ <input class="check_all" type="checkbox" name="user_ids[]" value="<?= htmlReady($user->id) ?>">
+ <a href="<?= $controller->link_for("admin/user/edit/{$user->id}") ?>"
+ title="<?= _('Nutzer bearbeiten') ?>">
+ <?= Avatar::getAvatar($user->id)->getImageTag(Avatar::SMALL) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for("admin/user/edit/{$user->id}") ?>"
+ title="<?= _('Nutzer bearbeiten') ?>">
+ <?= htmlReady($user->username) ?>
+ </a>
+ <? if ($user->locked) : ?>
+ <?= Icon::create('lock-locked', Icon::ROLE_INFO)->asImg(tooltip2(sprintf(_('%s ist gesperrt'), htmlReady($user->getFullname())))) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <?
+ $userdomains = UserDomain::getUserDomainsForUser($user->user_id);
+ $tooltxt = _('Sichtbarkeit:') . ' ' . $user->visible;
+ if (!empty($userdomains)) {
+ $domains = [];
+ array_walk($userdomains, function ($a) use (&$domains) {
+ if (!in_array($a->name, $domains)) {
+ $domains[] = $a->name;
+ }
+ });
+ $tooltxt .= "\n" . _('Domänen:') . ' ' . implode(', ', $domains);
+ }
+ if ($user->locked == '1') {
+ $tooltxt .= "\n" . _("Nutzer ist gesperrt!");
+ }
+ ?>
+ <?= tooltipHtmlIcon(htmlReady($tooltxt, true, true)) ?>
+ </td>
+ <td><?= $user['perms'] ?></td>
+ <td><?= htmlReady($user->Vorname) ?></td>
+ <td><?= htmlReady($user->nachname) ?></td>
+ <td><?= htmlReady($user->email) ?></td>
+ <td>
+ <? if ($user->online->last_lifesign) :
+ $inactive = time() - $user->online->last_lifesign;
+ if ($inactive < 3600 * 24) {
+ $inactive = gmdate('H:i:s', $inactive);
+ } else {
+ $inactive = floor($inactive / (3600 * 24)) . ' ' . _('Tage');
+ }
+ else :
+ $inactive = _('nie benutzt');
+ endif ?>
+ <?= $inactive ?>
+ </td>
+ <td>
+ <?= $user->mkdate ? strftime('%x', $user->mkdate) : _('unbekannt') ?>
+ </td>
+ <td><?= htmlReady($user['auth_plugin'] === null ? _('vorläufig') : $user->auth_plugin) ?></td>
+ <td class="actions" nowrap>
+ <?
+ $actionMenu = ActionMenu::get();
+ $actionMenu->addLink(
+ $controller->url_for("admin/user/edit/{$user->id}"),
+ _('Nutzer bearbeiten'),
+ Icon::create('edit')
+ );
+
+ $actionMenu->addLink(
+ $controller->url_for('profile',['username' => $user->username]),
+ _('Zum Profil'),
+ Icon::create('person')
+ );
+ if ($GLOBALS['perm']->have_perm('root')) {
+ $actionMenu->addLink(
+ $controller->url_for('admin/user/activities/' . $user->user_id, ['from_index' => 1]),
+ _('Datei- und Aktivitätsübersicht'),
+ Icon::create('vcard'),
+ ['data-dialog' => 'size=50%']
+ );
+ if (Config::get()->LOG_ENABLE) {
+ $actionMenu->addLink(
+ $controller->url_for('event_log/show', ['search' => $user->username, 'type' => 'user', 'object_id' => $user->id]),
+ _('Personeneinträge im Log'),
+ Icon::create('log')
+ );
+ }
+ }
+
+ $actionMenu->addLink(
+ $controller->url_for('messages/write', ['rec_uname' => $user->username]),
+ _('Nachricht an Nutzer verschicken'),
+ Icon::create('mail'),
+ ['data-dialog' => 'size=auto']
+ );
+
+ if ($user->locked) {
+ $actionMenu->addLink(
+ $controller->url_for("admin/user/unlock/{$user->id}", ['from_index' => 1]),
+ _('Nutzeraccount entsperren'),
+ Icon::create('lock-unlocked')
+ );
+ } else {
+ $actionMenu->addLink(
+ $controller->url_for("admin/user/lock_comment/{$user->id}", ['from_index' => 1]),
+ _('Nutzeraccount sperren'),
+ Icon::create('lock-locked'),
+ ['data-dialog' => 'size=auto']
+ );
+ }
+
+ if ($user->auth_plugin !== 'preliminary' && ($GLOBALS['perm']->have_perm('root') || $GLOBALS['perm']->is_fak_admin() || !in_array($user->perms, words('root admin')))) {
+ if (!StudipAuthAbstract::CheckField('auth_user_md5.password', $user->auth_plugin)) {
+ $actionMenu->addLink(
+ $controller->url_for("admin/user/change_password/{$user->id}", ['from_index' => 1]),
+ _('Passwortlink zusenden'),
+ Icon::create('key')
+ );
+ }
+
+ $actionMenu->addButton(
+ 'delete_user',
+ _('Nutzer löschen'),
+ Icon::create('trash'),
+ ['formaction' => $controller->url_for("admin/user/bulk/{$user->id}", ['method' => 'delete'])]
+ );
+
+ }
+
+ if (Privacy::isVisible($user_id)) {
+ $actionMenu->addLink(
+ $controller->url_for("privacy/landing/{$user->id}"),
+ _('Anzeige Personendaten'),
+ Icon::create('log'),
+ ['data-dialog' => 'size=medium']
+ );
+ $actionMenu->addLink(
+ $controller->url_for("privacy/print/{$user->id}"),
+ _('Personendaten drucken'),
+ Icon::create('print'),
+ ['class' => 'print_action', 'target' => '_blank']
+ );
+ $actionMenu->addLink(
+ $controller->url_for("privacy/export/{$user->id}"),
+ _('Export Personendaten als CSV'),
+ Icon::create('file-text')
+ );
+ $actionMenu->addLink(
+ $controller->url_for("privacy/xml/{$user->id}"),
+ _('Export Personendaten als XML'),
+ Icon::create('file-text')
+ );
+ $actionMenu->addLink(
+ $controller->url_for("privacy/filesexport/{$user->id}"),
+ _('Export persönlicher Dateien als ZIP'),
+ Icon::create('file-archive')
+ );
+ }
+
+ echo $actionMenu;
+ ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="11" align="right">
+ <input style="vertical-align: middle" type="checkbox" name="check_all" title="<?= _('Alle Benutzer auswählen') ?>"
+ data-proxyfor=".check_all" data-activates=".bulkAction">
+ <select name="method" class="bulkAction size-s" required>
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <option value="send_message"><?= _('Nachricht senden') ?></option>
+ <option value="delete"><?= _('Löschen') ?></option>
+ </select>
+
+ <?= Studip\Button::create(_('Ausführen'), [
+ 'title' => _('Ausgewählte Aktion ausführen'),
+ 'class' => 'bulkAction',
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
diff --git a/app/views/admin/user/_waiting_list.php b/app/views/admin/user/_waiting_list.php
new file mode 100644
index 0000000..392c751
--- /dev/null
+++ b/app/views/admin/user/_waiting_list.php
@@ -0,0 +1,49 @@
+<section class="contentbox">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href('seminar_wait') ?>">
+ <?= _('Übersicht Wartelisten von Veranstaltungen') ?>
+ </a>
+ </h1>
+ </header>
+ <? if (!empty($memberships)) : ?>
+ <section>
+ <table class="default">
+ <colgroup>
+ <col style="width: 200px">
+ <col>
+ <col style="width: 15%">
+ <col style="width: 15%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Veranstaltungsnummer') ?></th>
+ <th><?= _('Veranstaltung') ?></th>
+ <th><?= _('Status') ?></th>
+ <th style="text-align: center"><?= _('Position') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($memberships as $membership): ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $membership->course->id]) ?>">
+ <?= htmlReady($membership->course->veranstaltungsnummer) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $membership->course->id]) ?>">
+ <?= sprintf('%s (%s)', htmlReady($membership->course->getFullName('type-name')), htmlReady($membership->course->getFullName('sem-duration-name'))) ?>
+ </a>
+ </td>
+ <td><?= htmlReady($membership->status) ?></td>
+ <td style="text-align: center"><?= htmlReady($membership->position) ?></td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ </section>
+ <? else : ?>
+ <?= $this->render_partial('admin/user/_activities_no_courses.php') ?>
+ <? endif ?>
+</section> \ No newline at end of file
diff --git a/app/views/admin/user/activities.php b/app/views/admin/user/activities.php
new file mode 100644
index 0000000..733df26
--- /dev/null
+++ b/app/views/admin/user/activities.php
@@ -0,0 +1,74 @@
+<h1 class="hide-in-dialog">
+ <?= htmlReady(PageLayout::getTitle()) ?>
+</h1>
+<section class="contentbox">
+ <header>
+ <h1>
+ <?= _('Informationen') ?>
+ </h1>
+ </header>
+ <table class="default">
+ <colgroup>
+ <col style="width: 60%">
+ <col>
+ <col style="width: 40px">
+ </colgroup>
+ <? foreach ($queries as $query): ?>
+ <tr>
+ <td style="font-weight: bold;"><?= $query['desc'] ?></td>
+ <td class="actions">
+ <?= htmlReady($query['value']) ?>
+ </td>
+ <td>
+ <? if ($query['details']) : ?>
+ <a href="<?= $controller->url_for('admin/user/activities/' . $user['user_id'], ['view' => $query['details']] + $params) ?>"
+ <?= Request::isXhr() ? 'data-dialog="size=50%"' : ''?>>
+ <?= Icon::create('info-circle', 'clickable', ['title' => _('Übersicht anzeigen')])->asImg('16') ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </table>
+</section>
+
+<? if (Request::get('view') !== 'files') : ?>
+ <? if (Request::get('view') == 'courses') : ?>
+ <?= $this->render_partial('admin/user/_course_list.php',
+ ['memberships' => $sections['courses'],
+ 'headline' => _('Übersicht Veranstaltungen'),
+ 'class' => 'courses']) ?>
+ <? endif ?>
+
+ <? if (Request::get('view') == 'closed_courses') : ?>
+ <?= $this->render_partial('admin/user/_course_list.php',
+ ['memberships' => $sections['closed_courses'],
+ 'headline' => _('Übersicht geschlossene Veranstaltungen'),
+ 'class' => 'closed_courses']) ?>
+ <? endif ?>
+
+
+ <? if (Request::get('view') == 'seminar_wait') : ?>
+ <?= $this->render_partial('admin/user/_waiting_list.php', ['memberships' => $sections['seminar_wait']]) ?>
+ <? endif ?>
+
+ <? if (Request::get('view') == 'priorities') : ?>
+ <?= $this->render_partial('admin/user/_priority_list.php', ['priorities' => $sections['priorities']]) ?>
+ <? endif ?>
+<? endif ?>
+<? if (!Request::get('view') || Request::get('view') === 'files') : ?>
+ <? if (!empty($sections['course_files'])) : ?>
+ <?= $this->render_partial('admin/user/_course_files.php', ['course_files' => $sections['course_files']]) ?>
+ <? endif ?>
+
+ <? if ($sections['institutes']) : ?>
+ <?= $this->render_partial('admin/user/_institute_files.php', ['institutes' => $sections['institutes']]) ?>
+ <? endif ?>
+<? endif ?>
+
+
+<? if (Request::int('from_index')) : ?>
+ <footer data-dialog-button>
+ <?= \Studip\LinkButton::create(_('Zurück zur Übersicht'), $controller->url_for('admin/user')) ?>
+ </footer>
+<? endif ?>
diff --git a/app/views/admin/user/edit.php b/app/views/admin/user/edit.php
new file mode 100644
index 0000000..f44ccd0
--- /dev/null
+++ b/app/views/admin/user/edit.php
@@ -0,0 +1,611 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<? if ($flash['delete']) : ?>
+ <?= $this->render_partial('admin/user/_delete', ['data' => $flash['delete']]) ?>
+<? endif ?>
+
+<span class="content-title">
+ <?= sprintf(_('Benutzerverwaltung für %s'), htmlReady($user->getFullName())) ?>
+
+ <? if ($prelim): ?>
+ (<?= _('vorläufiger Benutzer') ?>)
+ <? endif; ?>
+ <? if ($user->locked): ?>
+ <br>
+ <span style="color: red">
+ (<?= sprintf(_('gesperrt von %s'), htmlReady(get_fullname($user->locked_by))) ?>
+ <? if ($user->lock_comment): ?>
+ , <?= _('Kommentar') ?>: <?= htmlReady($user->lock_comment) ?>
+ <? endif; ?>
+ )
+ </span>
+ <? endif; ?>
+</span>
+
+<form method="post" action="<?= $controller->url_for('admin/user/edit/' . $user->id) ?>" class="default collapsable">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Allgemeine Daten') ?>
+ </legend>
+
+ <label>
+ <span class="required">
+ <?= _('Benutzername') ?>
+ </span>
+
+ <input class="user_form" type="text" id="username"
+ value="<?= htmlReady($user->username) ?>" required
+ <?= StudipAuthAbstract::CheckField('auth_user_md5.username', $user->auth_plugin)
+ || LockRules::check($user->user_id, 'username') ? 'readonly' : 'name="username"' ?>>
+ </label>
+
+ <label>
+ <?= _('Globaler Status') ?>
+
+ <select name="perms[]" id="permission"
+ <?= StudipAuthAbstract::CheckField('auth_user_md5.perms', $user->auth_plugin) ? 'disabled' : '' ?>>
+ <? foreach (array_keys($GLOBALS['perm']->permissions) as $permission): ?>
+ <option <? if ($permission === $user->perms) echo 'selected'; ?>>
+ <?= htmlReady($permission) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label >
+ <?= _('Sichtbarkeit') ?>
+
+ <div class="hgroup">
+ <? if (!$prelim): ?>
+ <?= vis_chooser($user->visible, false, 'visible') ?>
+ <? endif; ?>
+ </div>
+ </label>
+
+ <label >
+ <span class="required">
+ <?= _('Vorname') ?>
+ </span>
+
+ <input class="user_form" type="text" id="vorname"
+ value="<?= htmlReady($user->vorname) ?>" required
+ <?= StudipAuthAbstract::CheckField('auth_user_md5.Vorname', $user->auth_plugin)
+ || LockRules::check($user->user_id, 'name') ? 'readonly' : 'name="Vorname"' ?>>
+ </label>
+
+ <label >
+ <span class="required">
+ <?= _('Nachname') ?>
+ </span>
+
+ <input class="user_form" type="text" id="nachname"
+ value="<?= htmlReady($user->nachname) ?>" required
+ <?= StudipAuthAbstract::CheckField('auth_user_md5.Nachname', $user->auth_plugin)
+ || LockRules::check($user->user_id, 'name') ? 'readonly' : 'name="Nachname"' ?>>
+ </label>
+
+ <label >
+ <?= _('Titel') ?>
+
+ <? $disable_field = false ?>
+ <? if (StudipAuthAbstract::CheckField('user_info.title_front', $user->auth_plugin) || LockRules::check($user->user_id, 'title')): ?>
+ <? $disable_field = true ?>
+ <? endif ?>
+
+ <div class="hgroup">
+ <select name="title_front_chooser" id="title_front" class="size-s"
+ onchange="jQuery(this).next().val(this.value);"
+ <?= $disable_field ? 'disabled' : '' ?>>
+ <? foreach (Config::get()->TITLE_FRONT_TEMPLATE as $title): ?>
+ <option value="<?= htmlReady($title) ?>" <? if ($title === $user->title_front) echo 'selected'; ?>>
+ <?= htmlReady($title) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <input class="user_form" type="text"
+ value="<?= htmlReady($user->title_front) ?>"
+ <?= $disable_field ? 'readonly' : 'name="title_front"' ?>>
+ </div>
+ </label>
+
+
+ <label >
+ <?= _('Titel nachgestellt') ?>
+
+ <? $disable_field = false ?>
+ <? if (StudipAuthAbstract::CheckField('user_info.title_rear', $user->auth_plugin) || LockRules::check($user->user_id, 'title')): ?>
+ <? $disable_field = true ?>
+ <? endif ?>
+
+ <div class="hgroup">
+ <select name="title_rear_chooser" id="title_rear" class="size-s"
+ onchange="jQuery(this).next().val(this.value);"
+ <?= $disable_field ? 'disabled' : '' ?>>
+ <? foreach (Config::get()->TITLE_REAR_TEMPLATE as $rtitle): ?>
+ <option value="<?= htmlReady($rtitle) ?>" <? if ($rtitle === $user->title_rear) echo 'selected'; ?>>
+ <?= htmlReady($rtitle) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <input class="user_form" type="text"
+ value="<?= htmlReady($user->title_rear) ?>"
+ <?= $disable_field ? 'readonly' : 'name="title_rear"' ?>>
+ </div>
+ </label>
+
+ <label >
+ <?= _('Sprache') ?>
+
+ <select name="preferred_language">
+ <? foreach ($GLOBALS['INSTALLED_LANGUAGES'] as $key => $language): ?>
+ <option value="<?= $key ?>"
+ <? if ($user->preferred_language == $key) echo 'selected'; ?>>
+ <?= $language['name'] ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <section class="col-2">
+ <span class="label-text">
+ <?= _('Geschlecht') ?>
+ </span>
+
+ <? $disable_field = false ?>
+ <? if (StudipAuthAbstract::CheckField('user_info.geschlecht', $user->auth_plugin) || LockRules::check($user->user_id, 'gender')): ?>
+ <? $disable_field = true ?>
+ <? endif ?>
+
+ <div class="hgroup">
+ <label>
+ <input type="radio" name="geschlecht" value="0"
+ <? if (!$user->geschlecht) echo 'checked'; ?>
+ <?= $disable_field ? 'disabled' : '' ?>>
+ <?= _('unbekannt') ?>
+ </label>
+ <label>
+ <input type="radio" name="geschlecht" value="1"
+ <? if ($user->geschlecht == 1) echo 'checked'; ?>
+ <?= $disable_field ? 'disabled' : '' ?>>
+ <?= _('männlich') ?>
+ </label>
+ <label>
+ <input type="radio" name="geschlecht" value="2"
+ <? if ($user->geschlecht == 2) echo 'checked'; ?>
+ <?= $disable_field ? 'disabled' : '' ?>>
+ <?= _('weiblich') ?>
+ </label>
+ <label>
+ <input type="radio" name="geschlecht" value="3"
+ <? if ($user->geschlecht == 3) echo 'checked'; ?>
+ <?= $disable_field ? 'disabled' : '' ?>>
+ <?= _('divers') ?>
+ </label>
+ </div>
+ </section>
+ </fieldset>
+
+
+
+ <fieldset>
+ <legend>
+ <?= _('Registrierungsdaten') ?>
+ </legend>
+
+
+ <? if ($GLOBALS['perm']->have_perm('root')
+ && Config::get()->ALLOW_ADMIN_USERACCESS
+ && !StudipAuthAbstract::CheckField('auth_user_md5.password', $user->auth_plugin)
+ && !$prelim
+ ): ?>
+
+ <label>
+ <?= _('Neues Passwort') ?>
+ <input class="user_form" name="pass_1" type="password" id="pass_1" autocomplete="new-password">
+ </label>
+
+ <label>
+ <?= _('Passwortwiederholung') ?>
+
+ <input class="user_form" name="pass_2" type="password" id="pass_2" autocomplete="new-password"
+ onkeyup="jQuery('#pw_success').toggle(jQuery('#pass_1').val() === $('#pass_2').val())">
+ </label>
+
+ <label class="col-2">
+ <?= Icon::create('accept', 'accept')->asImg([
+ 'id' => 'pw_success',
+ 'style' => 'display: none',
+ ]) ?>
+ </label>
+ <? endif; ?>
+
+
+ <section>
+ <label for="email" <? if (!$prelim) echo 'class="required"'; ?>>
+ <?= _('E-Mail') ?>
+ </label>
+
+ <? if (StudipAuthAbstract::CheckField('auth_user_md5.Email', $user->auth_plugin) || LockRules::check($user->user_id, 'email')) : ?>
+ <input class="user_form" type="email" id="email"
+ value="<?= htmlReady($user['Email']) ?>" <? if (!$prelim) echo 'required'; ?> readonly>
+ <? else : ?>
+ <input class="user_form" type="email" name="Email" id="email"
+ value="<?= htmlReady($user['Email']) ?>" <? if (!$prelim) echo 'required'; ?>>
+ <? if ($GLOBALS['MAIL_VALIDATE_BOX']) : ?>
+ <label>
+ <input type="checkbox" name="disable_mail_host_check" value="1">
+ <?= _('Mailboxüberprüfung deaktivieren') ?>
+ </label>
+ <? endif ?>
+ <? endif ?>
+ </section>
+
+ <label>
+ <?= _('Authentifizierung') ?>
+
+ <select name="auth_plugin" id="auth_plugin">
+ <? foreach ($available_auth_plugins as $key => $val): ?>
+ <option value="<?= $key ?>" <? if (strcasecmp($key, $user->auth_plugin) == 0) echo 'selected'; ?>>
+ <?= htmlReady($val) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+
+ <section class="col-2">
+ <label for="expiration_date">
+ <?= _('Ablaufdatum') ?>
+ </label>
+
+ <div class="hgroup">
+ <input class="user_form" type="text"
+ name="expiration_date" id="expiration_date"
+ data-date-picker
+ value="<? if (UserConfig::get($user->user_id)->EXPIRATION_DATE) echo strftime('%x', UserConfig::get($user->user_id)->EXPIRATION_DATE); ?>">
+
+ <label>
+ <input type="checkbox" onchange="jQuery('input[name=expiration_date]').val('');"
+ name="expiration_date_delete" value="1">
+ <?= _('löschen') ?>
+ </label>
+ </div>
+ </section>
+
+ <? if ($user->validation_key|| true) : ?>
+ <section class="col-3">
+ <span class="label-text">
+ <?= _('Validation-Key') ?>
+ </span>
+
+ <div class="hgroup">
+ <?= htmlReady($user->validation_key) ?>
+
+ <label>
+ <input type="checkbox" name="delete_val_key" value="1">
+ <?= _('löschen') ?>
+ </label>
+ </div>
+ </section>
+ <? endif ?>
+
+
+ <section class="col-2">
+ <span class="label-text">
+ <?= _('Zuletzt aktiv') ?>
+ </span>
+
+ <br>
+
+ <? if ($user->online->last_lifesign): ?>
+ <abbr title="<?= strftime('%x %X', $user->online->last_lifesign) ?>">
+ <?= reltime($user->online->last_lifesign, true, 2) ?>
+ </abbr>
+ <? else: ?>
+ <?= _('nie benutzt') ?>
+ <? endif; ?>
+ </section>
+
+ <section class="col-2">
+ <span class="label-text">
+ <?= _('Registriert seit') ?>
+ </span>
+
+ <br>
+
+ <? if ($user->mkdate): ?>
+ <?= strftime('%x', $user->mkdate) ?>
+ <? else: ?>
+ <?= _('unbekannt') ?>
+ <? endif; ?>
+ </section>
+ </fieldset>
+
+ <? if (in_array($user->perms, ['autor', 'tutor', 'dozent'])): ?>
+ <fieldset>
+ <legend>
+ <?= _('Studiendaten') ?>
+ </legend>
+
+ <? if (!StudipAuthAbstract::CheckField('studiengang_id', $user->auth_plugin)) : ?>
+ <section class="col-3">
+ <span class="label-text"><?= _('Neuer Studiengang') ?></span>
+
+ <div class="hgroup">
+ <select style="width: 30%" name="new_studiengang" id="new_studiengang" aria-label="<?= _('-- Bitte Fach auswählen --')?>">
+ <option selected value="none"><?= _('-- Bitte Fach auswählen --')?></option>
+ <? foreach ($faecher as $fach) :?>
+ <?= sprintf('<option value="%s">%s</option>', $fach->id, htmlReady(my_substr($fach->name, 0, 50)));?>
+ <? endforeach?>
+ </select>
+
+ <select style="width: 30%" name="new_abschluss" id="new_abschluss" aria-label="<?= _('-- Bitte Abschluss auswählen --')?>">
+ <option selected value="none"><?= _('-- Bitte Abschluss auswählen --')?></option>
+ <? foreach ($abschluesse as $abschluss) :?>
+ <?= sprintf('<option value="%s">%s</option>' . "\n", $abschluss->id, htmlReady(my_substr($abschluss->name, 0, 50)));?>
+ <? endforeach?>
+ </select>
+
+ <select name="fachsem" aria-label="<?= _("Bitte Fachsemester wählen") ?>">
+ <? for ($i = 1; $i <= 50; $i += 1): ?>
+ <option><?= $i ?></option>
+ <? endfor; ?>
+ </select>
+ </div>
+ </section>
+ <? endif ?>
+ <label class="col-3">
+ <?= _('Neue Einrichtung') ?>
+
+ <select name="new_student_inst" id="new_student_inst" class="nested-select">
+ <option value="" class="is-placeholder">
+ <?= _('-- Bitte Einrichtung auswählen --') ?>
+ </option>
+ <? foreach ($available_institutes as $i) : ?>
+
+ <? if (InstituteMember::countBySql('user_id = ? AND institut_id = ?', [$user->user_id, $i['Institut_id']]) == 0
+ && (!($i['is_fak'] && $user->perms == 'admin') || $GLOBALS['perm']->have_perm('root'))
+ ) : ?>
+ <option class="<?= $i['is_fak'] ? 'nested-item-header' : 'nested-item' ?>"
+ value="<?= htmlReady($i['Institut_id']) ?>">
+ <?= htmlReady(my_substr($i['Name'], 0, 70)) ?>
+ </option>
+ <? else: ?>
+ <option class="<?= $i['is_fak'] ? 'nested-item-header' : 'nested-item' ?>" disabled>
+ <?= htmlReady(my_substr($i['Name'], 0, 70)) ?>
+ </option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <? if (sizeof($user->studycourses)) : ?>
+ <section class="col-3">
+ <ol class="default">
+ <? foreach ($user->studycourses as $i => $usc) : ?>
+ <li>
+ <?= sprintf(
+ '%s, %s, %s. %s',
+ htmlReady($usc->studycourse->name),
+ htmlReady($usc->degree->name),
+ htmlReady($usc->semester),
+ _('Fachsemester')
+ ) ?>
+ <a href="<?= $controller->url_for('admin/user/delete_studycourse/' . $user->user_id . '/' . $usc->fach_id . '/' . $usc->abschluss_id) ?>">
+ <?= Icon::create('trash')->asImg([
+ 'class' => 'text-bottom',
+ 'title' => _('Diesen Studiengang löschen'),
+ ]) ?>
+ </a>
+ <? $versionen = StgteilVersion::findByFachAbschluss($usc->fach_id, $usc->abschluss_id); ?>
+ <? $versionen = array_filter($versionen, function ($ver) {
+ return $ver->hasPublicStatus('genehmigt');
+ }); ?>
+ <? if (count($versionen)): ?>
+ <br>
+ <select name="change_version[<?= $usc->fach_id ?>][<?= $usc->abschluss_id ?>]"
+ aria-labelledby="version_label">
+ <option value=""><?= _('-- Bitte Version auswählen --') ?></option>
+ <? foreach ($versionen as $version) : ?>
+ <option <? if ($version->getId() == $usc->version_id) echo 'selected'; ?>
+ value="<?= htmlReady($version->getId()) ?>">
+ <?= htmlReady($version->getDisplayName()) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <?= tooltipIcon(_('Keine Version in der gewählten Fach-Abschluss-Kombination verfügbar.'), true) ?>
+ <? endif; ?>
+ </li>
+ <? endforeach ?>
+ </ol>
+ </section>
+ <? endif ?>
+
+ <? if (isset($student_institutes) && count($student_institutes)) : ?>
+ <section class="col-3">
+ <ol class="default">
+ <? foreach ($student_institutes as $i => $inst_membership) : ?>
+ <li>
+ <?= htmlReady($inst_membership->institute->name) ?>
+
+ <? if ($GLOBALS['perm']->have_studip_perm('admin', $inst_membership->institut_id)) : ?>
+ <a href="<?= $controller->url_for('admin/user/delete_institute/' . $user->user_id . '/' . $inst_membership->institut_id) ?>">
+ <?= Icon::create('trash')->asImg([
+ 'class' => 'text-bottom',
+ 'title' => _('Diese Einrichtung löschen'),
+ ]) ?>
+ </a>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ol>
+ </section>
+ <? endif; ?>
+ <? endif; ?>
+ </fieldset>
+
+ <? if ($user['perms'] !== 'root'): ?>
+ <fieldset>
+ <legend>
+ <?= _('Einrichtungsdaten') ?>
+ </legend>
+
+ <label class="col-3">
+ <?= _('Neue Einrichtung') ?>
+
+ <select name="new_inst[]" id="new_inst" class="nested-select" multiple>
+ <option value="" class="is-placeholder">
+ <?= _('-- Bitte Einrichtung auswählen --') ?>
+ </option>
+ <? foreach ($available_institutes as $i) : ?>
+ <? if (InstituteMember::countBySql('user_id = ? AND institut_id = ?', [$user->user_id, $i['Institut_id']]) == 0
+ && (!($i['is_fak'] && $user->perms == 'admin') || $GLOBALS['perm']->have_perm('root'))
+ ) : ?>
+ <option class="<?= $i['is_fak'] ? 'nested-item-header' : 'nested-item' ?>"
+ value="<?= htmlReady($i['Institut_id']) ?>">
+ <?= htmlReady(my_substr($i['Name'], 0, 70)) ?>
+ </option>
+ <? else: ?>
+ <option class="<?= $i['is_fak'] ? 'nested-item-header' : 'nested-item' ?>" disabled>
+ <?= htmlReady(my_substr($i['Name'], 0, 70)) ?>
+ </option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? if (isset($institutes) && count($institutes)) : ?>
+ <section class="col-3">
+ <ol class="default">
+ <? foreach ($institutes as $i => $inst_membership) : ?>
+ <li>
+ <?= htmlReady($inst_membership->institute->name) ?>
+
+ <? if ($GLOBALS['perm']->have_studip_perm("admin", $inst_membership->institut_id)) : ?>
+ <a data-dialog="size=auto"
+ href="<?= $controller->url_for('admin/user/edit_institute/' . $user->user_id . '/' . $inst_membership->institut_id) ?>">
+ <?= Icon::create('edit')->asImg([
+ 'class' => 'text-bottom',
+ 'title' => _('Diese Einrichtung bearbeiten'),
+ ]) ?>
+ </a>
+ <a href="<?= $controller->url_for('admin/user/delete_institute/' . $user->user_id . '/' . $inst_membership->institut_id) ?>">
+ <?= Icon::create('trash')->asImg([
+ 'class' => 'text-bottom',
+ 'title' => _('Diese Einrichtung löschen'),
+ ]) ?>
+ </a>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ol>
+ </section>
+ <? endif;?>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Nutzerdomänen') ?>
+ </legend>
+
+ <? if (!empty($domains)) : ?>
+ <label class="col-3">
+ <?= _('Neue Nutzerdomäne') ?>
+
+ <select name="new_userdomain" id="new_userdomain">
+ <option selected value="none"><?= _('-- Bitte Nutzerdomäne auswählen --') ?></option>
+ <? foreach ($domains as $domain) : ?>
+ <option value="<?= $domain->id ?>">
+ <?= htmlReady(my_substr($domain->name, 0, 50)) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif ?>
+
+ <? if (count($userdomains) > 0): ?>
+ <section class="col-3">
+ <ol class="default">
+ <? foreach ($userdomains as $i => $domain): ?>
+ <li>
+ <?= htmlReady($domain->name) ?>
+
+ <a href="<?= $controller->url_for('admin/user/delete_userdomain/' . $user->id, ['domain_id' => $domain->id]) ?>">
+ <?= Icon::create('trash')->asImg([
+ 'class' => 'text-bottom',
+ 'title' => _('Aus dieser Nutzerdomäne austragen'),
+ ]) ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ol>
+ </section>
+ <? endif; ?>
+ </fieldset>
+ <? endif; /* $user['perms'] !== 'root' */ ?>
+
+ <? if ($GLOBALS['perm']->have_perm('root') && count(LockRule::findAllByType('user')) > 0) : ?>
+ <fieldset>
+ <legend>
+ <?= _('Sperrebene') ?>
+ </legend>
+
+ <label>
+ <?= _('Sperrebene') ?>
+
+ <select name="lock_rule" id="lock_rule">
+ <option value="none">
+ <?= _('-- Bitte Sperrebene auswählen --') ?>
+ </option>
+ <? foreach (LockRule::findAllByType('user') as $rule) : ?>
+ <option value="<?= $rule->getId() ?>" <? if ($user['lock_rule'] == $rule->getId()) echo 'selected'; ?>>
+ <?= htmlReady($rule->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+ <? endif ?>
+
+ <? if (count($userfields) > 0) : ?>
+ <fieldset>
+ <legend>
+ <?= _('Datenfelder') ?>
+ </legend>
+
+ <? foreach ($userfields as $entry) : ?>
+ <? if ($entry->isVisible()) : ?>
+ <? $text = $entry->isVisible($user->perms)
+ ? ''
+ : _('Systemfeld (für die Person selbst nicht sichtbar)') ?>
+
+ <? if ($entry->isEditable() && !LockRules::Check($user->user_id, $entry->getId())) : ?>
+ <section class="col-3">
+ <?= $entry->getHTML('datafields', ['tooltip' => $text]) ?>
+ </section>
+ <? else : ?>
+ <section class="col-3">
+ <?= htmlReady($entry->getName()) ?> <?= $text ? tooltipIcon($text) : '' ?><br>
+ <?= $entry->getDisplayValue() ?: '<span class="empty">'. _('keine Angabe') .'</span>' ?>
+ </section>
+ <? endif ?>
+ <? endif ?>
+ <? endforeach ?>
+ </fieldset>
+ <? endif ?>
+
+ <footer>
+ <label>
+ <input name="u_edit_send_mail" value="1" checked type="checkbox">
+ <?= _('E-Mail-Benachrichtigung bei Änderung der Daten verschicken?') ?>
+ </label>
+ <br>
+
+ <?= Button::createAccept(_('Speichern'), 'edit') ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/user'), ['name' => 'abort']) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/user/edit_institute.php b/app/views/admin/user/edit_institute.php
new file mode 100644
index 0000000..d1f5b85
--- /dev/null
+++ b/app/views/admin/user/edit_institute.php
@@ -0,0 +1,65 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<form action="<?= $controller->url_for('admin/user/store_user_institute/' . $institute->user_id . '/' . $institute->institut_id) ?>"
+ method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= $user->getFullName() ?> -
+ <?= _('Bearbeiten der Einrichtungsdaten') ?>
+ </legend>
+
+ <label>
+ <?= _('Status') ?>
+ <select name="inst_perms">
+ <? foreach ($perms as $perm) : ?>
+ <option value="<?= htmlReady($perm) ?>" <? if ($institute->inst_perms === $perm) echo 'selected'; ?>>
+ <?= htmlReady($perm) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Raum') ?>
+ <input type="text" name="raum" value="<?= htmlReady($institute->raum) ?>">
+ </label>
+ <label>
+ <?= _('Sprechzeiten') ?>
+ <input type="text" name="sprechzeiten" value="<?= htmlReady($institute->sprechzeiten) ?>">
+ </label>
+ <label>
+ <?= _('Telefon') ?>
+ <input type="text" name="telefon" value="<?= htmlReady($institute->Telefon) ?>">
+ </label>
+ <label>
+ <?= _('Fax') ?>
+ <input type="text" name="fax" value="<?= htmlReady($institute->Fax) ?>">
+ </label>
+ <label>
+ <input type="checkbox" name="externdefault" value="1" <? if ($institute->externdefault) echo 'checked'; ?>>
+ <?= _('Standard-Adresse') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="visible" value="1" <? if ($institute->visible) echo 'checked'; ?>>
+ <?= _('Auf der Profilseite und in Adressbüchern sichtbar') ?>
+ </label>
+
+ <? if (count($datafields) > 0) : ?>
+ <? foreach ($datafields as $entry) : ?>
+ <? if ($entry->isEditable()): ?>
+ <?= $entry->getHTML('datafields') ?>
+ <? else : ?>
+ <section>
+ <?= htmlReady($entry->getName()) ?>
+ <?= $entry->getDisplayValue() ?: '<span class="empty">'. _('keine Angabe') .'</span>' ?>
+ </section>
+ <? endif ?>
+ <? endforeach ?>
+ <? endif ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Übernehmen'), 'uebernehmen', ['title' => _('Änderungen übernehmen')]) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/user/edit/' . $user->user_id)) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/user/index.php b/app/views/admin/user/index.php
new file mode 100644
index 0000000..a344bfa
--- /dev/null
+++ b/app/views/admin/user/index.php
@@ -0,0 +1,214 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+
+
+<form action="<?= $controller->url_for('admin/user') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Benutzerverwaltung') ?></legend>
+
+ <label class="col-3">
+ <?= _('Benutzername') ?>
+ <input name="username" type="text" value="<?= htmlReady($request['username']) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('E-Mail') ?>
+ <input name="email" type="text" value="<?= htmlReady($request['email']) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Vorname') ?>
+ <input name="vorname" type="text" value="<?= htmlReady($request['vorname']) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Nachname') ?>
+ <input name="nachname" type="text" value="<?= htmlReady($request['nachname']) ?>">
+ </label>
+
+ <label class="col-2">
+ <?= _('Status')?>
+
+ <select name="perm">
+ <? foreach(words('alle user autor tutor dozent admin root') as $one): ?>
+ <option value="<?= $one ?>" <?= ($request['perm'] === $one) ? 'selected' : '' ?>>
+ <?= ($one === 'alle') ? _('alle') : $one ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label class="col-2">
+ <span class="label-text"><?= _('inaktiv') ?></span>
+
+ <div class="hgroup">
+ <select name="inaktiv" class="size-s">
+ <? foreach(['<=' => '>=', '=' => '=', '>' => '<', 'nie' =>_('nie')] as $i => $one): ?>
+ <option value="<?= htmlready($i) ?>" <?= ($request['inaktiv'][0] === $i) ? 'selected' : '' ?>>
+ <?= htmlReady($one) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+
+ <input name="inaktiv_tage" type="number" id="inactive"
+ value="<?= htmlReady($request['inaktiv'][1]) ?>">
+ <?= _('Tage') ?>
+ </div>
+ </label>
+
+ <label class="col-2" style="padding-top: 1.8em;">
+ <input type="checkbox" name="locked" value="1" <?= ($request['locked']) ? 'checked' : '' ?>>
+ <?= _('nur gesperrt') ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable <?= (!$advanced) ? 'collapsed' : '' ?>">
+ <legend><?= _('Erweiterte Suche') ?></legend>
+
+ <label for="institute" class="col-3">
+ <?=_('Einrichtung')?>
+ <select name="institute">
+ <option value=""><?= _('Alle')?></option>
+ <? foreach($institutes as $institute) : ?>
+ <option value="<?= $institute['Institut_id']?>" <?= $request['institute'] == $institute['Institut_id'] ? 'selected' : ''?>>
+ <?= htmlReady($institute['Name'])?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <?= _('Nutzerdomäne') ?>
+
+ <select name="userdomains">
+ <option value=""><?= _('Alle') ?></option>
+ <option value="null-domain" <?= $request['userdomains'] === 'null-domain' ? 'selected' : '' ?>>
+ <?= _('Ohne Domäne') ?>
+ </option>
+ <? foreach ($userdomains as $one): ?>
+ <option value="<?= htmlReady($one->id) ?>" <?= $request['userdomains'] === $one->id ? 'selected' : ''?>>
+ <?= htmlReady($one->name ?: $one->id) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <?=_('Abschluss')?>
+ <select name="degree[]" multiple class="nested-select">
+ <option value=""><?=_('Alle')?></option>
+ <? foreach($degrees as $degree) : ?>
+ <option value="<?= $degree->id ?>"
+ <?= !empty($request['degree']) && in_array($degree->id, $request['degree']) ? 'selected' : ''?>>
+ <?=htmlReady($degree->name)?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <?=_('Fach')?>
+ <select name="studycourse[]" multiple class="nested-select">
+ <option value=""><?=_('Alle')?></option>
+ <? foreach($studycourses as $studycourse) : ?>
+ <option value="<?= $studycourse->id ?>"
+ <?= !empty($request['studycourse']) && in_array($studycourse->id, $request['studycourse']) ? 'selected' : ''?>>
+ <?=htmlReady($studycourse->name)?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <?= _('Fachsemester') ?>
+ <select name="fachsem">
+ <option value=""><?= _('Alle') ?></option>
+ <? for ($i = 1; $i <= 50; $i += 1): ?>
+ <option <?= $request['fachsem'] && (int)$request['fachsem'] === $i ? 'selected' : ''?>>
+ <?= $i ?>
+ </option>
+ <? endfor; ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <?= _('Authentifizierung') ?>
+ <select name="auth_plugins">
+ <option value=""><?= _('Alle') ?></option>
+ <? foreach (array_merge(['preliminary' => _('vorläufig')], $available_auth_plugins) as $key => $val): ?>
+ <option value="<?= $key ?>" <?= $request['auth_plugins'] === $key ? 'selected' : '' ?>>
+ <?= htmlReady($val) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <? foreach ($datafields as $datafield): ?>
+ <label class="col-3">
+ <?= htmlReady($datafield->name) ?>
+
+ <? if ($datafield->type === 'bool'): ?>
+ <section class="hgroup">
+ <span class="col-2">
+ <input type="radio" name="<?= $datafield->id ?>" value="" <?= (mb_strlen($request[$datafield->id]) === 0) ? 'checked' : '' ?>>
+ <?= _('egal') ?>
+ </span>
+ <span class="col-2">
+ <input type="radio" name="<?= $datafield->id ?>" value="1" <?= ($request[$datafield->id] === '1') ? 'checked' : '' ?>>
+ <?= _('ja') ?>
+ </span>
+ <span class="col-2">
+ <input type="radio" name="<?= $datafield->id ?>" value="0" <?= ($request[$datafield->id] === '0') ? 'checked' : '' ?>>
+ <?= _('nein') ?>
+ </span>
+ </section>
+ <? elseif ($datafield->type === 'selectbox' || $datafield->type === 'radio') : ?>
+ <? $datafield_entry = DataFieldEntry::createDataFieldEntry($datafield);?>
+ <select name="<?= $datafield->id ?>">
+ <option value="---ignore---"><?= _('alle') ?></option>
+ <? foreach ($datafield_entry->type_param as $pkey => $pval) :?>
+ <? $value = $datafield_entry->is_assoc_param ? (string) $pkey : $pval; ?>
+ <option value="<?= $value ?>" <?= ($request[$datafield->id] === $value) ? 'selected' : '' ?>>
+ <?= htmlReady($pval) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? else : ?>
+ <input type="text" name="<?= $datafield->id ?>" value="<?= htmlReady($request[$datafield->id]) ?>">
+ <? endif ?>
+ </label>
+ <? endforeach; ?>
+ <? if(!empty($roles)) :?>
+ <label class="col-3">
+ <?= _('Rollen')?>
+ <select name="roles[]" multiple class="nested-select">
+ <option value=""><?=_('Alle')?></option>
+ <? foreach($roles as $role) : ?>
+ <option value="<?= $role->roleid ?>" <?= !empty($request['roles']) && in_array($role->roleid, $request['roles']) ? 'selected' : '' ?>>
+ <?= htmlReady($role->rolename) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif?>
+ <label>
+ <input type="checkbox" name="show_only_not_lectures" value="1"
+ <? if ($request['show_only_not_lectures']) echo 'checked'; ?>>
+ <?= _('Nur Personen anzeigen, die in keiner Veranstaltung Lehrende sind')?>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Suchen'), 'search')?>
+ <?= Button::create(_('Zurücksetzen'), 'reset')?>
+ </footer>
+</form>
+
+<? if (!empty($users) && is_array($users)): ?>
+ <?= $this->render_partial('admin/user/_results') ?>
+<? endif; ?>
diff --git a/app/views/admin/user/list_files.php b/app/views/admin/user/list_files.php
new file mode 100644
index 0000000..3707d87
--- /dev/null
+++ b/app/views/admin/user/list_files.php
@@ -0,0 +1,58 @@
+<section class="contentbox">
+ <header>
+ <h1><?= _('Dateiübersicht') ?></h1>
+ </header>
+<? foreach ($folders as $folder) : ?>
+ <? foreach($folder->getFiles() as $file): ?>
+ <? if ($file->user_id === $user->id): ?>
+ <article id="<?= $file->id ?>" class="<?= ContentBoxHelper::classes($file->id) ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($file->id) ?>">
+ <?= htmlReady($file->name) ?>
+ </a>
+ </h1>
+ <? if ($folder->isFileDownloadable($file->id, $user->id)): ?>
+ <?= ActionMenu::get()->addLink(
+ $file->getDownloadURL(),
+ _('Datei herunterladen'),
+ Icon::create('download', 'clickable')
+ )->render() ?>
+ <? endif ?>
+ </header>
+ <section>
+ <article>
+ <p>
+ <?= htmlReady($file->description ?: _('Keine Beschreibung vorhanden'), true, true) ?>
+ </p>
+ <p>
+ <strong><?= _('Dateigröße') ?>:</strong>
+ <?= relsize($file->file->size) ?>
+ </p>
+ <p>
+ <strong><?= _('Dateiname') ?>:</strong>
+ <?= htmlReady($file->name) ?>
+ </p>
+ </article>
+
+ <? if ($file->terms_of_use->download_condition > 0): ?>
+ <article>
+ <?= MessageBox::warning(_('Das Herunterladen dieser Datei ist aufgrund von Nutzungsbedingungen nur eingeschränkt möglich!')) ?>
+ </article>
+ <? endif ?>
+ </section>
+ </article>
+ <? endif ?>
+ <? endforeach ?>
+<? endforeach ?>
+</section>
+
+<? if (Request::int('from_index')) : ?>
+ <footer data-dialog-button>
+ <?= Studip\LinkButton::create(
+ _('Zurück zur Übersicht'),
+ $controller->url_for('admin/user/activities/' . $user->user_id, $params),
+ ['data-dialog' => 'size=50%']
+ ) ?>
+ </footer>
+<? endif ?>
diff --git a/app/views/admin/user/lock_comment.php b/app/views/admin/user/lock_comment.php
new file mode 100644
index 0000000..4e87df0
--- /dev/null
+++ b/app/views/admin/user/lock_comment.php
@@ -0,0 +1,17 @@
+<form action="<?=$controller->url_for('admin/user/lock/' . $user->id, $params)?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag()?>
+
+ <fieldset>
+ <legend>
+ <?= _('Benutzer sperren') ?>
+ </legend>
+
+ <label>
+ <span class="required"><?= _('Kommentar') ?>:</span>
+ <input required class="user_form" name="lock_comment" type="text">
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Benutzer sperren'))?>
+ </footer>
+</form>
diff --git a/app/views/admin/user/migrate.php b/app/views/admin/user/migrate.php
new file mode 100644
index 0000000..8b26766
--- /dev/null
+++ b/app/views/admin/user/migrate.php
@@ -0,0 +1,55 @@
+<?
+# Lifter010: TODO - Quicksearches still lack a label
+
+use Studip\Button, Studip\LinkButton;
+
+?>
+<form action="<?= $controller->url_for('admin/user/migrate') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Benutzermigration') ?>
+ </legend>
+
+ <label>
+ <?= _('Quellaccount') ?>
+
+ <? if ($user !== null): ?>
+ <?= QuickSearch::get('old_id', new StandardSearch('user_id'))
+ ->defaultValue($user->id, $user->getFullname() . ' (' . $user->username . ')')
+ ->render() ?>
+ <? else: ?>
+ <?= QuickSearch::get('old_id', new StandardSearch('user_id'))->render() ?>
+ <? endif; ?>
+ </label>
+
+ <label>
+ <?= _('Zielaccount') ?>
+
+ <?= QuickSearch::get('new_id', new StandardSearch('user_id'))->render() ?>
+ </label>
+
+
+ <label>
+ <input type="checkbox" name="convert_ident" id="convert_ident" checked>
+
+ <?= _('Identitätsrelevante Daten migrieren') ?>
+ <?= tooltipIcon(_('(Es werden zusätzlich folgende Daten migriert: '
+ .'Veranstaltungen, Studiengänge, persönliche '
+ .'Profildaten inkl. Nutzerbild, Institute, '
+ .'generische Datenfelder und Buddies.)')) ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="delete_old" id="delete_old" value="1">
+ <?= _('Den alten Benutzer löschen') ?>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Umwandeln'),
+ 'umwandeln',
+ ['title' => _('Den ersten Benutzer in den zweiten Benutzer migrieren')]) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/user/index')) ?>
+ </footer>
+</form>
diff --git a/app/views/admin/user/new.php b/app/views/admin/user/new.php
new file mode 100644
index 0000000..4d0c24d
--- /dev/null
+++ b/app/views/admin/user/new.php
@@ -0,0 +1,212 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+
+<form method="post" action="<?= $controller->url_for('admin/user/new/' . $prelim) ?>" class="default" data-secure="true">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Einen neuen Benutzer anlegen') ?>
+ </legend>
+
+ <label>
+ <? if (!$prelim) : ?>
+ <span class="required">
+ <?= _("Benutzername") ?>
+ </span>
+ <? else: ?>
+ <?= _("Benutzername") ?>
+ <? endif ?>
+
+ <input class="user_form" type="text" name="username" value="<?= $user['username'] ?>" <?= (!$prelim ? 'required' : '')?> >
+ </label>
+
+ <label>
+ <span class="required">
+ <?= _("Globaler Status") ?>
+ </span>
+
+ <select class="user_form" name="perm" id="perm" onchange="jQuery('#admin_special').toggle( jQuery('#institut').val() != '0' && jQuery('#perm').val() == 'admin' )">
+ <option <? if ($user['perm'] == 'user') echo 'selected'; ?>>user</option>
+ <option <? if (!$user['perm'] || $user['perm'] == 'autor') echo 'selected'; ?>>autor</option>
+ <option <? if ($user['perm'] == 'tutor') echo 'selected'; ?>>tutor</option>
+ <option <? if ($user['perm'] == 'dozent') echo 'selected'; ?>>dozent</option>
+ <? if (!$prelim) : ?>
+ <? if ($GLOBALS['perm']->is_fak_admin()) : ?>
+ <option <? if ($user['perm'] == 'admin') echo 'selected'; ?>>admin</option>
+ <? endif ?>
+ <? if ($GLOBALS['perm']->have_perm('root')) : ?>
+ <option <? if ($user['perm'] == 'root') echo 'selected'; ?>>root</option>
+ <? endif ?>
+ <? endif ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _("Sichtbarkeit") ?>
+ <? if (!$prelim) : ?>
+ <?= vis_chooser($user['visible'], true) ?>
+ <? else : ?>
+ <?= _("niemals") ?>
+ <? endif ?>
+ </label>
+
+ <label>
+ <span class="required">
+ <?= _("Vorname") ?>
+ </span>
+
+ <input class="user_form" type="text" name="Vorname" value="<?= htmlReady($user['Vorname']) ?>" required>
+ </label>
+
+ <label>
+ <span class="required">
+ <?= _("Nachname") ?>
+ </span>
+
+ <input class="user_form" type="text" name="Nachname" value="<?= htmlReady($user['Nachname']) ?>" required>
+ </label>
+
+ <section>
+ <?= _("Geschlecht") ?>
+ <div class="hgroup">
+ <label>
+ <input id="unknown" type="radio" name="geschlecht" value="0"
+ <? if (!$user['geschlecht']) echo 'checked'; ?>>
+ <?= _('unbekannt') ?>
+ </label>
+
+ <label>
+ <input id="male" type="radio" name="geschlecht" value="1"
+ <? if ($user['geschlecht'] == 1) echo 'checked'; ?>>
+ <?= _('männlich') ?>
+ </label>
+
+ <label>
+ <input id="female" type="radio" name="geschlecht" value="2"
+ <? if ($user['geschlecht'] == 2) echo 'checked'; ?>>
+ <?= _('weiblich') ?>
+ </label>
+
+ <label>
+ <input id="diverse" type="radio" name="geschlecht" value="3"
+ <? if ($user['geschlecht'] == 3) echo 'checked'; ?>>
+ <?= _('divers') ?>
+ </div>
+ </section>
+
+ <label>
+ <?= _("Titel") ?>
+
+ <div class="hgroup">
+ <select name="title_front_chooser" onchange="jQuery('input[name=title_front]').val( jQuery(this).val() );" class="size-s">
+ <? foreach(Config::get()->TITLE_FRONT_TEMPLATE as $title) : ?>
+ <option value="<?= $title ?>" <?= ($title == $user['title_front']) ? 'selected' : '' ?>><?= $title ?></option>
+ <? endforeach ?>
+ </select>
+ <input class="user_form" type="text" name="title_front" value="<?= htmlReady($user['title_front']) ?>">
+ </div>
+ </label>
+
+ <label>
+ <?=_("Titel nachgestellt") ?>
+
+ <div class="hgroup">
+ <select name="title_rear_chooser" onchange="jQuery('input[name=title_rear]').val( jQuery(this).val() );" class="size-s">
+ <? foreach(Config::get()->TITLE_REAR_TEMPLATE as $rtitle) : ?>
+ <option value="<?= $rtitle ?>" <?= ($rtitle == $user['title_rear']) ? 'selected' : '' ?>><?= $rtitle ?></option>
+ <? endforeach ?>
+ </select>
+ <input class="user_form" type="text" name="title_rear" value="<?= htmlReady($user['title_rear']) ?>">
+ </div>
+ </label>
+
+ <label>
+ <?= _('Sprache') ?>
+
+ <select name="preferred_language">
+ <? foreach ($GLOBALS['INSTALLED_LANGUAGES'] as $key => $language): ?>
+ <option value="<?= $key ?>"
+ <? if ($user['preferred_language'] == $key) echo 'selected'; ?>>
+ <?= $language['name'] ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <? if (!$prelim) : ?>
+ <span class="required">
+ <?= _("E-Mail") ?>
+ </span>
+ <? else : ?>
+ <?= _("E-Mail") ?>
+ <? endif ?>
+
+ <input class="user_form" type="email" name="Email" value="<?= htmlReady($user['Email']) ?>" <?= (!$prelim ? 'required' : '')?>>
+ </label>
+
+
+ <? if ($GLOBALS['MAIL_VALIDATE_BOX']) : ?>
+ <label>
+ <input type="checkbox" id="disable_mail_host_check" name="disable_mail_host_check" value="1">
+ <?= _("Mailboxüberprüfung deaktivieren") ?>
+ </label>
+ <? endif ?>
+
+ <label>
+ <?= _("Einrichtung") ?>
+
+ <select multiple id="institut" class="user_form nested-select" name="institutes[]" onchange="jQuery('#admin_special').toggle( jQuery('#institut').val() != '0' && jQuery('#perm').val() == 'admin')">
+ <option value="" class="is-placeholder">
+ <?= _('-- Bitte Einrichtung auswählen --') ?>
+ </option>
+ <? foreach ($faks as $fak) : ?>
+ <option value="<?= $fak['Institut_id'] ?>" <?= ($user['institute'] == $fak['Institut_id']) ? 'selected' : '' ?> class="<?= $fak['is_fak'] ? 'nested-item-header' : 'nested-item'; ?>">
+ <?= htmlReady($fak['Name']) ?>
+ </option>
+ <? foreach ($fak['institutes'] as $institute) : ?>
+ <option value="<?= $institute['Institut_id'] ?>" <?= ($user['institute'] == $institute['Institut_id']) ? 'selected' : '' ?> class="nested-item">
+ <?= htmlReady($institute['Name']) ?>
+ </option>
+ <? endforeach ?>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <div style="display: none;" id="admin_special">
+ <label>
+ <input type="checkbox" value="admin" name="enable_mail_admin" id="enable_mail_admin">
+ <?= _('Admins der Einrichtung benachrichtigen') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" value="dozent" name="enable_mail_dozent" id="enable_mail_dozent">
+ <?= _('Lehrende der Einrichtung benachrichtigen') ?>
+ </label>
+ </div>
+
+ <? if (count($domains) > 0) : ?>
+ <label>
+ <?= _("Nutzerdomäne") ?>
+
+ <select class="user_form" name="select_dom_id">
+ <option value=""><?= _('-- Bitte Nutzerdomäne auswählen --') ?></option>
+ <? foreach ($domains as $domain) : ?>
+ <option value="<?= htmlReady($domain->id) ?>">
+ <?= htmlReady($domain->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Speichern'),'speichern', ['title' => _('Einen neuen Benutzer anlegen')])?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/user/?reset'), ['name' => 'abort'])?>
+ </footer>
+</form>
diff --git a/app/views/admin/webservice_access/index.php b/app/views/admin/webservice_access/index.php
new file mode 100644
index 0000000..2a63164
--- /dev/null
+++ b/app/views/admin/webservice_access/index.php
@@ -0,0 +1,82 @@
+<?
+# Lifter010: TODO
+?>
+<h3><?=_("Liste der Zugriffsregeln")?></h3>
+<form action="<?=$controller->url_for('admin/webservice_access/update#edit')?>" method="post" class="default">
+<?=CSRFProtection::tokenTag()?>
+<table class="default">
+<tr>
+ <th style="width: 30%;">
+ <?= _('API-Key') ?>
+ </th>
+ <th style="width: 30%;">
+ <?= _('Methode') ?>
+ </th>
+ <th style="width: 30%;">
+ <?= _('IP Bereich') ?>
+ </th>
+ <th style="width: 5%;">
+ <?= _('Typ') ?>
+ </th>
+ <th style="width: 5%;">
+ <?= _('Aktion') ?>
+ </th>
+</tr>
+<? foreach ($ws_rules as $rule): ?>
+ <tr class="<?= TextHelper::cycle('table_row_even', 'table_row_odd') ?>">
+ <? if (isset($edit) && $edit == $rule->id) :?>
+ <td>
+ <a name="edit"></a>
+ <input name="ws_rule_id" type="hidden" value="<?=$rule->id?>">
+ <input name="ws_rule_api_key" style="width:90%" type="text" required value="<?= htmlReady($rule->api_key) ?>">
+ </td>
+ <td>
+ <input name="ws_rule_method" style="width:90%" type="text" value="<?= htmlReady($rule->method) ?>">
+ </td>
+ <td>
+ <input name="ws_rule_ip_range" style="width:90%" type="text" value="<?= htmlReady($rule->ip_range) ?>">
+ </td>
+ <td>
+ <select name="ws_rule_type">
+ <option <?=($rule->type == 'allow' ? 'selected' : '') ?>>allow</option>
+ <option <?=($rule->type == 'deny' ? 'selected' : '') ?>>deny</option>
+ </select>
+ </td>
+ <td>
+ <?= Icon::create('accept', 'accept', ['title' => _('Änderungen speichern')])->asInput(["type" => "image", "class" => "middle", "name" => "ok"]) ?>
+ <?= Icon::create('decline', 'attention', ['title' => _('Abbrechen')])->asInput(['type' => "image", 'class' => "middle", 'name' => "cancel"]) ?>
+ </td>
+ <? else : ?>
+ <td>
+ <?= htmlReady($rule->api_key) ?>
+ </td>
+ <td>
+ <?= htmlReady($rule->method) ?>
+ </td>
+ <td>
+ <?= htmlReady($rule->ip_range) ?>
+ </td>
+ <td>
+ <?= htmlReady($rule->type) ?>
+ </td>
+ <td>
+ <a href="<?= $controller->url_for('admin/webservice_access/edit/'.$rule->id.'#edit') ?>">
+ <?= Icon::create('edit', 'clickable', ['title' => _('bearbeiten')])->asImg() ?>
+ </a>
+ <a href="<?= $controller->url_for('admin/webservice_access/delete/'.$rule->id) ?>">
+ <?= Icon::create('trash', 'clickable', ['title' => _('löschen')])->asImg() ?>
+ </a>
+ </td>
+ <? endif;?>
+ </tr>
+<? endforeach ?>
+</table>
+</form>
+<?
+$sidebar = Sidebar::Get();
+
+$actions = new ActionsWidget();
+$actions->addLink(_('Regeln testen'),$controller->url_for('admin/webservice_access/test'), Icon::create('add', 'clickable'));
+$actions->addLink(_('Neue Zugriffsregel anlegen'),$controller->url_for('admin/webservice_access/new'), Icon::create('add', 'clickable'));
+
+$sidebar->addWidget($actions);
diff --git a/app/views/admin/webservice_access/test.php b/app/views/admin/webservice_access/test.php
new file mode 100644
index 0000000..16b71a0
--- /dev/null
+++ b/app/views/admin/webservice_access/test.php
@@ -0,0 +1,38 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<form action="<?=$controller->url_for('admin/webservice_access/test')?>" method="post" class="default">
+ <?=CSRFProtection::tokenTag()?>
+ <fieldset>
+ <legend>
+ <?=_("Testen der Zugriffsregeln")?>
+ </legend>
+
+ <label>
+ <?= _('API KEY') ?>
+ <input type="text" name="test_api_key" size="50" required value="<?=htmlReady(Request::get("test_api_key"))?>">
+ </label>
+
+ <label>
+ <?= _('Methode') ?></td>
+ <input type="text" name="test_method" size="50" required value="<?=htmlReady(Request::get("test_method"))?>">
+ </label>
+
+ <label>
+ <?= _('IP Adresse') ?></td>
+ <input type="text" name="test_ip" size="50" required value="<?=htmlReady(Request::get("test_ip"))?>">
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::createAccept(_('Abschicken'), 'ok', ['title' => _('Test starten')])?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admin/webservice_access'), ['title' => _('Test abbrechen')])?>
+ </footer>
+</form>
+
+<?
+$sidebar = Sidebar::Get();
+
+$actions = new ActionsWidget();
+$actions->addLink(_('Liste der Zugriffsregeln'),$controller->url_for('admin/webservice_access'), Icon::create('add', 'clickable'));
+$actions->addLink(_('Neue Zugriffsregel anlegen'),$controller->url_for('admin/webservice_access/new'), Icon::create('add', 'clickable'));
+
+$sidebar->addWidget($actions);
diff --git a/app/views/admission/courseset/_institute_choose.php b/app/views/admission/courseset/_institute_choose.php
new file mode 100644
index 0000000..e684de6
--- /dev/null
+++ b/app/views/admission/courseset/_institute_choose.php
@@ -0,0 +1,68 @@
+<form action="?" method="post" name="institute_choose" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Anmeldesets auflisten') ?></legend>
+
+ <label>
+ <?=_("Einrichtung:")?>
+ <select name="choose_institut_id" class="nested-select">
+ <? while (list($institut_id,$institute) = each($myInstitutes)) : ?>
+ <option value="<?= $institut_id ?>" <?=($current_institut_id == $institut_id ? 'selected' : '')?> class="<?= $institute['is_fak'] ? 'nested-item-header' : 'nested-item' ?>">
+ <?= htmlReady(my_substr($institute["name"] . ' (' . $institute["num_sets"] . ')',0,100));?>
+ </option>
+ <? if ($institute['is_fak'] === 'all') : ?>
+ <? $num_inst = $institute['num_inst']; for ($i = 0; $i < $num_inst; ++$i) : ?>
+ <? list($institut_id,$institute) = each($myInstitutes);?>
+ <option value="<?= $institut_id?>" <?=($current_institut_id == $institut_id ? 'selected' : '')?> class="nested-item">
+ <?= htmlReady(my_substr($institute["name"] . ' (' . $institute["num_sets"] . ')',0,100));?>
+ </option>
+ <? endfor ?>
+ <? endif ?>
+ <? endwhile ?>
+ </select>
+ </label>
+
+ <label>
+ <?=_("Präfix des Namens:")?>
+ <input type="text" name="set_name_prefix" value="<?=htmlReady($set_name_prefix)?>" size="40">
+ </label>
+
+ <section>
+ <?=_("Enthaltene Regeln:")?>
+ <div class="hidden-no-js check_actions">
+ (<?= _('markieren') ?>:
+ <a onclick="STUDIP.Admission.checkUncheckAll('choose_rule_type', 'check')">
+ <?= _('alle') ?>
+ </a>
+ |
+ <a onclick="STUDIP.Admission.checkUncheckAll('choose_rule_type', 'uncheck')">
+ <?= _('keine') ?>
+ </a>
+ |
+ <a onclick="STUDIP.Admission.checkUncheckAll('choose_rule_type', 'invert')">
+ <?= _('Auswahl umkehren') ?>
+ </a>)
+ </div>
+ </section>
+
+ <div>
+ <? foreach ($ruleTypes as $type => $detail) : ?>
+ <label class="col-2">
+ <input type="checkbox" name="choose_rule_type[<?= $type?>]" <?=(isset($current_rule_types[$type]) ? 'checked' : '')?> value="1">
+ <?= htmlReady($detail['name']);?>
+ </label>
+ <? endforeach; ?>
+ </div>
+
+ <label>
+ <?=_("Zugewiesene Veranstaltungen aus diesem Semester:")?>
+ <?= Semester::getSemesterSelector(['name'=>'select_semester_id'], $current_semester_id, 'semester_id', true)?>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::create(_('Auswählen'), 'choose_institut', ['title' => _("Einrichtung auswählen")]) ?>
+ </footer>
+</form>
+<br>
diff --git a/app/views/admission/courseset/applications_list.php b/app/views/admission/courseset/applications_list.php
new file mode 100644
index 0000000..6eba77a
--- /dev/null
+++ b/app/views/admission/courseset/applications_list.php
@@ -0,0 +1,21 @@
+<table class="default">
+ <thead>
+ <tr>
+ <? foreach ($captions as $cap) :?>
+ <th><?= $cap ?></th>
+ <? endforeach ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($data as $row ) : ?>
+ <tr>
+ <? foreach ($row as $value ) : ?>
+ <td><?= htmlReady($value) ?></td>
+ <? endforeach ?>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+<div data-dialog-button>
+<?= Studip\LinkButton::create(_("Download"), $controller->url_for('admission/courseset/applications_list/' . $set_id .'/csv')) ?>
+</div> \ No newline at end of file
diff --git a/app/views/admission/courseset/configure.php b/app/views/admission/courseset/configure.php
new file mode 100644
index 0000000..3c3048d
--- /dev/null
+++ b/app/views/admission/courseset/configure.php
@@ -0,0 +1,244 @@
+<?php
+use Studip\Button, Studip\LinkButton;
+
+Helpbar::get()->addPlainText(_('Regeln'), _('Hier können Sie die Regeln, Eigenschaften und Zuordnungen des Anmeldesets bearbeiten.'));
+Helpbar::get()->addPlainText(_('Info'), _('Sie können das Anmeldeset allen Einrichtungen zuordnen, an denen Sie mindestens Lehrendenrechte haben.'));
+Helpbar::get()->addPlainText(_('Sichtbarkeit'), _('Alle Veranstaltungen der Einrichtungen, an denen Sie mindestens Lehrendenrechte haben, können zum Anmeldeset hinzugefügt werden.'));
+
+// Load assigned course IDs.
+$courseIds = $courseset ? $courseset->getCourses() : [];
+// Load assigned user list IDs.
+$userlistIds = $courseset ? $courseset->getUserlists() : [];
+
+if ($flash['error']) {
+ echo MessageBox::error($flash['error']);
+}
+?>
+<div class="hidden-alert" style="display:none">
+ <?= MessageBox::info(_("Diese Daten sind noch nicht gespeichert."));?>
+</div>
+<?= $this->render_partial('dialog/confirm_dialog') ?>
+<h1><?= $courseset ? _('Anmeldeset bearbeiten') : _('Anmeldeset anlegen') ?></h1>
+<form class="default" id="courseset-form" action="<?= $controller->url_for(!$instant_course_set_view ?
+ 'admission/courseset/save/' . ($courseset ? $courseset->getId() : '') :
+ 'course/admission/save_courseset/' . $courseset->getId()) ?>" method="post">
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label>
+ <span class="required"><?= _('Name des Anmeldesets') ?></span>
+ <input type="text" maxlength="255" name="name"
+ value="<?= $courseset ? htmlReady($courseset->getName()) : '' ?>"
+ required aria-required="true"/>
+ </label>
+ <? if (!$courseset || ($courseset->isUserAllowedToEdit($GLOBALS['user']->id) && !$instant_course_set_view)) : ?>
+ <label for="private">
+ <?= _('Sichtbarkeit') ?>
+ </label>
+ <input type="checkbox" id="private" name="private"<?= $courseset ? ($courseset->getPrivate() ? ' checked="checked"' : '') : 'checked' ?>/>
+ <?= _('Dieses Anmeldeset soll nur für mich selbst und alle Administratoren sichtbar und benutzbar sein.') ?>
+ <? endif ?>
+ <? if ($courseset) : ?>
+ <label>
+ <?= _('Besitzer des Anmeldesets') ?>
+ </label>
+ <div>
+ <? $user = User::find($courseset->getUserId()) ?>
+ <? if (isset($user)) : ?>
+ <a target="_blank" href="<?= $controller->url_for('profile', ['username' => $user->username]) ?>" >
+ <?= htmlReady($user->getFullName()) ?> (<?= htmlReady($user->username) ?>)
+ </a>
+ <? else : ?>
+ <?= _('unbekannt') ?>
+ <? endif ?>
+ </div>
+ <? endif ;?>
+ <label for="institutes">
+ <span class="required"><?= _('Einrichtungszuordnung') ?></span>
+ </label>
+ <? if ($GLOBALS['perm']->have_perm('admin') || $GLOBALS['perm']->have_perm('dozent') && Config::get()->ALLOW_DOZENT_COURSESET_ADMIN) : ?>
+ <div id="institutes">
+ <?php if ($myInstitutes) { ?>
+ <?php if ($instSearch) { ?>
+ <?= $instTpl ?>
+ <?php } else { ?>
+ <?php foreach ($myInstitutes as $institute) { ?>
+ <?php if (sizeof($myInstitutes) != 1) { ?>
+ <input type="checkbox" name="institutes[]" value="<?= $institute['Institut_id'] ?>"
+ <?= $selectedInstitutes[$institute['Institut_id']] ? 'checked="checked"' : '' ?>
+ class="institute" onclick="STUDIP.Admission.getCourses(
+ '<?= $controller->url_for('admission/courseset/instcourses', $courseset ? $courseset->getId() : '') ?>')"/>
+ <?php } else { ?>
+ <input type="hidden" name="institutes[]" value="<?= $institute['Institut_id'] ?>"/>
+ <?php } ?>
+ <?= htmlReady($institute['Name']) ?>
+ <br/>
+ <?php } ?>
+ <?php } ?>
+ <?php } else { ?>
+ <?php if ($instSearch) { ?>
+ <div id="institutes">
+ <?= Icon::create('arr_2down', 'sort', ['title' => _('Einrichtung hinzufügen')])->asImg(16, ["alt" => _('Einrichtung hinzufügen'), "onclick" => "STUDIP.Admission.updateInstitutes($('input[name=\"institute_id\"]').val(), '".$controller->url_for('admission/courseset/institutes',$courseset?$courseset->getId():'')."', '".$controller->url_for('admission/courseset/instcourses',$courseset?$courseset->getId():'')."', 'add')"]) ?>
+ <?= $instSearch ?>
+ <?= Icon::create('search', 'clickable', ['title' => _("Suche starten")])->asImg()?>
+ </div>
+ <i><?= _('Sie haben noch keine Einrichtung ausgewählt. Benutzen Sie obige Suche, um dies zu tun.') ?></i>
+ <?php } else { ?>
+ <i><?= _('Sie sind keiner Einrichtung zugeordnet.') ?></i>
+ <?php } ?>
+ <?php } ?>
+ </div>
+ <? else : ?>
+ <? foreach (SimpleCollection::createFromArray($selectedInstitutes)->orderBy('Name') as $institute) : ?>
+ <?= htmlReady($institute['Name']) ?>
+ <br>
+ <? endforeach ?>
+ <? endif ?>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Veranstaltungen') ?></legend>
+ <? if (!$instant_course_set_view) : ?>
+ <label>
+ <?= _('Semester') ?>
+ <select name="semester" onchange="STUDIP.Admission.getCourses('<?= $controller->url_for('admission/courseset/instcourses', $courseset ? $courseset->getId() : '') ?>')">
+ <?php foreach(array_reverse(Semester::getAll(), true) as $id => $semester) { ?>
+ <option value="<?= $id ?>"<?= $id == $selectedSemester ? ' selected="selected"' : '' ?>>
+ <?= htmlReady($semester->name) ?>
+ </option>
+ <?php } ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Filter auf Name/Nummer/Lehrperson') ?><br>
+ <input style="display:inline-block" type="text" onKeypress="if (event.which==13) return STUDIP.Admission.getCourses('<?= $controller->url_for('admission/courseset/instcourses', $courseset ? $courseset->getId() : '') ?>')" value="<?= htmlReady($current_course_filter) ?>" name="course_filter" >
+ <?=Icon::create('search', 'clickable', ['title' => _("Veranstaltungen anzeigen"),'onClick' => "return STUDIP.Admission.getCourses('" . $controller->url_for('admission/courseset/instcourses', $courseset ? $courseset->getId() : '') ."')"])->asImg()?>
+ </label>
+ <div id="instcourses">
+ <?= $coursesTpl; ?>
+ </div>
+ <? if (count($courseIds) && $courseset->getAdmissionRule('ParticipantRestrictedAdmission')) : ?>
+ <div>
+ <?= LinkButton::create(_('Ausgewählte Veranstaltungen konfigurieren'),
+ $controller->url_for('admission/courseset/configure_courses/' . $courseset->getId()),
+ ['data-dialog' => 'size=big', 'class' => 'autosave']
+ ); ?>
+ <? if ($num_applicants = $courseset->getNumApplicants()) :?>
+ <?= LinkButton::create(sprintf(_('Liste der Anmeldungen (%s Nutzer)'), $num_applicants),
+ $controller->url_for('admission/courseset/applications_list/' . $courseset->getId()),
+ ['data-dialog' => '', 'class' => 'autosave']
+ ); ?>
+ <?= LinkButton::create(_('Nachricht an alle Angemeldeten'),
+ $controller->url_for('admission/courseset/applicants_message/' . $courseset->getId()),
+ ['data-dialog' => '', 'class' => 'autosave']
+ ); ?>
+ <? endif ?>
+ </div>
+ <? endif ?>
+ <? else :?>
+ <? if (count($courseIds) > 100) :?>
+ <?= sprintf(_("%s zugewiesene Veranstaltungen"), count($courseIds)) ?>
+ <? else : ?>
+ <?
+ Course::findEachMany(function($c) {
+ echo htmlReady($c->getFullname('number-name-semester'));
+ echo '<br>';
+ },
+ $courseIds,
+ 'ORDER BY start_time,VeranstaltungsNummer,Name');
+ ?>
+ <? endif ?>
+ <? endif ?>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Anmelderegeln') ?></legend>
+ <div id="rules">
+ <?php if ($courseset) { ?>
+ <div id="rulelist">
+ <?php foreach ($courseset->getAdmissionRules() as $rule) { ?>
+ <?= $this->render_partial('admission/rule/save', ['rule' => $rule]) ?>
+ <?php } ?>
+ </div>
+ <?php } else { ?>
+ <span id="norules">
+ <i><?= _('Sie haben noch keine Anmelderegeln festgelegt.') ?></i>
+ </span>
+ <br/>
+ <?php } ?>
+ <div style="clear: both;">
+ <?= LinkButton::create(_('Anmelderegel hinzufügen'),
+ $controller->url_for('admission/rule/select_type' . ($courseset ? '/'.$courseset->getId() : '')),
+ [
+ 'onclick' => "return STUDIP.Admission.selectRuleType(this)"
+ ]
+ ); ?>
+ </div>
+ </div>
+ </fieldset>
+ <div class="hidden-alert" style="display:none">
+ <?= MessageBox::info(_("Diese Daten sind noch nicht gespeichert."));?>
+ </div>
+ <fieldset>
+ <legend><?= _('Weitere Daten') ?></legend>
+ <? if (!$instant_course_set_view) : ?>
+
+ <? if ($courseset && $courseset->getSeatDistributionTime()) :?>
+ <label>
+ <?= _('Personenlisten zuordnen') ?>
+ </label>
+ <?php if ($myUserlists) { ?>
+ <?php
+ foreach ($myUserlists as $list) {
+ $checked = '';
+ if (in_array($list->getId(), $userlistIds)) {
+ $checked = ' checked="checked"';
+ }
+ ?>
+ <input type="checkbox" name="userlists[]" value="<?= $list->getId() ?>"<?= $checked ?>/> <?= $list->getName() ?><br/>
+ <?php } ?>
+
+ <?php } else { ?>
+ <i><?= _('Sie haben noch keine Personenlisten angelegt.') ?></i>
+ <?php
+ }?>
+ <? if ($courseset) : ?>
+ <div>
+ <?= LinkButton::create(_('Liste der Nutzer'),
+ $controller->url_for('admission/courseset/factored_users/' . $courseset->getId()),
+ ['data-dialog' => '']
+ ); ?>
+ </div>
+ <? endif ?>
+ <?php
+ // Keep lists that were assigned by other users.
+ foreach ($userlistIds as $list) {
+ if (!in_array($list, array_keys($myUserlists))) {
+ ?>
+ <input type="hidden" name="userlists[]" value="<?= $list ?>"/>
+ <?php
+ }
+ }
+ ?>
+ <? endif ?>
+ <? endif ?>
+ <label for="infotext">
+ <?= _('Weitere Hinweise für die Teilnehmenden') ?>
+ </label>
+ <textarea cols="60" rows="3" name="infotext"><?= $courseset ? htmlReady($courseset->getInfoText()) : '' ?></textarea>
+ </fieldset>
+
+ <footer class="submit_wrapper" data-dialog-button>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= Button::createAccept(_('Speichern'), 'submit',
+ $instant_course_set_view ? ['data-dialog' => ''] : []) ?>
+ <?php if (Request::option('is_copy')) : ?>
+ <?= LinkButton::createCancel(_('Abbrechen'),
+ URLHelper::getURL('dispatch.php/admission/courseset/delete/' . $courseset->getId(),
+ ['really' => 1])) ?>
+ <?php else : ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admission/courseset')) ?>
+ <?php endif ?>
+ </footer>
+
+</form>
+<? if (Request::get('is_copy')) :?>
+ <script>STUDIP.Admission.toggleNotSavedAlert();</script>
+<? endif ?>
diff --git a/app/views/admission/courseset/configure_courses.php b/app/views/admission/courseset/configure_courses.php
new file mode 100644
index 0000000..b91c842
--- /dev/null
+++ b/app/views/admission/courseset/configure_courses.php
@@ -0,0 +1,77 @@
+<form name="configure_courses" action="<?= $controller->url_for('admission/courseset/configure_courses/' . $set_id) ?>" method="post">
+ <table class="default">
+ <thead>
+ <tr>
+ <th><?= _("Name")?></th>
+ <th><?= _("Lehrende")?></th>
+ <th><?= _("versteckt")?></th>
+ <th><?= _("vorläufige Anmeldung")?></th>
+ <th><?= _("verbindliche Anmeldung")?></th>
+ <th><?= _("max. Teilnehmende")?></th>
+ <th><?= _("Teilnehmende aktuell")?></th>
+ <th><?= _("Anmeldungen")?></th>
+ <th><?= _("Warteliste")?></th>
+ <th><?= _("Plätze")?></th>
+ <th><?= _("Nachrücken")?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($courses as $course) : ?>
+ <? $editable = (!$GLOBALS['perm']->have_studip_perm('admin', $course->id) && (!Config::get()->ALLOW_DOZENT_COURSESET_ADMIN && !$GLOBALS['perm']->have_perm('dozent'))) ? 'disabled' : '' ?>
+ <tr>
+ <td><?= htmlReady(($course->veranstaltungsnummer ? $course->veranstaltungsnummer .'|' : '')
+ . $course->name
+ . ($course->cycles ? ' (' . join('; ', $course->cycles->toString()) . ')' : ''))?></td>
+ <td><?= htmlReady(join(', ', $course->members->findBy('status','dozent')->orderBy('position')->limit(3)->pluck('Nachname')))?></td>
+ <td><input <?=$editable?> type="checkbox" name="configure_courses_hidden[<?= $course->id?>]" value="1" <?= $course->visible ? '' : 'checked'?>></td>
+ <td><input <?=$editable?> type="checkbox" name="configure_courses_prelim[<?= $course->id?>]" value="1" <?= $course->admission_prelim ? 'checked' : ''?>></td>
+ <td><input <?=$editable?> type="checkbox" name="configure_courses_binding[<?= $course->id?>]" value="1" <?= $course->admission_binding ? 'checked' : ''?>></td>
+ <td><input <?=$editable?> type="text" size="2" name="configure_courses_turnout[<?= $course->id?>]" value="<?= (int)$course->admission_turnout ?>"></td>
+ <td><?= $course->getNumParticipants() ?></td>
+ <td><?= sprintf("%d / %d", $applications[$course->id]['c'],$applications[$course->id]['h']) ?></td>
+ <td style="white-space:nowrap">
+ <input <?=$editable?> type="checkbox" name="configure_courses_disable_waitlist[<?= $course->id?>]" value="1" <?= $course->admission_disable_waitlist ? '' : 'checked' ?>
+ title="<?= htmlReady(sprintf(_('Warteliste für %s aktivieren'), $course->name)) ?>"
+ data-activates="#waitlist_move_<?= $course->id?>, #waitlist_max_<?= $course->id?>">
+ </td>
+ <td style="white-space:nowrap">
+ <input <?=$editable?> id="waitlist_max_<?= $course->id?>"
+ type="text" size="2" name="configure_courses_waitlist_max[<?= $course->id?>]"
+ value="<?= $course->admission_waitlist_max ?: ''?>"
+ title="<?= htmlReady(sprintf(_('Anzahl der Plätze auf der Warteliste für %s'), $course->name)) ?>"
+ <?= $course->admission_disable_waitlist ? 'disabled' : ''?>>
+ </td>
+ <td style="white-space:nowrap">
+ <input <?=$editable?> type="checkbox"
+ id="waitlist_move_<?= $course->id?>" <?= $course->admission_disable_waitlist ? 'disabled' : ''?>
+ name="admission_disable_waitlist_move[<?= $course->id?>]" value="1"
+ title="<?= htmlReady(sprintf(_('Aktivieren des automatischen Nachrückens aus der Warteliste für %s'), $course->name)) ?>"
+ <? if (!$course->admission_disable_waitlist_move) echo 'checked'; ?>>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+<div>
+ <?=_("Anzahl aller Teilnehmenden:")?> <?=$count_distinct_members?>
+ <? if ($count_distinct_members) : ?>
+ <a href="<?= $controller->link_for('admission/courseset/configure_courses/' . $set_id .'/download_all_members')?>" title="<?= _("Download")?>">
+ <?= Icon::create('file-office', 'clickable')->asImg()?>
+ </a>
+ <? endif ?>
+</div>
+<div>
+ <?=_("Mehrfachteilnahmen:")?> <?=$count_multi_members?>
+ <? if ($count_multi_members) : ?>
+ <a href="<?= $controller->link_for('admission/courseset/configure_courses/' . $set_id .'/download_multi_members')?>" title="<?= _("Download")?>">
+ <?= Icon::create('file-office', 'clickable')->asImg()?>
+ </a>
+ <? endif ?>
+</div>
+<div data-dialog-button>
+ <?= Studip\Button::create(_("Speichern"), 'configure_courses_save') ?>
+ <?= Studip\LinkButton::create(_("Download"), $controller->url_for('admission/courseset/configure_courses/' . $set_id .'/csv')) ?>
+</div>
+<?= CSRFProtection::tokenTag()?>
+</form>
+<?
diff --git a/app/views/admission/courseset/delete.php b/app/views/admission/courseset/delete.php
new file mode 100644
index 0000000..26cb7aa
--- /dev/null
+++ b/app/views/admission/courseset/delete.php
@@ -0,0 +1,7 @@
+<?= (string) QuestionBox::create(
+ sprintf(_('Sind Sie sicher, dass das Anmeldeset "%s" ' .
+ 'gelöscht werden soll? Damit werden alle Regeln zur Anmeldung zu den ' .
+ 'verknüpften Veranstaltungen aufgehoben.'), htmlReady($courseset->getName())),
+ $controller->deleteURL($courseset->getId(), ['really' => true]),
+ $controller->deleteURL($courseset->getId(), ['cancel' => true])
+) ?>
diff --git a/app/views/admission/courseset/factored_users.php b/app/views/admission/courseset/factored_users.php
new file mode 100644
index 0000000..a46760e
--- /dev/null
+++ b/app/views/admission/courseset/factored_users.php
@@ -0,0 +1,18 @@
+<table class="default">
+ <thead>
+ <tr>
+ <th><?= _("Name")?></th>
+ <th><?= _("Faktor")?></th>
+ <th><?= _("Angemeldet")?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($users as $user) : ?>
+ <tr>
+ <td><?= htmlReady($user['nachname'] . ', ' . $user['vorname'] . ' (' . $user['username'] . ')')?></td>
+ <td><?= $user['factor'] == PHP_INT_MAX ? _('maximal') : htmlReady($user['factor'])?></td>
+ <td><?= $user['applicant'] ? _("Ja") : _("Nein")?></td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/admission/courseset/index.php b/app/views/admission/courseset/index.php
new file mode 100644
index 0000000..f0f56b7
--- /dev/null
+++ b/app/views/admission/courseset/index.php
@@ -0,0 +1,102 @@
+<?php
+
+Helpbar::get()->addPlainText(_('Info'),_("Anmeldesets legen fest, wer sich zu den zugeordneten Veranstaltungen anmelden darf."));
+Helpbar::get()->addPlainText(_('Info'),_("Hier sehen Sie alle Anmeldesets, auf die Sie Zugriff haben."));
+
+?>
+<?= $this->render_partial('dialog/confirm_dialog') ?>
+<?= $this->render_partial('admission/courseset/_institute_choose.php') ?>
+<?php
+if ($coursesets) {
+?>
+<form action="<?= $controller->link_for('admission/courseset/bulk') ?>" method="post">
+ <table class="default nohover sortable-table" id="courseset-list">
+ <colgroup>
+ <col style="width: 24px">
+ <col>
+ <col style="width: 25%">
+ <col style="width: 5%">
+ <col style="width: 5%">
+ <col style="width: 10%">
+ <col style="width: 100px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th data-sort="false">
+ <input type="checkbox"
+ data-proxyfor="#courseset-list tbody :checkbox"
+ data-activates="#courseset-list tfoot .button">
+ </th>
+ <th data-sort="text"><?= _('Name des Sets') ?></th>
+ <th data-sort="text"><?= _('Besitzer') ?></th>
+ <th data-sort="htmldata"><?= _('Privat') ?></th>
+ <th data-sort="numeric"><?= _('Anzahl') ?></th>
+ <th data-sort="htmldata"><?= _('Letzte Änderung') ?></th>
+ <th data-sort="false" class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($coursesets as $courseset) : ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="ids[]" value="<?= htmlReady($courseset->getId()) ?>">
+ </td>
+ <td><?= htmlReady(my_substr($courseset->getName(),0,70)) ?></td>
+ <td><?= htmlReady(get_fullname($courseset->getUserId(), 'no_title_rev')) ?></td>
+ <td data-sort-value="'<?= $courseset->getPrivate() ? 1 : 0 ?>'">
+ <?= $courseset->getPrivate() ? _('Ja') : _('Nein') ?>
+ </td>
+ <td><?= count($courseset->getCourses()) ?></td>
+ <td data-sort-value="<?= $courseset->getChdate() ?>">
+ <time datetime="<?= date('Y-m-d H:i:s', $courseset->getChdate()) ?>" title="<?= strftime('%x %X', $courseset->getChdate()) ?>">
+ <?= reltime($courseset->getChdate()) ?>
+ </time>
+ </td>
+ <td class="actions">
+ <a class="load-in-new-row" href="<?= $controller->link_for('', ['course_set_details' => $courseset->getId()]); ?>">
+ <?= Icon::create('info', 'clickable', ['title' => _('Weitere Informationen einblenden')])->asImg() ?>
+ </a>
+ <? if ($courseset->isUserAllowedToEdit($GLOBALS['user']->id)) : ?>
+ <a href="<?= $controller->link_for('admission/courseset/copy/'.$courseset->getId()); ?>">
+ <?= Icon::create('edit+add', 'clickable', ['title' => _('Anmeldeset kopieren')])->asImg(16, ["alt" => _('Anmeldeset kopieren')]); ?>
+ </a>
+ <a href="<?= $controller->link_for('admission/courseset/configure/'.$courseset->getId()); ?>">
+ <?= Icon::create('edit')->asImg(['title' => _('Anmeldeset bearbeiten')]) ?>
+ </a>
+ <a href="<?= $controller->link_for('admission/courseset/delete/'. $courseset->getId(), ['really' => 1]) ?>"
+ data-confirm="<?= sprintf(_('Soll das Anmeldeset %s wirklich gelöscht werden?'), htmlReady($courseset->getName())) ?>">
+ <?= Icon::create('trash')->asImg(['title' => _('Anmeldeset löschen')]) ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+ <? if ($course_set_details == $courseset->getId()) : ?>
+ <tr>
+ <td colspan="7">
+ <?= $courseset->toString() ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="7">
+ <?= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Sollen die markierten Anmeldesets wirklich gelöscht werden?'),
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
+<?php
+} else {
+?>
+<?= MessageBox::info(sprintf(_('Es wurden keine Anmeldesets gefunden. Sie können ein '.
+ 'neues %sAnmeldeset anlegen%s.'), '<a href="'.
+ $controller->url_for('admission/courseset/configure').'">',
+ '</a>')); ?>
+<?php
+}
+?>
diff --git a/app/views/admission/courseset/instcourses.php b/app/views/admission/courseset/instcourses.php
new file mode 100644
index 0000000..447a55e
--- /dev/null
+++ b/app/views/admission/courseset/instcourses.php
@@ -0,0 +1,62 @@
+<table id="courselist" class="default">
+ <thead>
+ <colgroup>
+ <col width="15">
+ <col width="75">
+ <col>
+ </colgroup>
+ <tr>
+ <th>
+ <input type="checkbox" data-proxyfor="[name^=courses]">
+ </th>
+ <th colspan="2">
+ <?= _('Veranstaltungszuordnung:') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if(!empty($allCourses)) : ?>
+ <?foreach ($allCourses as $course) {
+ $title = $course['Name'];
+ $title .= (!$course['visible'] ? ' (' . _("versteckt") . ')' : '');
+ $title .= " (" . (int)$course['admission_turnout'] . ")";
+ if (in_array($course['seminar_id'], $selectedCourses)) {
+ $selected = ' checked="checked"';
+ } else {
+ $selected = '';
+ }
+ ?>
+ <tr class="course">
+ <td>
+ <input type="checkbox" name="courses[]" id="<?= $course['seminar_id'] ?>" value="<?= $course['seminar_id'] ?>"<?= $selected ?>>
+ </td>
+ <td>
+ <label for="<?= $course['seminar_id'] ?>">
+ <?= htmlReady($course['VeranstaltungsNummer']) ?>
+ </label>
+ </td>
+ <td>
+ <label for="<?= $course['seminar_id'] ?>">
+ <a href="<?=URLHelper::getScriptLink('dispatch.php/course/details/index/' . $course['seminar_id']) ?>" data-dialog>
+ <?= Icon::create(
+ 'info-circle',
+ Icon::ROLE_INACTIVE,
+ ['title' =>_('Veranstaltungsdetails anzeigen')]
+ )?>
+ </a>
+ <?= htmlReady($title) ?>
+ <? if ($course['admission_type']) : ?>
+ <? $typename = call_user_func($course['admission_type'] . '::getName') ?>
+ <?= Icon::create(
+ 'exclaim-circle',
+ Icon::ROLE_ATTENTION,
+ ['title' => sprintf(_("vorhandene Anmelderegel: %s"), $typename)])
+ ?>
+ <? endif ?>
+ </label>
+ </td>
+ </tr>
+ <?php } ?>
+ <? endif?>
+ </tbody>
+</table>
diff --git a/app/views/admission/courseset/institutes.php b/app/views/admission/courseset/institutes.php
new file mode 100644
index 0000000..865e61e
--- /dev/null
+++ b/app/views/admission/courseset/institutes.php
@@ -0,0 +1,17 @@
+<?= Icon::create('arr_2down', 'sort', ['title' => _('Einrichtung hinzufügen')])->asImg(16, ["alt" => _('Einrichtung hinzufügen'), "onclick" => "STUDIP.Admission.updateInstitutes($('input[name=\"institute_id\"]').val(), '".$controller->url_for('admission/courseset/institutes',$courseset?$courseset->getId():'')."', '".$controller->url_for('admission/courseset/instcourses',$courseset?$courseset->getId():'')."', 'add')"]) ?>
+<?= $instSearch ?>
+<?= Icon::create('search', 'clickable', ['title' => _("Suche starten")])->asImg()?>
+
+<ul>
+ <?php foreach (SimpleCollection::createFromArray($selectedInstitutes)->orderBy('Name') as $institute => $data) { ?>
+ <li id="<?= $institute ?>">
+ <input type="hidden" name="institutes[]" value="<?= $institute ?>" class="institute">
+ <span class="hover_box">
+ <?= htmlReady($data['Name']) ?>
+ <span class="action_icons">
+ <?= Icon::create('trash', 'clickable', ['title' => _('Einrichtung entfernen')])->asImg(16, ["onclick" => "STUDIP.Admission.updateInstitutes('".$institute."', '".$controller->url_for('admission/courseset/institutes',$institute)."', '".$controller->url_for('admission/courseset/instcourses',$institute)."', 'delete')"]); ?>
+ </span>
+ </span>
+ </li>
+ <?php } ?>
+</ul> \ No newline at end of file
diff --git a/app/views/admission/restricted_courses/_institute_choose.php b/app/views/admission/restricted_courses/_institute_choose.php
new file mode 100644
index 0000000..9c53d5f
--- /dev/null
+++ b/app/views/admission/restricted_courses/_institute_choose.php
@@ -0,0 +1,39 @@
+<form action="?" method="post" name="institute_choose" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Anmeldesets auflisten') ?></legend>
+
+ <label>
+ <?=_("Einrichtung:")?>
+ <select name="choose_institut_id" class="nested-select">
+ <? while (list($institut_id,$institute) = each($my_inst)) : ?>
+ <option value="<?= $institut_id?>" <?=($current_institut_id == $institut_id ? 'selected' : '')?> class="<?= $institute['is_fak'] ? 'nested-item-header' : 'nested-item' ?>">
+ <?= htmlReady(my_substr($institute["name"] . ' (' . $institute["num_sem"] . ')',0,100));?>
+ </option>
+ <? if ($institute["is_fak"] == 'all') : ?>
+ <? $num_inst = $institute["num_inst"]; for ($i = 0; $i < $num_inst; ++$i) : ?>
+ <? list($institut_id,$institute) = each($my_inst);?>
+ <option value="<?= $institut_id?>" <?=($current_institut_id == $institut_id ? 'selected' : '')?> class="nested-item">
+ <?= htmlReady(my_substr($institute["name"] . ' (' . $institute["num_sem"] . ')',0,100));?>
+ </option>
+ <? endfor ?>
+ <? endif ?>
+ <? endwhile ?>
+ </select>
+ </label>
+
+ <label>
+ <?=_("Präfix des Veranstaltungsnamens / Nummer:")?>
+ <input type="text" name="sem_name_prefix" value="<?=htmlReady($sem_name_prefix)?>" size="40">
+ </label>
+
+ <label>
+ <?=_("Veranstaltungen aus diesem Semester:")?>
+ <?= Semester::getSemesterSelector(['name'=>'select_semester_id'], $current_semester_id, 'semester_id', false)?>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::create(_('Auswählen'), 'choose_institut', ['title' => _("Einrichtung auswählen")]) ?>
+ </footer>
+</form>
diff --git a/app/views/admission/restricted_courses/index.php b/app/views/admission/restricted_courses/index.php
new file mode 100644
index 0000000..096e825
--- /dev/null
+++ b/app/views/admission/restricted_courses/index.php
@@ -0,0 +1,49 @@
+<?= $this->render_partial('admission/restricted_courses/_institute_choose.php')?>
+<br>
+<? if (count($courses)) : ?>
+ <table class="default nohover sortable-table">
+ <thead>
+ <tr>
+ <th data-sort="text"><?= _('Anmeldeset') ?></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="digit"><?= _('max. Teilnehmende') ?></th>
+ <th data-sort="digit"><?= _('Teilnehmer aktuell') ?></th>
+ <th data-sort="htmldata"><?= _('Anmeldungen') ?></th>
+ <th data-sort="htmldata"><?= _('Warteliste') ?></th>
+ <th data-sort="htmldata"><?= _('Platzverteilung') ?></th>
+ <th data-sort="htmldata"><?= _('Startzeitpunkt') ?></th>
+ <th data-sort="htmldata"><?= _('Endzeitpunkt') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($courses as $course) : ?>
+ <tr>
+ <td><a href="<?= URLHelper::getLink('dispatch.php/admission/courseset/configure/' . $course['set_id'])?>"><?= htmlReady($course['cs_name'])?></td>
+ <td><a href="<?= URLHelper::getLink('dispatch.php/course/members/index', ['cid' => $course['seminar_id']])?>"><?= htmlReady(($course['course_number'] ? $course['course_number'] .'|' : '') . $course['course_name'])?></a></td>
+ <td><?= htmlReady($course['admission_turnout'])?></td>
+ <td>
+ <?= htmlReady($course['count_teilnehmer'] + $course['count_prelim'])?>
+ <? if ($course['admission_prelim'] && $course['count_prelim']) : ?>
+ <?= tooltipIcon(_('vorläufige Teilnahme: ') . $course['count_prelim']) ?>
+ <? endif ?>
+ </td>
+ <td data-value="<?= $course['count_claiming'] ?: 0 ?>">
+ <?= htmlReady(isset($course['count_claiming']) ? $course['count_claiming'] : '-') ?>
+ </td>
+ <td data-sort-value="<?= $course['count_waiting'] ?: 0 ?>">
+ <?= htmlReady(isset($course['count_waiting']) ? $course['count_waiting'] : '-') ?>
+ </td>
+ <td style="white-space:nowrap" data-sort-value="<?= (int) $course['distribution_time']?>">
+ <?= htmlReady($course['distribution_time'] ? strftime('%x %R', $course['distribution_time']) : '-') ?>
+ </td>
+ <td style="white-space:nowrap" data-sort-value="<?= (int) $course['start_time']?>">
+ <?= htmlReady($course['start_time'] ? strftime('%x %R', $course['start_time']) : '-') ?>
+ </td>
+ <td style="white-space:nowrap" data-sort-value="<?= (int) $course['end_time']?>">
+ <?= htmlReady($course['end_time'] ? strftime('%x %R', $course['end_time']) : '-') ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? endif ?>
diff --git a/app/views/admission/rule/configure.php b/app/views/admission/rule/configure.php
new file mode 100644
index 0000000..17914da
--- /dev/null
+++ b/app/views/admission/rule/configure.php
@@ -0,0 +1,14 @@
+<?php
+use Studip\Button, Studip\LinkButton;
+?>
+<div id="errormessage"></div>
+<form action="<?= $controller->url_for('admission/rule/save', get_class($rule), $rule->getId()) ?>"
+ id="ruleform" class="default"
+ onsubmit="return STUDIP.Admission.checkAndSaveRule('<?= $rule->getId() ?>', 'errormessage', '<?= $controller->url_for('admission/rule/validate', get_class($rule)) ?>', 'rules', '<?= $controller->url_for('admission/rule/save', get_class($rule), $rule->getId()) ?>')">
+ <?= $ruleTemplate ?>
+ <footer data-dialog-button>
+ <input type="hidden" id="action" name="action" value="">
+ <?= Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), 'cancel') ?>
+ </footer>
+</form>
diff --git a/app/views/admission/rule/save.php b/app/views/admission/rule/save.php
new file mode 100644
index 0000000..16a5f78
--- /dev/null
+++ b/app/views/admission/rule/save.php
@@ -0,0 +1,16 @@
+<div class="hover_box admissionrule" id="rule_<?= $rule->getId() ?>">
+ <span id="rule_data_<?= $rule->getId() ?>">
+ <?= $rule->toString() ?>
+ <input type="hidden" name="rules[]" value="<?= htmlReady(ObjectBuilder::exportAsJson($rule)) ?>"/>
+ </span>
+ <span class="action_icons" id="rule_actions_<?= $rule->getId() ?>">
+ <a href="#" onclick="return STUDIP.Admission.configureRule('<?= get_class($rule) ?>', '<?=
+ $controller->url_for('admission/rule/configure', get_class($rule), $rule->getId()) ?>', '<?=
+ $rule->getId() ?>')">
+ <?= Icon::create('edit', 'clickable')->asImg(); ?></a>
+ <a href="#" onclick="return STUDIP.Dialogs.showConfirmDialog('<?=
+ _('Soll die Anmelderegel wirklich gelöscht werden?') ?>',
+ 'javascript:STUDIP.Admission.removeRule(\'rule_<?= $rule->getId() ?>\', \'rules\')')">
+ <?= Icon::create('trash', 'clickable')->asImg(); ?></a>
+ </span>
+</div>
diff --git a/app/views/admission/rule/select_type.php b/app/views/admission/rule/select_type.php
new file mode 100644
index 0000000..4bd75e3
--- /dev/null
+++ b/app/views/admission/rule/select_type.php
@@ -0,0 +1,30 @@
+<form name="select_rule_type" class="default" action="<?= $controller->url_for('admission/rule/configure') ?>" method="post">
+ <fieldset>
+ <legend><?= _('Anmelderegel konfigurieren') ?></legend>
+ <?php
+ use Studip\Button, Studip\LinkButton;
+
+ foreach ($ruleTypes as $className => $classDetail) {
+ $disabled = $courseset && !$courseset->isAdmissionRuleAllowed($className) ? 'disabled' : '';
+ ?>
+ <section id="<?= $className ?>">
+ <label>
+ <input <?=$disabled ?> type="radio" name="ruletype" value="<?= $className ?>"/>
+ <span <?=($disabled ? 'style="text-decoration:line-through"' : '')?>><?=$classDetail['name'] ?></span>
+ <?= Icon::create('question-circle', 'clickable', ['title' => $classDetail['description']])->asImg() ?>
+ </label>
+ </section>
+
+ <?php
+ }
+ ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= Button::create(_('Weiter >>'), 'configure', [
+ 'onclick' => "return $('input[name=ruletype]:checked').val() ? STUDIP.Admission.configureRule($('input[name=ruletype]:checked').val(), '".
+ $controller->url_for('admission/rule/configure')."') : false"]) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admission/courseset/configure'), ['onclick' => "STUDIP.Admission.closeDialog('configurerule'); return false;"]) ?>
+ </footer>
+</form>
diff --git a/app/views/admission/rule/validate.php b/app/views/admission/rule/validate.php
new file mode 100644
index 0000000..58ac715
--- /dev/null
+++ b/app/views/admission/rule/validate.php
@@ -0,0 +1,5 @@
+<?php
+if ($errors) {
+ echo MessageBox::error(_('Fehler:'), $errors);
+}
+?> \ No newline at end of file
diff --git a/app/views/admission/rule_administration/check_activation.php b/app/views/admission/rule_administration/check_activation.php
new file mode 100644
index 0000000..10a7b98
--- /dev/null
+++ b/app/views/admission/rule_administration/check_activation.php
@@ -0,0 +1,100 @@
+<?php
+use Studip\Button, Studip\LinkButton;
+
+?>
+<form class="default" id="rule_activation_form"
+ action="<?= $controller->url_for('admission/ruleadministration/activate/' . $type) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Verfügbarkeit der Anmelderegel') ?></legend>
+
+ <label class="caption">
+ <input type="checkbox" name="enabled"
+ onclick="STUDIP.Admission.checkRuleActivation('rule_activation_form')"<?= $ruleTypes[$type]['active'] ? ' checked="checked"' : '' ?>/>&nbsp;<?= _('Regel ist aktiv') ?>
+ </label>
+
+ <section>
+ <?= _('Regel ist verfügbar') ?>
+ </section>
+
+ <label>
+ <input type="radio" name="activated" value="studip"
+ onclick="STUDIP.Admission.checkRuleActivation('rule_activation_form')"<?= $globally ? ' checked="checked"' : '' ?>>
+ <?= _('systemweit') ?>
+ </label>
+ <label>
+ <input type="radio" name="activated" value="inst"
+ onclick="STUDIP.Admission.checkRuleActivation('rule_activation_form')"<?= $atInst ? ' checked="checked"' : '' ?>>
+ <?= _('an ausgewählten Einrichtungen') ?>
+ </label>
+
+ <div id="institutes_activation"<?= $globally ? ' style="display:none"' : '' ?>>
+ <ul>
+ <?php foreach (Institute::findBySQL("`fakultaets_id`=`Institut_id`") as $fak) { ?>
+ <li id="<?= $fak->Institut_id ?>">
+ <input type="checkbox" name="institutes[]"
+ value="<?= $fak->Institut_id ?>"<?= $activated[$fak->Institut_id] ? ' checked="checked"' : '' ?>>
+ <a href="">
+ <?= htmlReady($fak->name) ?>
+ </a>
+ <?php if ($fak->sub_institutes) { ?>
+ <ul>
+ <?php
+ foreach ($fak->sub_institutes as $inst) {
+ if ($inst->Institut_id != $fak->Institut_id) {
+ ?>
+ <li id="<?= $inst->Institut_id ?>">
+ <input type="checkbox" name="institutes[]"
+ value="<?= $inst->Institut_id ?>"<?= $activated[$inst->Institut_id] ? ' checked="checked"' : '' ?>>
+ <a href="">
+ <?= htmlReady($inst->name) ?>
+ </a>
+ </li>
+ <?php
+ }
+ }
+ ?>
+ </ul>
+ <?php } ?>
+ </li>
+ <?php } ?>
+ </ul>
+ <script type="text/javascript">
+ //<!--
+ $(function () {
+ $('#institutes_activation').bind('loaded.jstree', function (event, data) {
+ // Show checked checkboxes.
+ var checkedItems = $('#institutes_activation').find('.jstree-checked');
+ checkedItems.removeClass('jstree-unchecked');
+ // Open parent nodes of checked nodes.
+ checkedItems.parents().each(function () {
+ data.inst.open_node(this, false, true);
+ });
+ }).bind('select_node.jstree', function (event, data) {
+ return data.inst.toggle_node(data.rslt.obj);
+ }).jstree({
+ 'core': {
+ 'animation': 100,
+ 'open_parents': true
+ },
+ 'checkbox': {
+ 'real_checkboxes': true,
+ 'selected_parent_open': true,
+ 'override_ui': false
+ },
+ 'themes': {
+ 'icons': false
+ },
+ 'plugins': ['html_data', 'themes', 'checkbox', 'ui']
+ });
+ });
+ //-->
+ </script>
+ </div>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), '', ['rel' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/admission/rule_administration/compatibility.php b/app/views/admission/rule_administration/compatibility.php
new file mode 100644
index 0000000..2dc8aa4
--- /dev/null
+++ b/app/views/admission/rule_administration/compatibility.php
@@ -0,0 +1,55 @@
+<form class="default" action="<?= $controller->url_for('admission/ruleadministration/save_compat') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= _('Welche Anmelderegeln sind wie miteinander kombinierbar?') ?>
+ </caption>
+ <colgroup>
+ <col width="15%">
+ <?php foreach ($ruletypes as $data) : ?>
+ <col width="<?= floor(85 / count($ruletypes)) ?>%">
+ <?php endforeach ?>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>&nbsp;</th>
+ <th colspan="<?= count($ruletypes) + 1 ?>">
+ <?= _('ist kompatibel mit') ?>
+ </th>
+ </tr>
+ <tr>
+ <th><?= _('Regeltyp') ?></th>
+ <?php foreach ($ruletypes as $class => $type) : ?>
+ <th>
+ <?= htmlReady($type['name']) ?>
+ </th>
+ <?php endforeach ?>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($ruletypes as $class => $type) : ?>
+ <tr>
+ <td>
+ <?= htmlReady($type['name']) ?>
+ </td>
+ <?php foreach ($ruletypes as $compat_class => $compat_type) : ?>
+ <td>
+ <input type="checkbox" name="compat[<?= $class ?>][]"
+ value="<?= $compat_class ?>"<?=
+ in_array($compat_class, $matrix[$class] ?: []) ? ' checked' : ''?>>
+ </td>
+ <?php endforeach ?>
+ </tr>
+ <?php endforeach ?>
+ </tbody>
+
+ <tfoot>
+ <tr>
+ <td colspan="<?= count($ruletypes) + 2 ?>">
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+
+</form>
diff --git a/app/views/admission/rule_administration/index.php b/app/views/admission/rule_administration/index.php
new file mode 100644
index 0000000..ce50d3e
--- /dev/null
+++ b/app/views/admission/rule_administration/index.php
@@ -0,0 +1,54 @@
+<?php
+if (isset($flash['error'])) {
+ echo MessageBox::error($flash['error'], $flash['error_detail']);
+} elseif (isset($flash['success'])) {
+ echo MessageBox::success($flash['success']);
+}
+// New rules found in file system that are not yet installed.
+if ($newRules) {
+ echo MessageBox::info(_('Es wurden Anmelderegeln gefunden, die zwar im' .
+ 'Dateisystem unter lib/admissionrules vorhanden sind, aber noch nicht ' .
+ 'installiert wurden:'), $newRules);
+}
+?>
+
+<?php
+if ($ruleTypes) : ?>
+ <table class="default" id="admissionrules">
+ <caption><?= _('Installierte Anmelderegeln:') ?></caption>
+ <thead>
+ <th><?= _('aktiv?') ?></th>
+ <th><?= _('Art der Anmelderegel') ?></th>
+ </thead>
+ <tbody>
+ <?php
+ foreach ($ruleTypes as $type => $details) {
+ if ($details['active']) {
+ $text = _('Diese Regel ist aktiv. Klicken Sie hier, um die Einstellungen zu bearbeiten.');
+ $img = 'checkbox-checked';
+ } else {
+ $text = _('Diese Regel ist inaktiv. Klicken Sie hier, um die Einstellungen zu bearbeiten.');
+ $img = 'checkbox-unchecked';
+ }
+ ?>
+ <tr id="ruletype_<?= $type ?>">
+ <td>
+ <a href="<?= $controller->url_for('admission/ruleadministration/check_activation', $type) ?>"
+ data-dialog>
+ <?= Icon::create($img, 'clickable', ['title' => $text])->asImg() ?>
+ </a>
+ </td>
+ <td>
+ <b><?= htmlReady($details['name']) ?></b> (<?= $type ?>)
+ <br/>
+ <?= htmlReady($details['description']) ?>
+ </td>
+ </tr>
+ <?php } ?>
+ </tbody>
+ </table>
+
+<? else : ?>
+
+ <?= MessageBox::info(sprintf(_('Sie haben noch keine Anmelderegeln installiert!'))); ?>
+<?php endif ?> \ No newline at end of file
diff --git a/app/views/admission/user_list/configure.php b/app/views/admission/user_list/configure.php
new file mode 100644
index 0000000..391e758
--- /dev/null
+++ b/app/views/admission/user_list/configure.php
@@ -0,0 +1,103 @@
+<?php
+use Studip\Button, Studip\LinkButton;
+
+Helpbar::get()->addPlainText(_('Info'), "Personenlisten dienen dazu, um Sonderfälle erfassen zu ".
+ "können, die in Anmeldeverfahren gesondert behandelt ".
+ "werden sollen (Härtefälle etc.).");
+Helpbar::get()->addPlainText(_('Info'), "Stellen Sie hier ein, wie die Chancen bei der ".
+ "Platzverteilung verändert werden sollen. Ein Wert ".
+ "von 1 bedeutet normale Verteilung, ein Wert kleiner ".
+ "als 1 führt zur Benachteiligung, mit einem Wert ".
+ "größer als 1 werden die betreffenden Personen ".
+ "bevorzugt.");
+?>
+<?= $this->render_partial('dialog/confirm_dialog') ?>
+<?= $error ? $error : '' ?>
+<form class="default" action="<?= $controller->url_for('admission/userlist/save', $userlist_id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= ($userlist_id) ? _('Personenliste bearbeiten') : _('Personenliste anlegen') ?>
+ </legend>
+ <label>
+ <span class="required">
+ <?= _('Name der Personenliste') ?>
+ </span>
+ <input type="text" size="60" maxlength="255" name="name" value="<?= $userlist ? htmlReady($userlist->getName()) : '' ?>" required>
+ </label>
+ <br/>
+ <label for="factor">
+ <?= _('Wie sollen die Personen auf dieser Liste bei der Platzverteilung berücksichtigt werden?') ?>
+ </label>
+ <label for="factor-0">
+ <input type="radio" name="factor" id="factor-0" value="0"<?= $userlist->getFactor() == 0 ? ' checked' : '' ?>>
+ <?= _('Nachrangig (nach allen anderen Personen in der Platzvergabe)') ?>
+ </label>
+ <label for="factor-max">
+ <input type="radio" name="factor" id="factor-max"
+ value="<?= (float) PHP_INT_MAX ?>"<?= $userlist->getFactor() == PHP_INT_MAX ? ' checked' : '' ?>>
+ <?= _('Bevorzugt (erhalten zuerst einen Platz)') ?>
+ </label>
+ <table class="default">
+ <caption>
+ <?= _('Personen') ?>
+ <span class="actions">
+ <?= MultiPersonSearch::get('add_userlist_member_' . $userlist_id)
+ ->setTitle(_('Personen zur Liste hinzufügen'))
+ ->setSearchObject($userSearch)
+ ->setDefaultSelectedUser(array_map(function ($u) { return $u->id; }, $users))
+ ->setDataDialogStatus(Request::isXhr())
+ ->setJSFunctionOnSubmit(Request::isXhr() ? 'jQuery(this).closest(".ui-dialog-content").dialog("close");' : false)
+ ->setExecuteURL($controller->url_for('admission/userlist/add_members', $userlist_id))
+ ->render() ?>
+ </span>
+ </caption>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($users) === 0): ?>
+ <tr>
+ <td colspan="3">
+ <?= _('Niemand ist in die Liste eingetragen.') ?>
+ </td>
+ </tr>
+ <? else: $i = 1; ?>
+ <? foreach ($users as $u) : ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $u->username) ?>">
+ <?= Avatar::getAvatar($u->id, $u->username)->getImageTag(Avatar::SMALL) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $u->username) ?>">
+ <?= $u->getFullname('full_rev') . ' (' . $u->username . ')' ?>
+ </a>
+ <input type="hidden" name="users[]" value="<?= $u->id ?>"/>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->url_for('admission/userlist/delete_member',
+ $userlist_id, $u->id) ?>" class="userlist-delete-user"
+ data-confirm="<?= sprintf(_('Soll %s wirklich von der Liste entfernt werden?'),
+ htmlReady($u->getFullname())) ?>">
+ <?= Icon::create('trash', 'clickable') ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+ </tbody>
+ </table>
+ </fieldset>
+
+ <footer>
+ <?= Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admission/userlist')) ?>
+ </footer>
+</form>
diff --git a/app/views/admission/user_list/delete.php b/app/views/admission/user_list/delete.php
new file mode 100644
index 0000000..383ceda
--- /dev/null
+++ b/app/views/admission/user_list/delete.php
@@ -0,0 +1,9 @@
+<?= QuestionBox::create(
+ sprintf(
+ _('Soll die Nutzerliste %s wirklich gelöscht werden?'),
+ htmlReady($list->getName())
+ ),
+ $controller->deleteURL($userlist->getId(), ['really' => true]),
+ $controller->deleteURL($userlist->getId(), ['cancel' => true])
+)
+?>
diff --git a/app/views/admission/user_list/index.php b/app/views/admission/user_list/index.php
new file mode 100644
index 0000000..30e3f7a
--- /dev/null
+++ b/app/views/admission/user_list/index.php
@@ -0,0 +1,49 @@
+<?php
+Helpbar::get()->addPlainText(_('Info'),"Personenlisten erfassen eine Menge von Personen, die ".
+ "mit modifizierten Chancen in die Platzverteilung bei ".
+ "Anmeldeverfahren eingehen. Dies können z.B. ".
+ "Härtefälle sein, die bevorzugt einen Platz in ".
+ "Veranstaltungen erhalten sollen.");
+Helpbar::get()->addPlainText(_('Info'), "Hier sehen Sie alle Personenlisten, auf die Sie Zugriff ".
+ "haben.");
+?>
+<?= $this->render_partial('dialog/confirm_dialog') ?>
+
+<?php
+if ($userlists) {
+?>
+<div id="userlists">
+ <?php foreach ($userlists as $list) { ?>
+ <div id="userlist_<?= $list->getId() ?>">
+ <a href="#" onclick="return STUDIP.Admission.toggleDetails('userlist_arrow_<?= $list->getId() ?>', 'userlist_details_<?= $list->getId() ?>')">
+ <?= Icon::create('arr_1right', 'clickable')->asImg(20, ["id" => 'userlist_arrow_'.$list->getId(), "align" => 'top', "rel" => Icon::create('arr_1down', 'clickable')->asImagePath(20)]) ?>
+ <?= htmlReady($list->getName()) ?>
+ </a>
+ <a class="userlist-action"
+ href="<?= URLHelper::getURL('dispatch.php/admission/userlist/configure/'.$list->getId()); ?>">
+ <?= Icon::create('edit', 'clickable', ['title' => _('Nutzerliste bearbeiten')])->asImg(20, ["alt" => _('Nutzerliste bearbeiten')]); ?>
+ </a>
+ <a class="userlist-action" href="<?= $controller->url_for('admission/userlist/delete',
+ $list->getId()) ?>"
+ onclick="return STUDIP.Dialogs.showConfirmDialog('<?=
+ sprintf(_('Soll die Nutzerliste %s wirklich gelöscht werden?'), htmlReady($list->getName())) ?>', '<?=
+ URLHelper::getURL('dispatch.php/admission/userlist/delete/'.
+ $list->getId(), ['really' => 1]) ?>')">
+ <?= Icon::create('trash', 'clickable', ['title' => _('Personenliste löschen')])->asImg(20) ?>
+ </a>
+ </div>
+ <div id="userlist_details_<?= $list->getId() ?>" style="display: none; margin-left: 20px;">
+ <?= $list->toString() ?>
+ </div>
+ <?php } ?>
+</div>
+<?php
+} else {
+?>
+<?= MessageBox::info(sprintf(_('Es wurden keine Personenlisten gefunden. Sie können eine '.
+ 'neue %sPersonenliste anlegen%s.'), '<a href="'.
+ $controller->url_for('admission/userlist/configure').'">',
+ '</a>')); ?>
+<?php
+}
+?>
diff --git a/app/views/api/authorizations/index.php b/app/views/api/authorizations/index.php
new file mode 100644
index 0000000..1b07dad
--- /dev/null
+++ b/app/views/api/authorizations/index.php
@@ -0,0 +1,44 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<? if (empty($consumers)): ?>
+<?= MessageBox::info(_('Sie haben noch keinen Apps Zugriff auf Ihren Account gewährt.')) ?>
+<? else: ?>
+<table class="oauth-apps default">
+ <caption><?= _('Applikationen') ?></caption>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th>&nbsp;</th>
+ </thead>
+ <tbody>
+ <? foreach ($consumers as $consumer): ?>
+ <tr>
+ <td>
+ <h3>
+ <? if ($consumer->url): ?>
+ <a href="<?= htmlReady($consumer->url) ?>" target="_blank" rel="noopener noreferrer">
+ <?= htmlReady($consumer->title) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($consumer->title) ?>
+ <? endif; ?>
+ <? if ($type = $types[$consumer->type]): ?>
+ <small>(<?= htmlReady($type) ?>)</small>
+ <? endif; ?>
+ </h3>
+ <? if ($consumer->description): ?>
+ <p><?= htmlReady($consumer->description) ?></p>
+ <? endif; ?>
+ </td>
+ <td class="actions">
+ <?= LinkButton::createCancel(
+ _('App entfernen'),
+ $controller->url_for('api/authorizations/revoke', $consumer->id),
+ ['data-confirm' => _('Wollen Sie der App wirklich den Zugriff auf Ihre Daten untersagen?')]
+ ) ?>
+ </td>
+ </tr>
+<? endforeach; ?>
+ </tbody>
+</table>
+<? endif; ?>
diff --git a/app/views/api/oauth/authorize.php b/app/views/api/oauth/authorize.php
new file mode 100644
index 0000000..8330e9f
--- /dev/null
+++ b/app/views/api/oauth/authorize.php
@@ -0,0 +1,33 @@
+<section class="oauth authorize">
+ <p>
+ <?= sprintf(
+ _('Die Applikation <strong>%s</strong> möchte auf Ihre Daten zugreifen.'),
+ htmlReady($consumer->title)
+ ) ?>
+ </p>
+
+ <form action="<?= $controller->url_for('api/oauth/authorize?oauth_token=' . $token) ?>" method="post">
+ <input type="hidden" name="oauth_callback" value="<?= htmlReady($oauth_callback) ?>">
+ <p>
+ <?= Studip\Button::createAccept(_('Erlauben'), 'allow') ?>
+ <?= Studip\LinkButton::createCancel(_('Verweigern'), $consumer->callback) ?>
+ </p>
+ </form>
+
+ <p>
+ <?= Avatar::getAvatar($GLOBALS['user']->id)->getImageTag(Avatar::SMALL) ?>
+
+ <?= sprintf(
+ _('Angemeldet als <strong>%s</strong> (%s)'),
+ htmlReady($GLOBALS['user']->getFullName()),
+ htmlReady($GLOBALS['user']->username)
+ ) ?><br>
+ <small>
+ <?= sprintf(
+ _('Sind sie nicht <strong>%s</strong>, so <a href="%s">melden Sie sich bitte ab</a> und versuchen es erneut.'),
+ htmlReady($GLOBALS['user']->getFullName()),
+ URLHelper::getLink('logout.php')
+ ) ?>
+ </small>
+ </p>
+</section>
diff --git a/app/views/api/oauth/authorized.php b/app/views/api/oauth/authorized.php
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/views/api/oauth/authorized.php
diff --git a/app/views/archive/forum.php b/app/views/archive/forum.php
new file mode 100644
index 0000000..103f010
--- /dev/null
+++ b/app/views/archive/forum.php
@@ -0,0 +1,5 @@
+<? if ($course) : ?>
+ <?= $course->forumdump ?>
+<? else : ?>
+ <?= MessageBox::error(_('Es wurde keine Veranstaltung ausgewählt!')) ?>
+<? endif ?>
diff --git a/app/views/archive/overview.php b/app/views/archive/overview.php
new file mode 100644
index 0000000..b7f4d79
--- /dev/null
+++ b/app/views/archive/overview.php
@@ -0,0 +1,5 @@
+<? if ($course) : ?>
+ <?= $course->dump ?>
+<? else : ?>
+ <?= MessageBox::error(_('Es wurde keine Veranstaltung ausgewählt!')) ?>
+<? endif ?>
diff --git a/app/views/archive/wiki.php b/app/views/archive/wiki.php
new file mode 100644
index 0000000..0cee5b7
--- /dev/null
+++ b/app/views/archive/wiki.php
@@ -0,0 +1,5 @@
+<? if ($course) : ?>
+ <?= $course->wikidump ?>
+<? else : ?>
+ <?= MessageBox::error(_('Es wurde keine Veranstaltung ausgewählt!')) ?>
+<? endif ?>
diff --git a/app/views/avatar/update.php b/app/views/avatar/update.php
new file mode 100644
index 0000000..c5b87c9
--- /dev/null
+++ b/app/views/avatar/update.php
@@ -0,0 +1,65 @@
+<form class="default settings-avatar" enctype="multipart/form-data"
+ action="<?= $controller->url_for('avatar/upload', $type, $id) ?>" method="post">
+ <fieldset>
+ <legend>
+ <?= $type == 'user' ? _('Profilbild bearbeiten und zuschneiden') :
+ ($type == 'course' ? _('Veranstaltungsbild bearbeiten und zuschneiden') :
+ _('Einrichtungsbild bearbeiten und zuschneiden')) ?>
+ </legend>
+ <div class="form-group">
+ <div id="avatar-preview">
+ <img class="avatar-normal" id="new-avatar" src="<?= $avatar ?>"
+ data-message-too-small="<?= _('Das Bild ist kleiner als 250 x 250 Pixel. Wollen Sie wirklich fortfahren?') ?>">
+ </div>
+
+ <label class="file-upload">
+ <?= _('Wählen Sie ein Bild von Ihrer Festplatte aus.') ?>
+ <input type="file" id="avatar-upload" accept="image/gif,image/png,image/jpeg"
+ capture="camera"
+ data-max-size="<?= Avatar::MAX_FILE_SIZE ?>"
+ data-message-too-large="<?= _('Die hochgeladene Datei ist zu groß. Bitte wählen Sie ein anderes Bild.') ?>">
+
+ <p class="form-text">
+ <?= sprintf(
+ _('Die Bilddatei darf max. %s groß sein, es sind nur Dateien mit den Endungen .jpg, .png oder .gif erlaubt!'),
+ relsize(Avatar::MAX_FILE_SIZE)
+ ) ?>
+ </p>
+
+ <a onclick="javascript:void 0" class=button><?= _('Auswählen') ?></a>
+ </label>
+
+ <input type="hidden" name="cropped-image" id="cropped-image" value="">
+
+ <div id="avatar-buttons" class="hidden-js">
+ <a href="" id="avatar-zoom-in" title="<?= _('Vergrößern') ?>">
+ <?= Icon::create('zoom-in')->asImg(24) ?>
+ <?= _('Vergrößern') ?>
+ </a>
+ <a href="" id="avatar-zoom-out" title="<?= _('Verkleinern') ?>">
+ <?= Icon::create('zoom-out')->asImg(24) ?>
+ <?= _('Verkleinern') ?>
+ </a>
+ <a href="" id="avatar-rotate-clockwise" title="<?= _('Nach rechts drehen') ?>">
+ <?= Icon::create('rotate-right')->asImg(24) ?>
+ <?= _('Nach rechts drehen') ?>
+ </a>
+ <a href="" id="avatar-rotate-counter-clockwise" title="<?= _('Nach links drehen') ?>">
+ <?= Icon::create('rotate-left')->asImg(24) ?>
+ <?= _('Nach links drehen') ?>
+ </a>
+ </div>
+ </div>
+ <?= CSRFProtection::tokenTag() ?>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Absenden'), 'upload', ['id' => 'submit-avatar']) ?>
+ <? if ($customized): ?>
+ <?= Studip\LinkButton::create(
+ _('Aktuelles Bild löschen'),
+ $controller->url_for('avatar/delete', $type, $id)
+ ) ?>
+ <? endif ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $cancel_link) ?>
+ </footer>
+</form>
diff --git a/app/views/bb/index.php b/app/views/bb/index.php
new file mode 100644
index 0000000..84c973b
--- /dev/null
+++ b/app/views/bb/index.php
@@ -0,0 +1,39 @@
+<table cellspacing="0" cellpadding="0" border="0" width="100%">
+ <tr>
+ <td class="table_header_bold" colspan=2>
+ <b><?=_("Der geheime Bilderbrowser")?></b>
+ </td>
+ </tr>
+</table>
+
+<br><br>
+<?=_("Unschön dass wir uns hier sehen... diese Seite ist das geheime Easteregg von Stud.IP. Wenn es jemand hierher geschafft hat, der nicht zum Team gehört, dann kündige ich.")?>
+<br><br>
+<i>Cornelis</i><br><br>
+
+<?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->set_attributes([
+ 'perPage' => $entries_per_page,
+ 'num_postings' => $entries,
+ 'page' => $page,
+ 'pagelink' => $controller->url_for('bb/index/%u')
+ ]);
+ echo $pagination->render();
+?>
+<br><br>
+
+<? foreach ($images as $image) : ?>
+ <div style="float: left; width: 250px; border: 1px solid gray; padding: 5px; text-align: center; font-weight: bold; margin: 5px;">
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username='. get_username($image['user_id'])) ?>">
+ <img border="0" src="<?= $GLOBALS['DYNAMIC_CONTENT_URL'] . '/user/' . $image['file'] ?>">
+ <br>
+ <?= get_fullname($image['user_id'], 'full' ,true) ?><br>
+ <?= date('d.m.Y', $image['time']) ?>
+ </a>
+ </div>
+<? endforeach ?>
+
+<br style="clear: both">
+<br>
+<?= $pagination->render() ?>
diff --git a/app/views/blubber/add_member_to_private.php b/app/views/blubber/add_member_to_private.php
new file mode 100644
index 0000000..f18f088
--- /dev/null
+++ b/app/views/blubber/add_member_to_private.php
@@ -0,0 +1,10 @@
+<form action="<?= $controller->add_member_to_private($thread) ?>" method="post" class="default" data-dialog>
+ <label>
+ <?= _('Person suchen') ?>
+ <?= QuickSearch::get('user_id', new StandardSearch('user_id'))->render() ?>
+ </label>
+
+ <div data-dialog-button>
+ <?= Studip\Button::create(_('Hinzufügen')) ?>
+ </div>
+</form>
diff --git a/app/views/blubber/compose.php b/app/views/blubber/compose.php
new file mode 100644
index 0000000..e23487a
--- /dev/null
+++ b/app/views/blubber/compose.php
@@ -0,0 +1,117 @@
+<form class="default" action="<?= $controller->compose($thread ? $thread->getId() : null) ?>" method="post">
+
+ <?= CSRFProtection::tokenTag() ?>
+
+ <div <?= !$thread ? "" : 'style="display: none;"' ?>>
+ <div class="file_select_possibilities">
+
+ <a href="#" onclick="jQuery('.file_select_possibilities').hide(); jQuery('.private_blubber_composer').show(); return false;">
+ <?= Icon::create('group3')->asImg(50) ?>
+ <?= _('Kontakte') ?>
+ </a>
+
+ <a href="<?= $controller->link_for("blubber/index/global") ?>">
+ <?= Icon::create('globe')->asImg(50) ?>
+ <?= _('Öffentlich') ?>
+ </a>
+
+ <? if (!$GLOBALS['perm']->have_perm('admin')) : ?>
+ <a href="#" onclick="jQuery('.file_select_possibilities').hide(); jQuery('.course_blubber_composer').show(); return false;">
+ <?= Icon::create('seminar')->asImg(50) ?>
+ <?= _('Veranstaltung') ?>
+ </a>
+ <? endif ?>
+
+ </div>
+ </div>
+
+ <div class="course_blubber_composer" style="display: none;">
+ <? if (!$GLOBALS['perm']->have_perm("admin")) : ?>
+ <ul class="clean">
+ <? foreach (CourseMember::findBySQL("INNER JOIN seminare USING (Seminar_id) WHERE user_id = ? ORDER BY seminare.name ASC", [$GLOBALS['user']->id]) as $member) : ?>
+ <li>
+ <a href="<?= $controller->to_course($member['seminar_id']) ?>">
+ <?= CourseAvatar::getAvatar($member['seminar_id'])->getImageTag(Avatar::SMALL) ?>
+ <?= htmlReady($member->course['name']) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ </div>
+
+ <div class="private_blubber_composer" style="display: none;">
+ <label for="blubber_contacts">
+ <?= _('Kontakte') ?>
+ </label>
+ <div class="blubber_composer_select_container">
+ <span class="container">
+ <select name="user_ids[]" class="select2" id="blubber_contacts" multiple>
+ <? foreach ($contacts as $contact) : ?>
+ <option value="<?= htmlReady($contact['user_id']) ?>" data-avatar="<?= htmlReady(Avatar::getAvatar($contact['user_id'])->getImageTag(AVATAR::SMALL)) ?>">
+ <?= htmlReady($contact->friend->getFullName()) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </span>
+
+ <a href="" onClick="$('#blubber_contacts').focus().select2('open'); return false;">
+ <?= Icon::create("search", "clickable")->asImg(20, ['class' => "text-bottom"]) ?>
+ </a>
+ <a href="" onClick="$('#blubber_contacts').val(null).trigger('change'); return false;">
+ <?= Icon::create("decline", "clickable")->asImg(20, ['class' => "text-bottom"]) ?>
+ </a>
+ </div>
+
+ <script>
+ jQuery(function ($) {
+ let format = function (state) {
+ if (!state.id) { // optgroup
+ return state.text;
+ }
+ let avatar = $(state.element).data('avatar');
+ let span = $('<span>');
+ span.text(state.text);
+ $(avatar).prependTo(span);
+ return span;
+ };
+ $('#blubber_contacts').select2({
+ width: '100%',
+ templateResult: format,
+ templateSelection: format
+ });
+ STUDIP.Blubber.Composer.init();
+ });
+ </script>
+
+ <div class=".more_persons">
+ <?= _('Weitere Personen') ?>
+
+ <ul class="clean" id="blubber_contact_ids">
+ <li v-for="user in users" :key="user.user_id">
+ <input type="hidden" name="user_ids[]" :value="user.user_id">
+ <span>{{ user.name }}</span>
+ <a href="#" @click.prevent="removeUser">
+ <studip-icon shape="trash" size="20" role="clickable"></studip-icon>
+ </a>
+ </li>
+ </ul>
+ <div class="blubber_composer_select_container">
+ <?= QuickSearch::get('search_user_id', new StandardSearch('user_id'))
+ ->fireJSFunctionOnSelect('STUDIP.Blubber.Composer.vue.addUser')->render() ?>
+
+ <a href="" onClick="$('input[name=search_user_id_parameter]').focus(); return false;">
+ <?= Icon::create("search", "clickable")->asImg(20, ['class' => "text-bottom"]) ?>
+ </a>
+ <a href="" onClick="STUDIP.Blubber.Composer.vue.clearUsers(); return false;">
+ <?= Icon::create("decline", "clickable")->asImg(20, ['class' => "text-bottom"]) ?>
+ </a>
+ </div>
+ </div>
+
+ </div>
+
+ <div data-dialog-button>
+ <?= Studip\Button::create($thread ? _('Speichern') : _('Erstellen'), 'submit_blubber') ?>
+ </div>
+</form>
diff --git a/app/views/blubber/dialog.php b/app/views/blubber/dialog.php
new file mode 100644
index 0000000..6be9bfd
--- /dev/null
+++ b/app/views/blubber/dialog.php
@@ -0,0 +1,12 @@
+<div class="blubber_panel"
+ data-thread_data="<?= htmlReady(json_encode($thread_data ?: [])) ?>"
+ data-threads_more_down="<?= htmlReady($threads_more_down) ?>">
+
+ <div id="blubber_stream_container" :class="waiting ? 'waiting' : ''">
+ <blubber-thread :thread_data="thread_data"></blubber-thread>
+ </div>
+</div>
+
+<div data-dialog-button>
+ <?= \Studip\LinkButton::create(_("Zum Kontext springen"), $thread->getURL()) ?>
+</div> \ No newline at end of file
diff --git a/app/views/blubber/index.php b/app/views/blubber/index.php
new file mode 100644
index 0000000..0daceb6
--- /dev/null
+++ b/app/views/blubber/index.php
@@ -0,0 +1,21 @@
+<div class="blubber_panel"
+ data-active_thread="<?= htmlReady($thread->getId()) ?>"
+ data-thread_data="<?= htmlReady(json_encode($thread_data ?: ['thread_posting' => []])) ?>"
+ data-threads_more_down="<?= htmlReady($threads_more_down) ?>"
+ :class="waiting ? 'waiting' : ''">
+
+ <div id="blubber_stream_container">
+ <blubber-thread :thread_data="thread_data"></blubber-thread>
+ </div>
+
+ <div class="blubber_sideinfo responsive-hidden" v-if="thread_data.context_info || thread_data.thread_posting.content">
+ <div class="posting" v-show="display_context_posting">
+ <div class="header">
+ <studip-date-time :timestamp="thread_data.thread_posting.mkdate" :relative="true"></studip-date-time>
+ <div>{{ thread_data.thread_posting.user_name }}</div>
+ </div>
+ <div class="content" v-html="thread_data.thread_posting.html"></div>
+ </div>
+ <div v-if="thread_data.context_info" class="context_info" v-html="thread_data.context_info"></div>
+ </div>
+</div>
diff --git a/app/views/blubber/leave_private.php b/app/views/blubber/leave_private.php
new file mode 100644
index 0000000..bfe45e8
--- /dev/null
+++ b/app/views/blubber/leave_private.php
@@ -0,0 +1,14 @@
+<form class="default"
+ method="post"
+ action="<?= $controller->link_for("blubber/leave_private/".$thread->getId()) ?>">
+
+
+ <label>
+ <input type="checkbox" name="delete_comments" value="1">
+ <?= _("Und auch alle meine Beiträge der Konversation löschen") ?>
+ </label>
+
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_("Verlassen")) ?>
+ </div>
+</form> \ No newline at end of file
diff --git a/app/views/blubber/private_to_studygroup.php b/app/views/blubber/private_to_studygroup.php
new file mode 100644
index 0000000..f6b584e
--- /dev/null
+++ b/app/views/blubber/private_to_studygroup.php
@@ -0,0 +1,26 @@
+<form action="<?= $controller->private_to_studygroup($thread) ?>"
+ method="post"
+ class="default"
+ enctype="multipart/form-data">
+
+ <div style="display: flex; justify-content: center; align-items: center">
+ <?= Icon::create('blubber', Icon::ROLE_INFO)->asImg(50, ['style' => "margin-right: 50px;"]) ?>
+ <?= Icon::create('arr_2right', Icon::ROLE_INFO)->asImg(20, ['style' => "margin-right: 50px;"]) ?>
+ <?= Icon::create('studygroup', Icon::ROLE_INFO)->asImg(50) ?>
+ </div>
+
+ <label>
+ <span class="required"><?= _('Name der Studiengruppe') ?></span>
+ <input type="text" name="name" required>
+ </label>
+
+ <label class="file-upload">
+ <?= _('Avatar für die Studiengruppe auswählen') ?>
+ <input type="file" name="avatar" accept="image/*">
+ </label>
+
+ <div data-dialog-button>
+ <?= Studip\Button::create(_('Erstellen'), 'submit') ?>
+ </div>
+
+</form>
diff --git a/app/views/calendar/contentbox/_termin.php b/app/views/calendar/contentbox/_termin.php
new file mode 100644
index 0000000..b0fd3a1
--- /dev/null
+++ b/app/views/calendar/contentbox/_termin.php
@@ -0,0 +1,53 @@
+<article class="studip toggle <?= ContentBoxHelper::classes($termin['id']) ?>" id="<?= $termin['id'] ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($termin['id']) ?>">
+ <?= Icon::create('date', 'inactive')->asImg(['class' => 'text-bottom']) ?>
+ <?= htmlReady($termin['title']) ?>
+ </a>
+ </h1>
+ <nav>
+ <span>
+ <?= $termin['room'] ? _('Raum') . ': ' . formatReady($termin['room']) : '' ?>
+ </span>
+ <? if($admin && $isProfile && $termin['type'] === 'CalendarEvent'): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/calendar/single/edit/' . $termin['range_id'] . '/' . $termin['event_id'], ['source_page' => 'dispatch.php/profile']) ?>">
+ <?= Icon::create('edit', 'clickable')->asImg(['class' => 'text-bottom']) ?>
+ </a>
+ <? endif; ?>
+ </nav>
+ </header>
+ <div>
+ <? $themen = $termin['topics'] ? : [] ?>
+ <? if ($termin['description'] || count($themen)) : ?>
+ <p><?= formatReady($termin['description']) ?></p>
+ <? if (count($themen)) : ?>
+ <? foreach ($themen as $thema) : ?>
+ <h3>
+ <?= Icon::create('topic', Icon::ROLE_INFO)->asImg(20, ['class' => "text-bottom"]) ?>
+ <?= htmlReady($thema['title']) ?>
+ </h3>
+ <div>
+ <?= formatReady($thema['description']) ?>
+ </div>
+ <? endforeach ?>
+ <? endif ?>
+ <? else : ?>
+ <?= _('Keine Beschreibung vorhanden') ?>
+ <? endif ?>
+ <ul class="list-csv" style="text-align: center;">
+ <? foreach($termin['info'] as $type => $info): ?>
+ <? if (trim($info)) : ?>
+ <li>
+ <small>
+ <? if (!is_numeric($type)): ?>
+ <em><?= htmlReady($type) ?>:</em>
+ <? endif; ?>
+ <?= htmlReady(trim($info)) ?>
+ </small>
+ </li>
+ <? endif ?>
+ <? endforeach; ?>
+ </ul>
+ </div>
+</article>
diff --git a/app/views/calendar/contentbox/display.php b/app/views/calendar/contentbox/display.php
new file mode 100644
index 0000000..3992753
--- /dev/null
+++ b/app/views/calendar/contentbox/display.php
@@ -0,0 +1,37 @@
+<? if ($admin || $termine): ?>
+<article class="studip">
+ <header>
+ <h1>
+ <?= Icon::create('schedule', 'info')->asImg() ?>
+ <?= htmlReady($title) ?>
+ </h1>
+ <nav>
+ <? if ($admin): ?>
+ <? if ($isProfile): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/calendar/single/edit/' . $termin->id, ['source_page' => 'dispatch.php/profile']) ?>">
+ <?= Icon::create('add', 'clickable')->asImg(['class' => 'text-bottom']) ?>
+ </a>
+ <? else: ?>
+ <a href="<?= URLHelper::getLink("dispatch.php/course/timesrooms", ['cid' => $range_id]) ?>">
+ <?= Icon::create('admin', 'clickable')->asImg(['class' => 'text-bottom']) ?>
+ </a>
+ <? endif; ?>
+ <? endif; ?>
+ </nav>
+ </header>
+ <? if($termine): ?>
+
+ <? foreach ($termine as $termin): ?>
+ <?= $this->render_partial('calendar/contentbox/_termin.php', ['termin' => $termin]); ?>
+ <? endforeach; ?>
+<? else: ?>
+ <section>
+ <? if($isProfile): ?>
+ <?= _('Es sind keine aktuellen Termine vorhanden. Um neue Termine zu erstellen, klicken Sie rechts auf das Plus.') ?>
+ <? else: ?>
+ <?= _('Es sind keine aktuellen Termine vorhanden. Um neue Termine zu erstellen, klicken Sie rechts auf die Zahnräder.') ?>
+ <? endif; ?>
+ </section>
+ <? endif; ?>
+</article>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/calendar/group/_attendees.php b/app/views/calendar/group/_attendees.php
new file mode 100644
index 0000000..3fbe27e
--- /dev/null
+++ b/app/views/calendar/group/_attendees.php
@@ -0,0 +1,82 @@
+<fieldset class="collapsed">
+ <legend>
+ <?= _('Teilnehmende/n hinzufügen') ?>
+ </legend>
+
+ <a class="toggler">
+ <?
+ if ($event->attendees->count()) {
+ $count_attendees = $event->attendees->filter(
+ function ($att, $k) use ($calendar) {
+ if ($att->range_id != $calendar->getRangeId()) {
+ return $att;
+ }
+ })->count();
+ } else {
+ $count_attendees = 0;
+ }
+ ?>
+ <? if ($count_attendees) : ?>
+ <? if ($count_attendees < $event->attendees->count()) : ?>
+ <?= sprintf(ngettext('(%s weitere/r Teilnehmende/r)', '(%s weitere Teilnehmende)', $count_attendees), $count_attendees) ?>
+ <? else : ?>
+ <?= sprintf(_('(%s Teilnehmende)'), $count_attendees) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </a>
+
+ <div>
+ <label for="user_id_1"><h4><?= _('Teilnehmende') ?></h4></label>
+ <ul class="clean" id="adressees">
+ <li id="template_adressee" style="display: none;" class="adressee">
+ <input type="hidden" name="attendees[]" value="">
+ <span class="visual"></span>
+ <a class="remove_adressee"><?= Icon::create('trash', 'clickable')->asImg(16, ['class' => 'text-bottom']) ?></a>
+ </li>
+ <? if ($event->isNew()) : ?>
+ <li style="padding: 0px;" class="adressee">
+ <input type="hidden" name="attendees[]" value="<?= $event->owner->id ?>">
+ <span class="visual">
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $event->owner->username], true) ?>"><?= htmlReady($event->owner->getFullname()) ?></a>
+ </span>
+ <a class="remove_adressee"><?= Icon::create('trash', 'clickable')->asImg(16, ['class' => 'text-bottom']) ?></a>
+ </li>
+ <? endif; ?>
+ <? $group_status = [
+ CalendarEvent::PARTSTAT_TENTATIVE => _('Abwartend'),
+ CalendarEvent::PARTSTAT_ACCEPTED => _('Angenommen'),
+ CalendarEvent::PARTSTAT_DECLINED => _('Abgelehnt'),
+ CalendarEvent::PARTSTAT_DELEGATED => _('Angenommen (keine Teilnahme)'),
+ CalendarEvent::PARTSTAT_NEEDS_ACTION => ''] ?>
+ <? foreach ($event->attendees as $attendee) : ?>
+ <? if ($attendee->owner) : ?>
+ <li style="padding: 0px;" class="adressee">
+ <input type="hidden" name="attendees[]" value="<?= htmlReady($attendee->owner->id) ?>">
+ <span class="visual">
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $attendee->owner->username], true) ?>"><?= htmlReady($attendee->owner->getFullname()) ?></a>
+ <? if ($event->havePermission(Event::PERMISSION_OWN, $attendee->owner->id)) : ?>
+ (<?= _('Organisator') ?>)
+ <? elseif ($group_status[$attendee->group_status]) : ?>
+ (<?= $group_status[$attendee->group_status] ?>)
+ <? endif; ?>
+ </span>
+ <a class="remove_adressee"><?= Icon::create('trash', 'clickable', ['title' => _('Teilnehmende/n entfernen')])->asImg(16, ['class' => 'text-bottom']) ?></a>
+ </li>
+ <? endif; ?>
+ <? endforeach ?>
+ </ul>
+
+ <section>
+ <?= $quick_search->render() ?>
+ <br clear="both">
+ </section>
+
+ <section>
+ <?= $mps->render(); ?>
+ </section>
+
+ <script>
+ STUDIP.MultiPersonSearch.init();
+ </script>
+ </div>
+</fieldset>
diff --git a/app/views/calendar/group/_tooltip.php b/app/views/calendar/group/_tooltip.php
new file mode 100644
index 0000000..aa8a9b1
--- /dev/null
+++ b/app/views/calendar/group/_tooltip.php
@@ -0,0 +1,27 @@
+<? $events = $events ?: $calendar->events ?>
+<? if (sizeof($events)) : ?>
+<div class="calendar-tooltip tooltip-content">
+ <h3><?= htmlReady($calendar->range_object->getFullname('no_title')) ?></h3>
+ <? foreach ($events as $event) : ?>
+ <div>
+ <? if (date('Ymd', $event->getStart()) == date('Ymd', $event->getEnd())) : ?>
+ <? if ($event->isDayEvent()) : ?>
+ <?= strftime('%x ', $event->getStart()) . '(' . _('ganztägig') . ')' ?>
+ <? else : ?>
+ <?= strftime('%x %X', $event->getStart()) . strftime(' - %X', $event->getEnd()) ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($event->isDayEvent()) : ?>
+ <?= strftime('%x', $event->getStart()) . strftime(' - %x', $event->getEnd()) . '(' . _('ganztägig') . ')' ?>
+ <? else : ?>
+ <?= strftime('%x %X', $event->getStart()) . strftime(' - %x %X', $event->getEnd()) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </div>
+ <div>
+ <?= htmlReady($event->getTitle()) ?>
+ </div>
+ <hr>
+ <? endforeach; ?>
+</div>
+<? endif; ?>
diff --git a/app/views/calendar/group/_tooltip_year.php b/app/views/calendar/group/_tooltip_year.php
new file mode 100644
index 0000000..edd81ca
--- /dev/null
+++ b/app/views/calendar/group/_tooltip_year.php
@@ -0,0 +1,21 @@
+<? $i = 0 ?>
+<? $html = '' ?>
+<? $list_day = date('Ymd', $aday) ?>
+<? foreach ($calendars as $calendar) : ?>
+ <? if ($count_lists[$i][$list_day]) : ?>
+ <?
+ $html .= '<div>'
+ . sprintf(ngettext('%s hat 1 Termin', '%s hat %s Termine',
+ count($count_lists[$i][$list_day])),
+ $calendar->range_object->getFullname('no_title'),
+ count($count_lists[$i][$list_day]))
+ . '</div>';
+ ?>
+ <? endif; ?>
+ <? $i++ ?>
+<? endforeach; ?>
+<? if ($html) : ?>
+<div class="calendar-tooltip tooltip-content">
+ <?= $html ?>
+</div>
+<? endif; ?>
diff --git a/app/views/calendar/group/day.php b/app/views/calendar/group/day.php
new file mode 100644
index 0000000..46758b1
--- /dev/null
+++ b/app/views/calendar/group/day.php
@@ -0,0 +1,130 @@
+<?
+$step_day = $settings['step_day_group'];
+$step = 3600 / $step_day;
+// add one cell for day events
+$cells = (($settings['end'] - $settings['start']) / (1 / $step)) + 2;
+$width1 = floor(90 / $cells);
+$width2 = 10 + (90 - $width1 * $cells);
+$start = $settings['start'] * 3600;
+$end = ($settings['end'] + 1) * 3600;
+// add skip link
+SkipLinks::addIndex(_('Tagesansicht'), 'main_content', 100);
+?>
+<table id="main_content" style="width:100%; table-layout:fixed;">
+ <thead>
+ <tr>
+ <td style="text-align: center; width: 10%; height: 40px;">
+ <div style="text-align: left; width: 20%; display: inline-block; white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/group/day', ['atime' => $atime - 86400]) ?>">
+ <?= Icon::create('arr_1left', 'clickable', ['title' => _('Einen Tag zurück')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ <?= strftime(_('%x'), strtotime('-1 day', $calendars[0]->getStart())) ?>
+ </a>
+ </div>
+ <div class="calhead" style="width: 50%; display: inline-block;">
+ <?= strftime('%A, %e. %B %Y', $atime) ?>
+ <div style="text-align: center; font-size: 12pt; color: #bbb; height: auto; overflow: visible; font-weight: bold;"><? $hd = holiday($atime); echo $holiday['name']; ?></div>
+ </div>
+ <div style="text-align: right; width: 20%; display: inline-block; white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/group/day', ['atime' => $atime + 86400]) ?>">
+ <?= strftime(_('%x'), strtotime('+1 day', $calendars[0]->getStart())) ?>
+ <?= Icon::create('arr_1right', 'clickable', ['title' => _('Einen Tag vor')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ </a>
+ </div>
+ </td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <div style="overflow:auto; width:100%;">
+ <table style="width: 100%;">
+ <? $time = mktime(0, 0, 0, date('n', $atime), date('j', $atime), date('Y', $atime)); ?>
+ <? if ($step_day < 3600) : $colsp = ' colspan="' . $step . '"'; endif ?>
+ <tr>
+ <td class="precol1w" nowrap="nowrap" style="text-align: center; width: <?= $width2 ?>%;">
+ <?= _('Mitglied') ?>
+ </td>
+ <td class="precol1w" style="text-align: center; width: <?= $width1 ?>%">
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Tagestermin am %x'), $calendars[0]->getStart()) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $calendars[0]->getStart(), 'isdayevent' => '1']) ?>">
+ <?= Icon::create('schedule', 'clickable')->asImg() ?>
+ </a>
+ </td>
+ <? for ($i = $time + $start; $i < $time + $end; $i += $step_day) : ?>
+ <? if (!($i % 3600)) : ?>
+ <td<?= $colsp ?> class="precol1w" style="text-align: center;">
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Termin um %R Uhr'), $i) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $i]) ?>" class="calhead">
+ <?= date('G', $i) ?>
+ </a>
+ </td>
+ <? endif ?>
+ <? endfor ?>
+ </tr>
+ <? foreach ($calendars as $calendar) : ?>
+ <? $adapted = $calendar->adapt_events($start, $end, $settings['step_day_group']); ?>
+ <tr>
+ <td style="width: <?= $width2 ?>%; white-space: nowrap;" class="month">
+ <a class="calhead" href="<?= $controller->url_for('calendar/single/day/' . $calendar->getRangeId(), ['atime' => $atime,]); ?>">
+ <?= htmlReady(($calendar->havePermission(Calendar::PERMISSION_OWN) ? _('Eigener Kalender') : get_fullname($calendar->getRangeId(), 'no_title_short'))) ?>
+ </a>
+ </td>
+ <? // display day events
+ $js_events = []; ?>
+ <? for ($i = 0; $i < sizeof($adapted['day_events']); $i++) :
+ $js_events[] = $calendar->events[$adapted['day_map'][$i]];
+ endfor; ?>
+ <? if ($calendar->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <td <?= sizeof($js_events) ? 'data-tooltip ' : '' ?>style="width: <?= $width1 ?>%; text-align: right;" class="calendar-day-edit<?= sizeof($js_events) ? ' calendar-group-events' : ' lightmonth' ?>">
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $calendar, 'events' => $js_events]) ?>
+ <a title="<?= strftime(_('Neuer Tagestermin am %x'), $calendar->getStart()) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $calendar->getStart(), 'isdayevent' => '1', 'user_id' => $calendar->getRangeId()]) ?>">+</a>
+ <? else : ?>
+ <td <?= sizeof($js_events) ? 'data-tooltip ' : '' ?>style="width: <?= $width1 ?>%;" class="<?= sizeof($js_events) ? 'calendar-group-events' : 'lightmonth' ?>">
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $calendar, 'events' => $js_events]) ?>
+ <? endif; ?>
+ </td>
+ <? $k = 0;
+ for ($i = $start + $calendar->getStart(); $i < $end + $calendar->getStart(); $i += $step_day) :
+ if (!($i % 3600)) {
+ $k++;
+ }
+ $js_events = [];
+ ?>
+ <? for ($j = 0; $j < sizeof($adapted['events']); $j++) : ?>
+ <? if (($adapted['events'][$j]->getStart() <= $i && $adapted['events'][$j]->getEnd() > $i) || ($adapted['events'][$j]->getStart() > $i && $adapted['events'][$j]->getStart() < $i + $step_day)) :
+ $js_events[] = $calendar->events[$adapted['map'][$j]];
+ endif; ?>
+ <? endfor; ?>
+ <? if ($calendar->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <td <?= sizeof($js_events) ? 'data-tooltip ' : '' ?>style="width: <?= $width1 ?>%; text-align: right;" class="calendar-day-edit<?= sizeof($js_events) ? ' calendar-group-events' : ' lightmonth' ?>">
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $calendar, 'events' => $js_events]) ?>
+ <a title="<?= strftime(_('Neuer Termin um %R Uhr'), $i) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $i, 'user_id' => $calendar->getRangeId()]) ?>">+</a>
+ <? else : ?>
+ <td <?= sizeof($js_events) ? 'data-tooltip ' : '' ?> style="width: <?= $width1 ?>%; text-align: right;" class="<?= sizeof($js_events) ? 'calendar-group-events' : 'lightmonth' ?>">
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $calendar, 'events' => $js_events]) ?>
+ <? endif; ?>
+ </td>
+ <? endfor ?>
+ </tr>
+ <? endforeach; ?>
+ <tr>
+ <td style="width: <?= $width2 ?>%;" class="precol1w"> </td>
+ <td width="<?= $width1 ?>%" class="precol1w" style="text-align: center;">
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Tagestermin am %x'), $calendars[0]->getStart()) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $calendars[0]->getStart(), 'isdayevent' => '1']) ?>">
+ <?= Icon::create('schedule', 'clickable')->asImg() ?>
+ </a>
+ </td>
+ <? for ($i = $time + $start; $i < $time + $end; $i += $step_day) : ?>
+ <? if (!($i % 3600)) : ?>
+ <td<?= $colsp ?> class="precol1w" style="text-align: center;">
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Termin um %R Uhr'), $i) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $i]) ?>" class="calhead">
+ <?= date('G', $i) ?>
+ </a>
+ </td>
+ <? endif ?>
+ <? endfor ?>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
diff --git a/app/views/calendar/group/month.php b/app/views/calendar/group/month.php
new file mode 100644
index 0000000..67212dd
--- /dev/null
+++ b/app/views/calendar/group/month.php
@@ -0,0 +1,110 @@
+<? $month = $calendar->view; ?>
+<table class="calendar-month">
+ <thead>
+ <tr>
+ <td colspan="8" style="text-align: center; vertical-align: middle;">
+ <div style="text-align: left; display: inline-block; width: 33%; white-space: nowrap;">
+ <a style="padding-right: 2em;" href="<?= $controller->url_for('calendar/group/month', ['atime' => mktime(12, 0, 0, date('n', $calendars[0][15]->getStart()), 15, date('Y', $calendars[0][15]->getStart()) - 1)]) ?>">
+ <?= Icon::create('arr_2left', 'clickable', ['title' => _('Ein Jahr zurück')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ <?= strftime('%B %Y', strtotime('-1 year', $calendars[0][15]->getStart())) ?>
+ </a>
+ <a href="<?= $controller->url_for('calendar/group/month', ['atime' => $calendars[0][0]->getStart() - 1]) ?>">
+ <?= Icon::create('arr_1left', 'clickable', ['title' => _('Einen Monat zurück')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ <?= strftime('%B %Y', strtotime('-1 month', $calendars[0][15]->getStart())) ?>
+ </a>
+ </div>
+ <div class="calhead" style="text-align: center; display: inline-block; width: 33%;">
+ <?= htmlReady(strftime("%B ", $calendars[0][15]->getStart())) .' '. date('Y', $calendars[0][15]->getStart()); ?>
+ </div>
+ <div style="text-align: right; display: inline-block; width: 33%; white-space: nowrap;">
+ <a style="padding-right: 2em;" href="<?= $controller->url_for('calendar/group/month', ['atime' => strtotime('+1 month', $calendars[0][15]->getStart())]) ?>">
+ <?= strftime('%B %Y', strtotime('+1 month', $calendars[0][15]->getStart())) ?>
+ <?= Icon::create('arr_1right', 'clickable', ['title' => _('Einen Monat vor')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ </a>
+ <a href="<?= $controller->url_for('calendar/group/month', ['atime' => mktime(12, 0, 0, date('n', $calendars[0][15]->getStart()), 15, date('Y', $calendars[0][15]->getEnd()) + 1)]) ?>">
+ <?= strftime('%B %Y', strtotime('+1 year', $calendars[0][15]->getStart())) ?>
+ <?= Icon::create('arr_2right', 'clickable', ['title' => _('Ein Jahr vor')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ </a>
+ </div>
+ </td>
+ </tr>
+ <tr class="calendar-month-weekdays">
+ <? $week_days = [39092400, 39178800, 39265200, 39351600, 39438000, 39524400, 39610800]; ?>
+ <? foreach ($week_days as $week_day) : ?>
+ <td class="precol1w">
+ <?= strftime('%a', $week_day) ?>
+ </td>
+ <? endforeach; ?>
+ <td align="center" class="precol1w">
+ <?= _('Woche') ?>
+ </td>
+ </tr>
+ </thead>
+ <tbody>
+ <? for ($i = $first_day, $j = 0; $i <= $last_day; $i += 86400, $j++) : ?>
+ <? $aday = date('j', $i); ?>
+ <?
+ $class_day = '';
+ if (($aday - $j - 1 > 0) || ($j - $aday > 6)) {
+ $class_cell = 'lightmonth';
+ $class_day = 'light';
+ } elseif (date('Ymd', $i) == date('Ymd')) {
+ $class_cell = 'celltoday';
+ } else {
+ $class_cell = 'month';
+ }
+ $hday = holiday($i);
+
+ if ($j % 7 == 0) {
+ ?><tr><?
+ }
+ ?>
+ <td class="<?= $class_cell ?>">
+ <? if (($j + 1) % 7 == 0) : ?>
+ <a class="<?= $class_day . 'sday' ?>" href="<?= $controller->url_for('calendar/group/day/' . $this->range_id, ['atime' => $i]) ?>">
+ <?= $aday ?>
+ </a>
+ <? if ($hday["name"] != "") : ?>
+ <div style="color: #aaaaaa;" class="inday"><?= $hday['name'] ?></div>
+ <? endif; ?>
+ <? foreach($calendars as $user_calendars) : ?>
+ <? $count = sizeof($user_calendars[$j]->events) ?>
+ <? if ($count) : ?>
+ <div data-tooltip="">
+ <a class="inday calendar-event-text" href="<?= $controller->url_for('calendar/single/day/' . $user_calendars[$j]->getRangeId(), ['atime' => $user_calendars[$j]->getStart()]) ?>"><?= htmlReady($user_calendars[$j]->range_object->getFullname('no_title')) ?></a>
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $user_calendars[$j]]) ?>
+ </div>
+ <? endif; ?>
+ <? endforeach; ?>
+ </td>
+ <td class="lightmonth calendar-month-week">
+ <a style="font-weight: bold;" class="calhead" href="<?= $controller->url_for('calendar/group/week/' . $this->range_id, ['atime' => $i]) ?>"><?= strftime("%V", $i) ?></a>
+ </td>
+ </tr>
+ <? else : ?>
+ <? $hday_class = ['day', 'day', 'shday', 'hday'] ?>
+ <? if ($hday['col']) : ?>
+ <a class="<?= $class_day . $hday_class[$hday['col']] ?>" href="<?= $controller->url_for('calendar/group/day', ['atime' => $i]) ?>">
+ <?= $aday ?>
+ </a>
+ <div style="color: #aaaaaa;" class="inday"><?= $hday['name'] ?></div>
+ <? else : ?>
+ <a class="<?= $class_day . 'day' ?>" href="<?= $controller->url_for('calendar/single/day', ['atime' => $i]) ?>">
+ <?= $aday ?>
+ </a>
+ <? endif; ?>
+ <? foreach($calendars as $user_calendars) : ?>
+ <? $count = sizeof($user_calendars[$j]->events) ?>
+ <? if ($count) : ?>
+ <div data-tooltip>
+ <a class="inday calendar-event-text" href="<?= $controller->url_for('calendar/single/day/' . $user_calendars[$j]->getRangeId(), ['atime' => $user_calendars[$j]->getStart()]) ?>"><?= htmlReady($user_calendars[$j]->range_object->getFullname('no_title')) ?></a>
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $user_calendars[$j]]) ?>
+ </div>
+ <? endif; ?>
+ <? endforeach; ?>
+ </td>
+ <? endif; ?>
+ <? endfor; ?>
+ </tr>
+ </tbody>
+</table>
diff --git a/app/views/calendar/group/week.php b/app/views/calendar/group/week.php
new file mode 100644
index 0000000..8f9644a
--- /dev/null
+++ b/app/views/calendar/group/week.php
@@ -0,0 +1,146 @@
+<?
+$width1 = 0;
+$width2 = 0;
+$cols = ceil(($settings['end'] - $settings['start'] + 1) * 3600 / $settings['step_week_group']) + 1;
+$start = $settings['start'] * 3600;
+$end = ($settings['end'] + 1) * 3600;
+$wlength = count($calendars[0]) - 1;
+// add skip link
+SkipLinks::addIndex(_('Wochenansicht'), 'main_content', 100);
+?>
+<table style="width: 100%">
+ <tr>
+ <td colspan="<?= $colspan_2 ?>" style="vertical-align: middle; text-align: center;">
+ <div style="text-align: left; width: 25%; display: inline-block; white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/group/week', ['atime' => mktime(12, 0, 0, date('n', $atime), date('j', $atime) - 7, date('Y', $atime))]) ?>">
+ <?= Icon::create('arr_1left', 'clickable', ['title' => _('Eine Woche zurück')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ <?= sprintf(_('%u. Woche'), strftime('%V'), strtotime('-1 week', $atime)) ?>
+ </a>
+ </div>
+ <div style="display: inline-block; text-align: center;" class="calhead">
+ <? printf(_("%s. Woche vom %s bis %s"), strftime("%V", $calendars[0][0]->getStart()), strftime("%x", $calendars[0][0]->getStart()), strftime("%x", $calendars[0][$wlength]->getEnd())) ?>
+ </div>
+ <div style="width: 25%; text-align: right; display: inline-block; white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/group/week', ['atime' => mktime(12, 0, 0, date('n', $atime), date('j', $atime) + 7, date('Y', $atime))]) ?>">
+ <?= sprintf(_('%u. Woche'), strftime('%V', strtotime('+1 week', $atime))) ?>
+ <?= Icon::create('arr_1right', 'clickable', ['title' => _('Eine Woche vor')])->asImg(16, ["style" => 'vertical-align: text-top;']) ?>
+ </a>
+ </div>
+ </td>
+ </tr>
+</table>
+<div style="overflow:auto; width:100%;">
+ <table id="main_content" style="width: 100%;">
+ <thead>
+ <tr>
+ <td width="<?= $width2 ?>%" class="precol1w"> </td>
+ <? $time = $calendars[0][0]->getStart(); ?>
+ <? for ($i = 0; $i <= $wlength; $i++) : ?>
+ <td colspan="<?= $cols ?>" style="text-align: center;" class="precol1w">
+ <a href="<?= $controller->url_for('calendar/group/day/' . $this->range_id, ['atime' => $time]) ?>" class="calhead">
+ <?= strftime('%a', $time) . ' ' . date('d', $time) ?>
+ </a>
+ </td>
+ <? $time += 86400; ?>
+ <? endfor ?>
+ </tr>
+ <tr>
+ <td width="<?= $width2 ?>%" class="precol1w" style="text-align: center;">
+ <?= _('Mitglied') ?>
+ </td>
+ <? foreach ($calendars[0] as $day) : ?>
+ <td class="precol1w" style="text-align: center; width: <?= $width1 ?>%;">
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Tagestermin am %x'), $day->getStart()) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $day->getStart(), 'isdayevent' => '1']) ?>">
+ <?= Icon::create('schedule', 'clickable')->asImg() ?>
+ </a>
+ </td>
+ <? for ($i = $day->getStart() + $start; $i < $day->getStart() + $end; $i += 3600 * ceil($settings['step_week_group'] / 3600)) : ?>
+ <td colspan="<?= ceil(3600 / $settings['step_week_group']) ?>" class="precol2w" style="text-align: center;">
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Termin um %R Uhr'), $i) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $i]) ?>" class="calhead">
+ <?= (date('G', $i) < 10 ? '&nbsp;' . date('G', $i) . '&nbsp;' : date('G', $i)) ?>
+ </a>
+ </td>
+ <? endfor ?>
+ <? endforeach ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($calendars as $user_calendar) : ?>
+ <tr>
+ <td style="width: <?= $width2 ?>%; white-space: nowrap;" class="month">
+ <a class="calhead" href="<?= $controller->url_for('calendar/single/week/' . $user_calendar[0]->getRangeId(), ['atime' => $atime]) ?>">
+ <?= htmlReady($user_calendar[0]->havePermission(Calendar::PERMISSION_OWN) ? _('Eigener Kalender') : get_fullname($user_calendar[0]->getRangeId(), 'no_title_short')) ?>
+ </a>
+ </td>
+ <? $k = 1; ?>
+ <? foreach ($user_calendar as $day) : ?>
+ <?
+ if (date('Ymd', $day->getStart()) == date('Ymd')) {
+ $css_class = 'celltoday';
+ } else {
+ if ($k % 2) {
+ $css_class = 'lightmonth';
+ } else {
+ $css_class = 'month';
+ }
+ }
+ $k++;
+ $adapted = $day->adapt_events($start, $end, $settings['step_week_group']);
+
+ // display day events
+ $js_events = []; ?>
+ <? for ($i = 0; $i < count($adapted['day_events']); $i++) : ?>
+ <? $js_events[] = $day->events[$adapted['day_map'][$i]]; ?>
+ <? endfor; ?>
+ <? if (count($js_events) && $day->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <td <?= count($js_events) ? 'data-tooltip ' : '' ?>style="text-align: right; width: <?= $width1 ?>%" class="calendar-day-edit <?= $css_class ?><?= count($js_events) ? ' calendar-group-events' : '' ?>">
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $day, 'events' => $js_events]) ?>
+ <a title="<?= strftime(_('Neuer Tagestermin am %x'), $day->getStart()) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $day->getStart(), 'isdayevent' => '1', 'user_id' => $day->getRangeId()]) ?>">+</a>
+ <? else : ?>
+ <td <?= count($js_events) ? 'data-tooltip ' : '' ?>style="text-align: right; width: <?= $width1 ?>%" class="<?= $css_class ?><?= count($js_events) ? ' calendar-group-events' : '' ?>">
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $day, 'events' => $js_events]) ?>
+ <? endif;?>
+ </td>
+
+ <? for ($i = $start + $day->getStart(); $i < $end + $day->getStart(); $i += $settings['step_week_group']) : ?>
+ <? $js_events = []; ?>
+ <? for ($j = 0; $j < count($adapted['events']); $j++) : ?>
+ <? if (($adapted['events'][$j]->getStart() <= $i && $adapted['events'][$j]->getEnd() > $i) || ($adapted['events'][$j]->getStart() > $i && $adapted['events'][$j]->getStart() < $i + $settings['step_week_group'])) : ?>
+ <? $js_events[] = $day->events[$adapted['map'][$j]]; ?>
+ <? endif ?>
+ <? endfor ?>
+ <? if ($day->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <td <?= count($js_events) ? 'data-tooltip ' : '' ?>style="text-align: right; width: <?= $width1 ?>%" class="calendar-day-edit <?= $css_class ?><?= count($js_events) ? ' calendar-group-events' : '' ?>">
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $day, 'events' => $js_events]) ?>
+ <a title="<?= strftime(_('Neuer Termin um %R Uhr'), $i) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $i, 'user_id' => $day->getRangeId()]) ?>">+</a>
+ <? else : ?>
+ <td <?= count($js_events) ? 'data-tooltip ' : '' ?>style="text-align: right; width: <?= $width1 ?>%" class="<?= $css_class ?><?= count($js_events) ? ' calendar-group-events' : '' ?>">
+ <?= $this->render_partial('calendar/group/_tooltip', ['calendar' => $day, 'events' => $js_events]) ?>
+ <? endif; ?>
+ </td>
+ <? endfor; ?>
+ <? endforeach; ?>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td style="width:<?= $width2 ?>%; text-align: center;" class="precol1"> </td>
+ <? foreach ($calendars[0] as $day) : ?>
+ <td style="width:<?= $width1 ?>%; text-align: center;" class="precol1w">
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Tagestermin am %x'), $day->getStart()) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $atime, 'isdayevent' => '1']) ?>">
+ <?= Icon::create('schedule', 'clickable')->asImg() ?>
+ </a>
+ </td>
+ <? for ($i = $day->getStart() + $start; $i < $day->getStart() + $end; $i += 3600 * ceil($settings['step_week_group'] / 3600)) : ?>
+ <td colspan="<?= ceil(3600 / $settings['step_week_group']) ?>" class="precol2w" style="text-align: center;">
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Termin um %R Uhr'), $i) ?>" href="<?= $controller->url_for('calendar/group/edit/' . $range_id, ['atime' => $i]) ?>" class="calhead">
+ <?= (date('G', $i) < 10 ? '&nbsp;' . date('G', $i) . '&nbsp;' : date('G', $i)) ?>
+ </a>
+ </td>
+ <? endfor; ?>
+ <? endforeach; ?>
+ </tr>
+ </tfoot>
+ </table>
+</div>
diff --git a/app/views/calendar/group/year.php b/app/views/calendar/group/year.php
new file mode 100644
index 0000000..b07f749
--- /dev/null
+++ b/app/views/calendar/group/year.php
@@ -0,0 +1,122 @@
+<table style="width: 100%;">
+ <tr>
+ <td colspan="3" style="text-align: center; vertical-align: middle;">
+ <div style="text-align: left; display: inline-block; width: 20%; white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/group/year', ['atime' => strtotime('-1 year', $atime)]) ?>">
+ <?= Icon::create('arr_2left', 'clickable', ['title' => _('Ein Jahr zurück')])->asImg(16, ['style' => 'vertical-align: text-bottom;']) ?>
+ <?= strftime('%Y', strtotime('-1 year', $atime)) ?>
+ </a>
+ </div>
+ <div class="calhead" style="text-align: center; display: inline-block; width:50%;">
+ <?= date('Y', $calendars[0]->getStart()) ?>
+ </div>
+ <div style="text-align: right; display: inline-block; width: 20%; white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/group/year', ['atime' => strtotime('+1 year', $atime)]) ?>">
+ <?= strftime('%Y', strtotime('+1 year', $atime)) ?>
+ <?= Icon::create('arr_2right', 'clickable', ['title' => _('Ein Jahr vor')])->asImg(16, ['style' => 'vertical-align: text-bottom;']) ?>
+ </a>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" class="blank">
+ <table style="width: 100%;">
+ <? $days_per_month = [31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+ if (date('L', $calendars[0]->getStart())) {
+ $days_per_month[2]++;
+ }
+ ?>
+ <tr>
+ <? for ($i = 1; $i < 13; $i++) : ?>
+ <? $ts_month += ( $days_per_month[$i] - 1) * 86400; ?>
+ <td style="text-align: center; width: 8%;">
+ <a class="calhead" href="<?= $controller->url_for('calendar/group/month', ['atime' => $calendars[0]->getStart() + $ts_month]) ?>">
+ <?= strftime('%B', $ts_month); ?>
+ </a>
+ </td>
+ <? endfor; ?>
+ </tr>
+ <? $now = date('Ymd'); ?>
+ <? for ($i = 1; $i < 32; $i++) : ?>
+ <tr>
+ <? for ($month = 1; $month < 13; $month++) : ?>
+ <? $aday = mktime(12, 0, 0, $month, $i, date('Y', $calendars[0]->getStart())); ?>
+ <? if ($i <= $days_per_month[$month]) : ?>
+ <? $wday = date('w', $aday);
+ // emphasize current day
+ if (date('Ymd', $aday) == $now) {
+ $day_class = ' class="celltoday"';
+ } else if ($wday == 0 || $wday == 6) {
+ $day_class = ' class="weekend"';
+ } else {
+ $day_class = ' class="weekday"';
+ }
+ ?>
+ <? if ($month == 1) : ?>
+ <td<?= $day_class ?> height="25">
+ <? else : ?>
+ <td<?= $day_class ?>>
+ <? endif; ?>
+ <? $tooltip = $this->render_partial('calendar/group/_tooltip_year',
+ ['aday' => $aday, 'calendars' => $calendars, 'count_lists' => $count_lists]) ?>
+ <? if (trim($tooltip)) : ?>
+ <table style="width: 100%;">
+ <tr>
+ <td<?= $day_class ?>>
+ <? endif; ?>
+ <? $weekday = strftime('%a', $aday); ?>
+
+ <? $hday = holiday($aday); ?>
+ <? if ($hday['col'] == '1') : ?>
+ <? if (date('w', $aday) == '0') : ?>
+ <a style="font-weight:bold;" class="sday" href="<?= $controller->url_for('calendar/group/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? $count++; ?>
+ <? else : ?>
+ <a style="font-weight:bold;" class="day" href="<?= $controller->url_for('calendar/group/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? endif; ?>
+ <? elseif ($hday['col'] == '2' || $hday['col'] == '3') : ?>
+ <? if (date('w', $aday) == '0') : ?>
+ <a style="font-weight:bold;" class="sday" href="<?= $controller->url_for('calendar/group/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? $count++; ?>
+ <? else : ?>
+ <a style="font-weight:bold;" class="hday" href="<?= $controller->url_for('calendar/group/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if (date('w', $aday) == '0') : ?>
+ <a style="font-weight:bold;" class="sday" href="<?= $controller->url_for('calendar/group/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? $count++; ?>
+ <? else : ?>
+ <a style="font-weight:bold;" class="day" href="<?= $controller->url_for('calendar/group/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? endif; ?>
+ <? endif; ?>
+ <? if (trim($tooltip)) : ?>
+ </td>
+ <td<?= $day_class ?> style="text-align: right;" data-tooltip="">
+ <?= Icon::create('date', 'clickable', ['title' => $event_count_txt])->asImg(16, ["alt" => $event_count_txt]); ?>
+ <?= $tooltip ?>
+ </td>
+ </tr>
+ </table>
+ <? endif; ?>
+ </td>
+ <? else : ?>
+ <td class="weekday"> </td>
+ <? endif; ?>
+ <? endfor; ?>
+ </tr>
+ <? endfor; ?>
+ <tr>
+ <? $ts_month = 0; ?>
+ <? for ($i = 1; $i < 13; $i++) : ?>
+ <? $ts_month += ( $days_per_month[$i] - 1) * 86400; ?>
+ <td align="center" width="8%">
+ <a class="calhead" href="<?= $controller->url_for('calendar/group/month', ['atime' => $calendars[0]->getStart() + $ts_month]) ?>">
+ <?= strftime('%B', $ts_month); ?>
+ </a>
+ </td>
+ <? endfor; ?>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
diff --git a/app/views/calendar/instschedule/_entry_details.php b/app/views/calendar/instschedule/_entry_details.php
new file mode 100644
index 0000000..7fd4a38
--- /dev/null
+++ b/app/views/calendar/instschedule/_entry_details.php
@@ -0,0 +1,29 @@
+<table class="default">
+ <caption>
+ <?= sprintf(_('Veranstaltungen mit regelmäßigen Zeiten am %s, %s Uhr'), htmlReady($day), htmlReady($start) .' - '. htmlReady($end)) ?>
+ </caption>
+ <colgroup>
+ <col width="15%">
+ <col width="85%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Nummer') ?></th>
+ <th><?= _('Name') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($seminars as $seminar) : ?>
+ <tr class="<?= TextHelper::cycle('table_row_odd', 'table_row_even')?>">
+ <td><?= htmlReady($seminar->getNumber()) ?></td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details/', ['sem_id' => $seminar->getId()]) ?>">
+ <?= Icon::create('link-intern', 'clickable')->asImg() ?>
+ <?= htmlReady($seminar->getName()) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+<br>
diff --git a/app/views/calendar/instschedule/index.php b/app/views/calendar/instschedule/index.php
new file mode 100644
index 0000000..bcfa72e
--- /dev/null
+++ b/app/views/calendar/instschedule/index.php
@@ -0,0 +1,15 @@
+<h1>
+ <?= htmlReady(Context::getHeaderLine()) ?> <?= _("im") ?>
+ <?= htmlReady($current_semester['name']) ?>
+</h1>
+
+<? if (Request::get('show_settings')) : ?>
+ <div class="ui-widget-overlay" style="width: 100%; height: 100%; z-index: 1001;"></div>
+ <?= $this->render_partial('calendar/schedule/_dialog', [
+ 'content_for_layout' => $this->render_partial('calendar/schedule/settings', [
+ 'settings' => $my_schedule_settings]),
+ 'title' => _('Darstellung ändern')
+ ]) ?>
+<? endif ?>
+
+<?= $calendar_view->render() ?>
diff --git a/app/views/calendar/schedule/_colorpicker.php b/app/views/calendar/schedule/_colorpicker.php
new file mode 100644
index 0000000..79ad8b2
--- /dev/null
+++ b/app/views/calendar/schedule/_colorpicker.php
@@ -0,0 +1,12 @@
+<section id="color_picker">
+ <?= _('Farbe des Termins') ?>
+ <div>
+ <? foreach ($GLOBALS['PERS_TERMIN_KAT'] as $index => $data): ?>
+ <span>
+ <input type="radio" name="entry_color" value="<?= $index ?>" id="color-<?= $index ?>"
+ <? if ($index == $selected) echo 'checked'; ?>>
+ <label class="undecorated schedule-category<?= $index ?>" for="color-<?= $index ?>"></label>
+ </span>
+ <? endforeach; ?>
+ </div>
+</section>
diff --git a/app/views/calendar/schedule/_dialog.php b/app/views/calendar/schedule/_dialog.php
new file mode 100644
index 0000000..0b64f9d
--- /dev/null
+++ b/app/views/calendar/schedule/_dialog.php
@@ -0,0 +1,12 @@
+<div class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-draggable ui-resizable ui-dialog-buttons <?= $class ?: 'schedule-dialog' ?>" tabindex="-1" role="dialog" aria-labelledby="ui-id-2" id="schedule_new_entry" style="width: 600px; height: auto; z-index: 1002;">
+ <div class="ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" style="z-index: 1001">
+ <span id="ui-id-2" class="ui-dialog-title"><?= $title ?></span>
+ <a class="ui-dialog-titlebar-close ui-corner-all" href="<?= $controller->link_for('calendar/schedule') ?>" role="button">
+ <span class="ui-icon ui-icon-closethick">close</span>
+ </a>
+ </div>
+
+ <div class="ui-widget-content" style="display: block; width: auto; min-height: 0px; height: 100%;" scrolltop="0" scrollleft="0">
+ <?= $content_for_layout ?>
+ </div>
+</div>
diff --git a/app/views/calendar/schedule/_entry_course.php b/app/views/calendar/schedule/_entry_course.php
new file mode 100644
index 0000000..ece5392
--- /dev/null
+++ b/app/views/calendar/schedule/_entry_course.php
@@ -0,0 +1,90 @@
+<?php
+$sem = Seminar::getInstance($show_entry['id']);
+?>
+<form class="default"
+ action="<?= $controller->link_for('calendar/schedule/editseminar/' . $show_entry['id'] . '/' . $show_entry['cycle_id']) ?>"
+ method="post" name="edit_entry">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Stundenplaneintrag') ?>
+ </legend>
+
+ <?= $this->render_partial('calendar/schedule/_colorpicker.php', [
+ 'selected' => $show_entry['color'],
+ ]) ?>
+
+ <? if ($show_entry['type'] == 'virtual') : ?>
+ <section>
+ <span
+ style="color: red; font-weight: bold"><?= _('Dies ist lediglich eine vorgemerkte Veranstaltung') ?></span><br><br>
+ </section>
+ <? endif ?>
+
+ <section>
+ <strong><?= _('Veranstaltungsnummer') ?></strong><br>
+ <?= htmlReady($sem->getNumber()) ?>
+ </section>
+
+ <section>
+ <strong><?= _('Name') ?></strong><br>
+ <?= htmlReady($sem->getName()) ?>
+ </section>
+
+ <section>
+ <strong><?= _('Lehrende') ?></strong><br>
+ <? $pos = 0;
+ foreach ($sem->getMembers('dozent') as $dozent) :?>
+ <?php if ($pos > 0) echo ', '; ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $dozent['username']]) ?>">
+ <?= htmlReady($dozent['fullname']) ?>
+ </a>
+ <? $pos++ ?>
+ <? endforeach ?>
+ </section>
+
+ <section>
+ <strong><?= _('Veranstaltungszeiten') ?></strong><br>
+ <?= $sem->getDatesHTML(['show_room' => true]) ?><br>
+ </section>
+
+ <section>
+ <?= Icon::create('link-intern') ?>
+ <? if ($show_entry['type'] == 'virtual') : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $show_entry['id']]) ?>">
+ <?= _('Zur Veranstaltung') ?>
+ </a>
+ <br>
+ <? else : ?>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $show_entry['id']]) ?>">
+ <?= _('Zur Veranstaltung') ?>
+ </a>
+ <br>
+ <? endif ?>
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), ['style' => 'margin-right: 20px']) ?>
+
+ <? if (!$show_entry['visible']) : ?>
+ <?= Studip\LinkButton::create(
+ _('Einblenden'),
+ $controller->url_for(
+ 'calendar/schedule/bind/' . $show_entry['id'] . '/' . $show_entry['cycle_id'] . '/',
+ ['show_hidden' => '1']
+ ),
+ ['style' => 'margin-right: 20px']) ?>
+ <? else : ?>
+ <?= Studip\LinkButton::create(
+ $show_entry['type'] == 'virtual' ? _('Löschen') : _('Ausblenden'),
+ $controller->url_for('calendar/schedule/unbind/' . $show_entry['id'] . '/' . $show_entry['cycle_id']),
+ ['style' => 'margin-right: 20px']) ?>
+ <? endif ?>
+
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('calendar/schedule'),
+ ['onclick' => "jQuery('#edit_sem_entry').fadeOut('fast'); STUDIP.Calendar.click_in_progress = false; return false"]) ?>
+ </footer>
+</form>
diff --git a/app/views/calendar/schedule/_entry_inst.php b/app/views/calendar/schedule/_entry_inst.php
new file mode 100644
index 0000000..fb9435b
--- /dev/null
+++ b/app/views/calendar/schedule/_entry_inst.php
@@ -0,0 +1,59 @@
+<table class="default">
+ <colgroup>
+ <col style="width: 15%">
+ <col style="width: 45%">
+ <col>
+ </colgroup>
+ <caption>
+ <?= sprintf(_('Veranstaltungen mit regelmäßigen Zeiten am %s, %s Uhr'), htmlReady($day), htmlReady($timespan)) ?>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Nummer') ?></th>
+ <th><?= _('Name') ?></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($seminars as $seminar) : ?>
+ <tr>
+ <td><?= htmlReady($seminar->getNumber()) ?></td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details/', ['sem_id' => $seminar->getId()]) ?>">
+ <?= Icon::create('link-intern') ?>
+ <?= htmlReady($seminar->getName()) ?>
+ </a>
+ </td>
+ <td class="schedule-adminbind">
+ <? $cycles = CalendarScheduleModel::getSeminarCycleId($seminar, $start, $end, $day) ?>
+
+ <? foreach ($cycles as $cycle) : ?>
+ <span><?= $cycle->toString() ?></span>
+
+ <? $visible = CalendarScheduleModel::isSeminarVisible($seminar->getId(), $cycle->getMetadateId()) ?>
+
+ <?= Studip\LinkButton::create(
+ _('Ausblenden'),
+ $controller->url_for('calendar/schedule/adminbind/' . $seminar->getId() . '/' . $cycle->getMetadateId() . '/0'),
+ [
+ 'id' => $seminar->getId() . '_' . $cycle->getMetadateId() . '_hide',
+ 'onclick' => "STUDIP.Schedule.instSemUnbind('" . $seminar->getId() . "','" . $cycle->getMetadateId() . "'); return false;",
+ 'style' => ($visible ? '' : 'display: none')
+ ]) ?>
+
+ <?= Studip\LinkButton::create(
+ _('Einblenden'),
+ $controller->url_for('calendar/schedule/adminbind/' . $seminar->getId() . '/' . $cycle->getMetadateId() . '/1'),
+ [
+ 'id' => $seminar->getId() . '_' . $cycle->getMetadateId() . '_show',
+ 'onclick' => "STUDIP.Schedule.instSemBind('" . $seminar->getId() . "','" . $cycle->getMetadateId() . "'); return false;",
+ 'style' => ($visible ? 'display: none' : '')
+ ]) ?>
+ <br>
+ <? endforeach ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+<br>
diff --git a/app/views/calendar/schedule/_entry_schedule.php b/app/views/calendar/schedule/_entry_schedule.php
new file mode 100644
index 0000000..6f3d8ff
--- /dev/null
+++ b/app/views/calendar/schedule/_entry_schedule.php
@@ -0,0 +1,73 @@
+<form class="default"
+ action="<?= $controller->link_for('calendar/schedule/addentry' . ($show_entry['id'] ? '/' . $show_entry['id'] : '')) ?>"
+ method="post" name="edit_entry" onSubmit="return STUDIP.Schedule.checkFormFields()">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Stundenplaneintrag') ?>
+ </legend>
+
+ <label class="col-2">
+ <?= _('Tag') ?>
+ <select name="entry_day" class="size-s">
+ <? foreach ([1, 2, 3, 4, 5, 6, 7] as $index) : ?>
+ <option
+ value="<?= $index ?>" <?= (isset($show_entry['day']) && $show_entry['day'] == $index) ? 'selected="selected"' : '' ?>>
+ <?= getWeekDay($index % 7, false) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label class="col-2">
+ <?= _('von') ?>
+ <input class="size-s studip-timepicker" placeholder="HH:mm" type="text" size="2" name="entry_start"
+ value="<?= $show_entry['start'] ? $show_entry['start_formatted'] : '' ?>"
+ id="entry-start" data-time-picker>
+ </label>
+
+ <label class="col-2">
+ <?= _('bis') ?>
+ <input class="size-s studip-timepicker" placeholder="HH:mm" type="text" size="2" name="entry_end"
+ value="<?= $show_entry['end'] ? $show_entry['end_formatted'] : '' ?>"
+ id="entry-end" data-time-picker>
+ </label>
+
+ <span class="invalid_message"><?= _('Die Endzeit liegt vor der Startzeit!') ?></span>
+
+ <?= $this->render_partial('calendar/schedule/_colorpicker.php', [
+ 'selected' => $show_entry['color'],
+ ]) ?>
+
+ <label>
+ <?= _('Titel') ?>
+ <input type="text" name="entry_title" value="<?= htmlReady($show_entry['title']) ?>">
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="entry_content"
+ rows="7"><?= htmlReady($show_entry['content']) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), ['style' => 'margin-right: 20px']) ?>
+ <? if ($show_entry['id']) : ?>
+ <?= Studip\LinkButton::create(
+ _('Löschen'),
+ $controller->url_for('calendar/schedule/delete/'. $show_entry['id']),
+ ['style' => 'margin-right: 20px']
+ ) ?>
+ <? endif ?>
+
+ <? if ($show_entry) : ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('calendar/schedule'),
+ ['onclick' => 'STUDIP.Schedule.cancelNewEntry(); STUDIP.Calendar.click_in_progress = false;return false;']) ?>
+ <? else: ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), 'javascript:STUDIP.Schedule.cancelNewEntry()') ?>
+ <? endif ?>
+ </footer>
+</form>
diff --git a/app/views/calendar/schedule/_semester_chooser.php b/app/views/calendar/schedule/_semester_chooser.php
new file mode 100644
index 0000000..3af4018
--- /dev/null
+++ b/app/views/calendar/schedule/_semester_chooser.php
@@ -0,0 +1,22 @@
+<form method="post" class="default" action="<?= $controller->link_for(
+ isset($inst_mode) && $inst_mode == true ? 'calendar/instschedule/index' : 'calendar/schedule/index'
+) ?>">
+ <select name="semester_id" class="submit-upon-select">
+ <? foreach ($semesters as $semester) : ?>
+ <? if ($semester['ende'] > time() - strtotime('1year 1day')) : ?>
+ <option
+ value="<?= $semester['semester_id'] ?>" <?= $current_semester['semester_id'] == $semester['semester_id'] ? 'selected="selected"' : '' ?>>
+ <?= htmlReady($semester['name']) ?>
+ <?= $semester['beginn'] < time() && $semester['ende'] > time() ? _('*') : '' ?>
+ </option>
+ <? endif ?>
+ <? endforeach ?>
+ </select>
+ <noscript>
+ <?= Icon::create(
+ 'accept',
+ Icon::ROLE_ACCEPT,
+ ['title' => _('auswählen')]
+ )->asInput(['type' => 'image', 'class' => 'middle']) ?>
+ </noscript>
+</form>
diff --git a/app/views/calendar/schedule/entry.php b/app/views/calendar/schedule/entry.php
new file mode 100644
index 0000000..b780aae
--- /dev/null
+++ b/app/views/calendar/schedule/entry.php
@@ -0,0 +1,9 @@
+<? if ($show_entry && in_array($show_entry['type'], ['sem', 'virtual']) !== false) : ?>
+ <?= $this->render_partial('calendar/schedule/_entry_course.php') ?>
+ <? unset($this->show_entry) ?>
+<? elseif ($show_entry && $show_entry['type'] == 'inst') : ?>
+ <?= $this->render_partial('calendar/schedule/_entry_inst.php') ?>
+ <? unset($this->show_entry) ?>
+<? else : ?>
+ <?= $this->render_partial('calendar/schedule/_entry_schedule.php') ?>
+<? endif ?>
diff --git a/app/views/calendar/schedule/index.php b/app/views/calendar/schedule/index.php
new file mode 100644
index 0000000..60e6d69
--- /dev/null
+++ b/app/views/calendar/schedule/index.php
@@ -0,0 +1,84 @@
+<?php
+# Lifter010: TODO
+$zoom = $my_schedule_settings['zoom'];
+
+$sidebar = Sidebar::get();
+
+$semester_widget = new SidebarWidget();
+$semester_widget->setTitle(_('Angezeigtes Semester'));
+$semester_widget->addElement(
+ new WidgetElement($this->render_partial('calendar/schedule/_semester_chooser')),
+ 'semester'
+);
+$sidebar->addWidget($semester_widget, 'calendar/schedule/semester');
+
+$actions = new ActionsWidget();
+if (!$inst_mode) {
+ $actions->addLink(
+ _('Neuer Eintrag'),
+ $controller->url_for('calendar/schedule/entry'),
+ Icon::create('date+add'),
+ ['data-dialog' => 'size=auto']
+ );
+}
+$actions->addLink(
+ _('Darstellung ändern'),
+ $controller->url_for('calendar/schedule/settings'),
+ Icon::create('admin'),
+ ['data-dialog' => 'size=auto']
+);
+if (!$show_hidden) {
+ $actions->addLink(
+ _('Ausgeblendete Veranstaltungen anzeigen'),
+ $controller->url_for('calendar/schedule', ['show_hidden' => '1']),
+ Icon::create('visibility-invisible')
+ );
+} else {
+ $actions->addLink(
+ _('Ausgeblendete Veranstaltungen verbergen'),
+ $controller->url_for('calendar/schedule', ['show_hidden' => '0']),
+ Icon::create('visibility-visible')
+ );
+}
+$sidebar->addWidget($actions, 'calendar/schedule/actions');
+
+$widget = new ExportWidget();
+$widget->addLink(_('Druckansicht'),
+ $controller->url_for(
+ 'calendar/schedule/index/' . implode(',', $days),
+ [
+ 'printview' => 'true',
+ 'semester_id' => $current_semester['semester_id'],
+ ]
+ ),
+ Icon::create('print'),
+ ['target' => '_blank']);
+$sidebar->addWidget($widget, 'calendar/schedule/print');
+
+$options = new OptionsWidget();
+$options->setTitle(_('Darstellungsgröße'));
+$options->addRadioButton(_('klein'), URLHelper::getURL('', ['zoom' => 0]), $zoom == 0);
+$options->addRadioButton(_('mittel'), URLHelper::getURL('', ['zoom' => 1]), $zoom == 1);
+$options->addRadioButton(_('groß'), URLHelper::getURL('', ['zoom' => 2]), $zoom == 2);
+$sidebar->addWidget($options, 'calendar/schedule/options');
+
+?>
+<div style="text-align: center; font-weight: bold; font-size: 1.2em">
+ <? if ($inst_mode) : ?>
+ <?= htmlReady($institute_name) ?>: <?= _('Stundenplan im') ?>
+ <? else : ?>
+ <?= _('Mein Stundenplan im') ?>
+ <? endif ?>
+ <?= htmlReady($current_semester['name']) ?>
+</div>
+
+<? if ($show_entry) : ?>
+ <div class="ui-widget-overlay" style="width: 100%; height: 100%; z-index: 1001;"></div>
+ <?= $this->render_partial('calendar/schedule/_dialog', [
+ 'content_for_layout' => $this->render_partial('calendar/schedule/entry', [
+ 'show_entry' => $show_entry]),
+ 'title' => _('Termindetails')
+ ]) ?>
+<? endif ?>
+
+<?= $calendar_view->render(['show_hidden' => $show_hidden]) ?>
diff --git a/app/views/calendar/schedule/settings.php b/app/views/calendar/schedule/settings.php
new file mode 100644
index 0000000..a9f24b2
--- /dev/null
+++ b/app/views/calendar/schedule/settings.php
@@ -0,0 +1,41 @@
+<form class="default" method="post" action="<?= $controller->link_for('calendar/schedule/storesettings') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Darstellung des Stundenplans ändern') ?>
+ </legend>
+ <section>
+ <?= _('Angezeigter Zeitraum') ?>
+ <section class="hgroup">
+ <label>
+ <?= _('von') ?>
+ <input type="text" name="start_hour" id="start-hour" class="size-s"
+ value="<?= sprintf('%02u:00', $settings['glb_start_time']) ?>"
+ data-time-picker>
+ </label>
+ <label>
+ <?= _('bis') ?>
+ <input type="text" name="end_hour" id="end-hour" class="size-s"
+ value="<?= sprintf('%02u:00', $settings['glb_end_time']) ?>"
+ data-time-picker>
+ </label>
+ <?= _('Uhr') ?><br>
+ </section>
+ </section>
+ <section class='settings'>
+ <?= _('Angezeigte Wochentage') ?>
+ <? foreach ([1, 2, 3, 4, 5, 6, 0] as $day) : ?>
+ <label>
+ <input type="checkbox" name="days[]" value="<?= $day ?>"
+ <?= in_array($day, $settings['glb_days']) !== false ? 'checked' : '' ?>>
+ <?= getWeekDay($day, false) ?>
+ </label>
+ <? endforeach ?>
+ <span class="invalid_message"><?= _('Bitte mindestens einen Wochentag auswählen.') ?></span><br>
+ </section>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Studip\Button::createSuccess(_('Speichern'), ['onclick' => "return STUDIP.Calendar.validateNumberOfDays();"]) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('calendar/schedule/#')) ?>
+ </footer>
+</form>
diff --git a/app/views/calendar/single/_attendees.php b/app/views/calendar/single/_attendees.php
new file mode 100644
index 0000000..c2ee568
--- /dev/null
+++ b/app/views/calendar/single/_attendees.php
@@ -0,0 +1,31 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? $show_members = $event->attendees->findOneBy('range_id',
+ $calendar->getRangeId(), '!=') ?>
+<? // Entkommentieren, wenn Mitglieder eines Termins sichtbar sein
+ // sollen, auch wenn man nicht selbst Mitglied ist und ... ?>
+<? // $show_members_visiter = $event->attendees->findOneBy('range_id', $GLOBALS['user']->id) ?>
+<? // folgende Zeile auskommentieren (siehe _attendees.php). ?>
+<? $show_members_visiter = true; ?>
+<? if ($show_members && $show_members_visiter) : ?>
+ <? $group_status = [
+ CalendarEvent::PARTSTAT_TENTATIVE => _('Abwartend'),
+ CalendarEvent::PARTSTAT_ACCEPTED => _('Angenommen'),
+ CalendarEvent::PARTSTAT_DECLINED => _('Abgelehnt'),
+ CalendarEvent::PARTSTAT_DELEGATED => _('Angenommen (keine Teilnahme)'),
+ CalendarEvent::PARTSTAT_NEEDS_ACTION => ''] ?>
+ <div>
+ <b><?= _('Teilnehmende:') ?></b>
+ <?= implode(', ', $event->attendees->map(
+ function ($att) use ($event, $group_status) {
+ $profil_link = ObjectdisplayHelper::link($att->user);
+ if ($event->havePermission(Event::PERMISSION_OWN, $att->user->getId())) {
+ $profil_link .= ' (' . _('Organisator') . ')';
+ } else {
+ if ($group_status[$att->group_status]) {
+ $profil_link .= ' (' . $group_status[$att->group_status] . ')';
+ }
+ }
+ return $profil_link;
+ })); ?>
+ </div>
+<? endif; ?>
diff --git a/app/views/calendar/single/_calhead.php b/app/views/calendar/single/_calhead.php
new file mode 100644
index 0000000..0d3e777
--- /dev/null
+++ b/app/views/calendar/single/_calhead.php
@@ -0,0 +1,16 @@
+<div class="calhead" style="white-space: nowrap; position: relative;">
+ <label>
+ <?= $calLabel ?>
+ <?= Icon::create('arr_1down', 'clickable') ?>
+
+ <input type="text"
+ id="date-chooser"
+ value="<?= strftime('%F', $atime) ?>"
+ data-url="<?= $controller->url_for('calendar/single/' . $calType, ['atime' => '%ATIME%']) ?>"
+ style="width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; left: 50%; z-index: -1;">
+ </label>
+
+ <script>
+ jQuery('#date-chooser').datepicker({ dateFormat: 'yy-mm-dd', onSelect: function () { window.location = $(this).data('url').replace(encodeURI("%ATIME%"), Math.floor($(this).datepicker('getDate').valueOf() / 1000)) } })
+ </script>
+</div>
diff --git a/app/views/calendar/single/_calhead_label_day.php b/app/views/calendar/single/_calhead_label_day.php
new file mode 100644
index 0000000..48d832f
--- /dev/null
+++ b/app/views/calendar/single/_calhead_label_day.php
@@ -0,0 +1,3 @@
+<span class="hidden-tiny-down"><?= strftime('%A, ', $atime) ?></span>
+<?= strftime('%d.%m.%Y', $atime) ?>
+<span class="hidden-medium-down" style="font-size: 12pt; color: #bbb; font-weight: bold;"><? $hd = holiday($atime); echo $hd['name']; ?></span>
diff --git a/app/views/calendar/single/_calhead_label_week.php b/app/views/calendar/single/_calhead_label_week.php
new file mode 100644
index 0000000..fc0a544
--- /dev/null
+++ b/app/views/calendar/single/_calhead_label_week.php
@@ -0,0 +1,3 @@
+<? printf(_("%s. Woche"), strftime("%V", $calendars[0]->getStart())) ?>
+<span class="hidden-large-up"><?= date('Y', $calendars[0]->getStart()) ?></span>
+<span class="hidden-medium-down"><? printf(_("vom %s bis %s"), strftime("%x", $calendars[0]->getStart()), strftime("%x", $calendars[$week_type - 1]->getStart())) ?></span>
diff --git a/app/views/calendar/single/_day.php b/app/views/calendar/single/_day.php
new file mode 100644
index 0000000..8b70fe9
--- /dev/null
+++ b/app/views/calendar/single/_day.php
@@ -0,0 +1,90 @@
+<?
+$at = date('G', $atime);
+if ($at >= $settings['start']
+ && $at <= $settings['end'] || !$atime) {
+ $start = $settings['start'] * 3600;
+ $end = $settings['end'] * 3600;
+} elseif ($at < $settings['start']) {
+ $start = 0;
+ $end = ($settings['start'] + 2) * 3600;
+} else {
+ $start = ($settings['end'] - 2) * 3600;
+ $end = 23 * 3600;
+}
+$em = $calendar->createEventMatrix($start, $end, $settings['step_day']);
+$max_columns = $em['max_cols'] ?: 1;
+?>
+
+<nav class="calendar-nav">
+ <span style="white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/single/day', ['atime' => strtotime('-1 day', $atime)]) ?>">
+ <?= Icon::create('arr_1left', 'clickable', ['title' => _('Einen Tag zurück')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ <span class="hidden-tiny-down">
+ <?= strftime(_('%x'), strtotime('-1 day', $calendar->getStart())) ?>
+ </span>
+ </a>
+ </span>
+
+ <?
+ $calType = 'day';
+ $calLabel = $this->render_partial('calendar/single/_calhead_label_day');
+ ?>
+
+ <?= $this->render_partial('calendar/single/_calhead', compact('calendar', 'atime', 'calType', 'calLabel')) ?>
+
+ <span style="white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/single/day', ['atime' => strtotime('+1 day', $atime)]) ?>">
+ <span class="hidden-tiny-down">
+ <?= strftime(_('%x'), strtotime('+1 day', $calendar->getStart())) ?>
+ </span>
+ <?= Icon::create('arr_1right', 'clickable', ['title' => _('Einen Tag vor')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ </a>
+ </span>
+</nav>
+
+<table class="calendar-day">
+ <colgroup>
+ <col style="max-width: 2em; width: 2em;">
+ <? if ($settings['step_day'] < 3600) : ?>
+ <col style="max-width: 2em; width: 2em;">
+ <? $max_columns_head = $max_columns + 3 ?>
+ <? else : ?>
+ <? $max_columns_head = $max_columns + 2 ?>
+ <? endif; ?>
+ <col span="<?= $em['max_cols'] ?: '1' ?>" style="width: <?= 100 / ($em['max_cols'] ?: 1) ?>%">
+ <col style="max-width: 0.8em; width: 0.8em;">
+ </colgroup>
+ <thead>
+ <? if ($start > 0) : ?>
+ <tr>
+ <td align="center"<?= $settings['step_day'] < 3600 ? ' colspan="2"' : '' ?>>
+ <a href="<?= $controller->url_for('calendar/single/day', ['atime' => ($atime - (date('G', $atime) * 3600 - $start + 3600))]) ?>">
+ <?= Icon::create('arr_1up', 'clickable', ['title' => _('Früher')])->asImg() ?>
+ </a>
+ </td>
+ <td colspan="<?= $max_columns + 1 ?>">
+ </td>
+ </tr>
+ <? endif; ?>
+ </thead>
+ <tbody>
+ <?= $this->render_partial('calendar/single/_day_table', ['start' => $start, 'end' => $end, 'em' => $em]) ?>
+ </tbody>
+ <tfoot>
+ <? if ($end / 3600 < 23) : ?>
+ <tr>
+ <td align="center"<?= $settings['step_day'] < 3600 ? ' colspan="2"' : '' ?>>
+ <a href="<?= $controller->url_for('calendar/single/day', ['atime' => ($atime + $end - date('G', $atime) * 3600 + 3600)]) ?>">
+ <?= Icon::create('arr_1down', 'clickable', ['title' => _('Später')])->asImg() ?>
+ </a>
+ </td>
+ <td colspan="<?= $max_columns + 1 ?>">
+ </td>
+ </tr>
+ <? else : ?>
+ <tr>
+ <td>&nbsp;</td>
+ </tr>
+ <? endif ?>
+ </tfoot>
+</table>
diff --git a/app/views/calendar/single/_day_cell.php b/app/views/calendar/single/_day_cell.php
new file mode 100644
index 0000000..058f628
--- /dev/null
+++ b/app/views/calendar/single/_day_cell.php
@@ -0,0 +1,54 @@
+<? $link_notset = true ?>
+<? $atime_new = $calendar->getStart() + $i * $step ?>
+<? if (!$em['term'][$row]) : ?>
+ <? if ($calendar->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <td class="calendar-day-edit <?= $class_cell ?>" <?= ($em['max_cols'] > 0 ? ' colspan="' . ($em['max_cols'] + 1) . '"' : '') ?>>
+ <a title="<?= strftime(_('Neuer Termin am %x, %R Uhr'), $atime_new) ?>" href="<?= $controller->url_for('calendar/single/edit/' . $calendar->getRangeId(), ['atime' => $atime_new]) ?>">+</a>
+ </td>
+ <? else : ?>
+ <td class="calendar-day-edit <?= $class_cell ?>" <?= ($em['max_cols'] > 0 ? ' colspan="' . ($em['max_cols'] + 1) . '"' : '') ?>>
+ </td>
+ <? endif; ?>
+<? $link_notset = false ?>
+<? else : ?>
+ <? for ($j = 0; $j < $em['colsp'][$row]; $j++) : ?>
+ <? $event = $em['term'][$row][$j]; ?>
+ <? $mapped_event = $calendar->events[$em['mapping'][$row][$j]]; ?>
+ <? if (is_object($event)) : ?>
+ <td data-tooltip<?= ($em['cspan'][$row][$j] > 1 ? ' colspan="' . $em['cspan'][$row][$j] . '"' : '') ?><?= ($em['rows'][$row][$j] > 1 ? ' rowspan="' . $em['rows'][$row][$j] . '"' : '') ?> class="<?= $event instanceof CourseEvent ? 'calendar-course-category' : 'calendar-category' ?><?= $event->getCategory() ?> calendar-day-event">
+ <? if ($em['rows'][$row][$j] > 1) : ?>
+ <div>
+ <?= date('H.i-', $mapped_event->getStart()) . date('H.i', $mapped_event->getEnd()) ?>
+ </div>
+ <? endif ?>
+ <div class="calendar-day-event-title">
+ <a title="<?= _('Termin bearbeiten') ?>" href="<?= $controller->url_for('calendar/single/edit/' . $calendar->getRangeId() . '/' . $event->event_id, ['atime' => $atime_new, 'evtype' => $event->getType()]) ?>"><?= htmlReady($event->getTitle()) ?></a>
+ <?= $this->render_partial('calendar/single/_tooltip', ['event' => $mapped_event]) ?>
+ </div>
+ </td>
+ <? elseif ($event == '#') : ?>
+ <td class="<?= $class_cell ?>"<?= ($em['cspan'][$row][$j] > 1 ? ' colspan="' . $em['cspan'][$row][$j] . '"' : '') ?>>
+ <span class="inday">&nbsp;</span>
+ </td>
+ <? elseif ($event == '') : ?>
+ <? if ($calendar->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <td class="calendar-day-edit <?= $class_cell ?>"<?= ($em['cspan'][$row][$j] > 1 ? ' colspan="' . $em['cspan'][$row][$j] . '"' : '') ?>>
+ <a title="<?= strftime(_('Neuer Termin am %x, %R Uhr'), $atime_new) ?>" href="<?= $controller->url_for('calendar/single/edit/' . $calendar->getRangeId(), ['atime' => $atime_new]) ?>">+</a>
+ </td>
+ <? else : ?>
+ <td class="calendar-day-edit <?= $class_cell ?>"<?= ($em['cspan'][$row][$j] > 1 ? ' colspan="' . $em['cspan'][$row][$j] . '"' : '') ?>></td>
+ <? endif ?>
+ <? $link_notset = false; ?>
+ <? break; ?>
+ <? endif ?>
+ <? endfor ?>
+<? endif ?>
+<? if ($link_notset) : ?>
+ <? if ($calendar->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <td class="calendar-day-edit <?= $class_cell ?>">
+ <a title="<?= strftime(_('Neuer Termin am %x, %R Uhr'), $atime_new) ?>" href="<?= $controller->url_for('calendar/single/edit/' . $calendar->getRangeId(), ['atime' => $atime_new]) ?>">+</a>
+ </td>
+ <? else : ?>
+ <td class="calendar-day-edit <?= $class_cell ?>"></td>
+ <? endif; ?>
+<? endif ?>
diff --git a/app/views/calendar/single/_day_dayevents.php b/app/views/calendar/single/_day_dayevents.php
new file mode 100644
index 0000000..397f0bf
--- /dev/null
+++ b/app/views/calendar/single/_day_dayevents.php
@@ -0,0 +1,33 @@
+<? if (isset($em['day_events']) && count($em['day_events']) > 0) : ?>
+ <td class="<?= $class_cell ?>" style="padding: 0px;" <?= (($em['max_cols'] > 0) ? ' colspan="' . ($em['max_cols']) . '"' : '') ?>>
+ <table style="width: 100%; border-spacing: 0;">
+ <? $i = 0; ?>
+ <? foreach ($em['day_events'] as $day_event) : ?>
+ <tr>
+ <? if ($day_event->getPermission() == Event::PERMISSION_CONFIDENTIAL) : ?>
+ <td class="calendar-category<?= $day_event->getCategory() ?>">
+ <?= htmlReady($day_event->getTitle()) ?>
+ </td>
+ <? else : ?>
+ <td data-tooltip onclick="STUDIP.Dialog.fromElement(jQuery(this).children('a').first(), {size: 'auto'}); return false;" class="calendar-category<?= $day_event->getCategory() ?>">
+ <?= $this->render_partial('calendar/single/_tooltip', ['event' => $calendar->events[$em['day_map'][$i]]]) ?>
+ <a style="color:#fff;" data-dialog="size=auto" href="<?= $controller->url_for('calendar/single/edit/' . $calendar->getRangeId() . '/' . $day_event->event_id, ['isdayevent' => '1']) ?>"><?= htmlReady($day_event->getTitle()) ?></a>
+ </td>
+ <? endif; ?>
+ </tr>
+ <? $i++; ?>
+ <? endforeach ?>
+ </table>
+ </td>
+ <td class="calendar-day-edit <?= $class_cell ?>" onclick="STUDIP.Dialog.fromElement(jQuery(this).children('a').first(), {size: 'auto'}); return false;">
+ <? if ($calendar->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Tagestermin am %x'), $calendar->getStart()) ?>" href="<?= $controller->url_for('calendar/single/edit/' . $calendar->getRangeId(), ['atime' => $calendar->getStart(), 'isdayevent' => '1']) ?>">+</a>
+ <? endif; ?>
+ </td>
+<? else : ?>
+ <td class="calendar-day-edit <?= $class_cell ?>" <?= (($em['max_cols'] > 0) ? ' colspan="' . ($em['max_cols'] + 1) . '"' : '') ?>>
+ <? if ($calendar->havePermission(Calendar::PERMISSION_WRITABLE)) : ?>
+ <a data-dialog="size=auto" title="<?= strftime(_('Neuer Tagestermin am %x'), $calendar->getStart()) ?>" href="<?= $controller->url_for('calendar/single/edit/' . $calendar->getRangeId(), ['atime' => $calendar->getStart(), 'isdayevent' => '1']) ?>">+</a>
+ <? endif; ?>
+ </td>
+<? endif; ?>
diff --git a/app/views/calendar/single/_day_table.php b/app/views/calendar/single/_day_table.php
new file mode 100644
index 0000000..1b0ebcd
--- /dev/null
+++ b/app/views/calendar/single/_day_table.php
@@ -0,0 +1,28 @@
+<?
+if ($settings['step_day'] >= 3600) {
+ $rowspan_precol = '';
+} else {
+ $rowspan_precol = ' rowspan="' . 3600 / $settings['step_day'] . '"';
+}
+?>
+<tr>
+ <td class="precol1w" <?= $rowspan_precol ? ' colspan="2"' : '' ?>><?= _('Tag') ?></td>
+ <?= $this->render_partial('calendar/single/_day_dayevents', ['em' => $em]); ?>
+</tr>
+<? for ($i = $start / $settings['step_day']; $i < $end / $settings['step_day'] + 3600 / $settings['step_day']; $i++) : ?>
+<? $row = $i - $start / $settings['step_day']; ?>
+<tr>
+ <? if (($i * $settings['step_day']) % 3600 == 0) : ?>
+ <td class="precol1w" <?= $rowspan_precol ?>>
+ <?= $i / (3600 / $settings['step_day']) ?>
+ </td>
+ <? endif ?>
+ <? if ($settings['step_day'] % 3600 != 0) : ?>
+ <? $minute = ($row % (3600 / $settings['step_day'])) * ($settings['step_day'] / 60); ?>
+ <td class="precol2w" style="height: 20px; width: 1%; padding-right: 3px;">
+ <?= $minute ? $minute : '00' ?>
+ </td>
+ <? endif ?>
+ <?= $this->render_partial('calendar/single/_day_cell', ['events' => $calendar->events, 'start' => $start, 'em' => $em, 'row' => $row, 'i' => $i, 'step' => $settings['step_day']]); ?>
+</tr>
+<? endfor; ?> \ No newline at end of file
diff --git a/app/views/calendar/single/_edit_status.php b/app/views/calendar/single/_edit_status.php
new file mode 100644
index 0000000..b5f41aa
--- /dev/null
+++ b/app/views/calendar/single/_edit_status.php
@@ -0,0 +1,48 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<form action="" method="post">
+ <div>
+ <b><?= _('Eigener Teilnahmestatus') ?>:</b>
+ <? $group_status = [
+ CalendarEvent::PARTSTAT_TENTATIVE => _('Abwartend'),
+ CalendarEvent::PARTSTAT_ACCEPTED => _('Angenommen'),
+ CalendarEvent::PARTSTAT_DECLINED => _('Abgelehnt'),
+ CalendarEvent::PARTSTAT_DELEGATED => _('Angenommen (keine Teilnahme)')] ?>
+ <ul>
+ <? foreach ($group_status as $value => $name) : ?>
+ <ul class="list-unstyled">
+ <label>
+ <input type="radio" value="<?= $value ?>" name="status" <?= $value == $event->group_status ? ' checked' : '' ?>>
+ <?= $name ?>
+ </label>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+ <div>
+ <? $author = $event->getAuthor() ?>
+ <? if ($author) : ?>
+ <?= sprintf(_('Eingetragen am: %s von %s'),
+ strftime('%x, %X', $event->mkdate),
+ htmlReady($author->getFullName('no_title'))) ?>
+ <? endif; ?>
+ </div>
+ <? if ($event->event->mkdate < $event->event->chdate) : ?>
+ <? $editor = $event->getEditor() ?>
+ <? if ($editor) : ?>
+ <div>
+ <?= sprintf(_('Zuletzt bearbeitet am: %s von %s'),
+ strftime('%x, %X', $event->chdate),
+ htmlReady($editor->getFullName('no_title'))) ?>
+ </div>
+ <? endif; ?>
+ <? endif; ?>
+ <div style="text-align: center;" data-dialog-button>
+ <?= Button::create(_('Speichern'), 'store', ['title' => _('Termin speichern')]) ?>
+ <? if ($event->havePermission(Event::PERMISSION_DELETABLE)) : ?>
+ <?= LinkButton::create(_('Löschen'), $controller->url_for('calendar/single/delete/' . implode('/', $event->getId()))) ?>
+ <? endif; ?>
+ <? if (!Request::isXhr()) : ?>
+ <?= LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view, [$event->getStart()])) ?>
+ <? endif; ?>
+ </div>
+</form>
diff --git a/app/views/calendar/single/_event_data.php b/app/views/calendar/single/_event_data.php
new file mode 100644
index 0000000..da9a5fe
--- /dev/null
+++ b/app/views/calendar/single/_event_data.php
@@ -0,0 +1,100 @@
+<? use Studip\LinkButton; ?>
+<div>
+ <h4><?= htmlReady($event->getTitle()) ?></h4>
+ <div>
+ <b><?= _('Beginn') ?>:</b> <?= strftime('%c', $event->getStart()) ?>
+ </div>
+ <div>
+ <b><?= _('Ende') ?>:</b> <?= strftime('%c', $event->getEnd()) ?>
+ </div>
+ <? if ($event->havePermission(Event::PERMISSION_READABLE)) : ?>
+ <? if ($event instanceof CourseEvent) : ?>
+ <div>
+ <b><?= _('Veranstaltung') ?>:</b>
+ <? if ($GLOBALS['perm']->have_studip_perm('user', $event->range_id)) : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details/?cid=' . $event->range_id) ?>">
+ <? else : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details/index/' . $event->range_id) ?>">
+ <? endif; ?>
+ <?= htmlReady($event->course->getFullname()) ?>
+ </a>
+ </div>
+ <? endif;?>
+ <? if ($text = $event->getDescription()) : ?>
+ <div>
+ <b><?= _('Beschreibung') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->toStringCategories()) : ?>
+ <div>
+ <b><?= _('Kategorie') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->getLocation()) : ?>
+ <div>
+ <b><?= _('Raum/Ort') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->toStringPriority()) : ?>
+ <div>
+ <b><?= _('Priorität') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->toStringAccessibility()) : ?>
+ <div>
+ <b><?= _('Zugriff') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->toStringRecurrence()) : ?>
+ <div>
+ <b><?= _('Wiederholung') ?>:</b> <?= htmlReady($text) ?>
+ </div>
+ <? endif; ?>
+ <? if ($event instanceof CalendarEvent) : ?>
+ <? if (Config::get()->CALENDAR_GROUP_ENABLE) : ?>
+ <?= $this->render_partial('calendar/single/_attendees.php') ?>
+ <? if ($calendar->havePermission(Calendar::PERMISSION_OWN)
+ && $event->toStringGroupStatus()) : ?>
+ <?= $this->render_partial('calendar/single/_edit_status') ?>
+ <? else : ?>
+ <div style="text-align: center;" data-dialog-button>
+ <? if ($event->havePermission(Event::PERMISSION_DELETABLE)) : ?>
+ <?= LinkButton::create(_('Löschen'), $controller->url_for('calendar/single/delete/' . implode('/', $event->getId()))) ?>
+ <? endif; ?>
+ <? if (!Request::isXhr()) : ?>
+ <?= LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view, [$event->getStart()])) ?>
+ <? endif; ?>
+ </div>
+ <? endif; ?>
+ <? endif; ?>
+ <? else : ?>
+ <? // durchführende Lehrende ?>
+ <? $related_persons = $event->dozenten; ?>
+ <? if (sizeof($related_persons)) : ?>
+ <div>
+ <b><?= ngettext('Durchführende Lehrperson', 'Durchführende Lehrende', sizeof($related_persons)) ?>:</b>
+ <ul class="list-unstyled">
+ <? foreach ($related_persons as $related_person) : ?>
+ <li>
+ <?= ObjectdisplayHelper::link($related_person) ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+ <? endif; ?>
+ <? // related groups ?>
+ <? $related_groups = $event->getRelatedGroups(); ?>
+ <? if (sizeof($related_groups)) : ?>
+ <div>
+ <b><?= _('Betroffene Gruppen') ?>:</b>
+ <?= htmlReady(implode(', ', $related_groups->pluck('name'))) ?>
+ </div>
+ <? endif; ?>
+ <? if (!Request::isXhr()) : ?>
+ <div style="text-align: center;" data-dialog-button>
+ <?= LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view, [$event->getStart()])) ?>
+ </div>
+ <? endif; ?>
+ <? endif; ?>
+ <? endif; ?>
+</div>
diff --git a/app/views/calendar/single/_include_month.php b/app/views/calendar/single/_include_month.php
new file mode 100644
index 0000000..342a386
--- /dev/null
+++ b/app/views/calendar/single/_include_month.php
@@ -0,0 +1,132 @@
+<? $now = mktime(12, 0, 0, date('n', time()), date('j', time()), date('Y', time())); ?>
+<table class="blank">
+ <tr>
+ <td style="text-align: center;">
+ <table style="width: 100%;">
+ <tr>
+ <td colspan="8" style="vertical-align: top; text-align: center; white-space:nowrap;">
+ <div style="float:left; width:15%;">
+ <? if ($mod == 'NONAVARROWS') : ?>
+ &nbsp;
+ <? else : ?>
+ <a href="<?= $controller->url_for($href, ['imt' => mktime(12, 0, 0, date('n', $imt), 1, date('Y', $imt) - 1)]) ?>">
+ <?= Icon::create('arr_2left', 'clickable', ['title' => _('Ein Jahr zurück')])->asImg() ?>
+ </a>
+ <a href="<?= $controller->url_for($href, ['imt' => mktime(12, 0, 0, date('n', $imt) - 1, 1, date('Y', $imt))]) ?>">
+ <?= Icon::create('arr_1left', 'clickable', ['title' => _('Einen Monat zurück')])->asImg() ?>
+ </a>
+ <? endif; ?>
+ </div>
+ <div class="precol1w" style="float:left; text-align:center; width:70%;">
+ <?= sprintf("%s %s\n", strftime('%B', $imt), date('Y', $imt)) ?>
+ </div>
+ <div style="float:right; width:15%;">
+ <? if ($mod == 'NONAVARROWS') : ?>
+ &nbsp;
+ <? else : ?>
+ <a href="<?= $controller->url_for($href, ['imt' => mktime(12, 0, 0, date('n', $imt) + 1, 1, date('Y', $imt))]) ?>">
+ <?= Icon::create('arr_1right', 'clickable', ['title' => _('Einen Monat vor')])->asImg() ?>
+ </a>
+ <a href="<?= $controller->url_for($href, ['imt' => mktime(12, 0, 0, date('n', $imt), 1, date('Y', $imt) + 1)]) ?>">
+ <?= Icon::create('arr_2right', 'clickable', ['title' => _('Ein Jahr vor')])->asImg() ?>
+ </a>
+ <? endif; ?>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="blank">
+ <table class="blank">
+ <tr>
+ <? $week_days = [39092400, 39178800, 39265200, 39351600, 39438000, 39524400, 39610800]; ?>
+ <? foreach ($week_days as $week_day) : ?>
+ <td align="center" class="precol2w" width="25">
+ <?= strftime('%a', $week_day) ?>
+ </td>
+ <? endforeach; ?>
+ <td class="precol2w" width="25"> </td>
+ </tr>
+ <? $adow = date('w', mktime(12, 0, 0, date('n', $imt), 1, date('Y', $imt))); ?>
+ <? if ($adow == 0) : ?>
+ <? $adow = 6; ?>
+ <? else : ?>
+ <? $adow--; ?>
+ <? endif; ?>
+ <? $first_day = mktime(12, 0, 0, date('n', $imt), 1, date('Y', $imt)) - $adow * 86400; ?>
+ <? $cor = 0; ?>
+ <? if (date('n', $imt) == 3) : ?>
+ <? $cor = 1; ?>
+ <? endif; ?>
+ <? $last_day = ((42 - ($adow + date('t', mktime(12, 0, 0, date('n', $imt), 1, date('Y', $imt))))) % 7 + $cor) * 86400
+ + mktime(12, 0, 0, date('n', $imt), date('t', $imt), date('Y', $imt)); ?>
+ <? for ($i = $first_day, $j = 0; $i <= $last_day; $i += 86400, $j++) : ?>
+ <?
+ $aday = date('j', $i);
+ $style = '';
+ if (($aday - $j - 1 > 0) || ($j - $aday > 6)) {
+ $style = 'light';
+ }
+ $hday = holiday($i);
+ if ($j % 7 == 0) {
+ $ret .= '<tr>';
+ }
+ ?>
+ <? if (abs($now - $i) < 43199 && !($style == 'light')) : ?>
+ <td class="celltoday" align="center" width="25" height="25">
+ <? elseif (date('m', $i) != date('n', $imt)) : ?>
+ <td class="lightmonth" align="center" width="25" height="25">
+ <? else : ?>
+ <td class="month" align="center" width="25" height="25">
+ <? endif; ?>
+ <? $js_inc = ''; ?>
+ <? if (is_array($js_include)) : ?>
+ <?
+ $js_inc = " onClick=\"{$js_include['function']}(";
+ if (sizeof($js_include['parameters'])) {
+ $js_inc .= implode(", ", $js_include['parameters']) . ", ";
+ }
+ $js_inc .= "'" . date('m', $i) . "', '$aday', '" . date('Y', $i) . "')\"";
+ ?>
+ <? endif; ?>
+ <? if (abs($atime - $i) < 43199) : ?>
+ <? $aday = '<span class="current">'.$aday.'</span>' ?>
+ <? endif; ?>
+ <? if (($j + 1) % 7 == 0) : ?>
+ <a class="<?= $style ?>sday" href="<?= $controller->url_for($href, ['atime' => $i]) ?>" <?= $hday['name'] ? tooltip($hday['name']) : '' ?> <?= $js_inc ?>>
+ <?= $aday ?>
+ </a>
+ </td>
+ <td class="lightmonth" style="text-align: center; width: 25px; height: 25px;">
+ <a href="<?= $controller->url_for('calendar/single/week/', ['atime' => $i]) ?>">
+ <span class="kwmin"><?= strftime('%V', $i) ?></span>
+ </a>
+ </td>
+ </tr>
+ <? else : ?>
+ <? switch ($hday['col']) {
+ case 1:
+ ?><a class="<?= $style ?>day" href="<?= $controller->url_for($href, ['atime' => $i]) ?>" <?= tooltip($hday['name']) . $js_inc ?>>
+ <?= $aday ?>
+ </a><?
+ break;
+ case 2:
+ case 3;
+ ?><a class="<?= $style ?>hday" href="<?= $controller->url_for($href, ['atime' => $i]) ?>" <?= tooltip($hday['name']) . $js_inc ?>>
+ <?= $aday ?>
+ </a><?
+ break;
+ default:
+ ?><a class="<?= $style ?>day" href="<?= $controller->url_for($href, ['atime' => $i]) ?>" <?= $js_inc ?>>
+ <?= $aday ?>
+ </a>
+ <?}?>
+ </td>
+ <? endif; ?>
+ <? endfor; ?>
+ </table>
+ </td>
+ </tr>
+</table> \ No newline at end of file
diff --git a/app/views/calendar/single/_jump_to.php b/app/views/calendar/single/_jump_to.php
new file mode 100644
index 0000000..b5e96bb
--- /dev/null
+++ b/app/views/calendar/single/_jump_to.php
@@ -0,0 +1,13 @@
+<form class="default" action="<?= $action_url ?>" method="post" name="jump_to">
+ <input type="hidden" name="action" value="<?= $action ?>">
+
+ <section class="hgroup">
+ <?= _('Gehe zu:') ?>
+ <input size="10" style="width: 16em;" type="text" id="jmp_date" name="jmp_date" type="text" value="<?= strftime('%x', $atime)?>">
+ <?= Icon::create('accept', 'clickable')->asInput(['class' => 'text-top']) ?>
+ </section>
+</form>
+
+<script>
+ jQuery('#jmp_date').datepicker();
+</script>
diff --git a/app/views/calendar/single/_select_calendar.php b/app/views/calendar/single/_select_calendar.php
new file mode 100644
index 0000000..6b8ee1a
--- /dev/null
+++ b/app/views/calendar/single/_select_calendar.php
@@ -0,0 +1,80 @@
+<form name="select_calendars" class="default" method="post" action="<?= htmlReady($action_url) ?>">
+
+ <section class="hgroup">
+ <?= _('Kalender') ?>
+ <select class="sidebar-selectlist submit-upon-select" style="width: 16em;" name="range_id">
+ <option value="user.<?= get_username() ?>"<?= (get_userid() == $calendar_id ? ' selected' : '') ?>>
+ <?= _("Eigener Kalender") ?>
+ </option>
+ <? $groups = Calendar::getGroups($GLOBALS['user']->id); ?>
+ <? if (count($groups)) : ?>
+ <optgroup style="font-weight:bold;" label="<?= _('Gruppenkalender:') ?>">
+ <? foreach ($groups as $group) : ?>
+ <option value="<?= $group->getId() ?>"<?= ($range_id == $group->getId() ? ' selected' : '') ?>>
+ <?= htmlReady($group->name) ?>
+ </option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif; ?>
+ <? $calendar_users = CalendarUser::getOwners($GLOBALS['user']->id)->getArrayCopy(); ?>
+ <? usort($calendar_users, function ($a, $b) {
+ return strnatcmp($a->owner->Nachname, $b->owner->Nachname);
+ }); ?>
+ <? if (count($calendar_users)) : ?>
+ <optgroup style="font-weight:bold;" label="<?= _('Einzelkalender:') ?>">
+ <? foreach ($calendar_users as $calendar_user) : ?>
+ <? if (!$calendar_user->owner) {
+ continue;
+ } ?>
+ <option value="<?= $calendar_user->owner_id ?>"<?= ($range_id == $calendar_user->owner_id ? ' selected' : '') ?>>
+ <?= htmlReady($calendar_user->owner->getFullname('full_rev')) ?>
+ </option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ <?/*
+ if ($GLOBALS['perm']->have_perm('dozent')) {
+ $lecturers = Calendar::GetLecturers();
+ } else {
+ $lecturers = array();
+ }
+ */
+ $lecturers = [];
+ ?>
+ <? if (count($lecturers)) : ?>
+ <optgroup style="font-weight:bold;" label="<?= _('Lehrendenkalender:') ?>">
+ <? foreach ($lecturers as $lecturer) : ?>
+ <option value="<?= $lecturer['id'] ?>"<?= ($range_id == $lecturer['id'] ? ' selected' : '') ?>>
+ <?= htmlReady(my_substr($lecturer['name'] . " ({$lecturer['username']})", 0, 30)) ?>
+ </option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ <? if (Config::get()->COURSE_CALENDAR_ENABLE) : ?>
+ <? $courses = Calendar::GetCoursesActivatedCalendar($GLOBALS['user']->id); ?>
+ <? if (count($courses)) : ?>
+ <optgroup style="font-weight:bold;" label="<?= _('Veranstaltungskalender:') ?>">
+ <? foreach ($courses as $course) : ?>
+ <option value="<?= $course->id ?>"<?= ($range_id == $course->id ? ' selected' : '') ?>>
+ <?= htmlReady($course->getFullname()) ?>
+ </option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ <? $insts = Calendar::GetInstituteActivatedCalendar($GLOBALS['user']->id); ?>
+ <? if (count($insts)) : ?>
+ <optgroup style="font-weight:bold;" label="<?= _('Einrichtungskalender:') ?>">
+ <? foreach ($insts as $inst_id => $inst_name) : ?>
+ <option value="<?= $inst_id ?>"<?= ($range_id == $inst_id ? ' selected' : '') ?>>
+ <?= htmlReady(my_substr($inst_name, 0, 30)); ?>
+ </option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ <? endif ?>
+ </select>
+
+ <input type="hidden" name="view" value="<?= $view ?>">
+ <?= Icon::create('accept', 'clickable')->asInput(['class' => "text-top"]) ?>
+ </section>
+</form>
diff --git a/app/views/calendar/single/_select_category.php b/app/views/calendar/single/_select_category.php
new file mode 100644
index 0000000..fe86bdc
--- /dev/null
+++ b/app/views/calendar/single/_select_category.php
@@ -0,0 +1,16 @@
+<form class="default" name="filter_categories" method="post" action="<?= $action_url ?>">
+
+ <section class="hgroup">
+ <?= _('Kategorie') ?>
+ <select class="sidebar-selectlist nested-select submit-upon-select" style="width: 16em;" name="category">
+ <option value=""><?= _('Alle Kategorien') ?></option>
+ <? foreach (Config::get()->getValue('PERS_TERMIN_KAT') as $key => $cat) : ?>
+ <option value="<?= $key ?>"<?= ($category == $key ? ' selected="selected"' : '') ?> class="calendar-category<?= $key ?>" data-color-class="calendar-category<?= $key ?>">
+ <?= htmlReady($cat['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+
+ <?= Icon::create('accept', 'clickable')->asInput(['class' => "text-top"]) ?>
+ </section>
+</form>
diff --git a/app/views/calendar/single/_semester_filter.php b/app/views/calendar/single/_semester_filter.php
new file mode 100644
index 0000000..016f1e5
--- /dev/null
+++ b/app/views/calendar/single/_semester_filter.php
@@ -0,0 +1,30 @@
+<form data-dialog action="<?= $controller->url_for('calendar/single/seminar_events/')?>" class="default">
+ <section class="hgroup">
+ <label>
+ <?= _('Semesterfilter') ?>:
+ <select name="sem_select" class="submit-upon-select">
+ <option <?= ($sem == 'current' ? 'selected' : '')?> value="current"><?= _('Aktuelles Semester') ?></option>
+ <option <?= ($sem == 'future' ? 'selected' : '')?> value="future"><?= _('Aktuelles und nächstes Semester') ?></option>
+ <option <?= ($sem == 'last' ? 'selected' : '')?> value="last"><?= _('Aktuelles und letztes Semester') ?></option>
+ <option <?= ($sem == 'lastandnext' ? 'selected' : '')?> value="lastandnext"><?= _('Letztes, aktuelles, nächstes Semester') ?></option>
+ <? if (Config::get()->MY_COURSES_ENABLE_ALL_SEMESTERS) : ?>
+ <option <?= ($sem == 'all' ? 'selected' : '')?> value="all"><?= _('Alle Semester') ?></option>
+ <? endif ?>
+
+ <? if (!empty($semesters)) : ?>
+ <optgroup label="<?=_('Semester auswählen')?>">
+ <? foreach ($semesters as $semester) :?>
+ <option value="<?=$semester->id?>" <?= ($sem == $semester->id ? 'selected' : '')?>>
+ <?= htmlReady($semester->name)?>
+ </option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ </select>
+ </label>
+ </section>
+
+ <noscript>
+ <?= \Studip\Button::createAccept(_('Auswählen'))?>
+ </noscript>
+</form>
diff --git a/app/views/calendar/single/_tooltip.php b/app/views/calendar/single/_tooltip.php
new file mode 100644
index 0000000..0979ec2
--- /dev/null
+++ b/app/views/calendar/single/_tooltip.php
@@ -0,0 +1,113 @@
+<div class="calendar-tooltip tooltip-content">
+ <h4><?= htmlReady($event->getTitle()) ?></h4>
+ <div>
+ <b><?= _('Beginn') ?>:</b> <?= strftime('%c', $event->getStart()) ?>
+ </div>
+ <div>
+ <b><?= _('Ende') ?>:</b> <?= strftime('%c', $event->getEnd()) ?>
+ </div>
+ <? if ($event->havePermission(Event::PERMISSION_READABLE)) : ?>
+ <? if ($event instanceof CourseEvent) : ?>
+ <div>
+ <b><?= _('Veranstaltung') ?>:</b> <?= htmlReady($event->course->getFullname()) ?>
+ </div>
+ <? endif;?>
+ <? if ($text = $event->getDescription()) : ?>
+ <div>
+ <b><?= _('Beschreibung') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->toStringCategories()) : ?>
+ <div>
+ <b><?= _('Kategorie') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->getLocation()) : ?>
+ <div>
+ <b><?= _('Raum/Ort') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->toStringPriority()) : ?>
+ <div>
+ <b><?= _('Priorität') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->toStringAccessibility()) : ?>
+ <div>
+ <b><?= _('Zugriff') ?>:</b> <?= htmlReady(mila($text, 50)) ?>
+ </div>
+ <? endif; ?>
+ <? if ($text = $event->toStringRecurrence()) : ?>
+ <div>
+ <b><?= _('Wiederholung') ?>:</b> <?= htmlReady($text) ?>
+ </div>
+ <? endif; ?>
+ <? endif; ?>
+ <? if ($event->havePermission(Event::PERMISSION_READABLE)) : ?>
+ <? if ($event instanceof CalendarEvent
+ && Config::get()->CALENDAR_GROUP_ENABLE
+ && $calendar->getRange() == Calendar::RANGE_USER) : ?>
+ <? $group_status = [
+ CalendarEvent::PARTSTAT_TENTATIVE => _('Abwartend'),
+ CalendarEvent::PARTSTAT_ACCEPTED => _('Angenommen'),
+ CalendarEvent::PARTSTAT_DECLINED => _('Abgelehnt'),
+ CalendarEvent::PARTSTAT_DELEGATED => _('Angenommen (keine Teilnahme)'),
+ CalendarEvent::PARTSTAT_NEEDS_ACTION => ''] ?>
+ <? $show_members = $event->attendees->findOneBy('range_id',
+ $calendar->getRangeId(), '!=') ?>
+ <? // Entkommentieren, wenn Mitglieder eines Termins sichtbar sein
+ // sollen, auch wenn man nicht selbst Mitglied ist und ... ?>
+ <? // $show_members_visiter = $event->attendees->findOneBy('range_id', $GLOBALS['user']->id) ?>
+ <? // folgende Zeile auskommentieren (siehe _attendees.php). ?>
+ <? $show_members_visiter = true; ?>
+ <? if ($show_members && $show_members_visiter) : ?>
+ <div>
+ <b><?= _('Teilnehmende:') ?></b>
+ <?= implode(', ', $event->attendees->map(
+ function ($att) use ($event, $group_status) {
+ if ($event->havePermission(Event::PERMISSION_OWN, $att->owner->id)) {
+ $ret = htmlReady($att->owner->getFullname())
+ . ' (' . _('Organisator') . ')';
+ } else {
+ $ret = htmlReady($att->owner->getFullname());
+ if ($group_status[$att->group_status]) {
+ $ret .= ' (' . $group_status[$att->group_status] . ')';
+ }
+ }
+ return $ret;
+ })); ?>
+ </div>
+ <? endif; ?>
+ <? endif; ?>
+ <? if ($event instanceof CourseEvent) : ?>
+ <? // durchführende Lehrende ?>
+ <? $related_persons = $event->dozenten; ?>
+ <? if (sizeof($related_persons)) : ?>
+ <div>
+ <b><?= ngettext('Durchführende Lehrperson', 'Durchführende Lehrende', sizeof($related_persons)) ?>:</b>
+ <ul class="list-unstyled">
+ <? foreach ($related_persons as $related_person) : ?>
+ <li>
+ <?= htmlReady($related_person->getFullName()) ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+ <? endif; ?>
+ <? // related groups ?>
+ <? $related_groups = $event->getRelatedGroups(); ?>
+ <? if (sizeof($related_groups)) : ?>
+ <div>
+ <b><?= _('Betroffene Gruppen') ?>:</b>
+ <ul class="list-unstyled">
+ <? foreach ($related_groups as $group) : ?>
+ <li>
+ <?= htmlReady($group->name) ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+ <? endif; ?>
+ <? endif; ?>
+ <? endif; ?>
+</div>
diff --git a/app/views/calendar/single/day.php b/app/views/calendar/single/day.php
new file mode 100644
index 0000000..6d78a52
--- /dev/null
+++ b/app/views/calendar/single/day.php
@@ -0,0 +1,17 @@
+<?
+// add skip link
+SkipLinks::addIndex(_('Tagesansicht'), 'main_content', 100);
+?>
+<div style="width: 100%; display: flex; flex-wrap: wrap;">
+ <div style="flex-grow:2; flex-basis: 60%;">
+ <?= $this->render_partial('calendar/single/_day'); ?>
+ </div>
+ <div class="hidden-medium-down" style="flex-grow:1; padding-left:1em;">
+ <? $imt = Request::int('imt', mktime(12, 0, 0, date('n', $atime) - 1, date('j', $atime), date('Y', $atime))) ?>
+ <?= $this->render_partial('calendar/single/_include_month', ['imt' => $imt, 'href' => '']) ?>
+ <? $imt = mktime(12, 0, 0, date('n', $imt) + 1, date('j', $imt), date('Y', $imt)) ?>
+ <?= $this->render_partial('calendar/single/_include_month', ['imt' => $imt, 'href' => '', 'mod' => 'NONAVARROWS']) ?>
+ <? $imt = mktime(12, 0, 0, date('n', $imt) + 1, date('j', $imt), date('Y', $imt)) ?>
+ <?= $this->render_partial('calendar/single/_include_month', ['imt' => $imt, 'href' => '', 'mod' => 'NONAVARROWS']) ?>
+ </div>
+</div> \ No newline at end of file
diff --git a/app/views/calendar/single/edit.php b/app/views/calendar/single/edit.php
new file mode 100644
index 0000000..e8c3eb0
--- /dev/null
+++ b/app/views/calendar/single/edit.php
@@ -0,0 +1,456 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $messagebox) : ?>
+ <?= $messagebox ?>
+ <? endforeach ?>
+<? else : ?>
+ <? SkipLinks::addIndex(_('Termine anlegen/bearbeiten'), 'main_content', 100); ?>
+<? endif; ?>
+<form data-dialog="" method="post" action="<?= $controller->url_for($base . 'edit/' . $range_id . '/' . $event->event_id) ?>" class="default collapsable">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <? if ($event->isNew()) : ?>
+ <?= _('Neuen Termin anlegen') ?>
+ <? else : ?>
+ <?= _('Termin bearbeiten') ?>
+ <? endif; ?>
+ </legend>
+
+ <label class="hidden-tiny-down">
+ <input type="checkbox" name="isdayevent" value="1" <?= $event->isDayEvent() ? 'checked' : '' ?>
+ onChange="jQuery(this).closest('fieldset').find('input[size=\'2\']').prop('disabled', function (i,val) { return !val; });">
+ <?= _('Ganztägig') ?>
+ </label>
+
+ <section class="required">
+ <?= _('Beginn') ?>
+ </section>
+
+ <label class="col-3">
+ <?= _('Datum') ?>
+ <input type="text" name="start_date" id="start-date" value="<?= strftime('%x', $event->getStart()) ?>" size="12" required>
+ </label>
+
+ <div class="col-3">
+ <?= _('Uhrzeit') ?>
+
+ <div class="hgroup">
+ <input class="size-s no-hint"
+ type="text"
+ name="start_hour"
+ value="<?= date('G', $event->getStart()) ?>"
+ size="2"
+ maxlength="2"<?= $event->isDayEvent() ? ' disabled' : '' ?>
+ aria-label="Stunde">
+ :
+ <input class="size-s no-hint"
+ type="text"
+ name="start_minute"
+ value="<?= date('i', $event->getStart()) ?>"
+ size="2"
+ maxlength="2"<?= $event->isDayEvent() ? ' disabled' : '' ?>
+ aria-label="Minuten">
+ </div>
+ </div>
+
+ <section class="required">
+ <?= _('Ende') ?>
+ </section>
+
+ <label class="col-3">
+ <?= _('Datum') ?>
+ <input type="text" name="end_date" id="end-date" value="<?= strftime('%x', $event->getEnd()) ?>" size="12" required>
+ </label>
+
+ <div class="col-3">
+ <?= _('Uhrzeit') ?>
+
+ <div class="hgroup">
+ <input class="size-s no-hint"
+ type="text"
+ name="end_hour"
+ value="<?= date('G', $event->getEnd()) ?>"
+ size="2"
+ aria-label="<?= _("Stunde") ?>"
+ maxlength="2"<?= $event->isDayEvent() ? ' disabled' : '' ?>>
+ :
+ <input class="size-s no-hint"
+ type="text"
+ name="end_minute"
+ value="<?= date('i', $event->getEnd()) ?>"
+ size="2"
+ aria-label="<?= _("Minuten") ?>"
+ maxlength="2"<?= $event->isDayEvent() ? ' disabled' : '' ?>>
+ </div>
+ </div>
+
+ <label>
+ <span class="required">
+ <?= _('Zusammenfassung') ?>
+ </span>
+
+ <input type="text" size="50" name="summary" id="summary" value="<?= htmlReady($event->getTitle()) ?>">
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea rows="2" cols="40" id="description" name="description"><?= htmlReady($event->getDescription()) ?></textarea>
+ </label>
+
+ <label class="col-3">
+ <?= _('Kategorie') ?>
+ <select name="category_intern" id="category-intern" class="nested-select">
+ <? foreach ($GLOBALS['PERS_TERMIN_KAT'] as $key => $category) : ?>
+ <option value="<?= $key ?>" <?= $key == $event->getCategory() ? 'selected' : '' ?> class="calendar-category<?= $key ?>" data-color-class="calendar-category<?= $key ?>">
+ <?= htmlReady($category['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <?= tooltipicon(_('Sie können beliebige Kategorien in das Freitextfeld eingeben. Trennen Sie einzelne Kategorien bitte durch ein Komma.')) ?>
+ <input type="text" name="categories" value="<?= htmlReady($event->getUserDefinedCategories()) ?>"
+ placeholder="<?= _('Eigener Kategoriename') ?>">
+ </label>
+
+ <label>
+ <?= _('Raum/Ort') ?>
+ <input type="text" name="location" id="location" value="<?= htmlReady($event->getLocation()) ?>">
+ </label>
+
+ <? if ($calendar->getPermissionByUser($GLOBALS['user']->id) == Calendar::PERMISSION_OWN) : ?>
+ <? $info = _('Private und vertrauliche Termine sind nur für Sie sichtbar.') ?>
+
+ <? /* SEMBBS nur private und vertrauliche Termine
+ <? $info = _('Private und vertrauliche Termine sind nur für Sie sichtbar. Öffentliche Termine werden auf ihrer internen Homepage auch anderen Nutzern bekanntgegeben.') ?>
+ *
+ */ ?>
+
+ <? elseif ($calendar->getRange() == Calendar::RANGE_SEM) : ?>
+ <? $info = _('In Veranstaltungskalendern können nur private Termine angelegt werden.') ?>
+ <? elseif ($calendar->getRange() == Calendar::RANGE_INST) : ?>
+ <? $info = _('In Einrichtungskalendern können nur private Termine angelegt werden.') ?>
+ <? else : ?>
+ <? $info = _('Im Kalender eines anderen Nutzers können Sie nur private oder vertrauliche Termine einstellen. Vertrauliche Termine sind nur für Sie und den Kalenderbesitzer sichtbar. Alle anderen sehen den Termin nur als Besetztzeit.') ?>
+ <? endif; ?>
+
+ <label for="accessibility">
+ <?= _('Zugriff') ?>
+ <?= tooltipicon($info) ?>
+
+ <select name="accessibility" id="accessibility" size="1">
+ <? foreach ($event->getAccessibilityOptions($calendar->getPermissionByUser($GLOBALS['user']->id)) as $key => $option) : ?>
+ <option value="<?= $key ?>"<?= $event->getAccessibility() == $key ? ' selected' : '' ?>><?= $option ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Priorität') ?>
+
+ <? $priority_names = [_('Keine Angabe'), _('Hoch'), _('Mittel'), _('Niedrig')] ?>
+ <select name="priority" id="priority" size="1">
+ <? foreach ($priority_names as $key => $priority) : ?>
+ <option value="<?= $key ?>"<?= $key == $event->getPriority() ? ' selected' : '' ?>><?= $priority ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <? if (!$event->isNew() && Config::get()->CALENDAR_GROUP_ENABLE) : ?>
+ <section>
+ <? $author = $event->getAuthor() ?>
+ <? if ($author) : ?>
+ <?= sprintf(_('Eingetragen am: %s von %s'),
+ strftime('%x, %X', $event->mkdate),
+ htmlReady($author->getFullName('no_title'))) ?>
+ <? endif; ?>
+ </section>
+ <? if ($event->event->mkdate < $event->event->chdate) : ?>
+ <? $editor = $event->getEditor() ?>
+ <? if ($editor) : ?>
+ <section>
+ <?= sprintf(_('Zuletzt bearbeitet am: %s von %s'),
+ strftime('%x, %X', $event->chdate),
+ htmlReady($editor->getFullName('no_title'))) ?>
+ </section>
+ <? endif; ?>
+ <? endif; ?>
+ <? endif; ?>
+ </fieldset>
+
+
+ <fieldset class="collapsed">
+ <legend>
+ <?= _('Wiederholung') ?>
+ <? if ($event->getRecurrence('rtype') != 'SINGLE') : ?>
+ (<?= $event->toStringRecurrence() ?>)
+ <? endif ?>
+ </legend>
+
+ <h2><?= _('Wiederholungsart') ?></h2>
+
+ <section>
+ <? $linterval = $event->getRecurrence('linterval') ?: '1' ?>
+ <? $rec_type = $event->toStringRecurrence(true) ?>
+ <ul class="recurrences">
+ <li>
+ <label class="rec-label">
+ <input type="radio" class="rec-select" id="rec-none" name="recurrence" value="single"<?= $event->getRecurrence('rtype') == 'SINGLE' ? ' checked' : '' ?>>
+ <?= _('Keine') ?>
+ <?= tooltipIcon(_('Der Termin wird nicht wiederholt.')) ?>
+ </label>
+ </li>
+ <li>
+ <label class="rec-label">
+ <input type="radio" class="rec-select" id="rec-daily" name="recurrence" value="daily"<?= $event->getRecurrence('rtype') == 'DAILY' ? ' checked' : '' ?>>
+ <?= _('Täglich') ?>
+ </label>
+
+ <div class="rec-content" id="rec-content-daily">
+ <div class="hgroup">
+ <label>
+ <input type="radio" name="type_daily" value="day"<?= in_array($rec_type, ['daily', 'xdaily']) ? ' checked' : '' ?>>
+ <?= sprintf(_('Jeden %s. Tag'), '<input type="text" size="3" name="linterval_d" value="' . $linterval . '">') ?>
+ </label>
+ </div>
+
+ <label>
+ <input type="radio" name="type_daily" value="workday"<?= $rec_type == 'workdaily' ? ' checked' : '' ?>>
+ <?= _('Jeden Werktag') ?>
+ </label>
+ </div>
+ </li>
+ <li>
+ <? $wdays = [
+ '1' => _('Montag'),
+ '2' => _('Dienstag'),
+ '3' => _('Mittwoch'),
+ '4' => _('Donnerstag'),
+ '5' => _('Freitag'),
+ '6' => _('Samstag'),
+ '7' => _('Sonntag')] ?>
+ <label class="rec-label" for="rec-weekly">
+ <input type="radio" class="rec-select" id="rec-weekly" name="recurrence" value="weekly"<?= $event->getRecurrence('rtype') == 'WEEKLY' ? ' checked' : '' ?>>
+ <?= _('Wöchentlich') ?>
+ </label>
+ <div class="rec-content" id="rec-content-weekly">
+ <div class="hgroup">
+ <label>
+ <?= sprintf(_('Jede %s. Woche am:'), '<input type="text" size="3" name="linterval_w" value="' . $linterval . '">') ?>
+ </label>
+ </div>
+ <div>
+ <? $aday = $event->getRecurrence('wdays') ?: date('N', $event->getStart()) ?>
+ <? foreach ($wdays as $key => $wday) : ?>
+ <label style="white-space: nowrap;">
+ <input type="checkbox" name="wdays[]" value="<?= $key ?>"<?= mb_strpos((string) $aday, (string) $key) !== false ? ' checked' : '' ?>>
+ <?= $wday ?>
+ </label>
+ <? endforeach; ?>
+ </div>
+ </div>
+ </li>
+ <li>
+ <? $mdays = [
+ '1' => _('Ersten'),
+ '2' => _('Zweiten'),
+ '3' => _('Dritten'),
+ '4' => _('Vierten'),
+ '5' => _('Letzten')] ?>
+ <? $mdays_options = '' ?>
+ <? $mday_selected = $event->getRecurrence('sinterval') ?>
+ <? foreach ($mdays as $key => $mday) :
+ $mdays_options .= '<option value="' . $key . '"';
+ if ($key == $mday_selected) {
+ $mdays_options .= ' selected';
+ }
+ $mdays_options .= '>' . $mday . '</option>';
+ endforeach; ?>
+ <? $wdays_options = '' ?>
+ <? $wday_selected = $event->getRecurrence('wdays') ?: date('N', $event->getStart()) ?>
+ <? foreach ($wdays as $key => $wday) :
+ $wdays_options .= '<option value="' . $key . '"';
+ if ($key == $wday_selected) {
+ $wdays_options .= ' selected';
+ }
+ $wdays_options .= '>' . $wday . '</option>';
+ endforeach; ?>
+
+ <label class="rec-label" for="rec-monthly">
+ <input type="radio" class="rec-select" id="rec-monthly" name="recurrence" value="monthly"<?= $event->getRecurrence('rtype') == 'MONTHLY' ? ' checked' : '' ?>>
+ <?= _('Monatlich') ?>
+ </label>
+ <div class="rec-content" id="rec-content-monthly">
+ <div class="hgroup">
+ <label>
+ <input type="radio" value="day" name="type_m"<?= in_array($rec_type, ['mday_monthly', 'mday_xmonthly']) ? ' checked' : '' ?>>
+ <? $mday = $event->getRecurrence('day') ?: date('j', $event->getStart()) ?>
+ <?= sprintf(_('Wiederholt am %s. jeden %s. Monat'),
+ '<input type="text" name="day_m" size="2" value="'
+ . $mday . '">',
+ '<input type="text" name="linterval_m1" size="3" value="'
+ . $linterval . '">') ?>
+ </label>
+ </div>
+ <div class="hgroup">
+ <label>
+ <input type="radio" value="wday" name="type_m"<?= in_array($rec_type, ['xwday_xmonthly', 'lastwday_xmonthly', 'xwday_monthly', 'lastwday_monthly']) ? ' checked' : '' ?>>
+ <?= sprintf(_('Jeden %s alle %s Monate'),
+ '<select size="1" name="sinterval_m">' . $mdays_options . '</select>'
+ . '<select size="1" name="wday_m">' . $wdays_options . '</select>',
+ '<input type="text" class="no-hint" size="3" maxlength="3" name="linterval_m2" value="'
+ . $linterval . '">')?>
+ </label>
+ </div>
+ </div>
+ </li>
+ <li>
+ <? $months = [
+ '1' => _('Januar'),
+ '2' => _('Februar'),
+ '3' => _('März'),
+ '4' => _('April'),
+ '5' => _('Mai'),
+ '6' => _('Juni'),
+ '7' => _('Juli'),
+ '8' => _('August'),
+ '9' => _('September'),
+ '10' => _('Oktober'),
+ '11' => _('November'),
+ '12' => _('Dezember')] ?>
+ <? $months_options = '' ?>
+ <? $month_selected = $event->getRecurrence('month') ?: date('n', $event->getStart()) ?>
+ <? foreach ($months as $key => $month) :
+ $months_options .= '<option value="' . $key . '"';
+ if ($key == $month_selected) {
+ $months_options .= ' selected';
+ }
+ $months_options .= '>' . $month . '</option>';
+ endforeach; ?>
+
+ <label class="rec-label" for="rec-yearly">
+ <input type="radio" class="rec-select" id="rec-yearly" name="recurrence" value="yearly"<?= $event->getRecurrence('rtype') == 'YEARLY' ? ' checked' : '' ?>>
+ <?= _('Jährlich') ?>
+ </label>
+ <div class="rec-content" id="rec-content-yearly">
+ <div class="hgroup">
+ <label>
+ <input type="radio" value="day" name="type_y"<?= $rec_type == 'mday_month_yearly' ? ' checked' : '' ?>>
+ <?= sprintf(_('Jeden %s. %s'),
+ '<input type="text" size="2" maxlength="2" name="day_y" value="'
+ . ($event->getRecurrence('day') ?: date('j', $event->getStart())) . '">',
+ '<select size="1" name="month_y1">' . $months_options . '</select>') ?>
+ </label>
+ </div>
+
+ <div class="hgroup">
+ <label>
+ <input type="radio" value="wday" name="type_y"<?= in_array($rec_type, ['xwday_month_yearly', 'lastwday_month_yearly']) ? ' checked' : '' ?>>
+ <?= sprintf(_('Jeden %s im %s'),
+ '<select size="1" name="sinterval_y">' . $mdays_options . '</select>'
+ . '<select size="1" name="wday_y">' . $wdays_options . '</select>',
+ '<select size="1" name="month_y2">' . $months_options . '</select>') ?>
+ </label>
+ </div>
+ </div>
+ </li>
+ </ul>
+ </section>
+
+ <h2><?= _('Wiederholung endet') ?></h2>
+
+ <label>
+ <? $checked = (!$event->getRecurrence('expire') || $event->getRecurrence('expire') >= Calendar::CALENDAR_END) && !$event->getRecurrence('count') ?>
+ <input type="radio" name="exp_c" value="never"<?= $checked ? ' checked' : '' ?>>
+ <?= _('Nie') ?>
+ </label>
+
+ <? $checked = $event->getRecurrence('expire') && $event->getRecurrence('expire') < Calendar::CALENDAR_END && !$event->getRecurrence('count') ?>
+
+ <section class="hgroup">
+ <label>
+ <input type="radio" name="exp_c" value="date"<?= $checked ? ' checked' : '' ?>>
+ <? $exp_date = $event->getRecurrence('expire') != Calendar::CALENDAR_END ? $event->getRecurrence('expire') : $event->getEnd() ?>
+ <?= sprintf(_('Am %s'),
+ '<input type="text" class="size-s" name="exp_date" id="exp-date" value="'
+ . strftime('%x', $exp_date) . '">') ?>
+ </label>
+ </section>
+
+ <section class="hgroup">
+ <? $checked = $event->getRecurrence('count') ?>
+ <label>
+ <input type="radio" name="exp_c" value="count"<?= $checked ? ' checked' : '' ?>>
+ <? $exp_count = $event->getRecurrence('count') ?: '10' ?>
+ <?= sprintf(_('Nach %s Wiederholungen'),
+ '<input type="text" size="5" name="exp_count" value="'
+ . $exp_count . '">') ?>
+ </label>
+ </section>
+
+
+ <label for="exc-dates">
+ <?= _('Ausnahmen') ?>
+ </label>
+
+ <ul id="exc-dates">
+ <? $exceptions = $event->getExceptions(); ?>
+ <? sort($exceptions, SORT_NUMERIC); ?>
+ <? foreach ($exceptions as $exception) : ?>
+ <li>
+ <label class="undecorated">
+ <input type="checkbox" name="del_exc_dates[]" value="<?= strftime('%d.%m.%Y', $exception) ?>" style="display: none;">
+ <span><?= strftime('%x', $exception) ?><?= Icon::create('trash', 'clickable', ['title' => _('Ausnahme löschen')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?></span>
+ </label>
+ <input type="hidden" name="exc_dates[]" value="<?= strftime('%d.%m.%Y', $exception) ?>">
+ </li>
+ <? endforeach; ?>
+ </ul>
+
+ <div class="hgroup">
+ <input style="vertical-align: top; opacity: 0.8;"
+ type="text" size="12" name="exc_date" id="exc-date" value=""
+ placeholder="<?= _("Datum eingeben") ?>">
+ <span style="vertical-align: top;" onclick="STUDIP.CalendarDialog.addException(); return false;">
+ <?= Icon::create('add', 'clickable', ['title' => _('Ausnahme hinzufügen')])->asInput(['class' => 'text-bottom']) ?>
+ </span>
+ </div>
+ </fieldset>
+
+ <? if (Config::get()->CALENDAR_GROUP_ENABLE && $calendar->getRange() == Calendar::RANGE_USER) : ?>
+ <?= $this->render_partial('calendar/group/_attendees') ?>
+ <? endif; ?>
+
+ <footer data-dialog-button>
+ <?= Button::create(_('Speichern'), 'store', ['title' => _('Termin speichern')]) ?>
+
+ <? if (!$event->isNew()) : ?>
+ <? if ($event->getRecurrence('rtype') != 'SINGLE') : ?>
+ <?= LinkButton::create(_('Aus Serie löschen'), $controller->url_for('calendar/single/delete_recurrence/' . implode('/', $event->getId()) . '/' . $atime)) ?>
+ <? endif; ?>
+ <?= LinkButton::create(_('Löschen'), $controller->url_for('calendar/single/delete/' . implode('/', $event->getId()))) ?>
+ <? endif; ?>
+ <? if (!Request::isXhr()) : ?>
+ <?= LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view, [$event->getStart()])) ?>
+ <? endif; ?>
+ </footer>
+</form>
+<script>
+ jQuery('#start-date').datepicker({
+ altField: '#end-date'
+ });
+ jQuery('#end-date').datepicker();
+ jQuery('#exp-date').datepicker();
+ jQuery('#exc-date').datepicker();
+
+ $('ul.recurrences input[type=radio][id^=rec]').bind('change', function() {
+ $('.rec-content').hide();
+
+ if ($(this).is(':checked')) {
+ $(this).parent().siblings('.rec-content').show();
+ }
+ })
+</script>
diff --git a/app/views/calendar/single/edit_status.php b/app/views/calendar/single/edit_status.php
new file mode 100644
index 0000000..3e3bfc3
--- /dev/null
+++ b/app/views/calendar/single/edit_status.php
@@ -0,0 +1,3 @@
+<form action="<?= $controller->url_for($base . 'edit_status/' . $range_id . '/' . $event->event_id) ?>" method="post">
+ <?= $this->render_partial('calendar/single/_event_data') ?>
+</form>
diff --git a/app/views/calendar/single/event.php b/app/views/calendar/single/event.php
new file mode 100644
index 0000000..e9d544f
--- /dev/null
+++ b/app/views/calendar/single/event.php
@@ -0,0 +1 @@
+<?= $this->render_partial('calendar/single/_event_data') ?>
diff --git a/app/views/calendar/single/export_calendar.php b/app/views/calendar/single/export_calendar.php
new file mode 100644
index 0000000..270e20e
--- /dev/null
+++ b/app/views/calendar/single/export_calendar.php
@@ -0,0 +1,56 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $messagebox) : ?>
+ <?= $messagebox ?>
+ <? endforeach ?>
+<? else : ?>
+ <? SkipLinks::addIndex(_('Termine exportieren'), 'main_content', 100); ?>
+<? endif; ?>
+<form action="<?= $controller->url_for('calendar/single/export_calendar/' . $calendar->getRangeId(), ['atime' => $atime, 'last_view' => $last_view]) ?>" method="post" name="sync_form" id="calendar_sync" class="default">
+ <fieldset>
+ <legend>
+ <?= sprintf(_('Termine exportieren')) ?>
+ </legend>
+
+ <label for="event-type">
+ <?= _('Welche Termine sollen exportiert werden') ?>:
+
+ <select name="event_type" id="event-type" size="1">
+ <option value="user" selected><?= _('Nur eigene Termine') ?></option>
+ <option value="course"><?= _('Nur Veranstaltungs-Termine') ?></option>
+ <option value="all"><?= _('Alle Termine') ?></option>
+ </select>
+ </label>
+
+ <label>
+ <input type="radio" name="export_time" value="all" id="export-all" checked>
+ <?= _('Alle Termine exportieren') ?>
+ </label>
+
+ <label>
+ <input type="radio" name="export_time" value="date" id="export-date">
+ <?= _('Nur Termin in folgendem Zeitraum exportieren') ?>
+ </label>
+
+ <section class="hgroup">
+ <? $start = strtotime('now') ?>
+ <? $end = strtotime('+1 year') ?>
+ <input id="export-start" type="text" name="export_start" class="no-hint"
+ maxlength="10" class="hasDatepicker" value="<?= strftime('%x', $start) ?>">
+ <input id="export-end" type="text" name="export_end" class="no-hint"
+ maxlength="10" class="hasDatepicker" value="<?= strftime('%x', $end) ?>">
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Termine exportieren'), 'export', ['title' => _('Termine exportieren')]) ?>
+
+ <? if (!Request::isXhr()) : ?>
+ <?= LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view)) ?>
+ <? endif; ?>
+ </footer>
+</form>
+<script>
+ jQuery('#export-start').datepicker();
+ jQuery('#export-end').datepicker();
+</script>
diff --git a/app/views/calendar/single/import.php b/app/views/calendar/single/import.php
new file mode 100644
index 0000000..a63104c
--- /dev/null
+++ b/app/views/calendar/single/import.php
@@ -0,0 +1,28 @@
+<?
+use Studip\Button, Studip\LinkButton;
+SkipLinks::addIndex(_('Termine importieren'), 'main_content', 100);
+?>
+<form action="<?= $controller->link_for('calendar/single/import/' . $calendar->getRangeId(), ['atime' => $atime, 'last_view' => $last_view]) ?>" method="post" enctype="multipart/form-data" class="default">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= sprintf(_('Termine importieren')) ?>
+ </legend>
+
+ <label for="event-type">
+ <input type="checkbox" name="import_privat" value="1" checked>
+ <?= _('Öffentliche Termine als "privat" importieren') ?>
+ </label>
+
+ <label class="file-upload">
+ <span class="required"><?= _('Datei zum Importieren wählen') ?></span>
+ <input required type="file" name="importfile" accept=".ics,.ifb,.iCal,.iFBf">
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Termine importieren'), 'import') ?>
+ <?= LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view)) ?>
+ </footer>
+</form>
diff --git a/app/views/calendar/single/manage_access.php b/app/views/calendar/single/manage_access.php
new file mode 100644
index 0000000..b5f1634
--- /dev/null
+++ b/app/views/calendar/single/manage_access.php
@@ -0,0 +1,99 @@
+<? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $messagebox) : ?>
+ <?= $messagebox ?>
+ <? endforeach ?>
+<? endif; ?>
+<form id="calendar-manage-access" data-dialog="" method="post" action="<?= $controller->url_for('calendar/single/store_permissions/' . $calendar->getRangeId()) ?>">
+ <? CSRFProtection::tokenTag() ?>
+ <? $perms = [1 => _('Keine'), 2 => _('Lesen'), 4 => _('Schreiben')] ?>
+ <table class="default">
+ <caption>
+ <?= htmlReady($title) ?>
+ <span class="actions" style="font-size: 0.8em;">
+ <label>
+ <?= _('Auswahl') ?>:
+ <select name="group_filter" size="1" class="submit-upon-select">
+ <option value="list"<?= $group_filter_selected == 'list' ? ' selected' : '' ?>><?= _('Alle Personen anzeigen') ?></option>
+ <? foreach ($filter_groups as $filter_group) : ?>
+ <option value="<?= $filter_group->getId() ?>"<?= $group_filter_selected == $filter_group->getId() ? ' selected' : '' ?>><?= htmlReady($filter_group->name) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <?= Icon::create('accept', 'clickable')
+ ->asInput([
+ 'id' => "calendar-group-submit",
+ 'name' => "calendar_group_submit",
+ 'class' => "text-top"]) ?>
+ <span style="padding-left: 1em;">
+ <?= $mps->render() ?>
+ </span>
+ <script>
+ STUDIP.MultiPersonSearch.init();
+ </script>
+ </span>
+ </caption>
+ <thead>
+ <tr>
+ <th>
+ <?= _('Name') ?>
+ </th>
+ <th>
+ <?= _('Berechtigung') ?>
+ </th>
+ <th>
+ <?= _('Eigene Berechtigung') ?>
+ </th>
+ <th class="actions">
+ <?= _('Aktionen') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($users as $header => $usergroup): ?>
+ <tr id="letter_<?= $header ?>" class="calendar-user-head">
+ <th colspan="4">
+ <?= $header ?>
+ </th>
+ </tr>
+ <? foreach ($usergroup as $user): ?>
+ <tr id="contact_<?= $user->user_id ?>">
+ <td>
+ <?= ObjectdisplayHelper::avatarlink($user->user) ?>
+ </td>
+ <td style="white-space: nowrap;">
+ <label>
+ <input type="radio" name="perm[<?= $user->user_id ?>]" value="<?= Calendar::PERMISSION_FORBIDDEN ?>"
+ <?= $user->permission < Calendar::PERMISSION_READABLE ? ' checked' : '' ?>>
+ <?= _('Keine') ?>
+ </label>
+ <label>
+ <input type="radio" name="perm[<?= $user->user_id ?>]" value="<?= Calendar::PERMISSION_READABLE ?>"
+ <?= $user->permission == Calendar::PERMISSION_READABLE ? ' checked' : '' ?>>
+ <?= _('Lesen') ?>
+ </label>
+ <label>
+ <input type="radio" name="perm[<?= $user->user_id ?>]" value="<?= Calendar::PERMISSION_WRITABLE ?>"
+ <?= $user->permission == Calendar::PERMISSION_WRITABLE ? ' checked' : '' ?>>
+ <?= _('Schreiben') ?>
+ </label>
+ </td>
+ <td>
+ <?= $perms[$own_perms[$user->user_id]] ?>
+ </td>
+ <td class="actions">
+ <a title="<?= _('Benutzer entfernen') ?>" onClick="STUDIP.CalendarDialog.removeUser(this);" href="<?= $controller->url_for('calendar/single/remove_user/' . $calendar->getRangeId() . $filter, ['user_id' => $user->user_id]) ?>">
+ <?= Icon::create('person+remove', 'clickable')->asImg() ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ <div style="text-align: center;" data-dialog-button>
+ <?= Studip\Button::create(_('Speichern'), 'store') ?>
+ <? if (!Request::isXhr()) : ?>
+ <?= Studip\LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view)) ?>
+ <? endif; ?>
+ </div>
+</form> \ No newline at end of file
diff --git a/app/views/calendar/single/month.php b/app/views/calendar/single/month.php
new file mode 100644
index 0000000..2b02036
--- /dev/null
+++ b/app/views/calendar/single/month.php
@@ -0,0 +1,111 @@
+<? $month = $calendar->view; ?>
+
+<nav class="calendar-nav" style="vertical-align: middle">
+ <span style="white-space: nowrap;">
+ <a class="hidden-medium-down" style="padding-right: 2em;" href="<?= $controller->url_for('calendar/single/month', ['atime' => strtotime('-1 year', $atime)]) ?>">
+ <?= Icon::create('arr_2left', 'clickable', ['title' => _('Ein Jahr zurück')])->asImg(['style' => 'vertical-align: text-top;']) ?>
+ <?= strftime('%B %Y', strtotime('-1 year', $atime)) ?>
+ </a>
+ <a class="hidden-tiny-down" href="<?= $controller->url_for('calendar/single/month', ['atime' => strtotime('-1 month', $atime)]) ?>">
+ <?= Icon::create('arr_1left', 'clickable', ['title' => _('Einen Monat zurück')])->asImg(['style' => 'vertical-align: text-top;']) ?>
+ <?= strftime('%B %Y', strtotime('-1 month', $atime)) ?>
+ </a>
+ </span>
+
+ <?
+ $calType = 'month';
+ $calLabel = htmlReady(strftime("%B ", $calendars[15]->getStart())) .' '. date('Y', $calendars[15]->getStart());
+ ?>
+
+ <?= $this->render_partial('calendar/single/_calhead', compact('calendar', 'atime', 'calType', 'calLabel')) ?>
+
+ <span style="text-align: right; white-space: nowrap;">
+ <a class="hidden-tiny-down" style="padding-right: 2em;" href="<?= $controller->url_for('calendar/single/month', ['atime' => strtotime('+1 month', $atime)]) ?>">
+ <?= strftime('%B %Y', strtotime('+1 month', $atime)) ?>
+ <?= Icon::create('arr_1right', 'clickable', ['title' => _('Einen Monat vor')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ </a>
+ <a class="hidden-medium-down" href="<?= $controller->url_for('calendar/single/month', ['atime' => strtotime('+1 year', $atime)]) ?>">
+ <?= strftime('%B %Y', strtotime('+1 year', $atime)) ?>
+ <?= Icon::create('arr_2right', 'clickable', ['title' => _('Ein Jahr vor')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ </a>
+ </span>
+</nav>
+
+<div class="table-scrollbox-horizontal">
+<table class="calendar-month">
+ <thead>
+ <tr class="calendar-month-weekdays">
+ <? $week_days = [39092400, 39178800, 39265200, 39351600, 39438000, 39524400, 39610800]; ?>
+ <? foreach ($week_days as $week_day) : ?>
+ <td class="precol1w">
+ <?= strftime('%a', $week_day) ?>
+ </td>
+ <? endforeach; ?>
+ <td align="center" class="precol1w">
+ <?= _('Woche') ?>
+ </td>
+ </tr>
+ </thead>
+ <tbody>
+ <? for ($i = $first_day, $j = 0; $i <= $last_day; $i += 86400, $j++) : ?>
+ <? $aday = date('j', $i); ?>
+ <?
+ $class_day = '';
+ if (($aday - $j - 1 > 0) || ($j - $aday > 6)) {
+ $class_cell = 'lightmonth';
+ $class_day = 'light';
+ } elseif (date('Ymd', $i) == date('Ymd')) {
+ $class_cell = 'celltoday';
+ } else {
+ $class_cell = 'month';
+ }
+ $hday = holiday($i);
+
+ if ($j % 7 == 0) {
+ ?><tr><?
+ }
+ ?>
+ <td class="<?= $class_cell ?>">
+ <? if (($j + 1) % 7 == 0) : ?>
+ <a class="<?= $class_day . 'sday' ?>" href="<?= $controller->url_for('calendar/single/day', ['atime' => $i]) ?>">
+ <?= $aday ?>
+ </a>
+ <? if ($hday["name"] != "") : ?>
+ <div style="color: #aaaaaa;" class="inday"><?= $hday['name'] ?></div>
+ <? endif; ?>
+ <? foreach ($calendars[$j]->events as $event) : ?>
+ <div data-tooltip>
+ <a data-dialog="size=auto" title="<?= _('Termin bearbeiten') ?>" class="inday <?= $event instanceof CourseEvent ? 'calendar-course-event-text' : 'calendar-event-text' ?><?= $event->getCategory() ?>" href="<?= $controller->url_for('calendar/single/edit/' . $event->range_id . '/' . $event->event_id, ['atime' => $event->getStart()]) ?>"><?= htmlReady($event->getTitle()) ?></a>
+ <?= $this->render_partial('calendar/single/_tooltip', ['event' => $event, 'calendar' => $calendars[$j]]) ?>
+ </div>
+ <? endforeach; ?>
+ </td>
+ <td class="lightmonth calendar-month-week">
+ <a style="font-weight: bold;" class="calhead" href="<?= $controller->url_for('calendar/single/week', ['atime' => $i]) ?>"><?= strftime("%V", $i) ?></a>
+ </td>
+ </tr>
+ <? else : ?>
+ <? $hday_class = ['day', 'day', 'shday', 'hday'] ?>
+ <? if ($hday['col']) : ?>
+ <a class="<?= $class_day . $hday_class[$hday['col']] ?>" href="<?= $controller->url_for('calendar/single/day', ['atime' => $i]) ?>">
+ <?= $aday ?>
+ </a>
+ <div style="color: #aaaaaa;" class="inday"><?= $hday['name'] ?></div>
+ <? else : ?>
+ <a class="<?= $class_day . 'day' ?>" href="<?= $controller->url_for('calendar/single/day', ['atime' => $i]) ?>">
+ <?= $aday ?>
+ </a>
+ <? endif; ?>
+ <? foreach ($calendars[$j]->events as $event) : ?>
+ <div data-tooltip>
+ <a data-dialog="size=auto" title="<?= _('Termin bearbeiten') ?>" class="inday <?= $event instanceof CourseEvent ? 'calendar-course-event-text' : 'calendar-event-text' ?><?= $event->getCategory() ?>" href="<?= $controller->url_for('calendar/single/edit/' . $event->range_id . '/' . $event->event_id, ['atime' => $event->getStart()]) ?>"><?= htmlReady($event->getTitle()) ?></a>
+ <?= $this->render_partial('calendar/single/_tooltip', ['event' => $event, 'calendar' => $calendars[$j]]) ?>
+ </div>
+ <? endforeach; ?>
+ </td>
+ <? endif; ?>
+ <? endfor; ?>
+ </tr>
+ </tbody>
+</table>
+</div>
diff --git a/app/views/calendar/single/seminar_events.php b/app/views/calendar/single/seminar_events.php
new file mode 100644
index 0000000..01c13aa
--- /dev/null
+++ b/app/views/calendar/single/seminar_events.php
@@ -0,0 +1,104 @@
+<? if (!empty($sem_courses)) : ?>
+ <?= $this->render_partial('calendar/single/_semester_filter') ?>
+ <? $_order = (!$order_by || $order == 'desc') ? 'asc' : 'desc' ?>
+ <form action="<?= $controller->url_for('calendar/single/store_selected_sem') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <div id="my_seminars">
+ <? foreach ($sem_courses as $sem_key => $course_group) : ?>
+ <table class="default collapsable">
+ <caption>
+ <?= htmlReady($sem_data[$sem_key]['name']) ?>
+ </caption>
+ <colgroup>
+ <col width="7px">
+ <col width="25px">
+ <? if ($config_sem_number) : ?>
+ <col width="10%">
+ <? endif ?>
+ <col>
+ <col width="45px">
+ <col width="10%">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <th></th>
+ <th></th>
+ <? if ($config_sem_number) : ?>
+ <th class=<?= ($order_by == 'veranstaltungsnummer') ? ($order == 'desc') ? 'sortdesc' : 'sortasc' : '' ?>>
+ <a href="<?= $controller->url_for(sprintf('my_courses/index/veranstaltungsnummer/%s', $_order)) ?>">
+ <?= _('Nr.') ?>
+ </a>
+ </th>
+ <? endif ?>
+ <th
+ class=<?= ($order_by == 'name') ? ($order == 'desc') ? 'sortdesc' : 'sortasc' : '' ?>>
+ <a href="<?= $controller->url_for(sprintf('calendar/single/seminar_events/name/%s', $_order)) ?>" data-dialog="size=auto">
+ <?= _('Name') ?>
+ </a>
+ </th>
+ <th></th>
+ <th><?= _('Auswahl') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($course_group as $course) : ?>
+ <? $sem_class = $course['sem_class']; ?>
+ <tr>
+ <td class="gruppe<?= $course['gruppe'] ?>"></td>
+ <td>
+ <? if ($sem_class['studygroup_mode']) : ?>
+ <?= StudygroupAvatar::getAvatar($course['seminar_id'])->getImageTag(Avatar::SMALL, ['title' => $course['name']])
+ ?>
+ <? else : ?>
+ <?= CourseAvatar::getAvatar($course['seminar_id'])->getImageTag(Avatar::SMALL, ['title' => $course['name']])
+ ?>
+ <? endif ?>
+ </td>
+ <? if($config_sem_number) :?>
+ <td><?= $course['veranstaltungsnummer']?></td>
+ <? endif?>
+ <td style="text-align: left">
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $course['seminar_id']]) ?>"
+ <?= $course['visitdate'] <= $course['chdate'] ? 'style="color: red;"' : '' ?>>
+ <?= htmlReady($course['name']) ?>
+ <?= ($course['is_deputy'] ? ' ' . _('[Vertretung]') : '');?>
+ </a>
+ <? if ($course['visible'] == 0) : ?>
+ <?= _('[versteckt]') ?>
+ <? endif ?>
+ </td>
+ <td>
+ <? if (!$sem_class['studygroup_mode']) : ?>
+ <a data-dialog href="<?= $controller->url_for(sprintf('course/details/index/%s', $course['seminar_id'])) ?>">
+ <? $params = tooltip2(_('Veranstaltungsdetails')); ?>
+ <? $params['style'] = 'cursor: pointer'; ?>
+ <?= Icon::create('info-circle', 'inactive')->asImg(20, $params) ?>
+ </a>
+ <? else : ?>
+ <?= Assets::img('blank.gif', ['width' => 20, 'height' => 20]); ?>
+ <? endif ?>
+ </td>
+ <td style="text-align: center;">
+ <input type="hidden" name="selected_sem[<?= $course['seminar_id'] ?>]" value="0">
+ <input type="checkbox" name="selected_sem[<?= $course['seminar_id'] ?>]" value="1"<?= in_array($course['seminar_id'], $bind_calendar) ? ' checked' : '' ?>>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </table>
+ <? endforeach ?>
+ </div>
+ <div style="text-align: center;" data-dialog-button>
+ <?= Studip\Button::create(_('Speichern'), 'store') ?>
+ <? if (!Request::isXhr()) : ?>
+ <?= Studip\LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view)) ?>
+ <? endif; ?>
+ </div>
+ </form>
+<? else : ?>
+ <?= PageLayout::postMessage(MessageBox::info(_('Es wurden keine Veranstaltungen gefunden. Mögliche Ursachen:'), [
+ sprintf(_('Sie haben zur Zeit keine Veranstaltungen belegt, an denen Sie teilnehmen können.<br>Bitte nutzen Sie %s<b>Veranstaltung suchen / hinzufügen</b>%s um sich für Veranstaltungen anzumelden.'),'<a href="' . URLHelper::getLink('dispatch.php/search/courses') . '">', '</a>'),
+ _('In dem ausgewählten <b>Semester</b> wurden keine Veranstaltungen belegt.').'<br>'._('Wählen Sie links im <b>Semesterfilter</b> ein anderes Semester aus')
+ ]))?>
+<? endif ?>
+<? if (is_array($my_bosses) && count($my_bosses)) : ?>
+ <?= $this->render_partial('my_courses/_deputy_bosses'); ?>
+<? endif ?>
diff --git a/app/views/calendar/single/share.php b/app/views/calendar/single/share.php
new file mode 100644
index 0000000..5a6c33b
--- /dev/null
+++ b/app/views/calendar/single/share.php
@@ -0,0 +1,62 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $messagebox) : ?>
+ <?= $messagebox ?>
+ <? endforeach ?>
+<? else : ?>
+ <? SkipLinks::addIndex(_('Kalender teilen'), 'main_content', 100); ?>
+<? endif; ?>
+<form data-dialog="size=auto" action="<?= $controller->url_for('calendar/single/share/' . $calendar->getRangeId()) ?>" method="post" class="default">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Kalender mit anderen Teilen und in andere Kalender einbetten') ?>
+ </legend>
+
+ <? if (!$short_id) : ?>
+ <?= _('Sie können sich eine Adresse generieren lassen, mit der Sie Termine aus Ihrem Stud.IP-Terminkalender in externen Terminkalendern einbinden können.') ?><br>
+ <? else : ?>
+ <?= _('Die folgende Adresse können Sie in externe Terminkalenderanwendungen eintragen, um Ihre Termine dort anzuzeigen:') ?>
+ <? $url = URLHelper::getLink($GLOBALS['ABSOLUTE_URI_STUDIP'] . 'dispatch.php/ical/index/' . $short_id, null, true) ?>
+ <div style="font-weight: bold;">
+ <a href="<?= $url ?>" target="_blank"><?= htmlReady($url) ?></a>
+ </div>
+
+ <section>
+ <?= _('Verschicken Sie die Export-Adresse als E-Mail:') ?>
+ <input type="email" name="email" value="<?= htmlReady($GLOBALS['user']->email) ?>" required="required">
+ <?= Button::create(_('Abschicken'), 'submit_email', ['title' => _('Abschicken')]) ?>
+ </section>
+
+ <section>
+ <?= _('Sie haben außerdem die Möglichkeit, sich eine neue Adresse generieren zu lassen.') ?>
+ <?= _('Achtung: Die alte Adresse wird damit ungültig!') ?>
+ </section>
+
+ <section>
+ <?= _('Sie können die Adresse auch löschen.') ?>
+ <?= _('Ein Zugriff auf Ihre Termine über diese Adresse ist dann nicht mehr möglich!') ?>
+ </section>
+ <? endif; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if (!$short_id) : ?>
+ <?= Button::create(_('Adresse generieren'), 'new_id') ?>
+ <? else :?>
+ <?= Button::create(_('Neue Adresse generieren'), 'new_id', [
+ 'title' => _('Achtung: Die alte Adresse wird damit ungültig!')
+ ]) ?>
+
+ <?= Button::create(_('Adresse löschen'), 'delete_id', [
+ 'title' => _('Ein Zugriff auf Ihre Termine über diese Adresse ist dann nicht mehr möglich!')
+ ]) ?>
+ <? endif ?>
+
+ <? if (!Request::isXhr()) : ?>
+ <?= LinkButton::create(_('Abbrechen'), $controller->url_for('calendar/single/' . $last_view)) ?>
+ <? endif; ?>
+ </footer>
+</form>
diff --git a/app/views/calendar/single/week.php b/app/views/calendar/single/week.php
new file mode 100644
index 0000000..a47c51e
--- /dev/null
+++ b/app/views/calendar/single/week.php
@@ -0,0 +1,201 @@
+<?
+// add skip link
+SkipLinks::addIndex(_('Wochenansicht'), 'main_content', 100);
+$at = date('G', $atime);
+if ($at >= $settings['start']
+ && $at <= $settings['end'] || !$atime) {
+ $start = $settings['start'];
+ $end = $settings['end'];
+} elseif ($at < $settings['start']) {
+ $start = 0;
+ $end = $settings['start'] + 2;
+} else {
+ $start = $settings['end'] - 2;
+ $end = 23;
+}
+$tab_arr = [];
+$max_columns = 0;
+$week_type = $settings['type_week'] == 'SHORT' ? 5 : 7;
+$rows = ($end - $start + 1) * 3600 / $settings['step_week'];
+
+for ($i = 0; $i < $week_type; $i++) {
+ $tab_arr[$i] = $calendars[$i]->createEventMatrix($start * 3600, $end * 3600, $settings['step_week']);
+ if ($tab_arr[$i]['max_cols']) {
+ $max_columns += ($tab_arr[$i]['max_cols'] + 1);
+ } else {
+ $max_columns++;
+ }
+}
+
+$rowspan = ceil(3600 / $settings['step_week']);
+$height = ' height="20"';
+
+if ($rowspan > 1) {
+ $colspan_1 = ' colspan="2"';
+ $colspan_2 = $max_columns + 4;
+ $width_daycols = 100 - (4 + $week_type) * 0.1;
+} else {
+ $colspan_1 = '';
+ $colspan_2 = $max_columns + 2;
+ $width_daycols = 100 - (2 + $week_type) * 0.1;
+}
+?>
+
+<nav class="calendar-nav" style="vertical-align: middle">
+ <span style="white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/single/week', ['atime' => strtotime('-1 week', $atime)]) ?>">
+ <?= Icon::create('arr_1left', 'clickable', ['title' => _('Eine Woche zurück')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ <span class="hidden-tiny-down"><?= sprintf(_('%u. Woche'), strftime('%V', strtotime('-1 week', $atime))) ?></span>
+ </a>
+ </span>
+
+ <?
+ $calType = 'week';
+ $calLabel = $this->render_partial('calendar/single/_calhead_label_week', compact('week_type'));
+ ?>
+
+ <?= $this->render_partial('calendar/single/_calhead', compact('calendar', 'atime', 'calType', 'calLabel')) ?>
+
+ <span style="white-space: nowrap; text-align: right;">
+ <a href="<?= $controller->url_for('calendar/single/week', ['atime' => strtotime('+1 week', $atime)]) ?>">
+ <span class="hidden-tiny-down"><?= sprintf(_('%u. Woche'), strftime('%V', strtotime('+1 week', $atime))) ?></span>
+ <?= Icon::create('arr_1right', 'clickable', ['title' => _('Eine Woche vor')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ </a>
+ </span>
+</nav>
+
+<table id="main_content" class="calendar-week">
+ <colgroup>
+ <col style="max-width: 1.5em; width: 1.5em;">
+ <? if ($rowspan > 1) : ?>
+ <col style="max-width: 1.5em; width: 1.5em;">
+ <? endif; ?>
+ <? for ($i = 0; $i < $week_type; $i++) : ?>
+ <? if ($tab_arr[$i]['max_cols'] > 0) : ?>
+ <? $event_cols = $tab_arr[$i]['max_cols'] ?: 1; ?>
+ <col span="<?= $event_cols ?>" style="width: <?= 100 / $week_type / $event_cols ?>%">
+ <col style="max-width: 0.9em; width: 0.9em;">
+ <? else : ?>
+ <col style="width: <?= 100 / $week_type ?>%">
+ <? endif; ?>
+ <? endfor; ?>
+ <col class="hidden-tiny-down" style="max-width: 1.5em; width: 1.5em;">
+ <? if ($rowspan > 1) : ?>
+ <col class="hidden-tiny-down" style="max-width: 1.5em; width: 1.5em;">
+ <? endif; ?>
+ </colgroup>
+ <thead>
+ <tr>
+ <td style="text-align: center; white-space: nowrap;" <?= $colspan_1 ?>>
+ <? if ($start > 0) : ?>
+ <a href="<?= $controller->url_for('calendar/single/week', ['atime' => mktime($start - 1, 0, 0, date('n', $atime), date('j', $atime), date('Y', $atime))]) ?>">
+ <?= Icon::create('arr_1up', 'clickable', ['title' => _('Früher')])->asImg() ?>
+ </a>
+ <? endif ?>
+ </td>
+ <? // weekday and date as title for each column ?>
+ <? for ($i = 0; $i < $week_type; $i++) : ?>
+ <td style="text-align:center; font-weight:bold;"<?= ($tab_arr[$i]['max_cols'] > 0 ? ' colspan="' . ($tab_arr[$i]['max_cols'] + 1) . '"' : '' ) ?>>
+ <a class="calhead" href="<?= $controller->url_for('calendar/single/day', ['atime' => $calendars[$i]->getStart()]) ?>">
+ <span class="hidden-tiny-down"><?= strftime('%a', $calendars[$i]->getStart()) ?></span> <?= date('d', $calendars[$i]->getStart()) ?>
+ </a>
+ <? if ($holiday = holiday($calendars[$i]->getStart())) : ?>
+ <div class="hidden-tiny-down" style="font-size:9pt; color:#bbb; height:auto; overflow:visible; font-weight:bold;"><?= $holiday['name'] ?></div>
+ <? endif ?>
+ </td>
+ <? endfor ?>
+ <td style="text-align: center; white-space: nowrap;" <?= $colspan_1 ?>>
+ <? if ($start > 0) : ?>
+ <a href="<?= $controller->url_for('calendar/single/week', ['atime' => mktime($start - 1, 0, 0, date('n', $calendars[0]->getStart()), date('j', $calendars[0]->getStart()), date('Y', $calendars[0]->getStart()))]) ?>">
+ <?= Icon::create('arr_1up', 'clickable', ['title' => _('Früher')])->asImg() ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <? // Zeile mit Tagesterminen ausgeben ?>
+ <td class="precol1w"<?= $colspan_1 ?> height="20">
+ <?= _("Tag") ?>
+ </td>
+ <? for ($i = 0; $i < $week_type; $i++) : ?>
+ <?
+ if (date('Ymd', $calendars[$i]->getStart()) == date('Ymd')) {
+ $class_cell = 'celltoday';
+ } else {
+ $class_cell = '';
+ }
+ ?>
+ <?= $this->render_partial('calendar/single/_day_dayevents', ['em' => $tab_arr[$i], 'calendar' => $calendars[$i], 'class_cell' => $class_cell]) ?>
+ <? endfor ?>
+ <td class="precol1w"<?= $colspan_1 ?>>
+ <?= _('Tag') ?>
+ </td>
+ </tr>
+ <? $j = $start ?>
+ <? for ($i = 0; $i < $rows; $i++) : ?>
+ <tr>
+ <? if ($i % $rowspan == 0) : ?>
+ <? if ($rowspan == 1) : ?>
+ <td class="precol1w"<?= $height ?>><?= $j ?></td>
+ <? else : ?>
+ <td class="precol1w" rowspan="<?= $rowspan ?>"><?= $j ?></td>
+ <? endif ?>
+ <? endif ?>
+ <? if ($rowspan > 1) : ?>
+ <? $minutes = (60 / $rowspan) * ($i % $rowspan); ?>
+ <? if ($minutes == 0) : ?>
+ <td class="precol2w"<?= $height ?>>00</td>
+ <? else : ?>
+ <td class="precol2w"<?= $height ?>><?= $minutes ?></td>
+ <? endif ?>
+ <? endif ?>
+ <? for ($y = 0; $y < $week_type; $y++) : ?>
+ <?
+ if (date('Ymd', $calendars[$y]->getStart()) == date('Ymd')) {
+ $class_cell = 'celltoday';
+ } else {
+ $class_cell = '';
+ }
+ ?>
+ <?= $this->render_partial('calendar/single/_day_cell', ['calendar' => $calendars[$y], 'em' => $tab_arr[$y], 'row' => $i, 'start' => $start * 3600, 'i' => $i + ($start * 3600 / $settings['step_week']), 'step' => $settings['step_week'], 'class_cell' => $class_cell]); ?>
+ <? endfor ?>
+ <? if ($rowspan > 1) : ?>
+ <? if ($minutes == 0) : ?>
+ <td class="precol2w"<?= $height ?>>00</td>
+ <? else : ?>
+ <td class="precol2w"<?= $height ?>><?= $minutes ?></td>
+ <? endif ?>
+ <? endif ?>
+ <? if (($i + 2) % $rowspan == 0) : ?>
+ <? if ($rowspan == 1) : ?>
+ <td class="precol1w"<?= $height ?>><?= $j ?></td>
+ <? else : ?>
+ <td class="precol1w" rowspan="<?= $rowspan ?>"><?= $j ?></td>
+ <? endif ?>
+ <? $j = $j + ceil($settings['step_week'] / 3600); ?>
+ <? endif ?>
+ </tr>
+ <? endfor ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td<?= $colspan_1 ?> style="text-align:center;">
+ <? if ($end < 23) : ?>
+ <a href="<?= $controller->url_for('calendar/single/week', ['atime' => mktime($end + 1, 0, 0, date('n', $calendars[0]->getStart()), date('j', $calendars[0]->getStart()), date('Y', $calendars[0]->getStart()))]) ?>">
+ <?= Icon::create('arr_1down', 'clickable', ['title' => _('Später')])->asImg() ?>
+ </a>
+ <? endif ?>
+ </td>
+ <td colspan="<?= $max_columns ?>">&nbsp;</td>
+ <td<?= $colspan_1 ?> style="text-align:center;">
+ <? if ($end < 23) : ?>
+ <a href="<?= $controller->url_for('calendar/single/week', ['atime' => mktime($end + 1, 0, 0, date('n', $calendars[0]->getStart()), date('j', $calendars[0]->getStart()), date('Y', $calendars[0]->getStart()))]) ?>">
+ <?= Icon::create('arr_1down', 'clickable', ['title' => _('Später')])->asImg() ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+ </tfoot>
+</table>
diff --git a/app/views/calendar/single/year.php b/app/views/calendar/single/year.php
new file mode 100644
index 0000000..f73c08f
--- /dev/null
+++ b/app/views/calendar/single/year.php
@@ -0,0 +1,139 @@
+<div class="calendar-single-year">
+
+ <nav class="calendar-nav" style="vertical-align: middle">
+ <span style="white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/single/year', ['atime' => strtotime('-1 year', $atime)]) ?>">
+ <?= Icon::create('arr_2left', 'clickable', ['title' => _('Ein Jahr zurück')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ <?= strftime('%Y', strtotime('-1 year', $atime)) ?>
+ </a>
+ </span>
+
+ <?
+ $calType = 'year';
+ $calLabel = date('Y', $calendar->getStart());
+ ?>
+
+ <?= $this->render_partial('calendar/single/_calhead', compact('calendar', 'atime', 'calType', 'calLabel')) ?>
+
+ <span style="text-align: right; white-space: nowrap;">
+ <a href="<?= $controller->url_for('calendar/single/year', ['atime' => strtotime('+1 year', $atime)]) ?>">
+ <?= strftime('%Y', strtotime('+1 year', $atime)) ?>
+ <?= Icon::create('arr_2right', 'clickable', ['title' => _('Ein Jahr vor')])->asImg(16, ['style' => 'vertical-align: text-top;']) ?>
+ </a>
+ </span>
+ </nav>
+
+ <div class="table-scrollbox-horizontal">
+ <table class="calendar-single-year--table" width="100%">
+ <? $days_per_month = [31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+ if (date('L', $calendar->getStart())) {
+ $days_per_month[2]++;
+ }
+ ?>
+
+ <thead>
+ <tr>
+ <? for ($i = 1; $i < 13; $i++) : ?>
+ <? $ts_month += ( $days_per_month[$i] - 1) * 86400; ?>
+ <th align="center" width="8%">
+ <a class="calhead" href="<?= $controller->url_for('calendar/single/month', ['atime' => $calendar->getStart() + $ts_month]) ?>">
+ <b><?= strftime('%B', $ts_month); ?></b>
+ </a>
+ </th>
+ <? endfor; ?>
+ </tr>
+ </thead>
+
+ <tbody>
+ <? $now = date('Ymd'); ?>
+ <? for ($i = 1; $i < 32; $i++) : ?>
+ <tr>
+ <? for ($month = 1; $month < 13; $month++) : ?>
+
+ <? $aday = mktime(12, 0, 0, $month, $i, date('Y', $calendar->getStart())); ?>
+ <? $iday = date('Ymd', $aday); ?>
+ <? if ($i <= $days_per_month[$month]) : ?>
+ <? $wday = date('w', $aday);
+ // emphasize current day
+ if (date('Ymd', $aday) == $now) {
+ $day_class = ' class="celltoday"';
+ } else if ($wday == 0 || $wday == 6) {
+ $day_class = ' class="weekend"';
+ } else {
+ $day_class = ' class="weekday"';
+ }
+ ?>
+
+ <td <?= $day_class ?> <?= $month == 1 ? 'height="25"' : '' ?>>
+
+ <? if (isset($count_list[$iday]) && count($count_list[$iday])) : ?>
+ <table width="100%" cellspacing="0" cellpadding="0">
+ <tr>
+ <td<?= $day_class ?>>
+ <? endif; ?>
+
+ <? $weekday = strftime('%a', $aday); ?>
+
+ <span class="yday">
+ <? $hday = holiday($aday); ?>
+ <? if ($hday['col'] == '1') : ?>
+ <? if (date('w', $aday) == '0') : ?>
+ <a style="font-weight:bold;" class="sday" href="<?= $controller->url_for('calendar/single/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? $count++; ?>
+ <? else : ?>
+ <a style="font-weight:bold;" class="day" href="<?= $controller->url_for('calendar/single/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? endif; ?>
+ <? elseif ($hday['col'] == '2' || $hday['col'] == '3') : ?>
+ <? if (date('w', $aday) == '0') : ?>
+ <a style="font-weight:bold;" class="sday" href="<?= $controller->url_for('calendar/single/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? $count++; ?>
+ <? else : ?>
+ <a style="font-weight:bold;" class="hday" href="<?= $controller->url_for('calendar/single/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if (date('w', $aday) == '0') : ?>
+ <a style="font-weight:bold;" class="sday" href="<?= $controller->url_for('calendar/single/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? $count++; ?>
+ <? else : ?>
+ <a style="font-weight:bold;" class="day" href="<?= $controller->url_for('calendar/single/day', ['atime' => $aday]) ?>"><?= $i ?></a> <?= $weekday; ?>
+ <? endif; ?>
+ <? endif; ?>
+ </span>
+
+ <? if (isset($count_list[$iday]) && count($count_list[$iday])) : ?>
+ <? $event_count_txt = sprintf(ngettext('1 Termin', '%s Termine', count($count_list[$iday])), count($count_list[$iday])) ?>
+ </td>
+ <td<?= $day_class ?> align="right">
+ <?= Icon::create('date', 'clickable', ['title' => $event_count_txt])->asImg(16, ["alt" => $event_count_txt]); ?>
+ </td>
+ </tr>
+ </table>
+ <? endif; ?>
+
+ </td>
+
+ <? else : ?>
+ <td class="weekday"> </td>
+ <? endif; ?>
+
+ <? endfor; ?>
+ </tr>
+ <? endfor; ?>
+ </tbody>
+
+ <tfoot>
+ <tr>
+ <? $ts_month = 0; ?>
+ <? for ($i = 1; $i < 13; $i++) : ?>
+ <? $ts_month += ( $days_per_month[$i] - 1) * 86400; ?>
+ <th align="center" width="8%">
+ <a class="calhead" href="<?= $controller->url_for('calendar/single/month', ['atime' => $calendar->getStart() + $ts_month]) ?>">
+ <b><?= strftime('%B', $ts_month); ?></b>
+ </a>
+ </th>
+ <? endfor; ?>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+</div>
diff --git a/app/views/calendar/stylesheet.php b/app/views/calendar/stylesheet.php
new file mode 100644
index 0000000..aaf7334
--- /dev/null
+++ b/app/views/calendar/stylesheet.php
@@ -0,0 +1,13 @@
+div.schedule_day {
+ height: <?= $whole_height ?>px;
+}
+
+div.schedule_marker {
+ height: <?= floor($entry_height / 2) ?>px;
+ line-height: <?= floor($entry_height / 2) ?>px;
+ margin-bottom: <?= floor($entry_height / 2) ?>px;
+}
+
+div.schedule_hours {
+ height: <?= $entry_height ?>px;
+}
diff --git a/app/views/consultation/admin/book.php b/app/views/consultation/admin/book.php
new file mode 100644
index 0000000..8f2db66
--- /dev/null
+++ b/app/views/consultation/admin/book.php
@@ -0,0 +1,48 @@
+<form action="<?= $controller->book($slot->block, $slot, $page) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Termin reservieren') ?></legend>
+
+ <label>
+ <?= _('Termin') ?><br>
+ <?= $this->render_partial('consultation/slot-details.php', compact('slot')) ?>
+ </label>
+
+ <label>
+ <?= _('Ort') ?><br>
+ <?= htmlready($slot->block->room) ?>
+ </label>
+
+ <label>
+ <span class="required">
+ <? if ($slot->block->range instanceof Course): ?>
+ <?= htmlReady(sprintf(
+ _('Teilnehmer der Veranstaltung "%s" suchen'),
+ $slot->block->range->getFullName()
+ )) ?>
+ <? else: ?>
+ <?= _('Person suchen') ?>
+ <? endif; ?>
+ </span>
+
+ <?= QuickSearch::get('user_id', $search_object)->setAttributes([
+ 'required' => '',
+ ])->withButton() ?>
+ </label>
+
+ <label>
+ <?= _('Grund') ?>
+ <textarea name="reason"></textarea>
+ </label>
+ </fieldset>
+
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Termin reservieren')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL($page, "#block-{$slot->block_id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/admin/cancel_block.php b/app/views/consultation/admin/cancel_block.php
new file mode 100644
index 0000000..06a33fe
--- /dev/null
+++ b/app/views/consultation/admin/cancel_block.php
@@ -0,0 +1,38 @@
+<form action="<?= $controller->cancel_block($block, $page) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Termine absagen') ?></legend>
+
+ <label>
+ <?= _('Termin' ) ?><br>
+ <ul class="default">
+ <? foreach ($block->slots as $slot): ?>
+ <? if ($slot->has_bookings): ?>
+ <li>
+ <?= $this->render_partial('consultation/slot-details.php', compact('slot')) ?>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ </ul>
+ </label>
+
+ <label>
+ <?= _('Ort') ?><br>
+ <?= htmlready($block->room) ?>
+ </label>
+
+ <label>
+ <?= _('Grund der Absage') ?>
+ <textarea name="reason"></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Termine absagen')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL($page, "#block-{$block->id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/admin/cancel_slot.php b/app/views/consultation/admin/cancel_slot.php
new file mode 100644
index 0000000..569fe64
--- /dev/null
+++ b/app/views/consultation/admin/cancel_slot.php
@@ -0,0 +1,50 @@
+<form action="<?= $controller->cancel_slot($slot->block, $slot, $page) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Termin absagen') ?></legend>
+
+ <label>
+ <?= _('Termin' ) ?><br>
+ <?= $this->render_partial('consultation/slot-details.php', compact('slot')) ?>
+ </label>
+
+ <label>
+ <?= _('Ort') ?><br>
+ <?= htmlready($slot->block->room) ?>
+ </label>
+
+ <? if (count($slot->bookings) > 1): ?>
+ <div>
+ <?= _('Den folgenden Personen absagen') ?><br>
+ <ul class="list-unstyled">
+ <? foreach ($slot->bookings as $booking): ?>
+ <li>
+ <input type="checkbox" name="ids[]" checked
+ class="studip-checkbox"
+ id="booking-<?= htmlReady($booking->id) ?>"
+ value="<?= htmlReady($booking->id) ?>">
+ <label for="booking-<?= htmlReady($booking->id) ?>" class="undecorated">
+ <?= htmlReady($booking->user->getFullName()) ?>
+ </label>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+ <br>
+ <? endif; ?>
+
+ <label>
+ <?= _('Grund der Absage') ?>
+ <textarea name="reason"></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Termin absagen')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL($page, "#block-{$slot->block_id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/admin/cancel_slots.php b/app/views/consultation/admin/cancel_slots.php
new file mode 100644
index 0000000..cb9679e
--- /dev/null
+++ b/app/views/consultation/admin/cancel_slots.php
@@ -0,0 +1,57 @@
+<form action="<?= $action ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <?= addHiddenFields('slot-id', $slots->map(function ($slot) {
+ return "{$slot->block_id}-{$slot->id}";
+ })) ?>
+
+ <fieldset>
+ <legend><?= _('Termine absagen') ?></legend>
+
+ <? if ($allow_delete): ?>
+ <p>
+ <?= _('Die folgenden Termine sind belegt und müssen abgesagt werden bevor sie gelöscht werden können.') ?>
+ <? if ($mixed): ?>
+ <?= _('Alternativ können Sie auch nur die freien Termine löschen.') ?>
+ <? endif; ?>
+ </p>
+ <? endif; ?>
+
+ <label>
+ <?= _('Termin') ?><br>
+ <ul class="default">
+ <? foreach ($slots as $slot): ?>
+ <? if ($slot->has_bookings): ?>
+ <li>
+ <?= $this->render_partial('consultation/slot-details.php', compact('slot')) ?>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ </ul>
+ </label>
+
+ <label>
+ <?= _('Grund der Absage') ?>
+ <textarea name="reason"></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if ($allow_delete): ?>
+ <?= Studip\Button::createAccept(_('Termine absagen und löschen'), 'delete', [
+ 'value' => 'cancel',
+ ]) ?>
+ <? if ($mixed): ?>
+ <?= Studip\Button::create(_('Nur freie Termine löschen'), 'delete', [
+ 'value' => 'skip',
+ ]) ?>
+ <? endif; ?>
+ <? else: ?>
+ <?= Studip\Button::createAccept(_('Termine absagen')) ?>
+ <? endif; ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL($page, "#block-{$block->id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/admin/create.php b/app/views/consultation/admin/create.php
new file mode 100644
index 0000000..4630cee
--- /dev/null
+++ b/app/views/consultation/admin/create.php
@@ -0,0 +1,191 @@
+<?php
+$days_of_the_week = [
+ _('Montag') => 1,
+ _('Dienstag') => 2,
+ _('Mittwoch') => 3,
+ _('Donnerstag') => 4,
+ _('Freitag') => 5,
+ _('Samstag') => 6,
+ _('Sonntag') => 0
+];
+$intervals = [
+ _('wöchentlich') => 1,
+ _('zweiwöchentlich') => 2,
+ _('dreiwöchentlich') => 3,
+ _('monatlich') => 4,
+];
+?>
+
+<form action="<?= $controller->store() ?>" method="post" class="default" data-dialog>
+ <?= CSRFProtection::tokenTag() ?>
+
+<? if ($flash['confirm-many']): ?>
+ <?= MessageBox::info(
+ _('Sie erstellen eine sehr große Anzahl an Terminen.') . ' ' .
+ _('Bitte bestätigen Sie diese Aktion.'),
+ [
+ '<label><input type="checkbox" name="confirmed" value="1">' .
+ sprintf(
+ _('Ja, ich möchte wirklich %s Termine erstellen.'),
+ number_format($flash['confirm-many'], 0, ',', '.')
+ ) .
+ '</label>'
+ ]
+ )->hideClose() ?>
+<? endif; ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Neue Terminblöcke anlegen') ?>
+ </legend>
+
+ <label>
+ <span class="required"><?= _('Ort') ?></span>
+
+ <input required type="text" name="room"
+ value="<?= htmlReady(Request::get('room', $room)) ?>"
+ placeholder="<?= _('Ort') ?>">
+ </label>
+
+ <label class="col-3">
+ <span class="required"><?= _('Beginn') ?></span>
+
+ <input required type="text" name="start-date" id="start-date"
+ value="<?= htmlReady(Request::get('start-date', strftime('%d.%m.%Y', strtotime('+7 days')))) ?>"
+ placeholder="<?= _('tt.mm.jjjj') ?>"
+ data-date-picker='{">=":"today"}'>
+ </label>
+
+ <label class="col-3">
+ <span class="required"><?= _('Ende') ?></span>
+
+ <input required type="text" name="end-date" id="end-date"
+ value="<?= htmlReady(Request::get('end-date', strftime('%d.%m.%Y', strtotime('+4 weeks')))) ?>"
+ placeholder="<?= _('tt.mm.jjjj') ?>"
+ data-date-picker='{">=":"#start-date"}'>
+ </label>
+
+ <label class="col-3">
+ <span class="required"><?= _('Am Wochentag') ?></span>
+
+ <select required name="day-of-week">
+ <? foreach ($days_of_the_week as $day => $value): ?>
+ <option value="<?= $value ?>" <? if (Request::get('day-of-week', strftime('%w')) == $value) echo 'selected'; ?>>
+ <?= htmlReady($day) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <span class="required"><?= _('Intervall') ?></span>
+ <select required name="interval">
+ <? foreach ($intervals as $interval => $value): ?>
+ <option value="<?= $value ?>" <? if (Request::int('interval') == $value) echo 'selected'; ?>>
+ <?= htmlReady($interval) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label for="start-time" class="col-3">
+ <span class="required"><?= _('Von') ?></span>
+
+ <input required type="text" name="start-time" id="start-time"
+ value="<?= htmlReady(Request::get('start-time', '08:00')) ?>"
+ placeholder="<?= _('HH:mm') ?>"
+ data-time-picker='{"<":"#end-time"}'>
+ </label>
+
+ <label for="ende_hour" class="col-3">
+ <span class="required"><?= _('Bis') ?></span>
+
+ <input required type="text" name="end-time" id="end-time"
+ value="<?= htmlReady(Request::get('end-time', '09:00')) ?>"
+ placeholder="<?= _('HH:mm') ?>"
+ data-time-picker='{">":"#start-time"}'>
+ </label>
+
+ <label class="col-3">
+ <span class="required"><?= _('Dauer eines Termins in Minuten') ?></span>
+ <input required type="text" name="duration"
+ value="<?= htmlReady(Request::int('duration', 15)) ?>"
+ maxlength="3" pattern="^\d+$">
+ </label>
+
+ <label class="col-3">
+ <?= _('Maximale Teilnehmerzahl') ?>
+ <?= tooltipIcon(_('Falls Sie mehrere Personen zulassen wollen (wie z.B. zu einer Klausureinsicht), so geben Sie hier die maximale Anzahl an Personen an, die sich anmelden dürfen.')) ?>
+ <input required type="text" name="size" id="size"
+ min="1" max="50" value="<?= Request::int('size', 1) ?>">
+ </label>
+
+ <? if ($responsible): ?>
+ <label>
+ <?= _('Durchführende Person') ?>
+ <select name="teacher_id">
+ <option value=""></option>
+ <? foreach ($responsible as $user): ?>
+ <option value="<?= htmlReady($user->id) ?>">
+ <?= htmlReady($user->getFullName()) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? endif; ?>
+
+ <label>
+ <?= _('Information zu den Terminen in diesem Block') ?>
+ <textarea name="note"><?= htmlReady(Request::get('note')) ?></textarea>
+ </label>
+
+ <label>
+ <input type="checkbox" name="calender-events" value="1"
+ <? if (Request::bool('calender-events')) echo 'checked'; ?>>
+ <?= _('Die freien Termine auch im Kalender markieren') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="show-participants" value="1"
+ <? if (Request::bool('show-participants')) echo 'checked'; ?>>
+ <?= _('Namen der buchenden Personen sind öffentlich sichtbar') ?>
+ </label>
+
+ <label>
+ <?= _('Grund der Buchung abfragen') ?>
+ </label>
+ <div class="hgroup">
+ <label>
+ <input type="radio" name="require-reason" value="yes"
+ <? if (Request::get('require-reason') === 'yes') echo 'checked'; ?>>
+ <?= _('Ja, zwingend erforderlich') ?>
+ </label>
+
+ <label>
+ <input type="radio" name="require-reason" value="optional"
+ <? if (Request::get('require-reason', 'optional') === 'optional') echo 'checked'; ?>>
+ <?= _('Ja, optional') ?>
+ </label>
+
+ <label>
+ <input type="radio" name="require-reason" value="no"
+ <? if (Request::get('require-reason') === 'no') echo 'checked'; ?>>
+ <?= _('Nein') ?>
+ </label>
+ </div>
+
+ <label>
+ <?= _('Bestätigung für folgenden Text einholen') ?>
+ (<?= _('optional') ?>)
+ <?= tooltipIcon(_('Wird hier ein Text eingegeben, so müssen Buchende bestätigen, dass sie diesen Text gelesen haben.')) ?>
+ <textarea name="confirmation-text"><?= htmlReady(Request::get('confirmation-text')) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Termin speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL()
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/admin/edit_room.php b/app/views/consultation/admin/edit_room.php
new file mode 100644
index 0000000..6c52436
--- /dev/null
+++ b/app/views/consultation/admin/edit_room.php
@@ -0,0 +1,21 @@
+<form action="<?= $controller->store_room($block, $page) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Ort des Terminblocks bearbeiten') ?></legend>
+
+ <label>
+ <span class="required"><?= _('Ort') ?></span>
+ <input required type="text" name="room" placeholder="<?= _('Ort') ?>"
+ value="<?= htmlReady($block->room) ?>">
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL($page)
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/admin/index.php b/app/views/consultation/admin/index.php
new file mode 100644
index 0000000..c6b36c3
--- /dev/null
+++ b/app/views/consultation/admin/index.php
@@ -0,0 +1,202 @@
+<? if (count($blocks) === 0): ?>
+
+<?= MessageBox::info(sprintf(
+ implode('<br>', [
+ _('Derzeit sind keine Termine eingetragen.'),
+ '<a href="%s" class="button" data-dialog="size=auto">%s</a>',
+ ]),
+ $controller->create(),
+ _('Terminblöcke anlegen')
+))->hideClose() ?>
+
+<? else: ?>
+
+<form action="<?= $controller->bulk($page, $current_action === 'expired') ?>" method="post">
+<table class="default consultation-overview">
+ <colgroup>
+ <col width="24px">
+ <col width="10%">
+ <col width="12%">
+ <col>
+ <col width="48px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" id="checkbox-proxy"
+ class="studip-checkbox"
+ data-proxyfor=".consultation-overview tbody th :checkbox"
+ data-activates=".consultation-overview tfoot button">
+ <label for="checkbox-proxy"></label>
+ </th>
+ </th>
+ <th><?= _('Uhrzeit') ?></th>
+ <th><?= _('Status') ?></th>
+ <th><?= _('Informationen') ?></th>
+ <th></th>
+ </tr>
+ </thead>
+<? foreach ($blocks as $block): ?>
+ <tbody id="block-<?= htmlReady($block['block']->id) ?>" <? if ($block['block']->is_expired) echo 'class="block-is-expired"'; ?>>
+ <tr class="<? if ($block['block']->has_bookings) echo 'is-occupied'; ?>">
+ <th>
+ <input type="checkbox" id="slots-<?= htmLReady($block['block']->id) ?>-checkbox"
+ class="studip-checkbox"
+ data-proxyfor="#block-<?= htmlReady($block['block']->id) ?> :checkbox[name^=slot]">
+ <label for="slots-<?= htmlReady($block['block']->id) ?>-checkbox"></label>
+ </th>
+ <th colspan="3">
+ <?= $this->render_partial('consultation/block-description.php', ['block' => $block['block']]) ?>
+ </th>
+ <th class="actions">
+ <?= ActionMenu::get()->addLink(
+ $controller->edit_roomURL($block['block'], $page),
+ _('Raum bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ )->addLink(
+ $controller->noteURL($block['block'], 0, $page),
+ _('Information bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ )->addLink(
+ $controller->url_for("consultation/export/print/{$block['block']->id}"),
+ _('Druckansicht anzeigen'),
+ Icon::create('print'),
+ ['target' => '_blank']
+ )->condition($block['block']->has_bookings)->addLink(
+ $controller->mailURL($block['block']),
+ _('Nachricht schreiben'),
+ Icon::create('mail'),
+ ['data-dialog' => 'size=50%', 'class' => 'send-mail']
+ )->condition($block['block']->has_bookings && !$block['block']->is_expired)->addLink(
+ $controller->cancel_blockURL($block['block'], $page),
+ _('Termine absagen'),
+ Icon::create('consultation+remove'),
+ ['data-dialog' => 'size=auto']
+ )->condition(!$block['block']->has_bookings || $block['block']->is_expired)->addButton(
+ 'remove',
+ _('Termine entfernen'),
+ Icon::create('trash'),
+ [
+ 'formaction' => $controller->removeURL($block['block'], 0, $page),
+ 'data-confirm' => _('Wollen Sie diese Termine wirklich löschen?'),
+ ]
+ ) ?>
+ </th>
+ </tr>
+ <? foreach ($block['slots'] as $slot): ?>
+ <tr id="slot-<?= htmlReady($slot->id) ?>" class="<? if ($slot->is_expired) echo 'slot-is-expired'; ?> <? if (count($slot->bookings) > 0) echo 'is-occupied'; ?>">
+ <td>
+ <input type="checkbox" name="slot-id[]" id="slot-<?= htmlReady($slot->id) ?>-checkbox"
+ class="studip-checkbox"
+ value="<?= htmlReady($block['block']->id) ?>-<?= htmlReady($slot->id) ?>">
+ <label for="slot-<?= htmlReady($slot->id) ?>-checkbox"></label>
+ </td>
+ <td>
+ <?= strftime('%R', $slot->start_time) ?>
+ -
+ <?= strftime('%R', $slot->end_time) ?>
+ </td>
+ <td>
+ <?= $this->render_partial('consultation/slot-occupation.php', compact('slot')) ?>
+ </td>
+ <td>
+ <? if (!$slot->note && count($slot->bookings) === 0): ?>
+ &ndash;
+ <? else: ?>
+ <? if ($slot->note): ?>
+ <?= formatLinks($slot->note) ?>
+ <br>
+ <? endif; ?>
+ <? if (count($slot->bookings) > 0): ?>
+ <ul class="default">
+ <? foreach ($slot->bookings as $booking): ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $booking->user->username]) ?>">
+ <?= htmlReady($booking->user->getFullName()) ?>
+ </a>
+ -
+ <? if ($booking->reason): ?>
+ <?= _('Grund') ?>:
+ <?= htmlReady($booking->reason) ?>
+ <? else: ?>
+ <span class="consultation-no-reason">
+ <?= _('Kein Grund angegeben') ?>
+ </span>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ <td class="actions">
+ <?= ActionMenu::get()->addLink(
+ $controller->noteURL($block['block'], $slot, $page),
+ _('Information bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ )->condition(!$slot->is_expired && count($slot->bookings) < $slot->block->size)->addLink(
+ $controller->bookURL($block['block'], $slot, $page),
+ _('Termin reservieren'),
+ Icon::create('consultation+add'),
+ ['data-dialog' => 'size=auto']
+ )->condition($slot->has_bookings)->addLink(
+ $controller->reasonURL($block['block'], $slot, $slot->bookings->first(), $page),
+ _('Grund bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ )->condition($slot->has_bookings)->addLink(
+ $controller->mailURL($block['block'], $slot),
+ _('Nachricht schreiben'),
+ Icon::create('mail'),
+ ['data-dialog' => 'size=50%', 'class' => 'send-mail']
+ )->condition($slot->has_bookings && !$slot->is_expired)->addLink(
+ $controller->cancel_slotURL($block['block'], $slot, $page),
+ _('Termin absagen'),
+ Icon::create('consultation+remove'),
+ ['data-dialog' => 'size=auto']
+ )->condition(!$slot->has_bookings || $slot->is_expired)->addButton(
+ 'delete',
+ _('Termin entfernen'),
+ Icon::create('trash'),
+ [
+ 'formaction' => $controller->removeURL($block['block'], $slot, $page),
+ 'data-confirm' => _('Wollen Sie diesen Termin wirklich entfernen?'),
+ ]
+ ) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+<? endforeach; ?>
+ <tfoot>
+ <tr>
+ <td colspan="5">
+ <?= Studip\Button::create(_('Nachricht schreiben'), 'mail', [
+ 'data-dialog' => 'size=50%',
+ 'data-activates-condition' => '.consultation-overview tbody tr.is-occupied:has(:checkbox:checked)',
+ 'formaction' => $controller->mailURL('bulk'),
+ ]) ?>
+ <?= Studip\Button::create(_('Absagen'), 'cancel', [
+ 'data-dialog' => 'size=auto',
+ 'data-activates-condition' => '.consultation-overview tbody tr.is-occupied:has(:checkbox:checked)',
+ ]) ?>
+ <?= Studip\Button::create(_('Löschen'), 'delete', [
+ 'class' => 'consultation-delete-check',
+ 'data-dialog' => 'size=auto',
+ ]) ?>
+
+ <div class="actions">
+ <?= Pagination::create($count, $page, $limit)->asLinks(function ($page) use ($controller, $current_action) {
+ return $controller->action_link($current_action, $page);
+ }) ?>
+ </div>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+</form>
+
+<? endif; ?>
diff --git a/app/views/consultation/admin/note.php b/app/views/consultation/admin/note.php
new file mode 100644
index 0000000..68703b4
--- /dev/null
+++ b/app/views/consultation/admin/note.php
@@ -0,0 +1,32 @@
+<? if (!$slot_id): ?>
+ <?= MessageBox::info(
+ _('Das Ändern der Information wird auch die Information aller Termine dieses Blocks ändern.')
+ )->hideClose() ?>
+<? endif; ?>
+
+<form action="<?= $controller->note($block, $slot_id ?: 0, $page) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <? if ($slot_id): ?>
+ <?= _('Information zu diesem Termin bearbeiten') ?>
+ <? else: ?>
+ <?= _('Information zu diesem Terminblock bearbeiten') ?>
+ <? endif; ?>
+ </legend>
+
+ <label>
+ <?=_('Information') ?> (<?= _('öffentlich einsehbar') ?>)
+ <textarea name="note"><?= htmlReady($slot_id ? $block->slots->find($slot_id)->note : $block->note ) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL($page, "#block-{$block->id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/admin/reason.php b/app/views/consultation/admin/reason.php
new file mode 100644
index 0000000..e7ad374
--- /dev/null
+++ b/app/views/consultation/admin/reason.php
@@ -0,0 +1,20 @@
+<form action="<?= $controller->reason($booking->slot->block, $booking->slot, $booking, $page) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Grund für die Buchung bearbeiten') ?></legend>
+
+ <label>
+ <?= _('Grund') ?>
+ <textarea name="reason"><?= htmlReady($booking->reason) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL($page, "#block-{$booking->slot->block_id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/admin/tab.php b/app/views/consultation/admin/tab.php
new file mode 100644
index 0000000..7b58c15
--- /dev/null
+++ b/app/views/consultation/admin/tab.php
@@ -0,0 +1,17 @@
+<form action="<?= $controller->tab($from_expired) ?>" method="post" class="default">
+ <fieldset>
+ <legend><?= _('Namen des Reiters ändern') ?></legend>
+
+ <label>
+ <?= _('Aktueller Name') ?>
+ <?= I18N::input('tab_title', $current_title, ['required' => '']) ?>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\Button::createCancel(
+ _('Abbrechen'),
+ $from_expired ? $controller->indexURL() : $controller->expiredURL()
+ ) ?>
+</form>
diff --git a/app/views/consultation/admin/ungrouped.php b/app/views/consultation/admin/ungrouped.php
new file mode 100644
index 0000000..881c940
--- /dev/null
+++ b/app/views/consultation/admin/ungrouped.php
@@ -0,0 +1,281 @@
+<? if (count($blocks) === 0): ?>
+
+<?= MessageBox::info(sprintf(
+ implode('<br>', [
+ _('Derzeit sind keine Termine eingetragen.'),
+ '<a href="%s" class="button" data-dialog="size=auto">%s</a>',
+ ]),
+ $controller->create(),
+ _('Terminblöcke anlegen')
+))->hideClose() ?>
+
+<? else: ?>
+
+<form action="<?= $controller->bulk($page, $current_action === 'expired') ?>" method="post">
+<table class="default consultation-overview block-overview">
+ <caption><?= _('Terminblöcke') ?></caption>
+ <colgroup>
+ <col style="width: 24px">
+ <col>
+ <col>
+ <col>
+ <col>
+ <col style="width: 96px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" id="checkbox-block-proxy"
+ class="studip-checkbox"
+ data-proxyfor=".block-overview tbody :checkbox"
+ data-activates=".block-overview tfoot button">
+ <label for="checkbox-block-proxy"></label>
+ </th>
+ <th><?= _('Tag') ?></th>
+ <th><?= _('Zeit') ?></th>
+ <th><?= _('Bei') ?></th>
+ <th><?= _('Ort') ?></th>
+ <th class="actions"><?= _('Optionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($blocks as $block): ?>
+ <tr id="block-<?= htmlReady($block->id) ?>" class="<? if ($block->is_expired) echo 'block-is-expired'; ?> <? if ($block->has_bookings) echo 'is-occupied'; ?>">
+ <td>
+ <input type="checkbox" id="block-checkbox-<?= htmlReady($block->id) ?>"
+ name="block-id[]"
+ class="studip-checkbox" value="<?= htmlReady($block->id) ?>">
+ <label for="block-checkbox-<?= htmlReady($block->id) ?>"></label>
+ </td>
+ <td>
+ <?= strftime('%A, %x', $block->start) ?>
+ </td>
+ <td>
+ <?= sprintf(
+ _('%s bis %s Uhr'),
+ date('H:i', $block->start),
+ date('H:i', $block->end)
+ ) ?>
+ </td>
+ <td>
+ <? if ($block->teacher): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $block->teacher->username]) ?>">
+ <?= htmlReady($block->teacher->getFullName()) ?>
+ </a>
+ <? else: ?>
+ &ndash;
+ <? endif; ?>
+ </td>
+ <td>
+ <?= formatLinks($block->room) ?>
+ </td>
+ <td class="actions">
+ <?= ActionMenu::get()->addLink(
+ $controller->edit_roomURL($block, $page),
+ _('Raum bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ )->addLink(
+ $controller->noteURL($block, 0, $page),
+ _('Information bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ )->addLink(
+ $controller->url_for("consultation/export/print/{$block->id}"),
+ _('Druckansicht anzeigen'),
+ Icon::create('print'),
+ ['target' => '_blank']
+ )->condition($block->has_bookings)->addLink(
+ $controller->mailURL($block),
+ _('Nachricht schreiben'),
+ Icon::create('mail'),
+ ['data-dialog' => 'size=50%', 'class' => 'send-mail']
+ )->condition($block->has_bookings && !$block->is_expired)->addLink(
+ $controller->cancel_blockURL($block, $page),
+ _('Termine absagen'),
+ Icon::create('consultation+remove'),
+ ['data-dialog' => 'size=auto']
+ )->condition(!$block->has_bookings || $block->is_expired)->addButton(
+ 'remove',
+ _('Termine entfernen'),
+ Icon::create('trash'),
+ [
+ 'formaction' => $controller->removeURL($block, 0, $page),
+ 'data-confirm' => _('Wollen Sie diese Termine wirklich löschen?'),
+ ]
+ ) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <?= Studip\Button::create(_('Nachricht schreiben'), 'mail', [
+ 'data-dialog' => 'size=50%',
+ 'data-activates-condition' => '.block-overview tbody tr.is-occupied:has(:checkbox:checked)',
+ 'formaction' => $controller->mailURL('bulk'),
+ ]) ?>
+ <?= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Wollen Sie diese Termine wirklich löschen?'),
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+
+<table class="default consultation-overview slot-overview">
+ <caption><?= _('Termine') ?></caption>
+ <colgroup>
+ <col width="24px">
+ <col width="15%">
+ <col>
+ <col>
+ <col>
+ <col>
+ <col>
+ <col style="width: 96px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" id="checkbox-slot-proxy"
+ class="studip-checkbox"
+ data-proxyfor=".slot-overview tbody :checkbox"
+ data-activates=".slot-overview tfoot button">
+ <label for="checkbox-slot-proxy"></label>
+ </th>
+ </th>
+ <th><?= _('Tag') ?></th>
+ <th><?= _('Zeit') ?></th>
+ <th><?= _('Ort') ?></th>
+ <th><?= _('Status') ?></th>
+ <th><?= _('Person(en)') ?></th>
+ <th><?= _('Grund') ?></th>
+ <th class="actions"><?= _('Optionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($slots as $slot): ?>
+ <tr id="slot-<?= htmlReady($slot->id) ?>" class="<? if ($slot->is_expired) echo 'slot-is-expired'; ?> <? if (count($slot->bookings) > 0) echo 'is-occupied'; ?>">
+ <td>
+ <input type="checkbox" name="slot-id[]" id="slot-<?= htmlReady($slot->id) ?>"
+ class="studip-checkbox"
+ value="<?= htmlReady($slot->block_id) ?>-<?= htmlReady($slot->id) ?>">
+ <label for="slot-<?= htmlReady($slot->id) ?>"></label>
+ </td>
+ <td>
+ <?= strftime(_('%A, %x'), $slot->start_time) ?>
+ </td>
+ <td>
+ <?= strftime('%H:%M', $slot->start_time) ?>
+ -
+ <?= strftime('%H:%M', $slot->end_time) ?>
+ <? if ($slot->note): ?>
+ <div style="color: black; font-size: 12px" title="<?= htmlReady($slot->note) ?>">
+ <? if (mb_strlen($slot->note) > 29): ?>
+ <?= htmlReady(mb_substr($slot->note, 0, 30)) ?>&hellip;
+ <? else: ?>
+ <?= htmlReady($slot->note) ?>
+ <? endif; ?>
+ </div>
+ <? endif; ?>
+ </td>
+ <td>
+ <?= htmlReady($block->room) ?>
+ </td>
+ <td>
+ <?= $this->render_partial('consultation/slot-occupation.php', compact('slot')) ?>
+ </td>
+ <td>
+ <? if (count($slot->bookings) === 0): ?>
+ &ndash;
+ <? else: ?>
+ <ul class="default">
+ <? foreach ($slot->bookings as $booking): ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $booking->user->username]) ?>">
+ <?= htmlReady($booking->user->getFullName()) ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ </td>
+ <td>
+ <? if (count($slot->bookings) === 0): ?>
+ &ndash;
+ <? else: ?>
+ <ul class="default">
+ <? foreach ($slot->bookings as $booking): ?>
+ <li>
+ <?= htmlReady($booking->reason ?: _('Kein Grund angegeben')) ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ </td>
+ <td class="actions">
+ <?= ActionMenu::get()->addLink(
+ $controller->noteURL($slot->block, $slot, $page),
+ _('Information bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ )->condition(!$slot->is_expired && count($slot->bookings) < $slot->block->size)->addLink(
+ $controller->bookURL($slot->block, $slot, $page),
+ _('Termin reservieren'),
+ Icon::create('consultation+add'),
+ ['data-dialog' => 'size=auto']
+ )->condition($slot->has_bookings)->addLink(
+ $controller->reasonURL($slot->block, $slot, $slot->bookings->first(), $page),
+ _('Grund bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ )->condition($slot->has_bookings)->addLink(
+ $controller->mailURL($slot->block, $slot),
+ _('Nachricht schreiben'),
+ Icon::create('mail'),
+ ['data-dialog' => 'size=50%', 'class' => 'send-mail']
+ )->condition($slot->has_bookings && !$slot->is_expired)->addLink(
+ $controller->cancel_slotURL($slot->block, $slot, $page),
+ _('Termin absagen'),
+ Icon::create('consultation+remove'),
+ ['data-dialog' => 'size=auto']
+ )->condition(!$slot->has_bookings || $slot->is_expired)->addButton(
+ 'delete',
+ _('Termin entfernen'),
+ Icon::create('trash'),
+ [
+ 'formaction' => $controller->removeURL($slot->block, $slot, $page),
+ 'data-confirm' => _('Wollen Sie diesen Termin wirklich entfernen?'),
+ ]
+ ) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="8">
+ <?= Studip\Button::create(_('Nachricht schreiben'), 'mail', [
+ 'data-dialog' => 'size=50%',
+ 'data-activates-condition' => '.slot-overview tbody tr.is-occupied:has(:checkbox:checked)',
+ 'formaction' => $controller->mailURL('bulk'),
+ ]) ?>
+ <?= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Wollen Sie diese Termine wirklich löschen?'),
+ 'data-activates-condition' => '.slot-overview tbody tr:not(.is-occupied):has(:checkbox:checked)',
+ ]) ?>
+
+ <div class="actions">
+ <?= Pagination::create($count, $page, $limit)->asLinks(function ($page) use ($controller, $current_action) {
+ return $controller->action_link($current_action, $page);
+ }) ?>
+ </div>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+</form>
+
+<? endif; ?>
diff --git a/app/views/consultation/block-description.php b/app/views/consultation/block-description.php
new file mode 100644
index 0000000..df3d0bd
--- /dev/null
+++ b/app/views/consultation/block-description.php
@@ -0,0 +1,28 @@
+<?= strftime('%A, %x', $block->start) ?>
+
+<?= sprintf(
+ _('%s bis %s Uhr'),
+ date('H:i', $block->start),
+ date('H:i', $block->end)
+) ?>
+
+<? if ($block->teacher): ?>
+/
+<a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $block->teacher->username]) ?>">
+ <?= htmlReady($block->teacher->getFullName()) ?>
+</a>
+<? endif; ?>
+
+(<?= formatLinks($block->room) ?>)
+
+<? if ($block->show_participants): ?>
+ - <?= _('öffentlich sichtbar') ?>
+ <?= tooltipIcon(_('Die Namen der buchenden Person sind sichtbar')) ?>
+<? endif; ?>
+
+<? if ($block->note): ?>
+<br>
+<small>
+ <?= formatLinks($block->note); ?>
+</small>
+<? endif; ?>
diff --git a/app/views/consultation/export/print.php b/app/views/consultation/export/print.php
new file mode 100644
index 0000000..dd42f93
--- /dev/null
+++ b/app/views/consultation/export/print.php
@@ -0,0 +1,144 @@
+<!doctype html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+ <title><?= _('Terminliste') ?></title>
+ <style>
+ body {
+ padding: 0;
+ font-family: Arial, Helvetica, sans-serif;
+ }
+ body:not(.extended) .reason {
+ display: none;
+ }
+ h1 {
+ font-weight: bold;
+ font-size: 20pt;
+ padding-bottom: 3pt;
+ border-bottom: 1pt solid #000000;
+ margin-bottom: 1em;
+ }
+ h1::after {
+ clear: right;
+ }
+ a {
+ text-decoration: none;
+ color: #000000;
+ }
+ table {
+ border: 1px solid #000000;
+ border-collapse: collapse;
+ border-spacing: 0;
+ width: 100%;
+ }
+ caption {
+ text-align: left;
+ }
+ td, th {
+ border: 1px solid #000000;
+ padding: 0.5em 1em;
+ }
+ th, td:nth-child(1), td:nth-child(2) {
+ text-align: center;
+ white-space: nowrap;
+ }
+ ul {
+ margin: 0;
+ padding: 0;
+ }
+ ul li:only-child {
+ list-style: none;
+ }
+ #toggle {
+ float: right;
+ }
+ </style>
+ <style media="print">
+ #toggle {
+ display: none;
+ }
+ </style>
+</head>
+<body id="body">
+ <h1>
+ <button id="toggle">
+ <?= _('Grund anzeigen / verbergen') ?>
+ </button>
+
+ <?= sprintf(
+ _('Terminliste von %s'),
+ htmlReady($current_user->getFullName())
+ ) ?>
+ </h1>
+<? foreach ($blocks as $block): ?>
+ <table>
+ <caption>
+ <h2>
+ <?= _('Termin') ?>:
+ <?= strftime('%A, %x', $block->start) ?>
+ (<?= htmlReady($block->room) ?>)
+ </h2>
+ </caption>
+ <colgroup>
+ <col width="20%">
+ <col>
+ <col width="50%" class="reason">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Zeit') ?></th>
+ <th>
+ <? if ($block->size > 1): ?>
+ <?= _('Person(en)') ?>
+ <? else: ?>
+ <?= _('Person') ?>
+ <? endif; ?>
+ </th>
+ <th class="reason"><?= _('Grund') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($block->slots as $slot): ?>
+ <tr>
+ <td>
+ <?= implode(' - ', [
+ date('H:i', $slot->start_time),
+ date('H:i', $slot->end_time)
+ ]) ?>
+ </td>
+ <td>
+ <? if (count($slot->bookings) > 0): ?>
+ <ul>
+ <? foreach ($slot->bookings as $booking): ?>
+ <li><?= htmlReady($booking->user->getFullName()) ?></li>
+ <? endforeach; ?>
+ </ul>
+ <? else: ?>
+ &ndash;
+ <? endif; ?>
+ </td>
+ <td class="reason">
+ <? if (count($slot->bookings) > 0): ?>
+ <ul>
+ <? foreach ($slot->bookings as $booking): ?>
+ <li><?= htmlReady($booking->reason) ?></li>
+ <? endforeach; ?>
+ </ul>
+ <? else: ?>
+ &ndash;
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+<? endforeach; ?>
+
+ <script>
+ document.getElementById('toggle').addEventListener('click', function (event) {
+ document.getElementById('body').classList.toggle('extended');
+ event.preventDefault();
+ }, false);
+ </script>
+</body>
+</html>
diff --git a/app/views/consultation/overview/book.php b/app/views/consultation/overview/book.php
new file mode 100644
index 0000000..e706184
--- /dev/null
+++ b/app/views/consultation/overview/book.php
@@ -0,0 +1,49 @@
+<form name="reason_form" action="<?= $controller->book($slot->block, $slot) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+<? if ($slot->block->show_participants): ?>
+ <?= MessageBox::info(_('Bitte beachten Sie, dass Ihre Buchung öffentlich sichtbar sein wird'))->hideClose() ?>
+<? endif; ?>
+
+ <fieldset>
+ <legend><?= _('Termin reservieren') ?></legend>
+
+ <label>
+ <?= _('Termin') ?><br>
+ <?= $this->render_partial('consultation/slot-details.php', compact('slot')) ?>
+ </label>
+
+ <label>
+ <?= _('Ort') ?><br>
+ <?= htmlready($slot->block->room) ?>
+ </label>
+
+ <? if ($slot->block->require_reason !== 'no'): ?>
+ <label>
+ <span <? if ($slot->block->require_reason === 'yes') echo 'class="required"'; ?>><?= _('Grund') ?></span>
+ <textarea name="reason" <? if ($slot->block->require_reason === 'yes') echo 'required'; ?>></textarea>
+ </label>
+ <? endif; ?>
+
+ <? if ($slot->block->confirmation_text): ?>
+ <label>
+ <?= _('Bitte lesen Sie sich den folgenden Hinweis durch:') ?>
+ <textarea disabled><?= htmlReady($slot->block->confirmation_text) ?></textarea>
+ </label>
+
+ <label>
+ <input type="checkbox" required>
+ <?= _('Ich habe den obigen Hinweis zur Kenntnis genommen') ?>
+ </label>
+ <? endif; ?>
+ </fieldset>
+
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Termin reservieren')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL("#block-{$slot->block_id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/overview/booked.php b/app/views/consultation/overview/booked.php
new file mode 100644
index 0000000..69a0cd9
--- /dev/null
+++ b/app/views/consultation/overview/booked.php
@@ -0,0 +1,58 @@
+<? if (count($slots) === 0): ?>
+
+<?= MessageBox::info(_('Sie haben aktuell keine Termine gebucht.'))->hideClose() ?>
+
+<? else: ?>
+
+<table class="default">
+ <colgroup>
+ <col width="10%">
+ <col width="10%">
+ <col>
+ <col width="24px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Uhrzeit') ?></th>
+ <th><?= _('Status') ?></th>
+ <th>
+ <?= _('Informationen') ?> /
+ <?= _('Mein Grund der Buchung') ?>:
+ </th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+<? $last_block = null;
+ foreach ($slots as $slot): ?>
+ <? if ($slot->block != $last_block): ?>
+ <tr id="block-<?= htmlReady($slot->block->id) ?>">
+ <th colspan="4">
+ <?= $this->render_partial('consultation/block-description.php', ['block' => $slot->block]) ?>
+ </th>
+ </tr>
+ <? endif; ?>
+ <tr id="slot-<?= htmlReady($slot->id) ?>">
+ <td>
+ <?= date('H:i', $slot->start_time) ?>
+ -
+ <?= date('H:i', $slot->end_time) ?>
+ </td>
+ <td>
+ <?= $this->render_partial('consultation/slot-occupation.php', compact('slot')) ?>
+ </td>
+ <td>
+ <?= $this->render_partial('consultation/slot-bookings.php', compact('slot')) ?>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->cancel($slot->block, $slot, 1) ?>" data-dialog="size=auto">
+ <?= Icon::create('trash')->asImg(tooltip2(_('Termin absagen'))) ?>
+ </a>
+ </td>
+ </tr>
+<? $last_block = $slot->block;
+ endforeach; ?>
+ </tbody>
+</table>
+
+<? endif; ?>
diff --git a/app/views/consultation/overview/cancel.php b/app/views/consultation/overview/cancel.php
new file mode 100644
index 0000000..f1c619c
--- /dev/null
+++ b/app/views/consultation/overview/cancel.php
@@ -0,0 +1,30 @@
+<form action="<?= $controller->cancel($slot->block, $slot, $from_booked) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Termin absagen') ?></legend>
+
+ <label>
+ <?= _('Termin' ) ?><br>
+ <?= $this->render_partial('consultation/slot-details.php', compact('slot')) ?>
+ </label>
+
+ <label>
+ <?= _('Ort') ?><br>
+ <?= htmlready($slot->block->room) ?>
+ </label>
+
+ <label>
+ <?= _('Grund') ?>
+ <textarea name="reason"></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Termin absagen')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->indexURL("#block-{$slot->block_id}")
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/consultation/overview/index.php b/app/views/consultation/overview/index.php
new file mode 100644
index 0000000..c209daa
--- /dev/null
+++ b/app/views/consultation/overview/index.php
@@ -0,0 +1,71 @@
+<? if (count($blocks) === 0): ?>
+
+<?= MessageBox::info(_('Aktuell werden keine Termine angeboten.'))->hideClose() ?>
+
+<? else: ?>
+
+<table class="default">
+ <colgroup>
+ <col width="10%">
+ <col width="10%">
+ <col>
+ <col width="24px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Uhrzeit') ?></th>
+ <th><?= _('Status') ?></th>
+ <th><?= _('Informationen') ?></th>
+ <th></th>
+ </tr>
+ </thead>
+<? foreach ($blocks as $block): ?>
+ <tbody>
+ <tr id="block-<?= htmlReady($block->id) ?>">
+ <th colspan="4">
+ <?= $this->render_partial('consultation/block-description.php', compact('block')) ?>
+ </th>
+ </tr>
+ <? foreach ($block->slots as $slot): ?>
+ <tr id="<?= htmlReady($slot->id) ?>">
+ <td>
+ <?= date('H:i', $slot->start_time) ?>
+ -
+ <?= date('H:i', $slot->end_time) ?>
+ </td>
+ <td>
+ <?= $this->render_partial('consultation/slot-occupation.php', compact('slot')) ?>
+ </td>
+ <td>
+ <?= $displayNote($slot->note, 2048) ?>
+ <?= $this->render_partial('consultation/slot-bookings.php', compact('slot')) ?>
+ </td>
+ <td class="actions">
+ <? if ($slot->isOccupied($GLOBALS['user']->id)): ?>
+ <a href="<?= $controller->cancel($block, $slot) ?>" data-dialog="size=auto">
+ <?= Icon::create('trash')->asImg(tooltip2(_('Termin absagen'))) ?>
+ </a>
+ <? elseif (!$slot->isOccupied()): ?>
+ <a href="<?= $controller->book($block, $slot) ?>" data-dialog="size=auto">
+ <?= Icon::create('add')->asImg(tooltip2(_('Termin reservieren'))) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+<? endforeach; ?>
+<? if ($count > $limit): ?>
+ <tfoot>
+ <tr>
+ <td colspan="4">
+ <?= Pagination::create($count, $page, $limit)->asLinks(function ($page) use ($controller) {
+ return $controller->index($page);
+ }) ?>
+ </td>
+ </tr>
+ </tfoot>
+<? endif; ?>
+</table>
+
+<? endif; ?>
diff --git a/app/views/consultation/overview/ungrouped.php b/app/views/consultation/overview/ungrouped.php
new file mode 100644
index 0000000..b8bccf5
--- /dev/null
+++ b/app/views/consultation/overview/ungrouped.php
@@ -0,0 +1,97 @@
+<? if (count($blocks) === 0): ?>
+
+<?= MessageBox::info(_('Aktuell werden keine Termine angeboten.'))->hideClose() ?>
+
+<? else: ?>
+
+<table class="default">
+ <colgroup>
+ <col>
+ <col>
+ <col>
+ <col>
+ <col>
+ <col>
+ <col>
+ <col style="width: 96px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Tag') ?></th>
+ <th><?= _('Zeit') ?></th>
+ <th><?= _('Bei') ?></th>
+ <th><?= _('Ort') ?></th>
+ <th><?= _('Status') ?></th>
+ <th><?= _('Person(en)') ?></th>
+ <th><?= _('Grund') ?></th>
+ <th class="actions"><?= _('Optionen') ?></th>
+ </tr>
+ </thead>
+<? foreach ($blocks as $block): ?>
+ <tbody id="block-<?= htmlReady($block->id) ?>">
+ <? foreach ($block->slots as $slot):
+ if (!$slot->block->show_participants && $slot->isOccupied() && !$slot->isOccupied($GLOBALS['user']->id)) continue;
+ ?>
+ <tr id="slot-<?= htmlReady($slot->id) ?>">
+ <td>
+ <?= strftime(_('%A, %x'), $slot->start_time) ?>
+ </td>
+ <td>
+ <?= strftime('%H:%M', $slot->start_time) ?>
+ -
+ <?= strftime('%H:%M', $slot->end_time) ?>
+
+ <?= $displayNote($slot->note, 29, 'below') ?>
+ </td>
+ <td>
+ <? if ($block->teacher): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $block->teacher->username]) ?>">
+ <?= htmlReady($block->teacher->getFullName()) ?>
+ </a>
+ <? else: ?>
+ &ndash;
+ <? endif; ?>
+ </td>
+ <td>
+ <?= formatLinks($block->room) ?>
+ </td>
+ <td>
+ <?= $this->render_partial('consultation/slot-occupation.php', compact('slot')) ?>
+ </td>
+ <td>
+ <?= $this->render_partial('consultation/slot-bookings.php', compact('slot')) ?>
+ </td>
+ <td>
+ <? if ($slot->isOccupied($GLOBALS['user']->id)): ?>
+ <?= htmlReady($slot->bookings->findOneBy('user_id', $GLOBALS['user']->id)->reason) ?>
+ <? endif; ?>
+ </td>
+ <td class="actions">
+ <? if ($slot->isOccupied($GLOBALS['user']->id)): ?>
+ <a href="<?= $controller->cancel($block, $slot) ?>" data-dialog="size=auto">
+ <?= Icon::create('remove/consultation')->asImg(tooltip2(_('Termin absagen'))) ?>
+ </a>
+ <? elseif (!$slot->isOccupied()): ?>
+ <a href="<?= $controller->book($block, $slot) ?>" data-dialog="size=auto">
+ <?= Icon::create('add/consultation')->asImg(tooltip2(_('Termin reservieren'))) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+<? endforeach; ?>
+<? if ($count > $limit): ?>
+ <tfoot>
+ <tr>
+ <td colspan="8">
+ <?= Pagination::create($count, $page, $limit)->asLinks(function ($page) use ($controller) {
+ return $controller->index($page);
+ }) ?>
+ </td>
+ </tr>
+ </tfoot>
+<? endif; ?>
+</table>
+
+<? endif; ?>
diff --git a/app/views/consultation/slot-bookings.php b/app/views/consultation/slot-bookings.php
new file mode 100644
index 0000000..56c7aad
--- /dev/null
+++ b/app/views/consultation/slot-bookings.php
@@ -0,0 +1,33 @@
+<? if (count($slot->bookings) === 0 || !($slot->block->show_participants || $slot->isOccupied($GLOBALS['user']->id))): ?>
+ &ndash;
+<? elseif ($slot->block->show_participants): ?>
+ <ul class="default">
+ <? foreach ($slot->bookings as $booking):
+ if (!$slot->block->show_participants && $booking->user_id !== $GLOBALS['user']->id) continue;
+ ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $booking->user->username]) ?>">
+ <?= htmlReady($booking->user->getFullName()) ?>
+ </a>
+ <? if ($booking->user_id === $GLOBALS['user']->id): ?>
+ -
+ <?= _('Mein Grund der Buchung') ?>:
+ <? if ($booking->reason): ?>
+ <?= htmlReady($booking->reason) ?>
+ <? else: ?>
+ <span class="consultation-no-reason">
+ <?= _('Kein Grund angegeben') ?>
+ </span>
+ <? endif; ?>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+<? elseif ($slot->isOccupied($GLOBALS['user']->id)): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $GLOBALS['user']->username]) ?>">
+ <?= htmlReady($GLOBALS['user']->getFullName()) ?>
+ </a>
+ <? if (count($slot->bookings) > 1): ?>
+ (<?= sprintf(_('+%u weitere'), count($slot->bookings) - 1) ?>)
+ <? endif; ?>
+<? endif; ?>
diff --git a/app/views/consultation/slot-details.php b/app/views/consultation/slot-details.php
new file mode 100644
index 0000000..e76ed54
--- /dev/null
+++ b/app/views/consultation/slot-details.php
@@ -0,0 +1,7 @@
+<?= strftime('%A, %x', $slot->start_time) ?>
+ -
+<?= sprintf(
+ _('%s bis %s Uhr'),
+ strftime('%R', $slot->start_time),
+ strftime('%R', $slot->end_time)
+) ?>
diff --git a/app/views/consultation/slot-occupation.php b/app/views/consultation/slot-occupation.php
new file mode 100644
index 0000000..656c3ca
--- /dev/null
+++ b/app/views/consultation/slot-occupation.php
@@ -0,0 +1,27 @@
+<? if ($slot->isOccupied()): ?>
+ <span class="consultation-occupied">
+ <? if ($slot->block->size > 1): ?>
+ <?= sprintf(
+ _('%u von %u belegt'),
+ count($slot->bookings),
+ $slot->block->size
+ ) ?>
+ <? elseif ($slot->isOccupied($GLOBALS['user']->id)): ?>
+ <?= _('Eigene Buchung') ?>
+ <? else: ?>
+ <?= _('belegt') ?>
+ <? endif; ?>
+ </span>
+<? else: ?>
+ <span class="consultation-free">
+ <? if ($slot->block->size > 1): ?>
+ <?= sprintf(
+ _('%u von %u frei'),
+ $slot->block->size - count($slot->bookings),
+ $slot->block->size
+ ) ?>
+ <? else: ?>
+ <?= _('frei') ?>
+ <? endif; ?>
+ </span>
+<? endif; ?>
diff --git a/app/views/contact/editGroup.php b/app/views/contact/editGroup.php
new file mode 100644
index 0000000..914b203
--- /dev/null
+++ b/app/views/contact/editGroup.php
@@ -0,0 +1,26 @@
+<form class="default" method="post" action="<?= $controller->link_for('contact/editGroup/' . $group->id) ?>">
+ <? CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend class="hide-in-dialog">
+ <? if ($group->isNew()) : ?>
+ <?= _('Gruppe anlegen') ?>
+ <? else : ?>
+ <?= _('Gruppe bearbeiten') ?>
+ <? endif ?>
+ </legend>
+ <label>
+ <span class="required"><?= _('Gruppenname') ?></span>
+ <input required type="text" name="name"
+ placeholder="<?= _('Gruppenname') ?>"
+ value='<?= htmlReady($group->name) ?>'>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept($group->isNew() ? _('Anlegen') : _('Speichern'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('contact/index')
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/contact/index.php b/app/views/contact/index.php
new file mode 100644
index 0000000..6b417df
--- /dev/null
+++ b/app/views/contact/index.php
@@ -0,0 +1,118 @@
+<? use \Studip\Button; ?>
+<form action="<?= $controller->url_for('contact/edit_contact/' . $filter) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= htmlReady($title) ?>
+ <span class='actions'>
+ <?= $multiPerson ?>
+ <? if ($filter): ?>
+ <a href="<?= $controller->url_for('contact/editGroup/' . $filter) ?>" data-dialog="size=auto"
+ title="<?= _('Gruppe bearbeiten') ?>">
+ <?= Icon::create('edit') ?>
+ </a>
+ <?= Icon::create('trash')->asInput(
+ ['formaction' => $controller->url_for('contact/deleteGroup/' . $filter),
+ 'title' => _('Gruppe löschen'),
+ 'data-confirm' => sprintf(_('Gruppe %s wirklich löschen?'), htmlReady($title))]) ?>
+ <? endif; ?>
+ </span>
+ </caption>
+ <thead>
+ <tr>
+ <th style="width:20px !important;">
+ <input aria-label="<?= _('Alle %s auswählen') ?>"
+ type="checkbox" name="all" value="1" data-proxyfor=":checkbox[name^=contact]">
+ </th>
+ <th>
+ <?= _('Name') ?>
+ </th>
+ <th class="hidden-small-down">
+ <?= _('Stud.IP') ?>
+ </th>
+ <th class="hidden-small-down">
+ <?= _('E-Mail') ?>
+ </th>
+ <th class="actions">
+ <?= _('Aktionen') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (!empty($contacts)) : ?>
+ <? foreach ($contacts as $header => $contactgroup): ?>
+ <tr id="letter_<?= $header ?>">
+ <th colspan="5">
+ <?= $header ?>
+ </th>
+ </tr>
+ <? foreach ($contactgroup as $contact): ?>
+ <tr id="contact_<?= $contact->id ?>">
+ <td>
+ <input aria-label="<?= _('Auswählen') ?>"
+ type="checkbox" name="contact[<?= $contact->username ?>]" value="1"
+ <? if (isset($flash['contacts']) && in_array($contact->id, $flash['contacts'])) echo 'checked'; ?>>
+ </td>
+ <td>
+ <?= ObjectdisplayHelper::avatarlink($contact) ?>
+ </td>
+ <td class="hidden-small-down">
+ <a data-dialog="button"
+ href="<?= URLHelper::getLink('dispatch.php/messages/write', ['rec_uname' => $contact->username]) ?>">
+ <?= htmlReady($contact->username) ?>
+ </a>
+ </td>
+ <td class="hidden-small-down">
+ <a href="mailto:<?= htmlReady($contact->email) ?>">
+ <?= htmlReady($contact->email) ?>
+ </a>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (Config::get()->BLUBBER_GLOBAL_MESSENGER_ACTIVATE) : ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/blubber/write_to/' . $contact->user_id),
+ _('Blubber diesen Nutzer an'),
+ Icon::create('blubber'),
+ ['data-dialog' => '']
+ ) ?>
+ <? endif ?>
+ <? $actionMenu->addLink($controller->url_for('contact/vcard', ['user[]' => $contact->username]),
+ _('vCard herunterladen'),
+ Icon::create('vcard')) ?>
+ <?= $actionMenu->addButton('remove_person',
+ $filter ? _('Kontakt aus Gruppe entfernen') : _('Kontakt entfernen'),
+ Icon::create('person+remove',
+ [
+ 'data-confirm' => sprintf(
+ _('Wollen Sie %s wirklich von der Liste entfernen'),
+ htmlReady($contact->username)
+ ),
+ 'formaction' => $controller->url_for('contact/remove/' . $filter, ['user' => $contact->username])
+ ])
+ )->render() ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ <? else : ?>
+ <tr>
+ <td colspan="4" style="text-align: center">
+ <?= $filter ? _('Keine Kontakte in der Gruppe vorhanden') : _('Keine Kontakte vorhanden') ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="5">
+ <select name="action_contact" id="contact_action" aria-label="<?= _('Aktion ausführen') ?>">
+ <option value="">- <?= _('Aktion auswählen') ?></option>
+ <option value="remove"><?= $filter ? _('Kontakte aus Gruppe entfernen') : _('Kontakte entfernen') ?></option>
+ </select>
+ <?= Button::create(_('Ausführen'), 'submit_action') ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
diff --git a/app/views/contact/vcard.php b/app/views/contact/vcard.php
new file mode 100644
index 0000000..e2e0ae5
--- /dev/null
+++ b/app/views/contact/vcard.php
@@ -0,0 +1 @@
+<?= $vCard ?> \ No newline at end of file
diff --git a/app/views/contents/courseware/bookmarks.php b/app/views/contents/courseware/bookmarks.php
new file mode 100755
index 0000000..9543faf
--- /dev/null
+++ b/app/views/contents/courseware/bookmarks.php
@@ -0,0 +1,29 @@
+<div class="cw-bookmarks">
+ <? if(!empty($bookmarks)): ?>
+ <ul class="cw-tiles">
+ <? foreach($bookmarks as $bookmark) :?>
+ <li class="tile <?= htmlReady($bookmark['element']['payload']['color'])?>">
+ <a href="<?= htmlReady($bookmark['url'])?>">
+ <div class="preview-image" style="background-image: url(<?= htmlReady($bookmark['element']->getImageUrl()) ?>)" ></div>
+ <div class="description">
+ <header><?= htmlReady($bookmark['element']['title']) ?></header>
+ <div class="description-text-wrapper">
+ <p><?= htmlReady($bookmark['element']['payload']['description']) ?></p>
+ </div>
+ <footer>
+ <? if($bookmark['course']): ?>
+ <?= Icon::create('seminar', Icon::ROLE_INFO_ALT)?> <?= htmlReady($bookmark['course']['name'])?>
+ <? endif; ?>
+ <? if($bookmark['user']): ?>
+ <?= Icon::create('headache', Icon::ROLE_INFO_ALT)?> <?= htmlReady($bookmark['user']->getFullName())?>
+ <? endif; ?>
+ </footer>
+ </div>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? else: ?>
+ <?= MessageBox::info(_('Sie haben noch keine Lesezeichen angelegt.')); ?>
+ <? endif; ?>
+</div> \ No newline at end of file
diff --git a/app/views/contents/courseware/courses_overview.php b/app/views/contents/courseware/courses_overview.php
new file mode 100644
index 0000000..97517fd
--- /dev/null
+++ b/app/views/contents/courseware/courses_overview.php
@@ -0,0 +1,34 @@
+
+<div class="cw-content-projects">
+ <? if(!empty($elements)): ?>
+ <ul class="cw-tiles">
+ <? foreach($elements as $element) :?>
+ <li class="tile <?= htmlReady($element['payload']['color'])?>">
+ <a href="<?= URLHelper::getLink('dispatch.php/course/courseware/?cid='.$element['range_id'].'#/structural_element/'.$element['id']) ?>">
+ <div class="preview-image" style="background-image: url(<?= htmlReady($element->getImageUrl()) ?>)" ></div>
+ <div class="description">
+ <header><?= htmlReady($element['title']) ?></header>
+ <div class="description-text-wrapper">
+ <p>
+ <?= htmlReady($element['payload']['description']) ?>
+ </p>
+ </div>
+ <footer>
+ <?= Icon::create('seminar', Icon::ROLE_INFO_ALT)?> <?= htmlReady($element['course']['name'])?>
+ </footer>
+ </div>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ <? if (empty($elements) && !$empty_courses): ?>
+ <?= MessageBox::info(_('Es wurden noch keine Lernunterlagen angelegt.')); ?>
+ <? endif; ?>
+ <? if ($empty_courses && !$all_semesters): ?>
+ <?= MessageBox::info(_('Es wurden für das gewählte Semester keine Veranstaltungen gefunden.')); ?>
+ <? endif; ?>
+ <? if ($empty_courses && $all_semesters): ?>
+ <?= MessageBox::info(_('Es wurden keine Veranstaltungen gefunden.')); ?>
+ <? endif; ?>
+</div> \ No newline at end of file
diff --git a/app/views/contents/courseware/courseware.php b/app/views/contents/courseware/courseware.php
new file mode 100755
index 0000000..2975b1b
--- /dev/null
+++ b/app/views/contents/courseware/courseware.php
@@ -0,0 +1,8 @@
+<div
+ id="courseware-index-app"
+ entry-element-id="<?= $entry_element_id ?>"
+ entry-type="users" entry-id="<?= $user_id ?>"
+ oer-title="<?= Config::get()->OER_TITLE ?>"
+ licenses='<?= $licenses ?>'
+ >
+</div>
diff --git a/app/views/contents/courseware/courseware_manager.php b/app/views/contents/courseware/courseware_manager.php
new file mode 100755
index 0000000..7d06bb7
--- /dev/null
+++ b/app/views/contents/courseware/courseware_manager.php
@@ -0,0 +1 @@
+<div id="courseware-manager-app" entry-type="users" entry-id="<?= $user_id ?>"></div>
diff --git a/app/views/contents/courseware/create_project.php b/app/views/contents/courseware/create_project.php
new file mode 100755
index 0000000..37fce11
--- /dev/null
+++ b/app/views/contents/courseware/create_project.php
@@ -0,0 +1,125 @@
+<form class="default" action="<?= $controller->link_for('contents/courseware/create_project') ?>"
+ method="post" enctype="multipart/form-data">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <label>
+ <span>
+ <?= _('Titel des Lernmaterials') ?>
+ </span>
+ <input required type="text" name="title">
+ </label>
+
+ <label>
+ <span>
+ <?= _('Zusammenfassung') ?>
+ </span>
+ <textarea name="description"></textarea>
+ </label>
+
+ <label>
+ <?= _('Art des Lernmaterials') ?>
+ <select name="project_type">
+ <option value="content">
+ <?= _('Inhalt') ?>
+ </option>
+ <option value="template">
+ <?= _('Vorlage') ?>
+ </option>
+ <option value="oer">
+ <?= _('OER-Material') ?>
+ </option>
+ <option value="portfolio">
+ <?= _('ePortfolio') ?>
+ </option>
+ <option value="draft">
+ <?= _('Entwurf') ?>
+ </option>
+ <option value="other">
+ <?= _('Sonstiges') ?>
+ </option>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Lizenztyp') ?>
+ <select name="license_type">
+ <? foreach (License::findBySQL("1 ORDER BY name ASC") as $l) : ?>
+ <option value="<?= htmlReady($l->id) ?>" <?= $l->id === License::findDefault()->id ? " selected" : "" ?>>
+ <?= htmlReady($l['name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label>
+ <span>
+ <?= _('Geschätzter zeitlicher Aufwand') ?>
+ </span>
+ <input type="text" name="required_time">
+ </label>
+
+ <label>
+ <span>
+ <?= _('Niveau') ?>
+ </span>
+ <select name="difficulty">
+ <? for ($i = 1; $i<=12; $i++): ?>
+ <option value="<?= $i?>"><?= $i?></option>
+ <? endfor; ?>
+ </select>
+ </label>
+
+ <label>
+ <span>
+ <?= _('Farbe') ?>
+ </span>
+ <select name="color">
+ <option value="royal-purple">
+ <?= _('Königliches Purpur') ?>
+ </option>
+ <option value="iguana-green">
+ <?= _('Leguangrün') ?>
+ </option>
+ <option value="charcoal">
+ <?= _('Holzkohle') ?>
+ </option>
+ <option value="queen-blue">
+ <?= _('Königin blau') ?>
+ </option>
+ <option value="verdigris">
+ <?= _('Helles Seegrün') ?>
+ </option>
+ <option value="mulberry">
+ <?= _('Maulbeere') ?>
+ </option>
+ <option value="pumpkin">
+ <?= _('Kürbis') ?>
+ </option>
+ <option value="apple-green">
+ <?= _('Apfelgrün') ?>
+ </option>
+ <option value="studip-blue">
+ <?= _('Blau') ?>
+ </option>
+ <option value="studip-gray">
+ <?= _('Grau') ?>
+ </option>
+ <option value="studip-green">
+ <?= _('Grün') ?>
+ </option>
+ </select>
+ </label>
+
+ <label class="file-upload">
+ <?= _('Vorschaubild hochladen') ?>
+ <input id="previewfile" name="previewfile" type="file" accept="image/*">
+ </label>
+
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Erstellen'), 'create_project', ['title' => _('Neues Lernmaterial erstellen')]) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('contents/courseware'), ['title' => _('Zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/contents/courseware/index.php b/app/views/contents/courseware/index.php
new file mode 100755
index 0000000..4ebc595
--- /dev/null
+++ b/app/views/contents/courseware/index.php
@@ -0,0 +1,40 @@
+
+<div class="cw-content-projects">
+ <? if(!empty($elements)): ?>
+ <ul class="cw-tiles">
+ <? foreach($elements as $element) :?>
+ <li class="tile <?= htmlReady($element['payload']['color'])?>">
+ <a href="<?= URLHelper::getLink('dispatch.php/contents/courseware/courseware#/structural_element/'.$element['id']) ?>">
+ <div class="preview-image" style="background-image: url(<?= htmlReady($element->getImageUrl()) ?>)" ></div>
+ <div class="description">
+ <header><?= htmlReady($element['title']) ?></header>
+ <div class="description-text-wrapper">
+ <p>
+ <?= htmlReady($element['payload']['description']) ?>
+ </p>
+ </div>
+ <footer>
+ <?= sprintf(ngettext('%d Seite', '%d Seiten', $element->countChildren()), $element->countChildren()); ?>
+ </footer>
+ </div>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? else: ?>
+ <div class="cw-contents-overview-teaser">
+ <div class="cw-contents-overview-teaser-content">
+ <header><?= _('Ihre persönlichen Lernmaterialien')?></header>
+ <p><?= _('Erstellen und Verwalten Sie hier ihre eigenen persönlichen Lernmaterialien in Form von ePorfolios,
+ Vorlagen für Veranstaltungen oder einfach nur persönliche Inhalte für das Studium.
+ Entwickeln Sie ihre eigenen (Lehr-)Materialien für Studium oder die Lehre und teilen diese mit anderen Nutzenden.')?></p>
+ <a class="button"
+ href="<?= $controller->link_for('contents/courseware/create_project', []) ?>"
+ data-dialog="size=700"
+ title="<?= _('Neues Lernmaterial anlegen') ?>">
+ <?= _('Neues Lernmaterial anlegen') ?>
+ </a>
+ </div>
+ </div>
+ <? endif; ?>
+</div> \ No newline at end of file
diff --git a/app/views/contents/overview/index.php b/app/views/contents/overview/index.php
new file mode 100755
index 0000000..088ebe1
--- /dev/null
+++ b/app/views/contents/overview/index.php
@@ -0,0 +1,23 @@
+<ul class="content-items">
+ <? foreach ($tiles as $key => $navigation): ?>
+ <? if ($navigation->isVisible() && $key !== 'overview'): ?>
+ <li class="content-item content-item-courseware">
+ <a href="<?= URLHelper::getLink($navigation->getURL()) ?>" class="content-item-link">
+ <div class="content-item-img-wrapper">
+ <? if ($navigation->getImage()): ?>
+ <?= $navigation->getImage()->asImg(64, $navigation->getLinkAttributes()) ?>
+ <? endif ?>
+ </div>
+ <div class="content-item-text">
+ <p class="content-item-title">
+ <?= htmlReady($navigation->getTitle()) ?>
+ </p>
+ <p class="content-item-description">
+ <?= htmlReady($navigation->getDescription()) ?>
+ </p>
+ </div>
+ </a>
+ </li>
+ <? endif ?>
+ <? endforeach ?>
+</ul>
diff --git a/app/views/course/admission/_change_admission.php b/app/views/course/admission/_change_admission.php
new file mode 100644
index 0000000..ca26341
--- /dev/null
+++ b/app/views/course/admission/_change_admission.php
@@ -0,0 +1,13 @@
+<? foreach(PageLayout::getMessages() as $pm) : ?>
+ <?= $pm ?>
+<? endforeach; ?>
+<form class="default" action="<?= $controller->link_for() ?>" method="post">
+<?= CSRFProtection::tokenTag()?>
+<? foreach(array_filter($request, function ($r) {return $r !== false;}) as $k => $v) : ?>
+ <?= addHiddenFields($k, $v) ?>
+<? endforeach ?>
+<footer data-dialog-button>
+ <?= Studip\Button::create(_("Ja"), $button_yes, ['data-dialog' => ''])?>
+ <?= Studip\Button::create(_("Nein"), $button_no, ['data-dialog' => ''])?>
+</footer>
+</form> \ No newline at end of file
diff --git a/app/views/course/admission/edit_courseset.php b/app/views/course/admission/edit_courseset.php
new file mode 100644
index 0000000..0013888
--- /dev/null
+++ b/app/views/course/admission/edit_courseset.php
@@ -0,0 +1 @@
+<?= $body ?> \ No newline at end of file
diff --git a/app/views/course/admission/index.php b/app/views/course/admission/index.php
new file mode 100644
index 0000000..9a91037
--- /dev/null
+++ b/app/views/course/admission/index.php
@@ -0,0 +1,233 @@
+<form class="default" action="<?= $controller->link_for('/change_course_set') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Anmelderegeln') ?></legend>
+ <section>
+ <?= _('Bitte geben Sie hier an, welche speziellen Anmelderegeln gelten sollen.'); ?>
+ </section>
+ <? if ($current_courseset) : ?>
+ <div>
+ <?= sprintf(_('Diese Veranstaltung gehört zum Anmeldeset "%s".'), htmlReady($current_courseset->getName())) ?>
+ <div id="courseset_<?= $current_courseset->getId() ?>">
+ <?= $current_courseset->toString(true) ?>
+ </div>
+ <div>
+ <? if (!$is_locked['admission_type'] || $current_courseset->isUserAllowedToEdit($user_id)) : ?>
+ <? if ($current_courseset->isUserAllowedToAssignCourse($user_id, $course_id)) : ?>
+ <?= Studip\Button::create(_("Zuordnung aufheben"), 'change_course_set_unassign', ['data-dialog' => '']) ?>
+ <? endif ?>
+ <? if ($current_courseset->isUserAllowedToEdit($user_id)) : ?>
+ <?= Studip\LinkButton::create(_("Anmeldeset bearbeiten"), $controller->url_for('/edit_courseset/' . $current_courseset->getId()), ['data-dialog' => '']); ?>
+ <? endif ?>
+ <? endif ?>
+ </div>
+ </div>
+ <? else : ?>
+ <div>
+ <? if (!$is_locked['passwort'] && isset($activated_admission_rules['PasswordAdmission'])) : ?>
+ <?= Studip\LinkButton::create(_("Anmeldung mit Passwort"), $controller->url_for('/instant_course_set', ['type' => 'PasswordAdmission']), ['data-dialog' => '']) ?>
+ <? endif ?>
+ <? if (!$is_locked['admission_type']) : ?>
+ <? if (isset($activated_admission_rules['LockedAdmission'])) : ?>
+ <?= Studip\LinkButton::create(_("Anmeldung gesperrt"), $controller->url_for('/instant_course_set', ['type' => 'LockedAdmission']), ['data-dialog' => '']) ?>
+ <? endif ?>
+ <? if (isset($activated_admission_rules['TimedAdmission'])) : ?>
+ <?= Studip\LinkButton::create(_("Zeitgesteuerte Anmeldung"), $controller->url_for('/instant_course_set', ['type' => 'TimedAdmission']), ['data-dialog' => '']) ?>
+ <? endif ?>
+ <br>
+ <? if (isset($activated_admission_rules['ParticipantRestrictedAdmission'])) : ?>
+ <?= Studip\LinkButton::create(_("Teilnahmebeschränkte Anmeldung"), $controller->url_for('/instant_course_set', ['type' => 'ParticipantRestrictedAdmission']), ['data-dialog' => '']) ?>
+ <? if (isset($activated_admission_rules['TimedAdmission'])) : ?>
+ <?= Studip\LinkButton::create(_("Zeitgesteuerte und Teilnahmebeschränkte Anmeldung"), $controller->url_for('/instant_course_set', ['type' => 'ParticipantRestrictedAdmission_TimedAdmission']), ['data-dialog' => '']) ?>
+ <? endif ?>
+ <? endif ?>
+ <? endif ?>
+ </div>
+ <? if (!$is_locked['admission_type'] && count($available_coursesets)) : ?>
+ <details class="studip">
+ <summary title="<?= _("Klicken um Zuordnungsmöglichkeiten zu öffnen") ?>">
+ <?= _("Zuordnung zu einem bestehenden Anmeldeset"); ?>
+ <?= tooltipIcon(_("Wenn die Veranstaltung die Anmelderegeln eines Anmeldesets übernehmen soll, klicken Sie hier und wählen das entsprechende Anmeldeset aus.")); ?>
+ </summary>
+
+ <select name="course_set_assign" style="display: inline-block;"
+ onChange="$('#course_set_assign_explain').load('<?= $controller->link_for('/explain_course_set') ?>&set_id=' + $(this).val(), function () { $(this).show(); });">
+ <option></option>
+ <? $my_own_sets = $available_coursesets->findBy('my_own', true); ?>
+ <? $other_sets = $available_coursesets->findBy('my_own', false); ?>
+ <? if ($my_own_sets->count()) : ?>
+ <optgroup label="<?= _("Meine Anmeldesets") ?>">
+ <? foreach ($my_own_sets as $cs) : ?>
+ <option
+ value="<?= $cs['id'] ?>"><?= htmlReady(my_substr($cs['name'], 0, 100)) ?></option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ <? if ($other_sets->count()) : ?>
+ <optgroup label="<?= _("Verfügbare Anmeldesets meiner Einrichtungen") ?>">
+ <? foreach ($available_coursesets->findBy('my_own', false) as $cs) : ?>
+ <option
+ value="<?= $cs['id'] ?>"><?= htmlReady(my_substr($cs['name'], 0, 100)) ?></option>
+
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ </select>
+
+ <?= Studip\Button::create(_("Zuordnen"), 'change_course_set_assign', ['data-dialog' => '']) ?>
+
+ <div id="course_set_assign_explain" class="messagebox messagebox_info" style="display: none"></div>
+ </details>
+ <? endif ?>
+ <? endif ?>
+ </fieldset>
+</form>
+<br>
+
+<? if ($current_courseset && $current_courseset->isSeatDistributionEnabled()) : ?>
+ <form class="default" action="<?= $controller->link_for('/change_admission_turnout') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Beschränkte Teilnehmendenanzahl') ?></legend>
+ <div>
+ <?= _('Bitte geben Sie hier an, wieviele Personen maximal für die Veranstaltung vorgesehen sind,
+ und ob eine Warteliste erstellt werden soll, falls die Zahl der Anmeldungen die maximale Personenzahl überschreitet.'); ?>
+ </div>
+
+ <label for="admission_turnout">
+ <?= _('max. Anzahl:') ?>
+ <input type="number" name="admission_turnout" id="admission_turnout"
+ value="<?= $course->admission_turnout ?>">
+ <small><?= sprintf(_("(%s freie Plätze)"), $course->getFreeSeats()) ?></small>
+ </label>
+ <br>
+ <?= _('Einstellungen für die Warteliste:') ?>
+ <label for="admission_disable_waitlist">
+ <input <?= $is_locked['admission_disable_waitlist'] ?>
+ type="checkbox" id="admission_disable_waitlist"
+ name="admission_disable_waitlist"
+ value="1" <?= $course->admission_disable_waitlist == 0 ? "checked" : "" ?>>
+ <?= _('Warteliste aktivieren') ?>
+ <? if ($num_waitlist = $course->admission_applicants->findBy('status', 'awaiting')->count()) : ?>
+ &nbsp;<?= sprintf(_("(%s Wartende)"), $num_waitlist) ?>
+ <? endif ?>
+ </label>
+ <label for="admission_disable_waitlist_move">
+ <input <?= $is_locked['admission_disable_waitlist_move'] ?>
+ type="checkbox"
+ id="admission_disable_waitlist_move"
+ name="admission_disable_waitlist_move"
+ value="1" <?= $course->admission_disable_waitlist_move == 0 ? "checked" : "" ?>>
+ <?= _('automatisches Nachrücken aus der Warteliste aktivieren') ?></label>
+ <label for="admission_waitlist_max">
+ <?= _('max. Anzahl an Wartenden (optional)') ?>
+ <input <?= $is_locked['admission_waitlist_max'] ?>
+ type="text"
+ id="admission_waitlist_max"
+ name="admission_waitlist_max"
+ value="<?= $course->admission_waitlist_max ?: '' ?>">
+ </label>
+ </fieldset>
+ <footer>
+ <?= Studip\Button::create(_('Teilnehmendenanzahl und Warteliste ändern'), 'change_admission_turnout', ['data-dialog' => '']) ?>
+ </footer>
+ </form>
+ <br>
+<? endif ?>
+
+<form class="default" action="<?= $controller->link_for('/change_admission_prelim') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Anmeldemodus') ?></legend>
+ <div>
+ <?= _('Bitte wählen Sie hier einen Anmeldemodus aus:'); ?>
+ </div>
+ <label for="admission_prelim_0">
+ <input <?= $is_locked['admission_prelim'] ?>
+ type="radio" id="admission_prelim_0"
+ name="admission_prelim"
+ value="0" <?= $course->admission_prelim == 0 ? "checked" : "" ?>>
+ <?= _('Direkter Eintrag') ?></label>
+ <label for="admission_prelim_1">
+ <input <?= $is_locked['admission_prelim'] ?>
+ type="radio" id="admission_prelim_1"
+ name="admission_prelim"
+ value="1" <?= $course->admission_prelim == 1 ? "checked" : "" ?>>
+ <?= _('Vorläufiger Eintrag') ?></label>
+ <? if ($course->admission_prelim == 1) : ?>
+ <label for="admission_prelim_txt"><?= _("Hinweistext bei vorläufigen Eintragungen:"); ?></label>
+ <textarea <?= $is_locked['admission_prelim_txt'] ?> id="admission_prelim_txt" name="admission_prelim_txt"
+ rows="4"><?
+ echo htmlReady($course->admission_prelim_txt);
+ ?></textarea>
+ <? endif ?>
+ <label for="admission_binding">
+ <input <?= $is_locked['admission_binding'] ?> id="admission_binding"
+ type="checkbox" <?= $course->admission_binding == 1 ? "checked" : "" ?>
+ name="admission_binding" value="1">
+ <?= _("Anmeldung ist <u>verbindlich</u>. (Teilnehmenden können sich nicht selbst wieder abmelden.)") ?>
+ </label>
+ </fieldset>
+ <footer>
+ <?= Studip\Button::create(_("Anmeldemodus ändern"), 'change_admission_prelim', ['data-dialog' => '']) ?>
+ </footer>
+</form>
+<br>
+
+<? if (Config::get()->ENABLE_FREE_ACCESS && !$current_courseset) : ?>
+ <form class="default" action="<?= $controller->link_for('/change_free_access') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Zugriff für externe Nutzer') ?></legend>
+ <div>
+ <?= _('Über diese Einstellung können Sie externen Nutzern, die keinen Zugang zum Stud.IP haben, Zugriff auf die Veranstaltung gewähren. Bitte beachten Sie, dass von Kursteilnehmern z.B. im Forum, Dateibereich oder Wiki erstellte Inhalte damit weltweit ohne Anmeldung einsehbar sind. Die Teilnehmerliste ist für externe Nutzer nicht sichtbar.'); ?>
+ </div>
+
+ <label for="lesezugriff">
+ <input <?= $is_locked['read_level'] ?>
+ id="lesezugriff"
+ type="checkbox" <?= $course->lesezugriff == 0 ? "checked" : "" ?>
+ name="read_level" value="1">
+ <?= _('Lesezugriff für nicht in Stud.IP angemeldete Personen erlauben') ?>
+ </label>
+
+ <? if (!$is_locked['write_level'] || $course->schreibzugriff == 0): ?>
+ <label for="schreibzugriff">
+ <input <?= $is_locked['write_level'] ?>
+ id="schreibzugriff"
+ type="checkbox" <?= $course->schreibzugriff == 0 ? "checked" : "" ?>
+ name="write_level" value="1">
+ <?= _('Schreibzugriff für nicht in Stud.IP angemeldete Personen erlauben') ?>
+ </label>
+ <? endif ?>
+ </fieldset>
+ <footer>
+ <?= Studip\Button::create(_('Zugriffseinstellung ändern'), 'change_free_access', ['data-dialog' => '']) ?>
+ </footer>
+ </form>
+ <br>
+<? endif ?>
+
+<? if (count($all_domains)) : ?>
+ <form class="default" action="<?= $controller->link_for('/change_domains') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Zugelassenene Nutzerdomänen') ?></legend>
+ <div>
+ <?= _('Bitte geben Sie hier an, welche Nutzerdomänen zugelassen sind.'); ?>
+ </div>
+ <? foreach ($all_domains as $domain) : ?>
+ <label for="user_domain_<?= htmlReady($domain->id) ?>">
+ <input <?= $is_locked['user_domain'] ?>
+ id="user_domain_<?= htmlReady($domain->id) ?>"
+ type="checkbox" <? if (in_array($domain->id, $seminar_domains)) echo 'checked'; ?>
+ name="user_domain[]" value="<?= htmlReady($domain->id) ?>">
+ <?= htmlReady($domain->name) ?>
+ </label>
+ <? endforeach ?>
+ </fieldset>
+ <footer>
+ <?= Studip\Button::create(_("Nutzerdomänen ändern"), 'change_domains', ['data-dialog' => '']) ?>
+ </footer>
+ </form>
+<? endif ?>
diff --git a/app/views/course/admission/instant_course_set.php b/app/views/course/admission/instant_course_set.php
new file mode 100644
index 0000000..fdd9702
--- /dev/null
+++ b/app/views/course/admission/instant_course_set.php
@@ -0,0 +1,20 @@
+<? foreach(PageLayout::getMessages() as $pm) : ?>
+ <?= $pm ?>
+<? endforeach; ?>
+<form class="default" action="<?= $controller->link_for() ?>" method="post">
+ <?= CSRFProtection::tokenTag()?>
+
+ <input type="hidden" name="type" value="<?=htmlReady($type)?>">
+ <input type="hidden" name="rule_id" value="<?=htmlReady($rule_id)?>">
+ <fieldset>
+ <legend><?= _('Neue Anmelderegel erstellen') ?></legend>
+ <?= $rule_template ?>
+ <br>
+ <label class="caption"><?= _("Name für diese Anmelderegel")?></label>
+ <input type="text" name="instant_course_set_name" size="70" value="<?= htmlReady($course_set_name) ?>">
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::create(_("Speichern"), 'save', ['data-dialog' => ''])?>
+ </footer>
+</form>
diff --git a/app/views/course/archive/archive.php b/app/views/course/archive/archive.php
new file mode 100644
index 0000000..b9ffebd
--- /dev/null
+++ b/app/views/course/archive/archive.php
@@ -0,0 +1,43 @@
+<? if ($archivedCourses) : ?>
+<?= MessageBox::info(
+ ngettext(
+ 'Veranstaltung erfolgreich archiviert!',
+ 'Veranstaltungen erfolgreich archiviert!',
+ count($archivedCourses)
+ )
+ ) ?>
+<script>
+ STUDIP.Archive.removeArchivedCourses([
+ <? for($i = 0; $i < count($archivedCourses); $i++ ) : ?>
+ <? if ($i > 0) : ?>,<? endif ?>
+ "<?= htmlReady($archivedCourses[$i]->id); ?>"
+ <? endfor ?>
+ ]);
+</script>
+
+<p><?= _('Die folgenden Veranstaltungen wurden erfolgreich archiviert') . ':' ?></p>
+<table class="default">
+ <tr>
+ <th><?= _('Name der Veranstaltung') ?></th>
+ </tr>
+<? foreach ($archivedCourses as $course) : ?>
+ <tr>
+ <td><?= htmlReady($course->name) ?></td>
+ </tr>
+<? endforeach ?>
+</table>
+
+<? else :
+//no course was archived successfully!
+?>
+<?= MessageBox::error(_('Fehler beim Archivieren von Veranstaltungen!')) ?>
+<? endif ?>
+
+<? if (!Request::isAjax()) :
+/*
+ If this view isn't requested via AJAX it was loaded from a course
+ and we have to provide a link back to the course management page.
+*/
+?>
+ <a href="<?= $controller->url_for('admin/courses') ?>" ><?= _("Zurück zur Veranstaltungsverwaltung") ?></a>
+<? endif ?>
diff --git a/app/views/course/archive/confirm.php b/app/views/course/archive/confirm.php
new file mode 100644
index 0000000..eaed515
--- /dev/null
+++ b/app/views/course/archive/confirm.php
@@ -0,0 +1,77 @@
+<? if ($courses) : ?>
+ <?= MessageBox::warning(
+ ngettext(
+ 'Sie sind im Begriff, die folgende Veranstaltung zu löschen. Dieser Schritt kann nicht rückgängig gemacht werden!',
+ 'Sie sind im Begriff, die folgenden Veranstaltungen zu löschen. Dieser Schritt kann nicht rückgängig gemacht werden!',
+ count($courses)
+ )
+ ) ?>
+<table class="default withdetails">
+ <thead>
+ <tr>
+ <th><?= _('Name der Veranstaltung') ?></th>
+ <th><?= _('Letzte Aktivität') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($courses as $course) : ?>
+ <tr <? if (count($courses) == 1) : ?>class="open"<? endif ?> >
+ <td>
+ <a onclick="jQuery(this).closest('tr').toggleClass('open'); return false;" href="">
+ <?= htmlReady($course['name']) ?>
+ </a>
+ </td>
+ <td>
+ <?= htmlReady($lastActivities[$course['id']]) ?>
+ </td>
+ </tr>
+ <tr class="details nohover">
+ <td colspan="2">
+ <div class="detailscontainer">
+ <dl class="default nohover">
+ <dt><?= _('Untertitel') . ':' ?></dt>
+ <dd>
+ <?= $course['untertitel'] ? htmlReady($course['untertitel']) : ' ' ?>
+ </dd>
+ <dt><?= _('Lehrende') ?></dt>
+ <dd>
+ <ul>
+ <? foreach ($dozenten[$course['id']] as $dozent) : ?>
+ <li>
+ <a href="<?= $controller->url_for('profile?username=' . htmlReady($dozent['username'])) ?>" >
+ <?= htmlReady($dozent['vorname']) . ' ' . htmlReady($dozent['nachname']) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </dd>
+ <dt><?= _('Veranstaltungsort') . ':' ?></dt>
+ <dd><?= $course['ort'] ? htmlReady($course['ort']) : ' ' ?></dd>
+ <dt><?= _('Semester') . ':'; ?></dt>
+ <dd><?= $course['start_semester'] ? htmlReady($course['start_semester']) : ' ' ?></dd>
+ <dt><?= _('Veranstaltungsnummer') . ':' ?></dt>
+ <dd><?= $course['veranstaltungsnummer'] ? htmlReady($course['veranstaltungsnummer']) : ' ' ?></dd>
+ </dl>
+ </div>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="4">
+ <form class="default" action="<?= $controller->url_for('course/archive/archive') ?>" method="post">
+ <? foreach ($courses as $course) : ?>
+ <input type="hidden" name="courseIds[]" value="<?= $course['id'] ?>">
+ <? endforeach ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Löschen')) ?>
+ </div>
+ </form>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+<? else : ?>
+<?= MessageBox::error(_('Es wurde keine Veranstaltung ausgewählt!')) ?>
+<? endif ?>
diff --git a/app/views/course/basicdata/_input.php b/app/views/course/basicdata/_input.php
new file mode 100644
index 0000000..ffaad5e
--- /dev/null
+++ b/app/views/course/basicdata/_input.php
@@ -0,0 +1,101 @@
+<?php
+# Lifter010: TODO
+$is_locked = $input['locked'] ? 'disabled readonly' : '';
+$is_locked_array = $input['locked'] ? ['disabled' => true, 'readonly' => true] : [];
+$is_required_array = $input['must'] ? ['required' => true] : [];
+$is_pattern_array = $input['pattern'] ? ['pattern' => $input['pattern']] : [];
+if ($input['type'] === "text") : ?>
+ <? if ($input['i18n']) : ?>
+ <?= I18N::input($input['name'], $input['value'], $is_locked_array + $is_required_array + $is_pattern_array) ?>
+ <? else : ?>
+ <input <?=$is_locked ?> type="text" name="<?= $input['name'] ?>" value="<?= htmlReady($input['value']) ?>" <? if ($input['must']) echo 'required'; ?> <? if ($input['pattern']) : ?>pattern="<?= htmlReady($input['pattern']) ?>"<? endif ?>>
+ <? endif ?>
+<? endif;
+
+if ($input['type'] === "number") : ?>
+ <input <?=$is_locked ?> type="number" name="<?= $input['name'] ?>" value="<?= htmlReady($input['value']) ?>" min="<?= $input['min'] ?>" <? if ($input['must']) echo 'required'; ?>>
+<? endif;
+
+if ($input['type'] === "textarea") : ?>
+ <? if ($input['i18n']) : ?>
+ <?= I18N::textarea($input['name'], $input['value'], $is_locked_array + $is_required_array) ?>
+ <? else : ?>
+ <textarea <?=$is_locked ?> name="<?= $input['name'] ?>" <? if ($input['must']) echo 'required'; ?>><?=
+ htmlReady($input['value'])
+ ?></textarea>
+ <? endif ?>
+<? endif;
+
+if ($input['type'] === "select") : ?>
+ <? if (!$input['choices'][$input['value']] && !(isset($input['changable']) && $input['changable'])): ?>
+ <?= _("Keine Änderung möglich") ?>
+ <? else: ?>
+ <select <?=$is_locked ?> name="<?= $input['name'] ?>" <? if ($input['must']) echo 'required'; ?>>
+<? foreach ($input['choices'] as $choice_value => $choice_name): ?>
+ <? if (is_array($choice_name)): ?>
+ <optgroup label="<?= htmlReady($choice_value) ?>">
+ <? foreach ($choice_name as $c_v => $c_n): ?>
+ <option value="<?= htmlReady($c_v) ?>" <? if (in_array($c_v, (array)$input['value'])) echo 'selected'; ?>>
+ <?= htmlReady($c_n) ?>
+ </option>
+ <? endforeach; ?>
+ </optgroup>
+ <? else: ?>
+ <option value="<?= htmlReady($choice_value) ?>" <? if (in_array($choice_value, (array)$input['value'])) echo 'selected'; ?>>
+ <?= htmlReady($choice_name) ?>
+ </option>
+ <? endif; ?>
+<? endforeach; ?>
+ </select>
+ <? endif; ?>
+<? endif;
+
+if ($input['type'] === "multiselect") : ?>
+ <select <?=$is_locked ?> name="<?= $input['name'] ?>" multiple class="nested-select" <? if ($input['must']) echo 'required'; ?>>
+ <? if ($input['choices']) : foreach ($input['choices'] as $choice_value => $choice_name) : ?>
+ <option value="<?= htmlReady($choice_value) ?>"<?=
+ in_array($choice_value, is_array($input['value']) ? $input['value'] : [$input['value']])
+ ? " selected"
+ : "" ?>><?= htmlReady($choice_name) ?></option>
+ <? endforeach; endif; ?>
+ </select>
+<? endif;
+
+if ($input['type'] === 'nested-select'): ?>
+<? if (isset($input['changable']) && !$input['changable']): ?>
+ <?= _("Keine Änderung möglich") ?>
+<? else: ?>
+ <select <?= $is_locked ?> name="<?= $input['name'] ?>" class="nested-select" <? if ($input['must']) echo 'required'; ?> <? if ($input['multiple']) echo 'multiple'; ?>>
+ <? foreach ($input['choices'] as $outer_id => $group): ?>
+ <? if ($group['label'] !== false): ?>
+ <option value="<?= htmlReady($outer_id) ?>" class="nested-item-header" <? if (in_array($outer_id, (array)$input['value'])) echo 'selected'; ?>>
+ <?= htmlReady($group['label']) ?>
+ </option>
+ <? endif; ?>
+ <? foreach ($group['children'] as $inner_id => $inner_label): ?>
+ <option value="<?= htmlReady($inner_id) ?>" class="nested-item" <? if (in_array($inner_id, (array)$input['value'])) echo 'selected'; ?>>
+ <?= htmlReady($inner_label) ?>
+ </option>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ </select>
+<? endif;
+endif;
+
+if ($input['type'] === 'datafield'): ?>
+ <? if ($is_locked): ?>
+ <label>
+ <?= htmlReady($input['title']) ?>
+
+ <? if ($input['description']): ?>
+ <?= tooltipIcon($input['description']) ?>
+ <? endif?>
+
+ <div>
+ <?= $input['display_value'] ?>
+ </div>
+ </label>
+ <? else: ?>
+ <?= $input['html_value'] ?>
+ <? endif ?>
+<? endif;
diff --git a/app/views/course/basicdata/view.php b/app/views/course/basicdata/view.php
new file mode 100644
index 0000000..f746147
--- /dev/null
+++ b/app/views/course/basicdata/view.php
@@ -0,0 +1,336 @@
+<?php
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+/*
+ * Copyright (C) 2010 - Rasmus Fuhse <fuhse@data-quest.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+$dialog_attr = Request::isXhr() ? ' data-dialog="size=50%"' : '';
+
+$message_types = ['msg' => "success", 'error' => "error", 'info' => "info"];
+?>
+
+<? if (is_array($flash['msg'])) foreach ($flash['msg'] as $msg) : ?>
+ <?= MessageBox::{$message_types[$msg[0]]}($msg[1]) ?>
+<? endforeach ?>
+
+<form name="course-details" name="details" method="post" action="<?= $controller->link_for('course/basicdata/set', $course_id) ?>" <?= $dialog_attr ?> class="default collapsable">
+ <?= CSRFProtection::tokenTag() ?>
+ <input id="open_variable" type="hidden" name="open" value="<?= $flash['open'] ?>">
+ <?= Studip\Button::createAccept(_('Speichern'), 'store', ['style' => 'display: none;']) ?>
+ <fieldset <?= isset($flash['open']) && $flash['open'] != 'bd_basicsettings' ? 'class="collapsed"' : ''?> data-open="bd_basicsettings">
+ <legend><?= _('Grundeinstellungen') ?></legend>
+
+<? if (!$attributes): ?>
+ <?= MessageBox::info(_('Fehlende Datenzeilen')) ?>
+<? else: ?>
+ <? foreach ($attributes as $attribute): ?>
+ <label>
+ <span <?= $attribute['must'] ? 'class="required"' : '' ?>>
+ <?= htmlReady($attribute['title']) ?>
+ </span>
+ <?= $attribute['description'] ? tooltipIcon($attribute['description']) : '' ?>
+
+ <?= $this->render_partial("course/basicdata/_input", ['input' => $attribute]) ?>
+ </label>
+ <? endforeach; ?>
+<? endif; ?>
+
+ <label>
+ <?= _('Erstellt') ?>
+ <br>
+ <?= htmlReady($mkstring) ?>
+ </label>
+
+ <label>
+ <?= _('Letzte Änderung') ?>
+ <br>
+ <?= htmlReady($chstring) ?>
+ </label>
+ </fieldset>
+
+ <fieldset <?= !isset($flash['open']) || $flash['open'] != 'inset' ? 'class="collapsed"' : ''?> data-open="bd_inst">
+ <legend><?= _('Einrichtungen') ?></legend>
+
+<? if (!$institutional): ?>
+ <?= MessageBox::info(_('Fehlende Datenzeilen')) ?>
+<? else: ?>
+ <? foreach ($institutional as $inst): ?>
+ <label>
+ <span <?= $inst['must'] ? 'class="required"' : '' ?>>
+ <?= htmlReady($inst['title']) ?>
+ </span>
+
+ <? if ($inst['type'] === 'select' && !$inst['choices'][$inst['value']]): ?>
+ <? $name = get_object_name($inst['value'], 'inst'); ?>
+ <?= htmlReady($name['name']) ?>
+ <? else: ?>
+ <?= $this->render_partial('course/basicdata/_input', ['input' => $inst]) ?>
+ <? endif; ?>
+ </label>
+ <? endforeach; ?>
+<? endif; ?>
+ </fieldset>
+
+ <fieldset <?= !isset($flash['open']) || $flash['open'] != 'bd_personal' ? 'class="collapsed"' : ''?>>
+ <legend><?= _('Personal') ?></legend>
+
+ <table class="default">
+ <caption>
+ <?= htmlReady($dozenten_title) ?>
+
+ <? if ($perm_dozent && !$dozent_is_locked): ?>
+ <span class="actions">
+ <?= MultiPersonSearch::get('add_member_dozent' . $course_id)
+ ->setTitle(_('Mehrere Lehrende hinzufügen'))
+ ->setSearchObject($dozentUserSearch)
+ ->setDefaultSelectedUser(array_keys($dozenten))
+ ->setDataDialogStatus(Request::isXhr())
+ ->setJSFunctionOnSubmit(Request::isXhr() ? 'jQuery(this).closest(".ui-dialog-content").dialog("close");' : false)
+ ->setExecuteURL($controller->url_for('course/basicdata/add_member/' . $course_id))
+ ->addQuickfilter(sprintf(_('%s der Einrichtung'), get_title_for_status('dozent', 2)), $lecturersOfInstitute)
+ ->render() ?>
+ </span>
+ <? endif; ?>
+ </caption>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Funktion') ?></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($dozenten) === 0): ?>
+ <tr>
+ <td colspan="4" style="text-align: center">
+ <?= _('Keine Lehrende eingetragen') ?>
+ </td>
+ </tr>
+ <? else: ?>
+ <? foreach (array_values($dozenten) as $num => $dozent) : ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $dozent['username']) ?>">
+ <?= Avatar::getAvatar($dozent['user_id'], $dozent['username'])->getImageTag(Avatar::SMALL) ?>
+ </a>
+ </td>
+ <td>
+ <?= get_fullname($dozent['user_id'], 'full_rev', true) . ' (' . $dozent['username'] . ')' ?>
+ </td>
+ <td>
+ <? if ($perm_dozent && !$dozent_is_locked): ?>
+ <input value="<?= htmlReady($dozent['label']) ?>" type="text" name="label[<?= htmlReady($dozent['user_id']) ?>]" title="<?= _('Die Funktion, die die Person in der Veranstaltung erfüllt.') ?>">
+ <? else : ?>
+ <?= htmlReady($dozent['label']) ?>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <? if ($perm_dozent && !$dozent_is_locked): ?>
+ <? if ($num > 0) : ?>
+ <a href="<?= $controller->link_for('course/basicdata/priorityupfor', $course_id, $dozent['user_id'], 'dozent') ?>" <?= $dialog_attr ?>>
+ <?= Icon::create('arr_2up', Icon::ROLE_SORT)->asImg(['class' => 'middle']) ?>
+ </a>
+ <? endif; ?>
+ <? if ($num < count($dozenten) - 1): ?>
+ <a href="<?= $controller->link_for('course/basicdata/prioritydownfor', $course_id, $dozent['user_id'], 'dozent') ?>" <?= $dialog_attr ?>>
+ <?= Icon::create('arr_2down', Icon::ROLE_SORT)->asImg(['class' => 'middle']) ?>
+ </a>
+ <? endif; ?>
+ <?= Icon::create('trash')->asInput([
+ 'formaction' => $controller->url_for('course/basicdata/deletedozent', $course_id, $dozent['user_id']),
+ 'data-confirm' => _('Soll die Person wirklich entfernt werden?'),
+ ]) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+ </tbody>
+ </table>
+
+ <!-- Stellvertreter -->
+ <? if ($deputies_enabled && ($perm_dozent || count($deputies) > 0)): ?>
+ <table class="default">
+ <caption>
+ <?= htmlReady($deputy_title) ?>
+ <? if ($perm_dozent && !$dozent_is_locked) : ?>
+ <span class="actions">
+ <?= MultiPersonSearch::get('add_member_deputy' . $course_id)
+ ->setTitle(_('Mehrere Vertretungen hinzufügen'))
+ ->setSearchObject($deputySearch)
+ ->setDefaultSelectedUser($deputies->pluck('user_id'))
+ ->setDataDialogStatus(Request::isXhr())
+ ->setJSFunctionOnSubmit(Request::isXhr() ? 'jQuery(this).closest(".ui-dialog-content").dialog("close");' : false)
+ ->setExecuteURL($controller->url_for('course/basicdata/add_member/' . $course_id . '/deputy'))
+ ->render() ?>
+ </span>
+ <? endif; ?>
+ </caption>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($deputies) === 0): ?>
+ <tr>
+ <td colspan="4" style="text-align: center">
+ <?= _('Keine Vertretung eingetragen') ?>
+ </td>
+ </tr>
+ <? else: ?>
+ <? foreach ($deputies as $deputy) : ?>
+ <tr>
+ <td>
+ <?= Avatar::getAvatar($deputy->user_id, $deputy->username)->getImageTag(Avatar::SMALL) ?>
+ </td>
+ <td>
+ <?= htmlReady($deputy->getDeputyFullname()) ?>
+ (<?= htmlReady($deputy->username) ?>,
+ <?= _('Status') ?>:
+ <?= $deputy->perms ?>)
+ </td>
+ <td></td>
+ <td class="actions">
+ <? if ($perm_dozent && !$dozent_is_locked): ?>
+ <?= Icon::create('trash')->asInput([
+ 'formaction' => $controller->url_for("course/basicdata/deletedeputy/{$course_id}/{$deputy['user_id']}"),
+ 'data-confirm' => _('Soll die Person wirklich entfernt werden?'),
+ ]) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? endif ?>
+ </tbody>
+ </table>
+ <? endif ?>
+
+ <!-- Tutoren -->
+ <table class="default">
+ <caption>
+ <?= htmlReady($tutor_title) ?>
+ <? if ($perm_dozent && !$tutor_is_locked): ?>
+ <span class="actions">
+ <?= MultiPersonSearch::get('add_member_tutor' . $course_id)
+ ->setTitle(_('Mehrere TutorInnen hinzufügen'))
+ ->setSearchObject($tutorUserSearch)
+ ->setDefaultSelectedUser(array_merge(array_keys($dozenten), array_keys($tutoren)))
+ ->setDataDialogStatus(Request::isXhr())
+ ->setJSFunctionOnSubmit(Request::isXhr() ? 'jQuery(this).closest(".ui-dialog-content").dialog("close");' : false)
+ ->setExecuteURL($controller->url_for('course/basicdata/add_member/' . $course_id . '/tutor'))
+ ->addQuickfilter(sprintf(_('%s der Einrichtung'), get_title_for_status('dozent', 2)), $lecturersOfInstitute)
+ ->addQuickfilter(sprintf(_('%s der Einrichtung'), get_title_for_status('tutor', 2)), $tutorsOfInstitute)
+ ->render() ?>
+ </span>
+ <? endif; ?>
+ </caption>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Funktion') ?></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($tutoren) === 0): ?>
+ <tr>
+ <td colspan="4" style="text-align: center">
+ <?= _('Keine TutorInnen eingetragen') ?>
+ </td>
+ </tr>
+ <? else: ?>
+ <? foreach (array_values($tutoren) as $num => $tutor): ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $tutor['username']) ?>">
+ <?= Avatar::getAvatar($tutor['user_id'], $tutor['username'])->getImageTag(Avatar::SMALL) ?>
+ </a>
+ </td>
+ <td>
+ <?= get_fullname($tutor['user_id'], 'full_rev', true) . ' (' . $tutor['username'] . ')' ?>
+ </td>
+ <td>
+ <? if ($perm_dozent && !$tutor_is_locked): ?>
+ <input value="<?= htmlReady($tutor['label']) ?>" type="text" name="label[<?= htmlReady($tutor['user_id']) ?>]" title="<?= _('Die Funktion, die die Person in der Veranstaltung erfüllt.') ?>">
+ <? else: ?>
+ <?= htmlReady($tutor['label']) ?>
+ <? endif; ?>
+ </td>
+ <td class="actions">
+ <? if ($perm_dozent && !$tutor_is_locked): ?>
+ <? if ($num > 0) : ?>
+ <a href="<?= $controller->link_for('course/basicdata/priorityupfor', $course_id, $tutor['user_id'], 'tutor') ?>" <?= $dialog_attr ?>>
+ <?= Icon::create('arr_2up', Icon::ROLE_SORT)->asImg(['class' => 'middle']) ?>
+ </a>
+ <? endif; ?>
+ <? if ($num < count($tutoren) - 1) : ?>
+ <a href="<?= $controller->link_for('course/basicdata/prioritydownfor', $course_id, $tutor['user_id'], 'tutor') ?>" <?= $dialog_attr ?>>
+ <?= Icon::create('arr_2down', Icon::ROLE_SORT)->asImg(['class' => 'middle']) ?>
+ </a>
+ <? endif; ?>
+ <?= Icon::create('trash')->asInput([
+ 'formaction' => $controller->url_for('course/basicdata/deletetutor', $course_id, $tutor['user_id']),
+ 'data-confirm' => _('Soll die Person wirklich entfernt werden?'),
+ ]) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset <?= !isset($flash['open']) || $flash['open'] != 'bd_description' ? 'class="collapsed"' : ''?> data-open="bd_description">
+ <legend><?= _('Beschreibungen') ?></legend>
+
+<? if (!$descriptions): ?>
+ <?= MessageBox::info(_('Fehlende Datenzeilen')) ?>
+<? else: ?>
+ <? foreach ($descriptions as $description): ?>
+ <? if ($description['type'] == 'datafield'): ?>
+ <?= $this->render_partial('course/basicdata/_input', ['input' => $description]) ?>
+ <? else : ?>
+ <label>
+ <span <?= $description['must'] ? 'class="required"' : '' ?>>
+ <?= $description['title'] ?>
+ </span>
+
+ <? if ($description['type'] === 'datafield' && $description['description']) : ?>
+ <?= tooltipIcon($description['description'])?>
+ <? endif?>
+
+ <?= $this->render_partial('course/basicdata/_input', ['input' => $description]) ?>
+ </label>
+ <? endif ?>
+ <? endforeach; ?>
+<? endif; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::create(_('Übernehmen')) ?>
+ </footer>
+</form>
+
+<script>
+jQuery(function ($) {
+ $('input[name^=label]').autocomplete({
+ source: <?=
+json_encode(preg_split('/[\s,;]+/', Config::get()->PROPOSED_TEACHER_LABELS, -1, PREG_SPLIT_NO_EMPTY));
+?>
+ });
+});
+STUDIP.MultiPersonSearch.init();
+</script> \ No newline at end of file
diff --git a/app/views/course/block_appointments/index.php b/app/views/course/block_appointments/index.php
new file mode 100644
index 0000000..4dc0b87
--- /dev/null
+++ b/app/views/course/block_appointments/index.php
@@ -0,0 +1,153 @@
+<? if (!Request::isXhr()) : ?>
+ <h1><?= _('Neuen Blocktermin anlegen') ?></h1>
+<? endif ?>
+
+<form <?= Request::isXhr() ? 'data-dialog="size=big"' : '' ?>
+ class="default collapsable"
+ action="<?= $controller->url_for('course/block_appointments/save/' . $course_id, $editParams) ?>"
+ method="post">
+
+<? if ($confirm_many): ?>
+ <?= MessageBox::info(sprintf(
+ _('Sie legen %s%u%s Termine an. Bitte kontrollieren Sie Ihre Eingaben '
+ . 'oder bestätigen Sie, dass die Termine angelegt werden sollen.'),
+ '<strong>',
+ $confirm_many,
+ '</strong>'
+ ), [
+ sprintf(
+ '<label><input type="checkbox" name="confirmed" value="1">%s</label>',
+ sprintf(_('Ja, ich möchte wirklich %u Termine anlegen.'), $confirm_many)
+ ),
+ ]) ?>
+<? endif; ?>
+
+ <fieldset>
+ <legend><?= _('Zeitraum') ?></legend>
+ <label for="block_appointments_start_day" class="col-3">
+ <?= _('Startdatum') ?>
+ <input type="text" class="size-s has-date-picker" data-date-picker id="block_appointments_start_day"
+ name="block_appointments_start_day" value="<?= $request['block_appointments_start_day'] ?>">
+ </label>
+ <label for="block_appointments_end_day" class="col-3">
+ <?= _('Enddatum') ?>
+ <input type="text" class="size-s has-date-picker" data-date-picker='{">=":"#block_appointments_start_day"}' id="block_appointments_end_day"
+ name="block_appointments_end_day" value="<?= $request['block_appointments_end_day'] ?>">
+ </label>
+ <label for="block_appointments_start_time" class="col-3">
+ <?= _('Startzeit') ?>
+ <input type="text" class="size-s studip-timepicker" id="block_appointments_start_time"
+ name="block_appointments_start_time" value="<?= $request['block_appointments_start_time'] ?>"
+ placeholder="HH:mm">
+ </label>
+
+ <label for="block_appointments_end_time" class="col-3">
+ <?= _('Endzeit') ?>
+ <input type="text" class="size-s studip-timepicker" id="block_appointments_end_time"
+ name="block_appointments_end_time" value="<?= $request['block_appointments_end_time'] ?>"
+ placeholder="HH:mm">
+ </label>
+
+ <div id="block_appointments_days">
+ <label><?= _('Die Veranstaltung findet an folgenden Tagen statt') ?></label>
+ <label for="block_appointments_days_0" class="col-2">
+ <input <?= empty($request['block_appointments_days']) || in_array('everyday', $request['block_appointments_days']) ? 'checked' : '' ?>
+ class="block_appointments_days"
+ name="block_appointments_days[]" id="block_appointments_days_0" type="checkbox" value="everyday">
+ <?= _('Jeden Tag') ?>
+ </label>
+
+ <label for="block_appointments_days_1" class="col-2">
+ <input <?= in_array('weekdays', (array) $request['block_appointments_days']) ? 'checked ' : '' ?>
+ class="block_appointments_days"
+ name="block_appointments_days[]" id="block_appointments_days_1" type="checkbox" value="weekdays">
+ <?= _('Mo-Fr') ?>
+ </label>
+ <? foreach (range(0, 6) as $d) : ?>
+ <? $id = 2 + $d ?>
+ <label for="block_appointments_days_<?= $id ?>" class="col-2">
+ <input <?= in_array($d+1, (array) $request['block_appointments_days']) ? 'checked ' : '' ?>
+ class="block_appointments_days"
+ name="block_appointments_days[]" id="block_appointments_days_<?= $id ?>" type="checkbox"
+ value="<?= $d + 1 ?>">
+ <?= strftime('%A', strtotime("+$d day", $start_ts)) ?>
+ </label>
+ <? endforeach ?>
+ </div>
+
+ </fieldset>
+
+ <fieldset class="collapsed">
+ <legend><?= _('Weitere Daten') ?></legend>
+ <label for="block_appointments_termin_typ">
+ <?= _('Art der Termine') ?>
+ <select clas="size-l" name="block_appointments_termin_typ" id="block_appointments_termin_typ">
+ <? foreach ($GLOBALS['TERMIN_TYP'] as $key => $value) : ?>
+ <option
+ value="<?= $key ?>" <?= $request['block_appointments_termin_typ'] == $key ? 'selected' : '' ?>>
+ <?= htmlReady($value['name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <? if (Config::get()->RESOURCES_ENABLE && ($selectable_rooms || $room_search)) : ?>
+ <label>
+ <?= _('Raum') ?>
+ <? if ($room_search): ?>
+ <?= $room_search->render() ?>
+ <? else: ?>
+ <select name="room_id" style="width: calc(100% - 23px);">
+ <option value=""><?= _('<em>Keinen</em> Raum buchen') ?></option>
+ <? foreach ($selectable_rooms as $room): ?>
+ <option value="<?= htmlReady($room->id) ?>">
+ <?= htmlReady($room->name) ?>
+ <? if ($room->seats > 1) : ?>
+ <?= sprintf(_('(%d Sitzplätze)'), $room->seats) ?>
+ <? endif ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ </label>
+ <? endif ?>
+
+ <label for="block_appointments_room_text">
+ <?= _('Freie Ortsangabe') ?>
+ <input type="text" name="block_appointments_room_text" id="block_appointments_room_text"
+ value="<?= $request['block_appointments_room_text'] ?>">
+ </label>
+
+ <? if (count($lecturers)): ?>
+ <label for="lecturers[]">
+ <?= _('Durchführende Lehrende') ?>
+ <? if (count($lecturers) > 1): ?>
+ <select name="lecturers[]" multiple="multiple" class="multiple">
+ <? foreach ($lecturers as $lecturer): ?>
+ <option value="<?= $lecturer->user_id ?>"
+ <? if (in_array($lecturer->user_id, Request::optionArray('lecturers'))) echo 'selected'; ?>>
+ <?= htmlReady($lecturer->user->getFullName()) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? else: ?>
+ <p style="margin-left: 15px">
+ <? $lecturer = array_pop($lecturers) ?>
+ <?= htmlReady($lecturer->user->getFullName()) ?>
+ </p>
+ <? endif; ?>
+ </label>
+ <? endif ?>
+
+ <label for="block_appointments_date_count">
+ <?= _('Anzahl der Termine') ?>
+ <input type="text" name="block_appointments_date_count" id="block_appointments_date_count" class="size-s" value="<?= $request['block_appointments_date_count'] ?: 1 ?>">
+ </label>
+
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ <?= Studip\LinkButton::create(_('Zurück zur Übersicht'), $controller->url_for('course/timesrooms/index'), ['data-dialog' => 'size=big']) ?>
+ </footer>
+</form>
diff --git a/app/views/course/cancel_dates/index.php b/app/views/course/cancel_dates/index.php
new file mode 100644
index 0000000..e427849
--- /dev/null
+++ b/app/views/course/cancel_dates/index.php
@@ -0,0 +1,31 @@
+<form action="<?= $controller->url_for('course/cancel_dates/store') ?>" method="post" class="default" name="cancel_dates">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Folgende Veranstaltungstermine ausfallen lassen') ?>
+ </legend>
+ <div style="padding: 5px; margin: 5px;font-weight: bold;">
+ <? echo join(', ', array_map(function ($d) {
+ return $d->toString();
+ }, $dates)); ?>
+ </div>
+
+ <label>
+ <?= _('Kommentar') ?>
+ <?= tooltipIcon(_('Wenn Sie die nicht stattfindenden Termine mit einem Kommentar versehen, werden die Ausfalltermine im Ablaufplan weiterhin dargestellt und auch im Terminkalender eingeblendet.')) ?>
+ <textarea wrap="virtual" name="cancel_dates_comment" id="cancel_dates_comment"></textarea>
+ </label>
+ <label>
+ <input type="checkbox" name="cancel_dates_snd_message" value="1">
+ <?= _('Benachrichtigung über ausfallende Termine an alle Teilnehmenden verschicken') ?>
+ </label>
+ </fieldset>
+ <? if ($issue_id) : ?>
+ <input type="hidden" name="issue_id" value="<?= $issue_id ?>">
+ <? else : ?>
+ <input type="hidden" name="termin_id" value="<?= $dates[0]->getTerminId() ?>">
+ <? endif ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/courseware/action_widget.php b/app/views/course/courseware/action_widget.php
new file mode 100644
index 0000000..b13792e
--- /dev/null
+++ b/app/views/course/courseware/action_widget.php
@@ -0,0 +1 @@
+<aside id="courseware-action-widget" class="widget-sidebar"></aside>
diff --git a/app/views/course/courseware/dashboard.php b/app/views/course/courseware/dashboard.php
new file mode 100755
index 0000000..d666b0d
--- /dev/null
+++ b/app/views/course/courseware/dashboard.php
@@ -0,0 +1,9 @@
+
+
+
+<script>
+ STUDIP.courseware_progress_data = <?= json_encode($courseware_progress_data);?>;
+ STUDIP.courseware_chapter_counter = <?= json_encode($courseware_chapter_counter);?>;
+</script>
+
+<div id="courseware-dashboard-app"></div>
diff --git a/app/views/course/courseware/index.php b/app/views/course/courseware/index.php
new file mode 100755
index 0000000..46a949c
--- /dev/null
+++ b/app/views/course/courseware/index.php
@@ -0,0 +1,9 @@
+<div
+ id="courseware-index-app"
+ entry-element-id="<?= $entry_element_id ?>"
+ entry-type="courses"
+ entry-id="<?= Context::getId() ?>"
+ oer-title="<?= Config::get()->OER_TITLE ?>"
+ licenses='<?= $licenses ?>'
+ >
+</div> \ No newline at end of file
diff --git a/app/views/course/courseware/manager.php b/app/views/course/courseware/manager.php
new file mode 100755
index 0000000..3107cf5
--- /dev/null
+++ b/app/views/course/courseware/manager.php
@@ -0,0 +1 @@
+<div id="courseware-manager-app" entry-type="courses" entry-id="<?= Context::getId() ?>"></div>
diff --git a/app/views/course/courseware/view_widget.php b/app/views/course/courseware/view_widget.php
new file mode 100755
index 0000000..8269134
--- /dev/null
+++ b/app/views/course/courseware/view_widget.php
@@ -0,0 +1 @@
+<aside id="courseware-view-widget" class="widget-sidebar"></aside>
diff --git a/app/views/course/dates/_date_row-exdate.php b/app/views/course/dates/_date_row-exdate.php
new file mode 100644
index 0000000..b905663
--- /dev/null
+++ b/app/views/course/dates/_date_row-exdate.php
@@ -0,0 +1,29 @@
+<tr id="date_<?= $date->id ?>" class="ausfall" data-termin-id="<?= htmlReady($date->id) ?>">
+ <td data-sort-value="<?= htmlReady($date->date) ?>" class="date_name">
+ <?= Icon::create('date', Icon::ROLE_INFO)->asImg(['class' => 'text-bottom']) ?>
+ <?= htmlReady($date->getFullname()) ?>
+ <?= tooltipIcon($date->content) ?>
+ <? if (count($date->dozenten) > 0): ?>
+ <br>
+ (<?= htmlReady(implode(', ', $date->dozenten->getFullname())) ?>)
+ <? endif; ?>
+ </td>
+ <td class="hidden-small-down"></td>
+ <td class="hidden-small-down">
+ <?= htmlReady($date->getTypeName()) ?>
+ </td>
+<? if (count($course->statusgruppen) > 0) : ?>
+ <td class="hidden-small-down"></td>
+<? endif ?>
+ <td></td>
+ <td class="actions">
+ <? if ($has_access && !$cancelled_dates_locked): ?>
+ <form action="<?= $controller->url_for("course/timesrooms/undeleteSingle/{$date->id}/1") ?>" method="post">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addButton('restore_date', _('Termin wiederherstellen'), Icon::create('trash+decline'),
+ ['data-confirm' => _('Diesen Termin wiederherstellen?')]) ?>
+ <?= $actionMenu->render() ?>
+ </form>
+ <? endif ?>
+ </td>
+</tr>
diff --git a/app/views/course/dates/_date_row.php b/app/views/course/dates/_date_row.php
new file mode 100644
index 0000000..86a48d2
--- /dev/null
+++ b/app/views/course/dates/_date_row.php
@@ -0,0 +1,75 @@
+<?php
+$icon = $date->chdate > $last_visitdate ? 'date+new' : 'date';
+$dialog_url = $show_raumzeit
+ ? $controller->url_for('course/dates/details/' . $date->id)
+ : $controller->url_for('course/dates/singledate/' . $date->id);
+?>
+<tr id="date_<?= $date->id ?>" <? if ($is_next_date) echo 'class="nextdate" title="' . _('Der nächste Termin') . '"'; ?> data-termin-id="<?= htmlReady($date->id) ?>">
+ <td data-sort-value="<?= htmlReady($date->date) ?>" class="date_name">
+ <a href="<?= $dialog_url ?>" data-dialog>
+ <?= Icon::create($icon)->asImg(['class' => 'text-bottom']) ?>
+ <?= htmlReady($date->getFullname(CourseDate::FORMAT_VERBOSE)) ?>
+ </a>
+ <? if (count($date->dozenten) > 0): ?>
+ <br>
+ (<?= htmlReady(implode(', ', $date->dozenten->getFullname())) ?>)
+ <? endif; ?>
+ </td>
+ <td class="hidden-small-down">
+ <ul class="themen-list clean">
+ <? foreach ($date->topics as $topic): ?>
+ <?= $this->render_partial('course/dates/_topic_li', compact('topic', 'date')) ?>
+ <? endforeach; ?>
+ </ul>
+ </td>
+ <td class="hidden-small-down">
+ <?= htmlReady($date->getTypeName()) ?>
+ </td>
+<? if (count($course->statusgruppen) > 0) : ?>
+ <td class="hidden-small-down">
+ <? if (count($date->statusgruppen) > 0) : ?>
+ <ul class="clean">
+ <? foreach ($date->statusgruppen as $statusgruppe) : ?>
+ <li><?= htmlReady($statusgruppe->name) ?></li>
+ <? endforeach ?>
+ </ul>
+ <? else : ?>
+ <?= _('alle') ?>
+ <? endif ?>
+ </td>
+<? endif ?>
+ <td>
+ <? $room = $date->getRoom(); ?>
+ <? if ($room): ?>
+ <a href="<?= $room->getActionLink('show') ?>" data-dialog>
+ <?= htmlReady($room->name) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($date->raum) ?>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $filecount = count($date->getAccessibleFolderFiles($GLOBALS['user']->id)['files']); ?>
+ <? if ($has_access): ?>
+ <? $actionMenu->addLink($dialog_url, _('Termin bearbeiten'), Icon::create('edit'), ['data-dialog' => '']) ?>
+ <? $actionMenu->addLink($controller->url_for('course/dates/new_topic?termin_id=' . $date->id),
+ _('Thema hinzufügen'), Icon::create('topic+add'), ['data-dialog' => 'size=auto']) ?>
+ <? endif ?>
+ <? if ($filecount): ?>
+ <? $actionMenu->addLink($controller->url_for('course/dates/details_files/' . $date->id),
+ _('Dateien anzeigen'), Icon::create('folder-topic-full'), ['data-dialog' => '']) ?>
+ <? endif ?>
+ <? if ($has_access): ?>
+ <? if (!$cancelled_dates_locked): ?>
+ <? $actionMenu->addLink($controller->url_for('course/cancel_dates', ['termin_id' => $date->id]),
+ _('Termin ausfallen lassen'), Icon::create('trash'), [
+ 'data-dialog' => 'size=auto',
+ 'data-confirm' => _('Wollen Sie diesen Termin wirklich ausfallen lassen?')
+ . '<br>' . implode('<br>', array_map('htmlReady', $date->getDeletionWarnings())),
+ ]) ?>
+ <? endif ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+</tr>
diff --git a/app/views/course/dates/_topic_li.php b/app/views/course/dates/_topic_li.php
new file mode 100644
index 0000000..88e267f
--- /dev/null
+++ b/app/views/course/dates/_topic_li.php
@@ -0,0 +1,11 @@
+<li data-issue_id="<?= $topic->id ?>" class="topic_<?= $date->id ?>_<?= $topic->id ?>">
+ <a href="<?= $controller->url_for("course/topics#{$topic->id}", ['open' => $topic->id]) ?>" class="title">
+ <?= Icon::create('topic')->asImg(['class' => 'text-bottom']) ?>
+ <?= htmlReady($topic['title']) ?>
+ </a>
+<? if ($has_access) : ?>
+ <a href="#" onClick="STUDIP.Dates.removeTopicFromIcon.call(this); return false;">
+ <?= Icon::create('trash')->asImg(['class' => 'text-bottom'] + tooltip2(_('Thema entfernen'))) ?>
+ </a>
+<? endif ?>
+</li>
diff --git a/app/views/course/dates/create_folders.php b/app/views/course/dates/create_folders.php
new file mode 100644
index 0000000..59cf3bb
--- /dev/null
+++ b/app/views/course/dates/create_folders.php
@@ -0,0 +1,50 @@
+<form class="default" action="<?= $controller->link_for() ?>" method="post" data-dialog="size=auto">
+ <?= CSRFProtection::tokenTag() ?>
+
+<? foreach ($previously_selected_dates as $date_id): ?>
+ <input type="hidden" name="previously_selected_dates[]" value="<?= htmlReady($date_id) ?>">
+<? endforeach ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Auswahl der Termine') ?>
+ </legend>
+
+ <label>
+ <input type="checkbox" name="all" data-proxyfor=":checkbox[name^=course_date_folders]">
+ <?=_('Alle auswählen')?>
+ </label>
+
+ <? foreach ($dates as $one) : ?>
+ <label>
+ <input type="checkbox" name="course_date_folders[]" value="<?= htmlReady($one->id) ?>"
+ <? if (in_array($one->id, $course_date_folders)) echo 'checked'; ?>>
+ <?= htmlReady(CourseDateFolder::formatDate($one)) ?>
+ <? if ($one->folders->count()) : ?>
+ <span style="font-size: smaller">
+ - <?= sprintf(_('%u Ordner vorhanden'), $one->folders->count()) ?>
+ </span>
+ <? endif;?>
+ </label>
+ <? endforeach; ?>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Schreibberechtigung für Studierende') ?>
+ </legend>
+
+ <label>
+ <input name="course_date_folder_perm_write" type="checkbox" checked value="1">
+ <?= _('Studierende dürfen Dateien in diesen Ordner hochladen') ?>
+ </label>
+ </fieldset>
+
+ <div data-dialog-button>
+ <? if ($show_confirmation_button): ?>
+ <?= Studip\Button::create(_('Trotzdem erstellen'), 'force_go') ?>
+ <? else: ?>
+ <?= Studip\Button::create(_('Ordner erstellen'), 'go') ?>
+ <? endif ?>
+ </div>
+</form>
diff --git a/app/views/course/dates/details-edit.php b/app/views/course/dates/details-edit.php
new file mode 100644
index 0000000..8991002
--- /dev/null
+++ b/app/views/course/dates/details-edit.php
@@ -0,0 +1,166 @@
+<form name="edit_termin" action='<?= $controller->url_for('course/dates/save_details/' . $date->id) ?>' method="post" class="default" data-termin-id="<?= htmlReady($date->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Termin bearbeiten') ?></legend>
+
+ <label>
+ <?= _('Art des Termins') ?>
+ <select name="dateType" <?=$metadata_locked ? 'disabled' : ''?>>>
+ <? foreach ($GLOBALS['TERMIN_TYP'] as $key => $val): ?>
+ <option value="<?= htmlReady($key) ?>" <? if ($date->date_typ == $key) echo 'selected'; ?>>
+ <?= htmlReady($val['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label for="new_topic">
+ <?= _('Themen') ?>
+ </label>
+
+ <ul class="themen-list">
+ <li class="list-placeholder"><?= _('Keine Themen zugeordnet') ?></li>
+ <? foreach ($date->topics as $topic) : ?>
+ <?= $this->render_partial('course/dates/_topic_li', compact('topic')) ?>
+ <? endforeach ?>
+ </ul>
+
+ <section class="hgroup">
+ <input type="text" name="new_topic" id="new_topic"
+ placeholder="<?= _('Thema suchen oder neu anlegen') ?>">
+
+ <?= Studip\Button::create(
+ _('Thema hinzufügen'), 'add_topic',
+ ['onclick' => 'STUDIP.Dates.addTopic(); return false;']
+ ) ?>
+ </section>
+
+ </fieldset>
+
+<? if (count($teachers) > 1): ?>
+ <fieldset class="studip-selection <?= $metadata_locked ? 'disabled' : ''?>" data-attribute-name="assigned_teachers">
+ <legend><?= _('Durchführende Lehrende') ?></legend>
+
+ <section class="studip-selection-selected">
+ <h2><?= _('Zugewiesene Lehrende') ?></h2>
+
+ <ul>
+ <? foreach ($assigned_teachers as $teacher): ?>
+ <li data-selection-id="<?= htmlReady($teacher->user_id) ?>">
+ <input type="hidden" name="assigned_teachers[]"
+ value="<?= htmlReady($teacher->user_id) ?>">
+
+ <span class="studip-selection-image">
+ <?= Avatar::getAvatar($teacher->user_id)->getImageTag(Avatar::SMALL) ?>
+ </span>
+ <span class="studip-selection-label">
+ <?= htmlReady($teacher->getFullname()) ?>
+ </span>
+ </li>
+ <? endforeach; ?>
+ <li class="empty-placeholder">
+ <?= _('Kein spezieller Lehrender zugewiesen') ?>
+ </li>
+ </ul>
+ </section>
+
+ <section class="studip-selection-selectable">
+ <h2><?= _('Lehrende der Veranstaltung') ?></h2>
+
+ <ul>
+ <? foreach ($teachers as $teacher): ?>
+ <? if (!$assigned_teachers->find($teacher->user_id)): ?>
+ <li data-selection-id="<?= htmlReady($teacher->id) ?>" >
+ <span class="studip-selection-image">
+ <?= Avatar::getAvatar($teacher->id)->getImageTag(Avatar::SMALL) ?>
+ </span>
+ <span class="studip-selection-label">
+ <?= htmlReady($teacher->getFullname()) ?>
+ </span>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ <li class="empty-placeholder">
+ <?= sprintf(
+ _('Ihre Auswahl entspricht dem Zustand "%s" und wird beim Speichern zurückgesetzt'),
+ _('Kein spezieller Lehrender zugewiesen')
+ ) ?>
+ </li>
+ </ul>
+ </section>
+ </fieldset>
+<? endif; ?>
+
+<? if (count($groups) > 0): ?>
+ <fieldset class="studip-selection <?= $metadata_locked ? 'disabled' : ''?>" data-attribute-name="assigned_groups">
+ <legend><?= _('Beteiligte Gruppen') ?></legend>
+
+ <section class="studip-selection-selected">
+ <h2><?= _('Zugewiesene Gruppen') ?></h2>
+
+ <ul>
+ <? foreach ($assigned_groups as $group) : ?>
+ <li data-selection-id="<?= htmlReady($group->id) ?>">
+ <input type="hidden" name="assigned_groups[]"
+ value="<?= htmlReady($group->id) ?>">
+
+ <span class="studip-selection-label">
+ <?= htmlReady($group->name) ?>
+ </span>
+ </li>
+ <? endforeach ?>
+ <li class="empty-placeholder">
+ <?= _('Keine spezielle Gruppe zugewiesen') ?>
+ </li>
+ </ul>
+ </section>
+
+ <section class="studip-selection-selectable">
+ <h2><?= _('Gruppen der Veranstaltung') ?></h2>
+
+ <ul>
+ <? foreach ($groups as $group): ?>
+ <? if (!$assigned_groups->find($group->id)): ?>
+ <li data-selection-id="<?= htmlReady($group->id) ?>" >
+ <span class="studip-selection-label">
+ <?= htmlReady($group->name) ?>
+ </span>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ <li class="empty-placeholder">
+ <?= _('Alle Gruppen wurden dem Termin zugewiesen') ?>
+ </li>
+ </ul>
+ </section>
+ </fieldset>
+<? endif; ?>
+
+ <footer data-dialog-button>
+ <? if (!$metadata_locked): ?>
+ <?= Studip\Button::createAccept(_('Speichern')); ?>
+ <? endif; ?>
+ <? if (!$dates_locked): ?>
+ <?= Studip\LinkButton::create(
+ _('Termin bearbeiten'),
+ $controller->url_for('course/timesrooms', ['raumzeitFilter' => 'all'])
+ ) ?>
+ <? endif; ?>
+ <? if (!$cancelled_dates_locked): ?>
+ <?= Studip\LinkButton::create(
+ _('Ausfallen lassen'),
+ $controller->url_for('course/cancel_dates', ['termin_id' => $date->id]),
+ ['data-dialog' => '']
+ ) ?>
+ <? endif ?>
+ </footer>
+</form>
+
+<script>
+jQuery(function ($) {
+ $('#new_topic').autocomplete({
+ source: <?= json_encode(Course::findCurrent()->topics->pluck('title')) ?>
+ });
+});
+</script>
diff --git a/app/views/course/dates/details.php b/app/views/course/dates/details.php
new file mode 100644
index 0000000..5a77268
--- /dev/null
+++ b/app/views/course/dates/details.php
@@ -0,0 +1,98 @@
+<table class="default nohover">
+ <colgroup>
+ <col width="25%">
+ <col width="75%">
+ </colgroup>
+ <tbody>
+ <? if (count($date->topics) > 0): ?>
+ <tr>
+ <td><strong><?= _('Thema') ?></strong></td>
+ <td>
+ <ul class="themen_list">
+ <? foreach ($date->topics as $topic) : ?>
+ <?= $this->render_partial('course/dates/_topic_li', compact('topic')) ?>
+ <? endforeach ?>
+ </ul>
+ </td>
+ </tr>
+ <? endif; ?>
+ <tr>
+ <td><strong><?= _("Art des Termins") ?></strong></td>
+ <td>
+ <?= htmlReady($GLOBALS['TERMIN_TYP'][$date['date_typ']]['name']) ?>
+ </td>
+ </tr>
+ <? if (count($date->dozenten) > 0): ?>
+ <tr>
+ <td><strong><?= _('Durchführende Lehrende') ?></strong></td>
+ <td>
+ <ul class="dozenten_list clean">
+ <? foreach ($date->dozenten as $teacher): ?>
+ <li>
+ <a href="<?= $controller->link_for('profile?username=' . $teacher->username) ?>">
+ <?= Avatar::getAvatar($teacher->user_id)->getImageTag(Avatar::SMALL) ?>
+ <?= htmlReady($teacher->getFullname()) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? if (count($date->statusgruppen) > 0): ?>
+ <tr>
+ <td><strong><?= _('Beteiligte Gruppen') ?></strong></td>
+ <td>
+ <ul>
+ <? foreach ($date->statusgruppen as $group): ?>
+ <li><?= htmlReady($group->name) ?></li>
+ <? endforeach ;?>
+ </ul>
+ </td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+</table>
+
+<? extract($date->getAccessibleFolderFiles($GLOBALS['user']->id))?>
+<? if (count($files) > 0): ?>
+ <? $one_folder = current($folders); ?>
+ <form method="post" action="<?= $controller->link_for('file/bulk/' . $one_folder->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <article class="studip">
+ <header>
+ <h1><?= _('Dateien') ?></h1>
+ </header>
+ <section>
+ <table id="course_date_files" class="default sortable-table documents" data-sortlist="[[2, 0]]">
+ <?= $this->render_partial('files/_files_thead', ['show_bulk_checkboxes' => true]) ?>
+ <? foreach($files as $file): ?>
+ <? if ($file->isVisible($GLOBALS['user']->id)) : ?>
+ <?= $this->render_partial('files/_fileref_tr', [
+ 'file' => $file,
+ 'current_folder' => $folders[$file->getFolderType()->getId()],
+ 'last_visitdate' => time(),
+ 'show_bulk_checkboxes' => true
+ ]) ?>
+ <? endif ?>
+ <? endforeach ?>
+ <tfoot>
+ <tr>
+ <td colspan="7">
+ <span class="multibuttons">
+ <?= Studip\Button::create(_('Herunterladen'), 'download', [
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=d] :checkbox:checked'
+ ]) ?>
+ <?= Studip\Button::create(_('Kopieren'), 'copy', ['data-dialog' => '']) ?>
+ </span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </section>
+ </article>
+ </form>
+ <script>
+ STUDIP.Table.enhanceSortableTable($('#course_date_files'));
+ </script>
+<? endif; ?>
diff --git a/app/views/course/dates/export.php b/app/views/course/dates/export.php
new file mode 100644
index 0000000..7a8b70d
--- /dev/null
+++ b/app/views/course/dates/export.php
@@ -0,0 +1,72 @@
+<?
+# Lifter010: TODO
+?>
+<html>
+<head>
+ <title><?= htmlReady(PageLayout::getTitle())?></title>
+</head>
+<body>
+
+<? if (sizeof($dates)) : ?>
+ <table cellspacing="0" cellpadding="0" border="1" width="100%">
+
+ <tr>
+ <th colspan="5">
+ <h2><?= htmlReady(PageLayout::getTitle())?></h2>
+ </th>
+ </tr>
+
+ <?
+ $all_semester = Semester::findAllVisible(false);
+
+ foreach ($dates as $date) :
+ if ( ($grenze == 0) || ($grenze < $date['start']) ) {
+ foreach ($all_semester as $zwsem) {
+ if ( ($zwsem['beginn'] < $date['start']) && ($zwsem['ende'] > $date['start']) ) {
+ $grenze = $zwsem['ende'];
+ ?>
+ <tr>
+ <td colspan="5">
+ <h3><?= htmlReady($zwsem['name']) ?></h3>
+ </td>
+ </tr>
+ <?
+ }
+ }
+ }
+ ?>
+ <tr>
+ <td width="20%">
+ <?= htmlReady($date['date']) ?> (<?= htmlReady($date['type']) ?>)
+ </td>
+ <td width="20%"><?= htmlReady($date['title']) ?></td>
+ <td width="20%">
+ <? if (count($date['related_persons']) != $lecturer_count) : ?>
+ <? foreach ($date['related_persons'] as $key => $user_id) {
+ echo ($key > 0 ? ", " : "").htmlReady(get_fullname($user_id));
+ } ?>
+ <? endif ?>
+ </td>
+ <td width="20%">
+ <? if (count($date['groups']) && count($date['groups']) < $group_count) : ?>
+ <? foreach ($date['groups'] as $key => $statusgruppe_id) {
+ echo ($key > 0 ? ", " : "").htmlReady(Statusgruppen::find($statusgruppe_id)->name);
+ } ?>
+ <? else : ?>
+ <?= _("alle") ?>
+ <? endif ?>
+ </td>
+ <td width="20%"><?= htmlReady($date['room']) ?></td>
+ </tr>
+ <? if ($date['description']) : ?>
+ <tr>
+ <td>&nbsp;</td>
+ <td colspan="3"><?= formatReady($date['description'])?></td>
+ </tr>
+ <? endif ?>
+ <? endforeach ?>
+
+ </table>
+<? endif ?>
+</body>
+</html>
diff --git a/app/views/course/dates/index.php b/app/views/course/dates/index.php
new file mode 100644
index 0000000..2e2617e
--- /dev/null
+++ b/app/views/course/dates/index.php
@@ -0,0 +1,101 @@
+<?php
+ $lastSemester = null;
+ $allSemesters = [];
+ foreach ($dates as $key => $date) {
+ $currentSemester = Semester::findByTimestamp($date['date']);
+ if ($currentSemester && (
+ !$lastSemester ||
+ $currentSemester->getId() !== $lastSemester->getId()
+ )) {
+ $allSemesters[] = $currentSemester;
+ $lastSemester = $currentSemester;
+ }
+ }
+ $lostDateKeys = [];
+
+ if (!count($dates)) {
+ PageLayout::postMessage(
+ MessageBox::info(_('Keine Termine vorhanden'))
+ );
+ }
+?>
+
+<? foreach ($allSemesters as $semester): ?>
+<table class="dates default sortable-table <?= $has_access ? 'has-access' : '' ?>" data-sortlist="[[0, 0]]" data-table-id="<?= htmlReady($semester->id) ?>">
+ <caption><?= htmlReady($semester['name']) ?></caption>
+ <colgroup class="hidden-small-down">
+ <col width="25%">
+ <col width="40%">
+ <col width="10%">
+ <? if (count($course->statusgruppen) > 0): ?>
+ <col width="10%">
+ <? endif; ?>
+ <col width="10%">
+ <col width="5%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th data-sort="htmldata"><?= _('Zeit') ?></th>
+ <th data-sort="text" class="hidden-small-down"><?= _('Thema') ?></th>
+ <th data-sort="text" class="hidden-small-down"><?= _('Typ') ?></th>
+ <? if (count($course->statusgruppen)): ?>
+ <th data-sort="text" class="hidden-small-down"><?= _('Gruppen') ?></th>
+ <? endif; ?>
+ <th data-sort="text"><?= _('Raum') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php
+ // print dates
+ foreach ($dates as $key => $date) {
+ $dateSemester = Semester::findByTimestamp($date['date']);
+ if ($dateSemester && $semester->getId() === $dateSemester->getId()) {
+ if (is_null($is_next_date) && $date['end_time'] >= time() && !is_a($date, 'CourseExDate')) {
+ $is_next_date = $key;
+ }
+ $partial = $date instanceof CourseExDate ? '_date_row-exdate' : '_date_row';
+ echo $this->render_partial("course/dates/{$partial}.php", [
+ 'date' => $date,
+ 'is_next_date' => $is_next_date === $key,
+ 'course' => $course,
+ 'has_acces' => $has_access,
+ ]);
+ } elseif (!$dateSemester && !in_array($key, $lostDateKeys)) {
+ $lostDateKeys[] = $key;
+ }
+ }
+ ?>
+ </tbody>
+</table>
+<? endforeach; ?>
+
+<? if (count($lostDateKeys) > 0): ?>
+<table class="dates default sortable-table" data-sortlist="[[0, 0]]" data-table-id="none">
+ <caption><?= _('Ohne Semester') ?></caption>
+ <thead>
+ <tr>
+ <th data-sort="htmldata"><?= _('Zeit') ?></th>
+ <th data-sort="text" class="hidden-small-down"><?= _('Thema') ?></th>
+ <th data-sort="text" class="hidden-small-down"><?= _('Typ') ?></th>
+ <? if (count($course->statusgruppen)): ?>
+ <th data-sort="text" class="hidden-small-down"><?= _('Gruppen') ?></th>
+ <? endif; ?>
+ <th data-sort="text"><?= _('Raum') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php
+ foreach ($lostDateKeys as $key) {
+ $date = $dates[$key];
+ $partial = $date instanceof CourseExDate ? '_date_row-exdate' : '_date_row';
+ echo $this->render_partial(
+ "course/dates/{$partial}.php",
+ compact('date', 'dates', 'key')
+ );
+ }
+ ?>
+ </tbody>
+</table>
+<? endif; ?>
diff --git a/app/views/course/dates/new_topic.php b/app/views/course/dates/new_topic.php
new file mode 100644
index 0000000..af4cffa
--- /dev/null
+++ b/app/views/course/dates/new_topic.php
@@ -0,0 +1,48 @@
+<form action="<?= URLHelper::getLink("dispatch.php/course/dates") ?>" method="post" id="dates_add_topic" class="default">
+ <input type="hidden" name="termin_id" value="<?= $date->getId() ?>">
+ <fieldset>
+ <legend><?= _('Thema anlegen / verknüpfen') ?></legend>
+ <table class="default">
+ <tbody>
+ <tr>
+ <td><?= _("Termin") ?></td>
+ <td class="date_name"><?= htmlReady($date->getFullname()) ?></td>
+ </tr>
+ <tr>
+ <td><label for="topic_title"><?= _("Thema") ?></label></td>
+ <td>
+ <input type="text" class="topic_title" name="topic_title" id="topic_title" required>
+ <script>
+ jQuery(function () {
+ jQuery("#dates_add_topic .topic_title").autocomplete({
+ 'source': <?= json_encode($course->topics->pluck('title')) ?>,
+ 'select': function () {
+ jQuery("form#dates_add_topic").submit();
+ }
+ });
+ });
+ </script>
+ </td>
+ </tr>
+ <tr>
+ <td><?= _("Vorhandenes Thema verknüpfen") ?></td>
+ <td>
+ <ul class="clean">
+ <? foreach ($course->topics as $topic) : ?>
+ <li>
+ <a href="#" onClick="jQuery('#dates_add_topic .topic_title').val('<?= htmlReady($topic['title']) ?>'); jQuery('#dates_add_topic').submit(); return false;">
+ <?= Icon::create('arr_2up', 'clickable')->asImg() ?>
+ <?= htmlReady($topic['title']) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= \Studip\Button::create(_("Hinzufügen")) ?>
+ </footer>
+</form>
diff --git a/app/views/course/dates/singledate.php b/app/views/course/dates/singledate.php
new file mode 100644
index 0000000..130e900
--- /dev/null
+++ b/app/views/course/dates/singledate.php
@@ -0,0 +1,57 @@
+<form name="single_termin" class="default" action="<?= $controller->url_for("course/dates/singledate/" . htmlReady($date->getId())) ?>" method="POST" data-dialog>
+<?= CSRFProtection::tokenTag()?>
+ <fieldset>
+ <legend><?= _("Einzeltermin") ?></legend>
+
+ <label for="startDate">
+ <?= _('Datum des Termins') ?>
+ <input id="startDate" class="has-date-picker no-hint" name="startDate" type="text" maxlength="10" value="<?= !$date->date ? _('Datum') : date("d.m.Y", $date->date ); ?>">
+ </label>
+
+ <label for="startStunde" class="col-3">
+ <?= _('Startuhrzeit') ?>
+
+ <section class="hgroup">
+ <input id="startStunde" class="no-hint size-s" name="start_stunde" type="text" maxlength="2" size="2" value="<?= !$date->date ? "" : date("H", $date->date ); ?>"> :
+ <input id="startMinute" class="no-hint size-s" name="start_minute" type="text" maxlength="2" size="2" value="<?= !$date->date ? "" : date("i", $date->date ); ?>">
+ </section>
+
+ </label>
+
+ <label for="endStunde" class="col-3">
+ <?= _('Enduhrzeit') ?>
+
+ <section class="hgroup">
+ <input id="endStunde" class="no-hint size-s" name="end_stunde" type="text" maxlength="2" size="2" value="<?= !$date->end_time ? "" : date("H", $date->end_time ); ?>"> :
+ <input id="endMinute" class="no-hint size-s" name="end_minute" type="text" maxlength="2" size="2" value="<?= !$date->end_time ? "" : date("i", $date->end_time ); ?>">
+ </section>
+ </label>
+
+ <label>
+ <?= _('Art des Termins') ?>
+ <select name="dateType" >
+ <? foreach ($GLOBALS['TERMIN_TYP'] as $key => $val) : ?>
+ <option value="<?= $key ?>" <?= $date['date_typ'] == $key ? ' selected' : '' ?> > <?= htmlReady($val['name']) ?> </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Freie Ortsangabe (keine Raumbuchung)') ?>
+ <textarea name="freeRoomText_sd" style="width: 98%;" rows="3" ><?= htmlReady($date->raum) ?></textarea>
+ </label>
+ </fieldset>
+
+ <input type="hidden" name="singleDateID" value="<?= htmlReady($date->getId()) ?>">
+
+ <footer data-dialog-button>
+ <div class="button-group">
+ <? if (!$dates_locked) : ?>
+ <?= \Studip\Button::create(_('Termin Speichern'), "editSingleDate_button" ); ?>
+ <? endif ?>
+ <? if (!$cancelled_dates_locked && !$date->isNew()) : ?>
+ <?= \Studip\LinkButton::create(_("Ausfallen lassen"), $controller->url_for("course/cancel_dates", ['termin_id' => $date->getId()]), ['data-dialog' => '']) ?>
+ <? endif ?>
+ </div>
+ </footer>
+</form>
diff --git a/app/views/course/details/index.php b/app/views/course/details/index.php
new file mode 100644
index 0000000..7621519
--- /dev/null
+++ b/app/views/course/details/index.php
@@ -0,0 +1,506 @@
+<style>
+ /* This should be done by an own class (maybe not table? maybe dd?) */
+ #tablefix {
+ padding: 0;
+ }
+ #tablefix > header {
+ margin: 0px;
+ }
+ #tablefix table {
+ margin-bottom: 0;
+ border-bottom: 0;
+ }
+ #tablefix table tbody tr:last-child td {
+ border-bottom: 0;
+ }
+</style>
+
+<article class="studip" id="tablefix">
+ <header>
+ <h1><?= _('Allgemeine Informationen') ?></h1>
+ </header>
+ <table class="default">
+ <colgroup>
+ <col style="width: 40%">
+ <col style="width: 60%">
+ </colgroup>
+ <tbody>
+ <tr>
+ <td><strong><?= _('Veranstaltungsname') ?></strong></td>
+ <td><?= htmlReady($course->getFullName()) ?></td>
+ </tr>
+ <? if ($course->untertitel) : ?>
+ <tr>
+ <td><strong><?= _('Untertitel') ?></strong></td>
+ <td><?= htmlReady($course->untertitel) ?></td>
+ </tr>
+ <? endif ?>
+ <? if ($course->veranstaltungsnummer) : ?>
+ <tr>
+ <td><strong><?= _('Veranstaltungsnummer') ?></strong></td>
+ <td><?= htmlReady($course->veranstaltungsnummer) ?></td>
+ </tr>
+ <? endif ?>
+ <? if ($course->start_semester): ?>
+ <tr>
+ <td>
+ <strong><?= _('Semester') ?></strong>
+ </td>
+ <td>
+ <?= htmlReady($course->getFullname('sem-duration-name')) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <tr>
+ <td>
+ <strong><?= _('Aktuelle Anzahl der Teilnehmenden') ?></strong>
+ </td>
+ <td><?= $course->getNumParticipants() ?></td>
+ </tr>
+ <? if ($course->admission_turnout) : ?>
+ <tr>
+ <td>
+ <strong>
+ <? if ($sem->isAdmissionEnabled()) : ?>
+ <?= _('maximale Teilnehmendenanzahl') ?>
+ <? else : ?>
+ <?= _('erwartete Teilnehmendenanzahl') ?>
+ <? endif ?>
+ </strong>
+ </td>
+ <td><?= htmlReady($course->admission_turnout) ?></td>
+ </tr>
+ <? endif ?>
+ <? if ($sem->isAdmissionEnabled() && $course->getNumWaiting()) : ?>
+ <tr>
+ <td>
+ <strong><?= _('Wartelisteneinträge') ?></strong>
+ </td>
+ <td><?= $course->getNumWaiting() ?></td>
+ </tr>
+ <? endif ?>
+ <tr>
+ <td><strong><?= _("Heimat-Einrichtung") ?></strong></td>
+ <td>
+ <a href="<?= URLHelper::getScriptLink("dispatch.php/institute/overview", ['auswahl' => $course->institut_id]) ?>">
+ <?= htmlReady($course->home_institut->name) ?>
+ </a>
+ </td>
+ </tr>
+ <? if ($course->institutes->count() > 1): ?>
+ <tr>
+ <td>
+ <strong><?= _('beteiligte Einrichtungen') ?></strong>
+ </td>
+ <td>
+ <?= join(', ', $course->institutes
+ ->findBy('institut_id', $course->institut_id, '<>')
+ ->orderBy('name')
+ ->map(function($i) {
+ return sprintf('<a href="%s">%s</a>', URLHelper::getScriptLink("dispatch.php/institute/overview", ['auswahl' => $i->id])
+ , htmlReady($i->name));
+ })
+ ) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <tr>
+ <td><strong><?= _("Veranstaltungstyp") ?></strong></td>
+ <td>
+ <?= sprintf(_("%s in der Kategorie %s"), $course->getSemType()->offsetGet('name'), $course->getSemClass()->offsetGet('name')) ?>
+ </td>
+ </tr>
+ <? if ($course->parent) : ?>
+ <tr>
+ <td><strong><?= _('Hauptveranstaltung') ?></strong></td>
+ <td>
+ <?= _('Diese Veranstaltung gehört zu einer Hauptveranstaltung') ?>:
+ <br><br>
+ <a href="<?= $controller->link_for('course/details/', ['sem_id' => $course->parent->id]) ?>"
+ title="<?= htmlReady($course->parent->getFullname()) ?>">
+ <?= htmlReady($course->parent->getFullname()) ?>
+ </a>
+ <? if (count($siblings) > 0) : ?>
+ <br><br>
+ <section>
+ <?= _('Ebenfalls zu dieser Hauptveranstaltung gehören:') ?>
+ <ul>
+ <? foreach ($siblings as $sibling): ?>
+ <li>
+ <a href="<?= $controller->link_for('course/details/', ['sem_id' => $sibling->id]) ?>"
+ title="<?= htmlReady($sibling->getFullname()) ?>">
+ <?= htmlReady($sibling->getFullname()) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </section>
+ <? endif ?>
+ </td>
+ </tr>
+ <? elseif ($children) : ?>
+ <tr>
+ <td><strong><?= _('Unterveranstaltungen') ?></strong></td>
+ <td>
+ <?= _('Dies ist eine Hauptveranstaltung mit folgenden Unterveranstaltungen:') ?>
+ <ul>
+ <? foreach ($children as $child): ?>
+ <li>
+ <a href="<?= $controller->link_for('course/details/', ['sem_id' => $child->id]) ?>"
+ title="<?= htmlReady($child->getFullname()) ?>">
+ <?= htmlReady($child->getFullname()) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </td>
+ </tr>
+ <? endif ?>
+
+ <? if ($prelim_discussion) : ?>
+ <tr>
+ <td><strong><?= _('Vorbesprechung') ?></strong></td>
+ <td><?= $prelim_discussion ?></td>
+ </tr>
+ <? endif ?>
+ <? $next_date = $sem->getNextDate() ?>
+ <? if ($next_date) : ?>
+ <tr>
+ <td><strong><?= _('Nächster Termin') ?></strong></td>
+ <td><?= $next_date ?></td>
+ </tr>
+ <? else : ?>
+ <? $firstTerm = $sem->getFirstDate() ?>
+ <? if ($firstTerm) : ?>
+ <tr>
+ <td><strong><?= _('Erster Termin') ?></strong></td>
+ <td><?= $firstTerm ?></td>
+ </tr>
+ <? endif ?>
+ <? endif ?>
+ <? if ($course->art) : ?>
+ <tr>
+ <td><strong><?= _("Art/Form") ?></strong></td>
+ <td><?= htmlReady($course->art) ?></td>
+ </tr>
+ <? endif ?>
+ <? if ($course->teilnehmer != "") : ?>
+ <tr>
+ <td><strong><?= _("Teilnehmende") ?></strong></td>
+ <td>
+ <?= htmlReady($course->teilnehmer, true, true) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? if ($course->vorrausetzungen != "") : ?>
+ <tr>
+ <td><strong><?= _("Voraussetzungen") ?></strong></td>
+ <td>
+ <?= htmlReady($course->vorrausetzungen, true, true) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? if ($course->lernorga != "") : ?>
+ <tr>
+ <td><strong><?= _("Lernorganisation") ?></strong></td>
+ <td>
+ <?= htmlReady($course->lernorga, true, true) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? if ($course->leistungsnachweis != "") : ?>
+ <tr>
+ <td><strong><?= _("Leistungsnachweis") ?></strong></td>
+ <td>
+ <?= htmlReady($course->leistungsnachweis, true, true) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? foreach ($course->datafields->getTypedDatafield() as $entry) : ?>
+ <? if ($entry->isVisible() && $entry->getValue()) : ?>
+ <tr>
+ <td><strong><?= htmlReady($entry->getName()) ?></strong></td>
+ <td>
+ <?= $entry->getDisplayValue() ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? endforeach ?>
+ <? if ($course->sonstiges != "") : ?>
+ <tr>
+ <td><strong><?= _("Sonstiges") ?></strong></td>
+ <td>
+ <?= formatLinks($course->sonstiges) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? if ($course->ects) : ?>
+ <tr>
+ <td><strong><?= _("ECTS-Punkte") ?></strong></td>
+ <td>
+ <?= htmlReady($course->ects, true, true) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+</article>
+
+<? $lecturers = $course->getMembersWithStatus('dozent'); ?>
+<? $count_lecturers = count($lecturers); ?>
+<? if ($count_lecturers) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= htmlReady(get_title_for_status('dozent', $count_lecturers, $course->status))?></h1>
+ </header>
+ <section>
+ <ul class="list-csv">
+ <? foreach ($lecturers as $lecturer) : ?>
+ <li>
+ <a href="<?= URLHelper::getScriptLink('dispatch.php/profile', ['username' => $lecturer['username']]) ?>">
+ <?= htmlReady($lecturer->getUserFullname() . ($lecturer->label ? " (" . $lecturer->label . ")" : "")) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </section>
+ </article>
+<? endif ?>
+
+<? $tutors = $course->getMembersWithStatus('tutor'); ?>
+<? $count_tutors = count($tutors); ?>
+<? if ($count_tutors) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= htmlReady(get_title_for_status('tutor', $count_tutors, $course->status)) ?></h1>
+ </header>
+ <section>
+ <ul class="list-csv">
+ <? foreach ($tutors as $tutor) : ?>
+ <li>
+ <a href="<?= URLHelper::getScriptLink('dispatch.php/profile', ['username' => $tutor['username']]) ?>">
+ <?= htmlReady($tutor->getUserFullname() . ($tutor->label ? " (" . $tutor->label . ")" : "")) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </section>
+ </article>
+<? endif ?>
+
+<? if (CourseConfig::get($course->id)->COURSE_PUBLIC_TOPICS && count($course->topics)) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _("Themen") ?></h1>
+ </header>
+ <section>
+ <? foreach ($course->topics as $key => $topic) {
+ if ($key > 0) {
+ echo ", ";
+ }
+ echo " ".htmlReady($topic['title']);
+ } ?>
+ </section>
+ </article>
+<? endif ?>
+
+<? if (isset($public_files)) : ?>
+ <?= $this->render_partial('profile/public_files') ?>
+<? endif ?>
+
+<article class="studip">
+ <header>
+ <h1><?= _('Veranstaltungsort') ?> / <?= _('Veranstaltungszeiten')?></h1>
+ </header>
+ <section>
+ <?= $sem->getDatesTemplate(
+ 'dates/seminar_html_location',
+ ['ort' => $course->ort, 'disable_list_shrinking' => true]
+ ) ?>
+ </section>
+</article>
+<? if ($this->studymodules) : ?>
+
+ <article class="studip">
+ <header>
+ <h1><?= _('Studienmodule') ?></h1>
+ </header>
+ <section>
+ <ul class="list-unstyled">
+ <? foreach ($this->studymodules as $module) : ?>
+ <li>
+ <a class="module-info" href="<?= URLHelper::getLink($module['nav']->getUrl())?>">
+ <?= htmlReady($module['title']) ?>
+ <? if ($module['nav']->getImage()) : ?>
+ <?= $module['nav']->getImage()->asImg($module['nav']->getLinkAttributes()) ?>
+ <? endif ?>
+ <span><?= htmlReady($module['nav']->getTitle())?></span>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </section>
+ </article>
+<? endif ?>
+
+<? if ($studyAreaTree && $studyAreaTree->required_children) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _('Studienbereiche') ?></h1>
+ </header>
+ <section>
+ <ul class="collapsable css-tree">
+ <?= $this->render_partial(
+ 'study_area/tree.php',
+ [
+ 'node' => $studyAreaTree,
+ 'open' => true,
+ 'dont_open' => Config::get()->COURSE_SEM_TREE_CLOSED_LEVELS
+ ]
+ ) ?>
+ </ul>
+ </section>
+ </article>
+<? endif ?>
+
+<? if ($study_areas && count($study_areas) > 0) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _('Studienbereiche') ?></h1>
+ </header>
+ <section>
+ <ul class="list-unstyled">
+ <? foreach ($study_areas as $area) : ?>
+ <li>
+ <a href="<?=URLHelper::getScriptLink('show_bereich.php?level=sbb&id=' . $area->id)?>">
+ <?= htmlReady($area->getPath(' > ')) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </section>
+ </article>
+<? endif ?>
+
+<?
+// Ausgabe der Modulzuordnung MVV
+if ($mvv_tree) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _('Modulzuordnungen') ?></h1>
+ </header>
+ <section>
+ <ul class="collapsable css-tree">
+ <?= $this->render_partial(
+ 'shared/mvv_tree.php',
+ ['tree' => $mvv_tree, 'node' => 'start', 'id_sfx' => $id_sfx]
+ ) ?>
+ </ul>
+ </section>
+ </article>
+<? endif; ?>
+
+<? if ($mvv_pathes) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _('Modulzuordnungen') ?></h1>
+ </header>
+ <section>
+ <ul class="list-unstyled">
+ <? foreach ($mvv_pathes as $mvv_path) : ?>
+ <li>
+ <a data-dialog href="<?= URLHelper::getScriptLink('dispatch.php/search/module/overview/' . reset(array_keys($mvv_path)) . '/' . $course->start_semester->id) ?>">
+ <?= htmlReady(implode(' > ', reset(array_values($mvv_path)))) ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </section>
+ </article>
+<? endif; ?>
+
+<? if (trim($course->beschreibung)) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _("Kommentar/Beschreibung") ?></h1>
+ </header>
+ <section>
+ <?= formatLinks($course->beschreibung) ?>
+ </section>
+ </article>
+<? endif ?>
+
+<? if ($courseset = $sem->getCourseSet()) : ?>
+ <article class="studip">
+ <header>
+ <h1><?=_("Anmelderegeln")?></h1>
+ </header>
+ <section>
+ <div>
+ <?= sprintf(_('Diese Veranstaltung gehört zum Anmeldeset "%s".'), htmlReady($courseset->getName())) ?>
+ </div>
+ <div id="courseset_<?= $courseset->getId() ?>">
+ <?= $courseset->toString(true) ?>
+ </div>
+ </section>
+ </article>
+<? endif ?>
+
+<? if ($course->admission_prelim == 1 || $course->admission_binding == 1) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _('Anmeldemodus') ?></h1>
+ </header>
+ <? if ($course->admission_prelim == 1) : ?>
+ <section>
+ <p><?= _("Die Auswahl der Teilnehmenden wird nach der Eintragung manuell vorgenommen.") ?></p>
+ <? if ($course->admission_prelim_txt) : ?>
+ <p><?= formatReady($course->admission_prelim_txt) ?></p>
+ <? else : ?>
+ <p><?=
+ _("Nutzer/-innen, die sich für diese Veranstaltung eintragen möchten,
+ erhalten nähere Hinweise und können sich dann noch gegen eine Teilnahme entscheiden.")?>
+ </p>
+ <? endif ?>
+ </section>
+ <? endif ?>
+ <? if ($course->admission_binding == 1) : ?>
+ <section>
+ <p><?= _("Die Anmeldung ist verbindlich, Teilnehmende können sich nicht selbst austragen.") ?></p>
+ </section>
+ <? endif ?>
+ </article>
+<? endif ?>
+
+<? if (!empty($course_domains)): ?>
+ <article class="studip">
+ <header>
+ <h1><?= _("Zugelassenene Nutzerdomänen:") ?></h1>
+ </header>
+ <ul>
+ <? foreach ($course_domains as $domain): ?>
+ <li><?= htmlReady($domain->name) ?></li>
+ <? endforeach ?>
+ </ul>
+ </article>
+<? endif ?>
+
+<? foreach (PluginManager::getInstance()->getPlugins('DetailspagePlugin') as $plugin) : ?>
+ <? $template = $plugin->getDetailspageTemplate($course) ?>
+ <? if ($template) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= htmlReady($template->title) ?></h1>
+ </header>
+ <?= $template->render() ?>
+ </article>
+ <? endif ?>
+<? endforeach ?>
+
+
+<? if (Request::get('from')) : ?>
+ <footer data-dialog-button>
+ <?= \Studip\LinkButton::createCancel(_('Zurück'), URLHelper::getURL(Request::get('from')))?>
+ </footer>
+<? endif ?>
+<?= Feedback::getHTML($course->id, 'Course'); ?>
diff --git a/app/views/course/elearning/edit.php b/app/views/course/elearning/edit.php
new file mode 100644
index 0000000..ede07fd
--- /dev/null
+++ b/app/views/course/elearning/edit.php
@@ -0,0 +1,142 @@
+<?php use Studip\Button, Studip\LinkButton; ?>
+<!--h2><?= _('Lernmodule hinzufügen / entfernen') ?></h2-->
+
+<? if ($elearning_active) : ?>
+ <?=ELearningUtils::getCMSSelectbox(_("Um Lernmodule hinzuzufügen, wählen Sie ein angebundenes System aus:"))?>
+
+ <? if (!count($content_modules)) : ?>
+ <? if (is_array($course_output['courses']) && count($course_output['courses'])) : ?>
+ <?=$course_output['text']?><br>
+ <? foreach ($course_output['courses'] as $course) : ?>
+ <a href="<?= $course['url'] ?>" target="_blank" rel="noopener noreferrer">
+ <?=sprintf(_('Kurs in %s'), $course['cms_name'])?>
+ </a>
+ <br>
+ <? endforeach ?>
+ <? endif ?>
+ <? else : ?>
+ <?foreach ($content_modules as $module) : ?>
+ <? if ($module['show_header']) : ?>
+ <?=ELearningUtils::getModuleHeader(_("Angebundene Lernmodule"))?>
+ <? endif ?>
+ <?=$module['module']?>
+ <br>
+ <? endforeach ?>
+ <? endif ?>
+ <br>
+ <? if ($cms_select) : ?>
+ <br>
+ <?=ELearningUtils::getCMSHeader($cms_name)?>
+ <br>
+ <? if (count($user_modules)) : ?>
+ <?=ELearningUtils::getModuleHeader(sprintf(_("Ihre Lernmodule in %s"), $cms_name))?>
+ <?foreach ($user_modules as $module) : ?>
+ <?=$module['module']?>
+ <br>
+ <? endforeach ?>
+ <? endif ?>
+ <? if ($show_search) : ?>
+ <br>
+ <? if ($anker_target == "search") : ?>
+ <a name='anker'></a>
+ <? endif ?>
+
+ <?=ELearningUtils::getSearchfield(
+ sprintf(_("Um im System %s nach Lernmodulen zu suchen, geben Sie einen Suchbegriff ein:"),
+ $cms_name))?>
+ <br>
+ <? if (count($search_modules)) : ?>
+ <?=ELearningUtils::getHeader( sprintf( _("Gefundene Lernmodule zum Suchbegriff \"%s\""), htmlReady($search_key) ))?>
+ <? foreach ($search_modules as $module) : ?>
+ <?=$module['module']?>
+ <br>
+ <? endforeach ?>
+ <br>
+ <? elseif (mb_strlen( trim($search_key) ) > 2) : ?>
+ <br>
+ <b><?=sprintf( _("Es gibt im System %s zu diesem Suchbegriff keine Lernmodule."), $cms_name)?></b><br>
+ <br>
+ <? endif ?>
+ <? else : ?>
+ <br>
+ <div class="messagebox messagebox_info" style="background-image: none; padding-left: 15px">
+ <?=sprintf(_('Sie können im System %s nicht suchen, da Sie bisher keinen Benutzer-Account angelegt haben.'),
+ $cms_name)?><br>
+ <a href="<?=URLHelper::getLink('dispatch.php/elearning/my_accounts')?>">
+ <?=_('Jetzt einen Account erstellen.')?><br>
+ </a>
+ </div>
+ <? endif ?>
+ <? if ($show_ilias_empty_course) : ?>
+ <form method="POST" action="<?=URLHelper::getLink() . "#anker"?>">
+ <?=CSRFProtection::tokenTag()?>
+ <?=ELearningUtils::getHeader(_("Leeren Kurs anlegen"))?>
+ <div align="center">
+ <br>
+ <?=_('Hier können Sie einen leeren Ilias-Kurs für diese Veranstaltung anlegen. Die Teilnehmenden '
+ .'der Veranstaltung können dann den Kurs betreten, auch wenn noch keine Lernmodule zugeordnet sind. '
+ .'Solange der Kurs leer ist, erscheint auf der Seite "Meine Veranstaltungen und Einrichtungen" kein '
+ .'Lernmodulsymbol für diese Veranstaltung. <b>Dieser Schritt kann nicht rückgängig gemacht werden.</b>')?>
+ <br>
+ <br>
+ <input type="HIDDEN" name="anker_target" value="search">
+ <input type="HIDDEN" name="view" value="<?=$view?>">
+ <input type="HIDDEN" name="cms_select" value="<?=$cms_select?>">
+ <?=Button::create(_('Anlegen'), 'create_course')?>
+ <br>
+ <br>
+ </div>
+ </form>
+ <? endif ?>
+ <? if (count($existing_courses)) : ?>
+ <form method="POST" action="<?=URLHelper::getLink() . "#anker"?>>
+ <?=CSRFProtection::tokenTag()?>
+ <?=ELearningUtils::getHeader(_("Verknüpfung mit einem bestehenden Kurs"))?>
+ <div align="center">
+ <br>
+ <?_('Wenn Sie die Veranstaltung mit einem bestehenden Ilias-Kurs verbinden wollen, wählen Sie hier '
+ .'die Stud.IP-Veranstaltung, mit der der bestehende Kurs verknüpft ist. Beide Stud.IP-Veranstaltungen '
+ .'sind dann mit dem selben Ilias-Kurs verknüpft. <b>Dieser Schritt kann nicht rückgängig gemacht werden.</b>')?>
+ <br>
+ <br>
+ <select name="connect_course_sem_id" size="1">
+ <option value="">
+ <?=_("Bitte auswählen")?>
+ </option>
+ <? foreach ($existing_courses as $key => $name) : ?>
+ <option value="<?=$key?>">
+ <?=$name?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <input type="HIDDEN" name="anker_target" value="search">
+ <input type="HIDDEN" name="view" value="<?=$view?>">
+ <input type="HIDDEN" name="cms_select" value="<?=$cms_select?>">
+ <?=Button::create(_('Auswählen'), 'connect_course')?>
+ <br>
+ </div>
+ </form>
+ <br>
+ <? endif ?>
+ <? if ($show_ilias_link_info) : ?>
+ <br>
+ <?=ELearningUtils::getHeader(_("Links zu anderen ILIAS-Objekten"))?>
+ <div align="center">
+ <br>
+ <?=_('Sie können beliebige weitere Objekte hinzufügen, indem Sie im verknüpften Kurs in ILIAS einen '
+ .'internen Link zu den entsprechenden Objekten anlegen. '
+ .'Wechseln Sie dazu in den Kurs, wählen Sie unter "Neues Objekt hinzufügen" die Option Weblink und legen '
+ .'einen Link innerhalb von ILIAS an. Kehren Sie anschließend auf diese Seite zurück und klicken Sie in der Infobox '
+ .'auf "Aktualisieren". Für die auf diese Weise verlinkten Objekte müssen Sie selbst sicherstellen, dass die Teilnehmenden '
+ .'des Kurses Zugriff darauf haben.')?>
+ <br>
+ <br>
+ </div>
+ <? endif ?>
+ <?=ELearningUtils::getCMSFooter($cms_logo)?>
+ <br>
+ <? if ($anker_target == "choose") : ?>
+ <a name='anker'></a>
+ <? endif ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/course/elearning/show.php b/app/views/course/elearning/show.php
new file mode 100644
index 0000000..b5ec294
--- /dev/null
+++ b/app/views/course/elearning/show.php
@@ -0,0 +1,42 @@
+<?php use Studip\Button, Studip\LinkButton; ?>
+<? if ($is_inst) : ?>
+ <!--h2><?= _('Lernmodule der Einrichtung') ?></h2-->
+<? else : ?>
+ <!--h2><?= _('Lernmodule der Veranstaltung') ?></h2-->
+<? endif ?>
+<? if ($elearning_active) : ?>
+ <? if ($new_account) : ?>
+ <?=ELearningUtils::getNewAccountForm($new_account)?>
+ <? else : ?>
+ <? if (!count($content_modules) AND count($course_output['courses'])) : ?>
+ <br>
+ <div class="messagebox messagebox_info" style="background-image: none; padding-left: 15px">
+ <?=$course_output['text']?><br>
+ <? foreach ($course_output['courses'] as $course) : ?>
+ <a href="<?= $course['url'] ?>" target="_blank" rel="noopener noreferrer">
+ <?= sprintf(_('Kurs in %s'), $course['cms_name']) ?>
+ </a>
+ <br>
+ <? endforeach ?>
+ </div>
+ <? elseif (count($content_modules)) : ?>
+ <?foreach ($content_modules as $module) : ?>
+ <? if ($module['show_header']) : ?>
+ <?=ELearningUtils::getModuleHeader(_("Angebundene Lernmodule"))?>
+ <? endif ?>
+ <?=$module['module']?>
+ <br>
+ <? endforeach ?>
+ <br>
+ <? if (count($course_output['courses'])) : ?>
+ <?=$course_output['text']?><br>
+ <? foreach ($course_output['courses'] as $course) : ?>
+ <a href="<?= $course['url'] ?>" target="_blank" rel="noopener noreferrer">
+ <?= sprintf(_('Kurs in %s'), $course['cms_name']) ?>
+ </a>
+ <br>
+ <? endforeach ?>
+ <? endif ?>
+ <? endif ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/course/enrolment/_priocourses.php b/app/views/course/enrolment/_priocourses.php
new file mode 100644
index 0000000..749a19c
--- /dev/null
+++ b/app/views/course/enrolment/_priocourses.php
@@ -0,0 +1,134 @@
+<?php
+$prios = [];
+foreach ($priocourses as $prio => $course) {
+ $name = $course->name;
+ if (Config::get()->IMPORTANT_SEMNUMBER) {
+ $name = $course->veranstaltungsnummer . ' ' . $name;
+ }
+ $tooltxt = [];
+ $tooltxt[] = $course->veranstaltungsnummer;
+ $tooltxt[] = $course->name;
+ $tooltxt[] = implode(', ', $course->members->findBy('status', 'dozent')->orderBy('position')->limit(3)->pluck('Nachname'));
+ $tooltxt[] = implode('; ', $course->cycles->toString());
+
+ $prios[$course->id] = [
+ 'name' => $name,
+ 'info' => implode("\n", $tooltxt),
+ 'selected' => isset($user_prio[$course->id]),
+ ];
+}
+
+asort($user_prio);
+?>
+
+<div id="enrollment">
+<? if ($max_limit > 1): ?>
+ <label for="admission_user_limit">
+ <?= _('Ich möchte folgende Anzahl an Veranstaltungen belegen:') ?>
+ <select name="admission_user_limit" class="size-s">
+ <? foreach (range(1, $max_limit) as $max) : ?>
+ <option <? if ($user_max_limit == $max) echo 'selected'; ?>>
+ <?= $max ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+<? endif; ?>
+
+ <p class="hidden-medium-down">
+ <?= _('Ziehen Sie die in Frage kommenden Veranstaltungen auf die rechte Seite '
+ . 'und ordnen Sie sie dort in der Reihenfolge der von Ihnen gewünschten '
+ . 'Priorität an. Sie können mehr Veranstaltungen nach rechts ziehen als Sie '
+ . 'tatsächlich belegen wollen.') ?>
+ </p>
+ <p class="hidden-medium-up">
+ <?= _('Sortieren Sie die in Frage kommenden Veranstaltungen auf die rechte Seite '
+ . 'und ordnen Sie sie dort in der Reihenfolge der von Ihnen gewünschten '
+ . 'Priorität an. Sie können mehr Veranstaltungen nach rechts zuweisen als Sie '
+ . 'tatsächlich belegen wollen.') ?>
+ </p>
+
+ <section class="priority-lists">
+
+ <div class="available">
+ <h3> <?= _("Verfügbare Veranstaltungen") ?></h3>
+ <input type="text" name="filter" placeholder="<?= _('Filter') ?>">
+
+ <ul id="available-courses">
+ <? foreach ($prios as $course_id => $data): ?>
+ <li <? if (!$data['selected']) echo 'class="visible"'; ?> data-id="<?= htmlReady($course_id) ?>">
+ <?= htmlReady($data['name']) ?>
+ <? if ($data['info']): ?>
+ <?= tooltipIcon($data['info']) ?>
+ <? endif; ?>
+ <div class="actions hidden-medium-up">
+ <?= Icon::create('accept')->asInput([
+ 'name' => 'admission_prio[' . htmlReady($course_id) . ']',
+ 'type' => 'submit',
+ 'value' => 0,
+ ]) ?>
+ </div>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+
+ <div class="selected">
+ <h3><?= _('Ausgewählte Veranstaltungen') ?></h3>
+ <input type="text" name="filter" placeholder="<?= _('Filter') ?>">
+ <ul id="selected-courses">
+ <li class="empty">
+ <span class="hidden-medium-up">
+ <?= _('Die gewünschten Veranstaltungen links auswählen') ?>
+ </span>
+ <span class="hidden-medium-down">
+ <?= _('Gewünschte Veranstaltungen hierhin ziehen') ?>
+ </span>
+ </li>
+ <? foreach ($user_prio as $id => $prio): ?>
+ <li data-id="<?= htmlReady($id) ?>">
+ <?= htmlReady($prios[$id]['name']) ?>
+ <? if ($data['info']): ?>
+ <?= tooltipIcon($prios[$id]['info']) ?>
+ <? endif; ?>
+
+ <input type="hidden" value="<?= $prio ?>" name="admission_prio[<?= htmlReady($id) ?>]">
+
+ <div class="actions">
+ <? if ($prio != 1): ?>
+ <?= Icon::create('arr_1up', Icon::ROLE_SORT)->asInput([
+ 'name' => 'admission_prio_order_up[' . htmlReady($id) . ']',
+ 'type' => 'submit',
+ 'class' => 'hidden-medium-up',
+ ]) ?>
+ <? endif; ?>
+
+ <? if ($prio != count($user_prio)): ?>
+ <?= Icon::create('arr_1down', Icon::ROLE_SORT)->asInput([
+ 'name' => 'admission_prio_order_down[' . htmlReady($id) . ']',
+ 'type' => 'submit',
+ 'class' => 'hidden-medium-up',
+ ])?>
+ <? endif; ?>
+
+ <?= Icon::create('trash')->asInput([
+ 'name' => 'admission_prio_delete[' . htmlReady($id) . ']',
+ 'type' => 'submit',
+ 'class' => 'delete',
+ ]) ?>
+ </div>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+
+ </section>
+</div>
+
+<script type="text/x-template" id="delete-icon-template">
+ <div class="actions">
+ <a class="delete" href="#">
+ <?= Icon::create('trash') ?>
+ </a>
+ </div>
+</script>
diff --git a/app/views/course/enrolment/apply.php b/app/views/course/enrolment/apply.php
new file mode 100644
index 0000000..9951808
--- /dev/null
+++ b/app/views/course/enrolment/apply.php
@@ -0,0 +1,63 @@
+<?= $admission_error ?>
+<? if ($courseset_message) : ?>
+<p>
+ <?= $courseset_message ?>
+</p>
+<? endif ?>
+<? foreach(PageLayout::getMessages() as $pm) : ?>
+ <?= $pm ?>
+<? endforeach; ?>
+
+<? if ($admission_form): ?>
+ <form name="apply_admission" action="<?= $controller->link_for("/apply/{$course_id}") ?>" method="post">
+ <?= $admission_form ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('OK'), 'apply', ['data-dialog' => 'size=big']) ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel') ?>
+ </div>
+ <?= CSRFProtection::tokenTag() ?>
+ </form>
+<? elseif ($priocourses): ?>
+ <form name="claim_admission" action="<?= $controller->link_for("/claim/{$course_id}") ?>" method="post" class="default">
+ <? if (is_array($priocourses)): ?>
+ <?= $this->render_partial('course/enrolment/_priocourses.php') ?>
+
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'claim', ['data-dialog' => 'size=big']) ?>
+ <?= Studip\Button::createCancel(_('Schließen'), 'cancel') ?>
+ </div>
+ <? else : ?>
+ <input type="hidden" name="courseset_claimed" value="<?= $already_claimed ? 0 : 1 ?>" >
+ <div>
+ (<?= sprintf(_("max. Teilnehmendenanzahl: %s / Anzahl der Anmeldungen: %s"), $priocourses->admission_turnout, $num_claiming) ?>)
+ </div>
+
+ <div data-dialog-button>
+ <? if (!$already_claimed) :?>
+ <?= Studip\Button::createAccept(_('Zur Platzverteilung anmelden'), 'claim', ['data-dialog' => 'size=big']); ?>
+ <? else : ?>
+ <?= Studip\Button::create(_('Von der Platzverteilung abmelden'), 'claim', ['data-dialog' => 'size=big']); ?>
+ <? endif ?>
+
+ <?= Studip\Button::createCancel(_('Schließen'), 'cancel') ?>
+ </div>
+ <? endif ?>
+ <?= CSRFProtection::tokenTag() ?>
+ </form>
+<? elseif (!$enrol_user): ?>
+ <div data-dialog-button>
+ <?= Studip\LinkButton::createAccept(
+ _('OK'),
+ URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $course_id])
+ ) ?>
+ </div>
+<? elseif ($confimed): ?>
+ <div data-dialog-button>
+ <?=Studip\LinkButton::createAccept(
+ _('Zur Veranstaltung'),
+ URLHelper::getLink('seminar_main.php', ['auswahl' => $course_id])
+ ) ?>
+ </div>
+<? endif ?>
+
+<script>STUDIP.enrollment();</script>
diff --git a/app/views/course/enrolment/prelim.php b/app/views/course/enrolment/prelim.php
new file mode 100644
index 0000000..672bc36
--- /dev/null
+++ b/app/views/course/enrolment/prelim.php
@@ -0,0 +1,18 @@
+<div>
+ <?=_("Um endgültig in die Veranstaltung aufgenommen zu werden, müssen Sie noch weitere Voraussetzungen erfüllen.")?>
+</div>
+<div>
+ <?=_("Lesen Sie bitte folgenden Hinweistext:")?>
+</div>
+<br>
+<div>
+ <?=formatReady($admission_prelim_txt)?>
+</div>
+<? if ($admission_prelim_comment) : ?>
+ <br>
+ <label for="admission_comment">
+ <?=_("Bemerkungen zu Teilnahmevoraussetzungen:")?>
+ </label>
+ <br>
+ <textarea name="admission_comment" id="admission_comment" cols="50" rows="5"></textarea>
+<? endif ?>
diff --git a/app/views/course/feedback/_add_edit_entry_form.php b/app/views/course/feedback/_add_edit_entry_form.php
new file mode 100644
index 0000000..80bec1f
--- /dev/null
+++ b/app/views/course/feedback/_add_edit_entry_form.php
@@ -0,0 +1,28 @@
+<? if ($feedback->mode != 0) : ?>
+<?php
+ $n = 5;
+ if ($feedback->mode == 2) {
+ $n = 10;
+ }
+ ?>
+<div class="rating">
+ <p><?= _('Bewertung') ?></p>
+ <? for ($i = 1; $i < $n+1; $i++) : ?>
+ <label class="star-rating undecorated <?= $i <= $entry->rating || $i === 1 ? ' checked' : '' ?>">
+ <input class="star-rating-input" name="rating" value="<?= $i ?>" type="radio"
+ <?= $i == $entry->rating ? ' selected' : '' ?> required/>
+ <?= Icon::create('star', 'clickable') ?>
+ </label>
+ <? endfor; ?>
+</div>
+<? endif; ?>
+<? if ($feedback->commentable == 1) : ?>
+<label>
+ <?= _('Kommentar') ?>
+ <textarea name="comment"><?= htmlReady($entry->comment) ?></textarea>
+</label>
+<? endif; ?>
+<div>
+ <?= Studip\Button::createAccept(_('Absenden'), 'add', ['class' => 'feedback-entry-submit']) ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['class' => 'feedback-entry-cancel']) ?>
+</div>
diff --git a/app/views/course/feedback/_entry.php b/app/views/course/feedback/_entry.php
new file mode 100644
index 0000000..b58fcd2
--- /dev/null
+++ b/app/views/course/feedback/_entry.php
@@ -0,0 +1,48 @@
+<article class="studip feedback-entry" data-id="<?= $entry->id ?>">
+ <header>
+ <h1>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $entry->user->username) ?>">
+ <?= Avatar::getAvatar($entry->user_id)->getImageTag(Avatar::SMALL) ?>
+ <?= $entry->user->getFullName(); ?>
+ </a>
+ </h1>
+ <nav>
+ <? if ($entry->isEditable()) : ?>
+ <a href="<?= $controller->link_for('course/feedback/entry_edit_form/' . $entry->id) ?>"
+ title="<?= _('Bearbeiten') ?>" data-dialog="size=auto"
+ class="feedback-entry-edit" >
+ <?= Icon::create('edit'); ?>
+ </a>
+ <? endif; ?>
+ <? if ($entry->isDeletable()) : ?>
+ <a href="<?= $controller->link_for('course/feedback/entry_delete/' . $entry->id) ?>"
+ title="<?= _('Löschen') ?>" data-dialog="size=auto"
+ data-confirm="<?= _('Feedback löschen?') ?>"
+ class="feedback-entry-delete"
+ onclick="return STUDIP.Dialog.confirmAsPost($(this).attr('data-confirm'), this.href);">
+ <?= Icon::create('trash'); ?>
+ </a>
+ <? endif; ?>
+ </nav>
+ </header>
+ <? if ($entry->feedback->mode != 0) : ?>
+ <div class="rating">
+ <span title="<?= $entry->rating ?>">
+ <? for ($i=0; $i < $entry->feedback->getMaxRating(); $i++) : ?>
+ <?= ($i >= $entry->rating) ? Icon::create('star-empty', 'info') : Icon::create('star', 'info') ?>
+ <? endfor; ?>
+ </span>
+ </div>
+ <? endif; ?>
+ <div class="comment">
+ <?= htmlReady($entry->comment) ?>
+ </div>
+ <div class="date">
+ <span title="<?= strftime('%x %X', $entry->chdate) ?>">
+ <? if ($entry->chdate != $entry->mkdate) : ?>
+ <?= _('Bearbeitet:') ?>
+ <? endif; ?>
+ <?= $entry->chdate ? reltime($entry->chdate) : "" ?>
+ </span>
+ </div>
+</article>
diff --git a/app/views/course/feedback/_feedback.php b/app/views/course/feedback/_feedback.php
new file mode 100644
index 0000000..6d46f3c
--- /dev/null
+++ b/app/views/course/feedback/_feedback.php
@@ -0,0 +1,47 @@
+<? if ($feedback->description != '') : ?>
+<section class="feedback-description">
+ <h2><?= _('Beschreibung') ?></h2>
+ <p><?= formatReady($feedback->description) ?></p>
+</section>
+<? endif; ?>
+<? if (($feedback->results_visible == 1 && !$feedback->isFeedbackable()) || $admin_perm) : ?>
+ <?= $this->render_partial('course/feedback/_results.php' , ['feedback' => $feedback]) ?>
+<? endif; ?>
+<? if ($feedback->getOwnEntry()) : ?>
+<section class="feedback-entries">
+ <h2><?= _('Mein Feedback') ?></h2>
+ <?= $this->render_partial('course/feedback/_entry.php' , ['entry' => $feedback->getOwnEntry()]) ?>
+</section>
+<? endif; ?>
+<? if (
+ count($feedback->entries) > 0
+ && (($feedback->results_visible == 1
+ && !$feedback->isFeedbackable())
+ || $admin_perm)
+ ) : ?>
+<section class="feedback-entries">
+ <h2>
+ <? if (
+ !$feedback->isOwner()
+ && !$feedback->isFeedbackable()
+ ) : ?>
+ <?= _('Andere Einträge') ?>
+ <? else : ?>
+ <?= _('Einträge') ?>
+ <? endif; ?>
+ </h2>
+ <? foreach($feedback->entries as $entry) : ?>
+ <? if ($entry->user_id !== $GLOBALS['user']->id) : ?>
+ <?= $this->render_partial('course/feedback/_entry.php' , ['entry' => $entry]) ?>
+ <? endif; ?>
+ <? endforeach; ?>
+</section>
+<? endif; ?>
+<? if ($feedback->isFeedbackable()) : ?>
+<form method="post" class="default feedback-entry-add"
+ action="<?= $controller->link_for('course/feedback/entry_add', $feedback->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <h2><?= _('Feedback geben') ?></h2>
+ <?= $this->render_partial('course/feedback/_add_edit_entry_form.php' , ['feedback' => $feedback]) ?>
+</form>
+<? endif; ?>
diff --git a/app/views/course/feedback/_feedback_stream.php b/app/views/course/feedback/_feedback_stream.php
new file mode 100644
index 0000000..888b463
--- /dev/null
+++ b/app/views/course/feedback/_feedback_stream.php
@@ -0,0 +1,36 @@
+<article class="studip toggle feedback-stream" id="feedback-stream-<?= $feedback->id ?>" data-id="<?= $feedback->id ?>">
+ <header>
+ <h1>
+ <a href="<?= $controller->link_for('course/feedback/view/' . $feedback->id) ?>">
+ <? if ($feedback->mode != 0 && ((!$feedback->isFeedbackable() && $feedback->results_visible == 1) || $admin_perm) && count($feedback->entries) > 0) : ?>
+ <?= Icon::create('star') ?>
+ <span class="mean"><?= $feedback->getMeanOfRating() ?></span>
+ <? endif; ?>
+ <?= htmlReady($feedback->question) ?>
+ </a>
+
+ <? if ($feedback->isOwner()) : ?>
+ <?= Icon::create('decline', 'info', ['title' => _('Das Feedback-Element wurde von Ihnen erstellt, daher können Sie kein Feedback geben'),]); ?>
+ <? elseif (!$feedback->isFeedbackable()) : ?>
+ <?= Icon::create('accept', 'status-green', ['title' => _('Bereits Feedback gegeben'),]); ?>
+ <? endif; ?>
+ </h1>
+ <? if ($admin_perm) : ?>
+ <nav>
+ <a href="<?= $controller->link_for('course/feedback/edit_form/' . $feedback->id) ?>"
+ title="<?= _('Bearbeiten') ?>" class="feedback-edit" data-id="<?= $feedback->id ?>"
+ data-dialog="">
+ <?= Icon::create('edit') ?>
+ </a>
+ <a href="<?= $controller->link_for('course/feedback/delete/' . $feedback->id) ?>" title="<?= _('Löschen') ?>"
+ class="feedback-delete" data-id="<?= $feedback->id ?>"
+ data-confirm="<?= _('Feedback-Element und dazugehörige Einträge löschen?') ?>">
+ <?= Icon::create('trash') ?>
+ </a>
+ </nav>
+ <? endif; ?>
+ </header>
+ <div class="feedback-view">
+ <?= $this->render_partial('course/feedback/_feedback.php' , ['feedback' => $feedback]) ?>
+ </div>
+</article> \ No newline at end of file
diff --git a/app/views/course/feedback/_new_edit_feedback_form.php b/app/views/course/feedback/_new_edit_feedback_form.php
new file mode 100644
index 0000000..e39fed4
--- /dev/null
+++ b/app/views/course/feedback/_new_edit_feedback_form.php
@@ -0,0 +1,46 @@
+<fieldset>
+ <legend>
+ <?= _('Grundeigenschaften') ?>
+ </legend>
+ <label>
+ <?= _('Fragestellung') ?>
+ <input required type="text" name="question" placeholder="<?= _('Frage') ?>"
+ value="<?= htmlReady($feedback->question); ?>">
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description" class="add_toolbar wysiwyg"
+ placeholder="<?= _('Optionale Beschreibung') ?>"><?= wysiwygReady($feedback->description); ?></textarea>
+ </label>
+ <label>
+ <input type="checkbox" name="results_visible" value="1" <?= $feedback->results_visible == 1 ? 'checked' : '' ?>>
+ <?= _('Feedback Ergebnisse nach Antwort sichtbar') ?>
+ </label>
+ <label>
+ <input id="comment-activated" type="checkbox" name="commentable" value="1" <? if ($this->current_action ==
+ 'edit_form') {echo ('disabled');} else { echo('data-activates="#comment-only"');}?>
+ <?= $feedback->commentable == 1 ? 'checked' : '' ?>>
+ <?= _('Abgegebenes Feedback kann einen Kommentar beinhalten') ?>
+ </label>
+ <label>
+ <input id="comment-only" type="checkbox" name="comment_only" value="1"
+ <?= $feedback->mode == 0 ? 'checked' : '' ?> <? if ($this->current_action ==
+ 'edit_form') {echo ('disabled');} else { echo('data-deactivates="#comment-activated, .feedback-mode"');}?>>
+ <?= _('Nur Kommentare (keine numerische Bewertung)') ?>
+ </label>
+</fieldset>
+<fieldset>
+ <legend>
+ <?= _('Bewertungsmodus') ?>
+ </legend>
+ <label>
+ <input class="feedback-mode" type="radio" name="mode" value="1" <?= $feedback->mode == 1 ? 'checked' : '' ?>
+ required <? if ($this->current_action ==
+ 'edit_form') {echo ('disabled');}?>><?= _('Sternbewertung von 1 bis 5') ?>
+ </label>
+ <label>
+ <input class="feedback-mode" type="radio" name="mode" value="2" <?= $feedback->mode == 2 ? 'checked' : '' ?> <?
+ if ($this->current_action ==
+ 'edit_form') {echo ('disabled');}?>><?= _('Sternbewertung von 1 bis 10') ?>
+ </label>
+</fieldset> \ No newline at end of file
diff --git a/app/views/course/feedback/_results.php b/app/views/course/feedback/_results.php
new file mode 100644
index 0000000..21e5cb1
--- /dev/null
+++ b/app/views/course/feedback/_results.php
@@ -0,0 +1,63 @@
+<? $entries_count = count($feedback->entries); ?>
+<section class="feedback-results">
+ <h2><?= _('Ergebnisse') ?></h2>
+ <? if ($entries_count == 0 ) {
+ print(_('Bisher wurde kein Feedback gegeben.'));
+ } ?>
+ <? if ($feedback->mode == 0) {
+ printf(_('Insgesamt wurde %s mal Feedback gegeben.'), $entries_count);
+ } ?>
+ <? if ($entries_count >= 1 && $feedback->mode != 0) : ?>
+ <?
+ $rating_scale = 5;
+ if ($feedback->mode == 2) {$rating_scale = 10;}
+ ?>
+ <div class="ratings">
+ <table class="default sortable-table feedback" data-sortlist="[[1, 1]]">
+ <colgroup>
+ <col>
+ <col width="15%">
+ <col width="15%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th data-sort="text"><?=_('Prozent')?></th>
+ <th data-sort="htmldata"><?=_('Bewertung')?></th>
+ <th data-sort="text"><?=_('Anzahl')?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? for ($i = 1; $i < $rating_scale+1; $i++) : ?>
+ <tr>
+ <td data-sort-value="<?= $feedback->getPercentageOfRating($i) ?>">
+ <div class="percentage">
+ <div class="percentage-bar" style="width: <?= $feedback->getPercentageOfRating($i) . '%' ?>;">
+ <?= $feedback->getPercentageOfRating($i) . '%' ?>
+ </div>
+ </div>
+ </td>
+ <td data-sort-value="<?= $i ?>">
+ <?= $i ?>
+ <?=Icon::create('star') ?>
+ </td>
+ <td>
+ <?= $feedback->getCountOfRating($i) ?>
+ </td>
+ </tr>
+ <? endfor; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <?= _('Durchschnitt: ') ?>
+ <?= $feedback->getMeanOfRating(); ?>
+ </td>
+ <td>
+ <strong><?= $entries_count ?></strong>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+ <? endif; ?>
+</section>
diff --git a/app/views/course/feedback/config.php b/app/views/course/feedback/config.php
new file mode 100644
index 0000000..5c12a7d
--- /dev/null
+++ b/app/views/course/feedback/config.php
@@ -0,0 +1,33 @@
+<form method="post" class="default" action="<?= $controller->url_for('course/feedback/config') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <label>
+ <span><?= _('Wer darf neue Feedback-Elemente anlegen?')?></span>
+ <select name="create_perm_level">
+ <option value="autor" <?= $create_perm_level == "autor" ? 'selected' : '' ?>>
+ <?= _('Studierende') ?>
+ </option>
+ <option value="tutor" <?= $create_perm_level == "tutor" ? 'selected' : '' ?>>
+ <?= _('Tutoren') ?></option>
+ <option value="dozent" <?= $create_perm_level == "dozent" ? 'selected' : '' ?>>
+ <?= _('Dozierende') ?>
+ </option>
+ </select>
+ </label>
+ <label>
+ <span><?= _('Wer darf Feedback-Elemente und Einträge verwalten?')?></span>
+ <select name="admin_perm_level">
+ <option value="autor" <?= $admin_perm_level == "autor" ? 'selected' : '' ?>>
+ <?= _('Studierende') ?>
+ </option>
+ <option value="tutor" <?= $admin_perm_level == "tutor" ? 'selected' : '' ?>>
+ <?= _('Tutoren') ?>
+ </option>
+ <option value="dozent" <?= $admin_perm_level == "dozent" ? 'selected' : '' ?>>
+ <?= _('Dozierende') ?>
+ </option>
+ </select>
+ </label>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ </div>
+</form>
diff --git a/app/views/course/feedback/create_form.php b/app/views/course/feedback/create_form.php
new file mode 100644
index 0000000..0636a6b
--- /dev/null
+++ b/app/views/course/feedback/create_form.php
@@ -0,0 +1,8 @@
+<form method="post" class="default" action="<?= $controller->link_for('course/feedback/create' , $feedback->range_id, $feedback->range_type) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('course/feedback/_new_edit_feedback_form.php') ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Erstellen')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen')) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/course/feedback/edit_form.php b/app/views/course/feedback/edit_form.php
new file mode 100644
index 0000000..9eb67d7
--- /dev/null
+++ b/app/views/course/feedback/edit_form.php
@@ -0,0 +1,8 @@
+<form method="post" class="default" action="<?= $controller->link_for('course/feedback/edit', $feedback->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('course/feedback/_new_edit_feedback_form.php', ['feedback' => $feedback]) ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\Button::createCancel() ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/course/feedback/entry_edit_form.php b/app/views/course/feedback/entry_edit_form.php
new file mode 100644
index 0000000..400b3ce
--- /dev/null
+++ b/app/views/course/feedback/entry_edit_form.php
@@ -0,0 +1,6 @@
+<form method="post" class="default feedback-entry-add"
+ action="<?= $controller->link_for('course/feedback/entry_edit', $entry->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <h2><?= _('Feedback bearbeiten') ?></h2>
+ <?= $this->render_partial('course/feedback/_add_edit_entry_form.php' , ['entry' => $entry, 'feedback' => $feedback]) ?>
+</form> \ No newline at end of file
diff --git a/app/views/course/feedback/index.php b/app/views/course/feedback/index.php
new file mode 100644
index 0000000..1f4aa22
--- /dev/null
+++ b/app/views/course/feedback/index.php
@@ -0,0 +1,116 @@
+<? if (empty($feedback_elements)): ?>
+ <?= MessageBox::info(_('Es wurden noch Feedback-Elemente angelegt.')) ?>
+<? else: ?>
+<table class="default feedback sortable-table" data-sortlist="[[6, 1]]">
+ <caption>
+ <div class="caption-container">
+ <?= _('Feedback-Elemente') ?>
+ </div>
+ </caption>
+ <colgroup>
+ <col width="50px" class="responsive-hidden">
+ <col>
+ <col width="80px" class="responsive-hidden">
+ <col width="100px" class="responsive-hidden">
+ <col width="100px">
+ <col width="150px" class="responsive-hidden">
+ <col width="120px">
+ <col width="80px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th data-sort="htmldata" class="responsive-hidden">
+ <?= _('Kontext') ?>
+ </th>
+ <th data-sort="text">
+ <?= _('Fragestellung') ?>
+ </th>
+ <th data-sort="htmldata">
+ <?= _('Ergebnis') ?>
+ </th>
+ <th data-sort="text" class="responsive-hidden">
+ <?= _('Einträge') ?>
+ </th>
+ <th data-sort="text" class="responsive-hidden">
+ <?= _('Modus') ?>
+ </th>
+ <th data-sort="text" class="responsive-hidden">
+ <?= _('Autor/-in') ?>
+ </th>
+ <th data-sort="htmldata">
+ <?= _('Datum') ?>
+ </th>
+ <th data-sort="false">
+ <?= _('Aktionen') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach($feedback_elements as $feedback) : ?>
+ <?php $range = $feedback->getRange(); ?>
+ <tr>
+ <td data-sort-value="<?= crc32($feedback->range_type) ?>" class="responsive-hidden">
+ <a href="<?= $controller->link_for($range->getRangeUrl()) ?>"
+ title="<?= $range->getRangeName() ?>">
+ <?= $range->getRangeIcon('clickable') ?>
+ </a>
+ </td>
+ <td data-sort="<?= htmlReady($feedback->question) ?>">
+ <a href="<?= $controller->link_for('course/feedback/view/' . $feedback->id) ?>" data-dialog="auto">
+ <?= htmlReady($feedback->question) ?>
+ <? if ($feedback->isOwner()) : ?>
+ <?= Icon::create('decline', 'info', ['title' => _('Das Feedback-Element wurde von Ihnen erstellt, daher können Sie kein Feedback abgeben'),]); ?>
+ <? elseif (!$feedback->isFeedbackable()) : ?>
+ <?= Icon::create('accept', 'status-green', ['title' => _('Bereits Feedback gegeben'),]); ?>
+ <? endif; ?>
+ </a>
+ </td>
+ <td>
+ <?php if (count($feedback->entries) >= 1 && $feedback->mode != 0) {
+ echo $feedback->getMeanOfRating();
+ }
+ ?>
+ </td>
+ <td class="responsive-hidden">
+ <?= count($feedback->entries) ?>
+ </td>
+ <td data-sort-value="<?= $feedback->mode ?>" class="responsive-hidden">
+ <? if($feedback->mode == 1) : ?>
+ <?= Icon::create('star', Icon::ROLE_INFO) ?> (1-5)
+ <? elseif($feedback->mode == 2): ?>
+ <?= Icon::create('star', Icon::ROLE_INFO) ?> (1-10)
+ <? else: ?>
+ <?= _('Kommentar') ?>
+ <? endif; ?>
+ </td>
+ <td data-sort-value="<?= $feedback->user->getFullName('no_title_rev') ?>" class="responsive-hidden">
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $feedback->user->username) ?>">
+ <?= $feedback->user->getFullName('no_title_rev') ?>
+ </a>
+ </td>
+ <td title="<?= strftime('%x %X', $feedback->chdate) ?>" data-sort-value="<?= $feedback->chdate ?>">
+ <?= $feedback->chdate ? reltime($feedback->chdate) : "" ?>
+ </td>
+ <td class="actions">
+ <?php
+ $actionMenu = ActionMenu::get();
+ $actionMenu->addLink(
+ $controller->link_for('course/feedback/edit_form/' . $feedback->id),
+ _('Feedback-Element bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE, ['size' => 20]),
+ ['data-dialog' => '']
+ );
+ $actionMenu->addLink(
+ $controller->link_for('course/feedback/delete/' . $feedback->id),
+ _('Feedback-Element löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, ['size' => 20]),
+ ['onclick' => "return STUDIP.Dialog.confirmAsPost('" . _('Feedback-Element und dazugehörige Einträge löschen?') . "', this.href);"]
+ );
+ ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+</table>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/course/feedback/index_for.php b/app/views/course/feedback/index_for.php
new file mode 100644
index 0000000..7e27bfd
--- /dev/null
+++ b/app/views/course/feedback/index_for.php
@@ -0,0 +1,22 @@
+<? if (!empty($feedback_elements)) : ?>
+<article class="studip">
+ <header>
+ <h1>
+ <?= Icon::create('star','info') ?>
+ <?= _('Feedback') ?>
+ </h1>
+ <? if($create_perm) : ?>
+ <nav>
+ <a href="<?= $controller->link_for('course/feedback/create_form/' . $range_id . '/' . $range_type) ?>"
+ title="<?= _('Neues Feedback-Element') ?>" class="feedback-add" data-id="<?= $feedback->id ?>"
+ data-dialog="">
+ <?= Icon::create('add'); ?>
+ </a>
+ </nav>
+ <? endif; ?>
+ </header>
+ <? foreach($feedback_elements as $feedback) : ?>
+ <?= $this->render_partial('course/feedback/_feedback_stream.php' , ['feedback' => $feedback]) ?>
+ <? endforeach; ?>
+</article>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/course/gradebook/_progress.php b/app/views/course/gradebook/_progress.php
new file mode 100644
index 0000000..459dfa1
--- /dev/null
+++ b/app/views/course/gradebook/_progress.php
@@ -0,0 +1,3 @@
+<div class="progress">
+ <div class="progress-bar" role="progressbar" style="width: <?= (int) $value ?>%;" aria-valuenow="<?= (int) $value?>" aria-valuemin="0" aria-valuemax="100"><?= (int) $value ?>%</div>
+</div>
diff --git a/app/views/course/gradebook/lecturers/_weight.php b/app/views/course/gradebook/lecturers/_weight.php
new file mode 100644
index 0000000..c14ba82
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/_weight.php
@@ -0,0 +1,7 @@
+<label class="gradebook-weight">
+ <?= htmlReady($definition->name) ?>
+ <div>
+ <input type="number" id="definition-<?= $definition->id ?>" name="definitions[<?= $definition->id ?>]" value="<?= htmlReady($definition->weight) ?>" min="0" max="1000000">
+ <output name="weight-percent" for="definition-<?= $definition->id ?>"><?= $this->controller->formatAsPercent($this->controller->getNormalizedWeight($definition)) ?></output>
+ </div>
+</label>
diff --git a/app/views/course/gradebook/lecturers/custom_definitions.php b/app/views/course/gradebook/lecturers/custom_definitions.php
new file mode 100644
index 0000000..864aa0d
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/custom_definitions.php
@@ -0,0 +1,74 @@
+<form class="default" action="<?= $controller->link_for('course/gradebook/lecturers/store_grades') ?>" method="POST">
+ <?= CSRFProtection::tokenTag()?>
+ <div style="overflow-x:auto;">
+ <table class="default gradebook-lecturer-custom-definitions">
+ <caption>
+ <?= _('Noten manuell erfassen') ?>
+ </caption>
+
+ <thead>
+ <tr class="tablesorter-ignoreRow">
+ <th><?= _('Name') ?></th>
+ <? if (count($customDefinitions)) { ?>
+ <? foreach ($customDefinitions as $definition) { ?>
+ <th>
+ <?= htmlReady($definition->name) ?>
+ </th>
+ <? } ?>
+ <? } else { ?>
+ <th>&nbsp;</th>
+ <? } ?>
+ </tr>
+ </thead>
+
+ <tbody>
+
+ <? foreach ($students as $index => $student) { ?>
+ <tr>
+ <td class="gradebook-student-name" data-sort-value="<?= $studentName = htmlReady(htmlReady($student->nachname . ', ' . $student->vorname)) ?>">
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $student->username]) ?>">
+ <?= $studentName ?>
+ </a>
+ </td>
+ <? if (count($customDefinitions)) { ?>
+ <? foreach ($customDefinitions as $definition) { ?>
+ <td class="gradebook-grade-input">
+ <? $instance = $controller->getInstanceForUser($definition, $student) ?>
+ <? $rawgrade = $instance ? $instance->rawgrade : 0 ?>
+ <label class="undecorated">
+ <input type="number"
+ name="grades[<?= htmlReady($student->user_id) ?>][<?= htmlReady($definition->id) ?>]"
+ value="<?= $controller->formatAsPercent($rawgrade) ?>"
+ min="0"> %
+ </label>
+
+ </td>
+ <? } ?>
+ <? } elseif ($index === 0) { ?>
+ <td rowspan="<?= count($students) ?>" class="gradebook-lecturer-blank-slate">
+ <p><?= _('Es sind keine manuellen Leistungen definiert.') ?></p>
+ </td>
+ <? } ?>
+ </tr>
+ <? } ?>
+
+ </tbody>
+
+ <? if (count($customDefinitions) && count($students)) { ?>
+ <? $tfootColspan = 1 + count($customDefinitions) ?>
+ <tfoot class="gradebook-lecturer-custom-definitions-actions">
+ <tr>
+ <td colspan="<?= $tfootColspan ?>">
+ <?= \Studip\Button::createAccept(_('Speichern')) ?>
+ <?= \Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/gradebook/lecturers')) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? } ?>
+ </table>
+ </div>
+</form>
+
+<? if (!count($students)) { ?>
+ <?= \MessageBox::info(_('Es gibt noch keine Teilnehmer.')) ?>
+<? } ?>
diff --git a/app/views/course/gradebook/lecturers/edit_custom_definition.php b/app/views/course/gradebook/lecturers/edit_custom_definition.php
new file mode 100644
index 0000000..ba9716d
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/edit_custom_definition.php
@@ -0,0 +1,14 @@
+<form class="default" action="<?= $controller->link_for('course/gradebook/lecturers/update_custom_definition', $definition->id) ?>" method="POST">
+ <?= CSRFProtection::tokenTag()?>
+ <fieldset>
+ <label>
+ <?= _('Name der Leistung') ?>
+ <input type="text" name="name" value="<?= htmlReady($definition->name) ?>" required>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= \Studip\Button::createAccept(_('Speichern')) ?>
+ <?= \Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/gradebook/lecturers/custom_definitions')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/gradebook/lecturers/edit_custom_definitions.php b/app/views/course/gradebook/lecturers/edit_custom_definitions.php
new file mode 100644
index 0000000..dbb3454
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/edit_custom_definitions.php
@@ -0,0 +1,66 @@
+<table class="default">
+ <caption>
+ <?= _('Manuelle Leistungen definieren') ?>
+ </caption>
+
+ <thead>
+ <tr class="tablesorter-ignoreRow">
+ <th><?= _('Name') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+
+ <? if (count($customDefinitions)) { ?>
+ <tbody>
+ <? foreach ($customDefinitions as $definition) { ?>
+ <tr>
+ <td>
+ <?= htmlReady($definition->name) ?>
+ </td>
+ <td class="actions">
+ <?=
+ \ActionMenu::get()
+ ->addLink(
+ $controller->url_for(
+ 'course/gradebook/lecturers/edit_custom_definition',
+ $definition->id
+ ),
+ _('Ändern'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=fit']
+ )
+ ->addLink(
+ $controller->url_for(
+ 'course/gradebook/lecturers/delete_custom_definition',
+ $definition->id
+ ),
+ _('Löschen'),
+ Icon::create('trash'),
+ ['onclick' => "return STUDIP.Dialog.confirmAsPost('" . _('Wollen Sie die Leistungsdefinition wirklich löschen?') . "', this.href);"]
+ ) ?>
+ </td>
+ </tr>
+ <? } ?>
+ </tbody>
+ <? } else { ?>
+ <tbody>
+ <tr>
+ <td colspan="2">
+ <?= \MessageBox::info(_('Es sind keine manuellen Leistungen definiert.')) ?>
+ </td>
+ </tbody>
+ <? } ?>
+
+
+ <tfoot class="gradebook-lecturer-custom-definitions-actions">
+ <tr>
+ <td colspan="2">
+ <?= \Studip\LinkButton::createAdd(
+ count($customDefinitions) ? _('Weitere Leistung definieren') : _('Leistung definieren'),
+ $controller->url_for('course/gradebook/lecturers/new_custom_definition'),
+ ['data-dialog' => 'size=fit']
+ ) ?>
+ </td>
+ </tr>
+ </tfoot>
+</table>
diff --git a/app/views/course/gradebook/lecturers/index.php b/app/views/course/gradebook/lecturers/index.php
new file mode 100644
index 0000000..62ebfcc
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/index.php
@@ -0,0 +1,74 @@
+<table class="default sortable-table gradebook-lecturer-overview" data-sortlist="[[0, 0]]">
+
+ <caption><?= _('Erbrachte Leistungen') ?></caption>
+
+ <colgroup>
+ <col class="gradebook-column-name">
+ <col class="gradebook-column-total">
+ </colgroup>
+
+ <? foreach ($categories as $i => $category) { ?>
+ <colgroup class="gradebook-column-category" span="<?= count($groupedDefinitions[$category]) ?>"/>
+ <? } ?>
+
+ <thead>
+ <tr class="tablesorter-ignoreRow">
+ <th>&nbsp;</th>
+ <th>&nbsp;</th>
+ <? foreach ($categories as $category) { ?>
+ <th colspan="<?= count($groupedDefinitions[$category]) ?>"><?= $controller->formatCategory($category) ?></th>
+ <? } ?>
+ </tr>
+
+ <tr class="sortable">
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="text"><?= _('Gesamtsumme') ?></th>
+
+ <? foreach ($categories as $category) { ?>
+ <? foreach ($groupedDefinitions[$category] as $definition) { ?>
+ <th data-sort="text" class="gradebook-lecturer-overview-definition">
+ <?= htmlReady($definition->name) ?>
+ <span class="gradebook-definition-weight">(<?= $controller->formatAsPercent($controller->getNormalizedWeight($definition)) ?> %)</span>
+ </th>
+ <? } ?>
+ <? } ?>
+ </tr>
+
+ </thead>
+
+ <tbody>
+ <? if (count($students)) { ?>
+ <? foreach ($students as $student) { ?>
+ <tr>
+ <td class="gradebook-student-name" data-sort-value="<?= $studentName = htmlReady($student->nachname . ', ' . $student->vorname) ?>">
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $student->username]) ?>">
+ <?= $studentName ?>
+ </a>
+ </td>
+ <? $totalSum = isset($totalSums[$student->user_id]) ? $totalSums[$student->user_id] : 0 ?>
+ <td data-sort-value="<?= $totalSum?>">
+ <?= $controller->formatAsPercent($totalSum) ?> %
+ </td>
+
+ <? foreach ($categories as $category) { ?>
+ <? foreach ($groupedDefinitions[$category] as $definition) { ?>
+ <? $instance = $controller->getInstanceForUser($definition, $student) ?>
+ <? $rawgrade = $instance ? $instance->rawgrade : 0 ?>
+ <td data-sort-value="<? $rawgrade ?>">
+ <?= $controller->formatAsPercent($rawgrade) ?> %
+ </td>
+ <? } ?>
+ <? } ?>
+ </tr>
+ <? } ?>
+ <? } ?>
+ </tbody>
+</table>
+
+<? if (!count($categories)) { ?>
+ <?= \MessageBox::info(_('Es wurden noch keine Leistungen definiert.')) ?>
+<? } ?>
+
+<? if (!count($students)) { ?>
+ <?= \MessageBox::info(_('Es gibt noch keine Teilnehmer.')) ?>
+<? } ?>
diff --git a/app/views/course/gradebook/lecturers/new_custom_definition.php b/app/views/course/gradebook/lecturers/new_custom_definition.php
new file mode 100644
index 0000000..cbecac4
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/new_custom_definition.php
@@ -0,0 +1,14 @@
+<form class="default" action="<?= $controller->link_for('course/gradebook/lecturers/create_custom_definition') ?>" method="POST">
+ <?= CSRFProtection::tokenTag()?>
+ <fieldset>
+ <label>
+ <?= _('Name der Leistung') ?>
+ <input type="text" name="name" required>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= \Studip\Button::createAccept(_('Speichern')) ?>
+ <?= \Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/gradebook/lecturers/custom_definitions')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/gradebook/lecturers/weights.php b/app/views/course/gradebook/lecturers/weights.php
new file mode 100644
index 0000000..ee54b41
--- /dev/null
+++ b/app/views/course/gradebook/lecturers/weights.php
@@ -0,0 +1,27 @@
+<? if (!count($categories)) { ?>
+ <?= \MessageBox::info(_('Es wurden noch keine Leistungen definiert.')) ?>
+<? } else { ?>
+
+ <form class="default gradebook-lecturer-weights" action="<?= $controller->link_for('course/gradebook/lecturers/store_weights') ?>" method="POST">
+ <?= CSRFProtection::tokenTag()?>
+ <span class="content-title"><?= _('Gewichtungen') ?></span>
+
+ <? foreach ($categories as $category) { ?>
+ <fieldset>
+
+ <legend><?= $controller->formatCategory($category) ?></legend>
+
+ <? foreach ($groupedDefinitions[$category] as $definition) { ?>
+ <?= $this->render_partial('course/gradebook/lecturers/_weight', compact('definition')) ?>
+ <? } ?>
+
+ </fieldset>
+ <? } ?>
+
+ <footer>
+ <?= \Studip\Button::createAccept(_('Speichern')) ?>
+ <?= \Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/gradebook/lecturers')) ?>
+ </footer>
+ </form>
+
+<? } ?> \ No newline at end of file
diff --git a/app/views/course/gradebook/students/index.php b/app/views/course/gradebook/students/index.php
new file mode 100644
index 0000000..ac4c370
--- /dev/null
+++ b/app/views/course/gradebook/students/index.php
@@ -0,0 +1,58 @@
+<article class="gradebook-student">
+ <header>
+ <h1><?= _("Gesamt") ?></h1>
+ <?= $this->render_partial("course/gradebook/_progress", ['value' => $controller->formatAsPercent($total)])?>
+ </header>
+
+ <? foreach ($categories as $category) { ?>
+ <section class="gradebook-student-category">
+ <header>
+ <h2><?= $controller->formatCategory($category) ?></h2>
+ <?= $this->render_partial("course/gradebook/_progress", ['value' => $controller->formatAsPercent($subtotals[$category])])?>
+ </header>
+
+ <table class="default">
+ <colgroup>
+ <col width="200px" />
+ <col width="150px" />
+ <col width="100px" />
+ <col />
+ </colgroup>
+
+ <thead>
+ <tr>
+ <th>&nbsp;</th>
+ <th><?= _("Tool") ?></th>
+ <th><?= _("Gewichtung") ?></th>
+ <th><?= _("Feedback") ?></th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <?
+ foreach ($groupedDefinitions[$category] as $definition) {
+ $instance = $groupedInstances[$definition->id];
+ $grade = $controller->formatAsPercent($instance ? $instance->rawgrade : 0);
+ $feedback = $instance ? $instance->feedback : '';
+ ?>
+ <tr>
+ <td>
+ <span class="gradebook-definition-name"><?= htmlReady($definition->name) ?></span>
+ <?= $this->render_partial("course/gradebook/_progress", ['value' => (int) $grade])?>
+ </td>
+ <td>
+ <?= htmlReady($definition->tool) ?>
+ </td>
+ <td>
+ <?= $controller->formatAsPercent($controller->getNormalizedWeight($definition)) ?>%
+ </td>
+ <td>
+ <?= htmlReady($feedback) ?>
+ </td>
+ </tr>
+ <? } ?>
+ </tbody>
+ </table>
+ </section>
+ <? } ?>
+</article>
diff --git a/app/views/course/grouping/_perm_level.php b/app/views/course/grouping/_perm_level.php
new file mode 100644
index 0000000..37f1080
--- /dev/null
+++ b/app/views/course/grouping/_perm_level.php
@@ -0,0 +1,137 @@
+<? if (count($members) > 0) : ?>
+ <table class="default">
+ <caption>
+ <?= htmlReady($level === 'deputy' ? _('Vertretung') : get_title_for_status($level, count($members), $current->status)) ?>
+ <span class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write', [
+ 'rec_uname' => $members->pluck('username'),
+ 'default_subject' => '[' . $current->getFullname() . ']',
+ ]),
+ _('Nachricht schicken'),
+ Icon::create('mail', Icon::ROLE_CLICKABLE, ['title' => _('Nachricht schicken')]),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </span>
+ </caption>
+ <colgroup>
+ <? if (count($members) > 1) : ?>
+ <col width="60">
+ <? endif ?>
+ <col width="10">
+ <col>
+ <col width="20">
+ </colgroup>
+ <thead>
+ <tr>
+ <? if (count($members) > 1) : ?>
+ <th>
+ <label>
+ <input type="checkbox" data-proxyfor=":checkbox.members-<?= $current->id ?>-<?= $level ?>">
+ <?= _('Alle') ?>
+ </label>
+ </th>
+ <? endif ?>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $i = 0;
+ foreach ($members as $m) : ?>
+ <tr>
+ <? if (count($members) > 1) : ?>
+ <td>
+ <input type="checkbox" name="members[<?= $current->id ?>][<?= $level ?>][]"
+ value="<?= $m->user_id ?>" class="members-<?= $current->id ?>-<?= $level ?>"
+ data-activates="#actions-<?= $current->id ?>_<?= $level ?>">
+ </td>
+ <? endif ?>
+ <td>
+ <?= sprintf('%02u', ++$i) ?>
+ </td>
+ <td>
+ <? if ($level === 'deputy'): ?>
+ <?= htmlReady($m->getDeputyFullname('full_rev')) ?>
+ <? else: ?>
+ <?= htmlReady($m->getUserFullname('full_rev')) ?>
+ <? endif; ?>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write', [
+ 'rec_uname' => $m->user_id,
+ 'default_subject' => '[' . $current->getFullname() . ']'
+ ]),
+ _('Nachricht schicken'),
+ Icon::create('mail', Icon::ROLE_CLICKABLE, ['title' => _('Nachricht schicken')]),
+ ['data-dialog' => 'size=auto']
+ ); ?>
+ <? if ($level !== 'dozent' || count($members) > 1) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for(
+ 'course/grouping/move_members_target',
+ $current->id,
+ $m->user_id
+ ),
+ _('In andere Unterveranstaltung verschieben'),
+ Icon::create('arr_2right', Icon::ROLE_CLICKABLE, ['title' => _('In andere Unterveranstaltung verschieben')]),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/grouping/remove_members', $current->id, $m->user_id),
+ _('Aus Veranstaltung austragen'),
+ Icon::create('door-leave', Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(
+ _('%s austragen'),
+ $level === 'deputy'
+ ? $m->getDeputyFullname('full_rev')
+ : $m->getUserFullname('full_rev')
+ )
+ ])
+ ) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <? if (count($members) > 1) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <label>
+ <input type="checkbox" data-proxyfor=":checkbox.members-<?= $current->id ?>-<?= $level ?>"
+ data-activates="#actions-<?= $current->id ?>-<?= $level ?>">
+ <?= _('Alle') ?>
+ </label>
+ </td>
+ <td colspan="2" class="actions">
+ <select id="actions-<?= $current->id ?>-<?= $level ?>"
+ name="selected_single_action_<?= $current->id ?>_<?= $level ?>">
+ <option value="message">
+ <?= _('Nachricht schicken') ?>
+ </option>
+ <option value="move">
+ <?= _('In andere Unterveranstaltung verschieben') ?>
+ </option>
+ <option value="remove">
+ <?= _('Austragen') ?>
+ </option>
+ </select>
+ <?= Studip\Button::createAccept(
+ _('Ausführen'),
+ 'single_action',
+ ['value' => $current->id . '-' . $level]
+ ) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+<? endif ?>
diff --git a/app/views/course/grouping/child_course_members.php b/app/views/course/grouping/child_course_members.php
new file mode 100644
index 0000000..791b231
--- /dev/null
+++ b/app/views/course/grouping/child_course_members.php
@@ -0,0 +1,21 @@
+<?= $this->render_partial('course/grouping/_perm_level', [
+ 'level' => 'dozent',
+ 'current' => $child,
+ 'members' => $child->members->findBy('status', 'dozent')->orderBy('nachname, vorname'),
+]) ?>
+<?= $this->render_partial('course/grouping/_perm_level', [
+ 'level' => 'deputy',
+ 'current' => $child,
+ 'members' => SimpleORMapCollection::createFromArray(Deputy::findByRange_id($child->id))->orderBy('nachname vorname'),
+]) ?>
+<? foreach (words('tutor autor user') as $level) :
+ $members = $child->members->findBy('status', $level)->orderBy('nachname, vorname')
+?>
+ <? if (count($members) > 0) : ?>
+ <?= $this->render_partial('course/grouping/_perm_level', [
+ 'level' => $level,
+ 'current' => $child,
+ 'members' => $members,
+ ]) ?>
+ <? endif ?>
+<? endforeach ?>
diff --git a/app/views/course/grouping/children.php b/app/views/course/grouping/children.php
new file mode 100644
index 0000000..789b0ce
--- /dev/null
+++ b/app/views/course/grouping/children.php
@@ -0,0 +1,39 @@
+<form class="default" method="post" action="<?= $controller->url_for('course/grouping/assign_child') ?>">
+ <fieldset>
+ <legend>
+ <?= _('Bereits zugeordnet') ?>
+ </legend>
+ <section>
+ <? if (count($children) > 0) : ?>
+ <ul>
+ <? foreach ($children as $child) : ?>
+ <li>
+ <a href="<?= $controller->url_for('course/management', ['cid' => $child->id]) ?>">
+ <?= htmlReady($child->getFullname()) ?>
+ </a>
+ <a href="<?= $controller->url_for('course/grouping/unassign_child', $child->id) ?>"
+ data-confirm="<?= _('Wollen Sie die Zuordnung dieser Unterveranstaltung wirklich entfernen?') ?>">
+ <?= Icon::create('trash') ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? else: ?>
+ <p>
+ <?= _('Diese Veranstaltung hat keine Unterveranstaltungen.') ?>
+ </p>
+ <? endif ?>
+ </section>
+ </fieldset>
+ <fieldset>
+ <legend>
+ <?= _('Unterveranstaltung hinzufügen') ?>
+ </legend>
+ <section>
+ <?= $search->render() ?>
+ </section>
+ </fieldset>
+ <footer>
+ <?= Studip\Button::createAccept(_('Unterveranstaltung zuordnen'), 'assign') ?>
+ </footer>
+</form>
diff --git a/app/views/course/grouping/create_children.php b/app/views/course/grouping/create_children.php
new file mode 100644
index 0000000..c40b619
--- /dev/null
+++ b/app/views/course/grouping/create_children.php
@@ -0,0 +1,51 @@
+<form class="default" action="<?= $controller->url_for('course/wizard/step') ?>" method="post" data-dialog>
+ <fieldset>
+ <legend>
+ <?= _('Anlegen von mehreren Unterveranstaltungen') ?>
+ </legend>
+
+ <label>
+ <span class="required">
+ <?= _('Anzahl anzulegender Veranstaltungen') ?>
+ </span>
+ <input type="number" name="batchcreate[number]" value="5" min="1" required>
+ </label>
+
+ <section>
+ <span class="required">
+ <?= _('Nummerierung/Kennzeichnung anhängen an') ?>
+ </span>
+ <label>
+ <input type="radio" name="batchcreate[add_number_to]" value="name" required>
+ <?= _('Name der Veranstaltung') ?>
+ </label>
+ <label>
+ <input type="radio" name="batchcreate[add_number_to]" value="number" required>
+ <?= _('Veranstaltungsnummer') ?>
+ </label>
+ </section>
+
+ <section>
+ <span class="required">
+ <?= _('Nummerierung/Kennzeichnung durch') ?>
+ </span>
+ <label>
+ <input type="radio" name="batchcreate[numbering]" value="number" required>
+ <?= _('Zahlen (1, 2, 3, ...)') ?>
+ </label>
+ <label>
+ <input type="radio" name="batchcreate[numbering]" value="letters" required>
+ <?= _('Buchstaben (A, B, C, ...)') ?>
+ </label>
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <input type="hidden" name="batchcreate[parent]" value="<?= $course->id ?>">
+ <?= Studip\Button::createAccept(_('Weiter zum Anlegeassistenten'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('course/grouping/children')
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/course/grouping/find_members_to_add.php b/app/views/course/grouping/find_members_to_add.php
new file mode 100644
index 0000000..381fd84
--- /dev/null
+++ b/app/views/course/grouping/find_members_to_add.php
@@ -0,0 +1,20 @@
+
+<form class="default" action="<?= $controller->url_for('course/grouping/add_members') ?>" method="post">
+ <label>
+ <?= $search->render(); ?>
+ </label>
+
+ <section>
+ <ul id="persons-to-add">
+ </ul>
+ </section>
+ <footer data-dialog-button>
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="permission" value="<?= $permission ?>">
+ <? foreach ($courses as $course) : ?>
+ <input type="hidden" name="courses[]" value="<?= $course ?>" required>
+ <? endforeach ?>
+ <?= Studip\Button::createAccept(_('Personen hinzufügen'), 'add') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/course/grouping/members.php b/app/views/course/grouping/members.php
new file mode 100644
index 0000000..7a12273
--- /dev/null
+++ b/app/views/course/grouping/members.php
@@ -0,0 +1,87 @@
+<? if (!empty($courses)) : ?>
+ <form class="default" action="<?= $controller->url_for('course/grouping/action') ?>" method="post"
+ data-dialog="size=auto">
+ <section class="studip">
+ <? foreach ($courses as $child) : ?>
+ <article class="studip toggle" id="<?= $child->id ?>">
+ <header>
+ <h1>
+ <input type="checkbox" name="courses[]" value="<?= $child->id ?>" class="courses"
+ data-activates="#actions-courses">
+ <a href="<?= ContentBoxHelper::href($child->id, ['contentbox_type' => 'news']) ?>"
+ data-course-id="<?= $child->id ?>"
+ data-get-members-url="<?= $controller->url_for('course/grouping/child_course_members', $child->id) ?>"
+ class="get-course-members">
+ <?= Icon::create('seminar') ?>
+ <?= htmlReady($child->getFullname()) ?>
+ </a>
+ </h1>
+ <span class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('messages/write', [
+ 'filter' => 'all',
+ 'course_id' => $child->id,
+ 'default_subject' => '[' . $child->getFullname() . ']',
+ ]),
+ _('Nachricht schicken'),
+ Icon::create('mail', Icon::ROLE_CLICKABLE, ['title' => _('Nachricht schicken')]),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </span>
+ </header>
+ <section>
+ <article id="course-members-<?= $child->id ?>">
+ </article>
+ </section>
+ </article>
+ <? endforeach ?>
+ <? if (is_array($parentOnly) && count($parentOnly) > 0) : ?>
+ <article class="studip toggle" id="<?= $course->id ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($course->id, ['contentbox_type' => 'news']) ?>"
+ data-course-id="<?= $course->id ?>"
+ data-get-members-url="<?= $controller->url_for('course/grouping/parent_only_members') ?>"
+ class="get-course-members">
+ <?= Icon::create('seminar') ?>
+ <?= _('In keiner Unterveranstaltung') ?>
+ </a>
+ </h1>
+ </header>
+ <section>
+ <article id="course-members-<?= $course->id ?>">
+ </article>
+ </section>
+ </article>
+ <? endif ?>
+ <footer>
+ <label>
+ <input type="checkbox" data-proxyfor=":checkbox.courses" data-activates="#actions-courses">
+ <?= _('Alle Veranstaltungen auswählen') ?>
+ </label>
+ <span class="actions">
+ <select id="actions-courses" name="action" disabled>
+ <option value="add_dozent">
+ <?= sprintf(_('%s eintragen'), htmlReady(get_title_for_status('dozent', 2))) ?>
+ </option>
+ <? if (Config::get()->DEPUTIES_ENABLE) : ?>
+ <option value="add_deputy">
+ <?= _('Vertretung/en eintragen') ?>
+ </option>
+ <? endif ?>
+ <option value="add_tutor">
+ <?= sprintf(_('%s eintragen'), htmlReady(get_title_for_status('tutor', 2))) ?>
+ </option>
+ <option value="add_autor">
+ <?= sprintf(_('%s eintragen'), htmlReady(get_title_for_status('autor', 2))) ?>
+ </option>
+ </select>
+ <input type="hidden" name="course" value="<?= $current->id ?>">
+ <?= Studip\Button::createAccept(_('Ausführen'), 'courses_action') ?>
+ </span>
+ </footer>
+ </section>
+ </form>
+<? endif ?>
diff --git a/app/views/course/grouping/move_members_target.php b/app/views/course/grouping/move_members_target.php
new file mode 100644
index 0000000..0322f92
--- /dev/null
+++ b/app/views/course/grouping/move_members_target.php
@@ -0,0 +1,23 @@
+<form class="default" action="<?= $controller->url_for('course/grouping/move_members', $source_id) ?>" method="post">
+ <fieldset>
+ <legend><?= _('Personen verschieben') ?></legend>
+
+ <h1><?= _('Wohin sollen die gewählten Personen verschoben werden?') ?></h1>
+ <section>
+ <? foreach ($targets as $one) : ?>
+ <label>
+ <input type="radio" name="target" value="<?= $one->id ?>">
+ <?= htmlReady($one->getFullname()) ?>
+ </label>
+ <? endforeach ?>
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? foreach ($users as $user) : ?>
+ <input type="hidden" name="users[]" value="<?= $user ?>">
+ <? endforeach ?>
+ <?= Studip\Button::createAccept(_('Personen verschieben'), 'move') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/course/grouping/parent.php b/app/views/course/grouping/parent.php
new file mode 100644
index 0000000..64c1b39
--- /dev/null
+++ b/app/views/course/grouping/parent.php
@@ -0,0 +1,44 @@
+<? if ($parent) : ?>
+<form class="default" method="post" action="<?= $controller->url_for('course/grouping/unassign_parent') ?>">
+ <fieldset>
+ <legend><?= _('Veranstaltung zuordnen') ?></legend>
+ <section>
+ <p>
+ <?= sprintf(
+ _('Diese Veranstaltung gehört zur Hauptveranstaltung %s%s%s.'),
+ sprintf(
+ '<a href="%s" title="%s">',
+ $controller->link_for('course/grouping/children', ['cid' => $parent->id]),
+ htmlReady($parent->getFullname())
+ ),
+ htmlReady($parent->getFullname()),
+ '</a>'
+ ) ?>
+ </p>
+ </section>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::createCancel(_('Zuordnung aufheben'), 'unassign') ?>
+ </footer>
+</form>
+<? else : ?>
+<form class="default" method="post" action="<?= $controller->url_for('course/grouping/assign_parent') ?>">
+ <fieldset>
+ <legend><?= _('Veranstaltung zuordnen') ?></legend>
+
+ <p>
+ <?= _('Diese Veranstaltung ist noch keiner Hauptveranstaltung zugeordnet.') ?>
+ </p>
+
+ <label>
+ <?= _('Veranstaltung') ?>
+ <?= $search->render() ?>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::createAccept(_('Zuordnen'), 'assign') ?>
+ </footer>
+</form>
+<? endif ?>
diff --git a/app/views/course/grouping/parent_only_members.php b/app/views/course/grouping/parent_only_members.php
new file mode 100644
index 0000000..0a92e83
--- /dev/null
+++ b/app/views/course/grouping/parent_only_members.php
@@ -0,0 +1,21 @@
+<?= $this->render_partial('course/grouping/_perm_level', [
+ 'level' => 'dozent',
+ 'current' => $course,
+ 'members' => $parentOnly->findBy('status', 'dozent'),
+]) ?>
+<?= $this->render_partial('course/grouping/_perm_level', [
+ 'level' => 'deputy',
+ 'current' => $course,
+ 'members' => SimpleORMapCollection::createFromArray(Deputy::findByRange_id($course->id))->orderBy('nachname vorname'),
+]) ?>
+<? foreach (words('tutor autor user') as $level):
+ $members = $parentOnly->findBy('status', $level);
+?>
+ <? if (count($members) > 0) : ?>
+ <?= $this->render_partial('course/grouping/_perm_level', [
+ 'level' => $level,
+ 'current' => $course,
+ 'members' => $members,
+ ]) ?>
+ <? endif ?>
+<? endforeach ?>
diff --git a/app/views/course/ilias_interface/add_groups.php b/app/views/course/ilias_interface/add_groups.php
new file mode 100755
index 0000000..495aa5f
--- /dev/null
+++ b/app/views/course/ilias_interface/add_groups.php
@@ -0,0 +1,32 @@
+<form class="default" action="<?= $controller->url_for('course/ilias_interface/add_groups/'.$ilias_index) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if (!$ilias_index) : ?>
+ <label>
+ <span class="required"><?= _('ILIAS-Installation auswählen') ?></span>
+ <select name="ilias_index" required>
+ <option></option>
+ <? foreach ($ilias_list as $ilias_list_index => $ilias) : ?>
+ <option value="<?=$ilias_list_index?>"><?=$ilias->getName()?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? elseif ($mode == 'add_groups') : ?>
+ <? else : ?>
+ <div>
+ <input type="hidden" name="cmd" value="create_groups">
+ <h3><?= _('Gruppen') ?></h3>
+ <? foreach ($groups as $group) : ?>
+ <article>
+ <?=$group->getName()?> (<?=count($group->members)?>)
+ </article>
+ <? endforeach ?>
+ <?= $groups_exist ? sprintf(_('Die Gruppen können nun in der %s-Installation aktualisiert werden.'), $ilias->getName()) : sprintf(_('Die Gruppen können nun in der %s-Installation angelegt werden.'), $ilias->getName())?>
+ </div>
+ <? endif ?>
+ <footer data-dialog-button>
+ <? if ($ilias->isActive() && $submit_text) : ?>
+ <?= Studip\Button::create($submit_text, 'submit', ($dialog && ! $ilias_index) ? ['data-dialog' => 'size=auto'] : []) ?>
+ <? endif ?>
+ <?= Studip\Button::createCancel(_('Schließen'), 'cancel', $dialog ? ['data-dialog' => 'close'] : []) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/course/ilias_interface/add_object.php b/app/views/course/ilias_interface/add_object.php
new file mode 100755
index 0000000..429ee58
--- /dev/null
+++ b/app/views/course/ilias_interface/add_object.php
@@ -0,0 +1,130 @@
+<form class="default" action="<?= $controller->url_for('course/ilias_interface/add_object/'.$mode.'/'.$ilias_index) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+<? if (!$ilias_index) : ?>
+ <label>
+ <span class="required"><?= _('ILIAS-Installation auswählen') ?></span>
+ <select name="ilias_index" required>
+ <option></option>
+ <? foreach ($ilias_list as $ilias_list_index => $ilias) : ?>
+ <option value="<?= htmlReady($ilias_list_index) ?>">
+ <?= htmlReady($ilias->getName()) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+<? elseif ($mode === 'search' && count($ilias_modules) === 0) : ?>
+ <label>
+ <span><?= _('Suche nach Lernobjekten') ?></span>
+ <input type="text" name="ilias_search" value="<?= htmlReady($ilias_search) ?>"
+ size="50" maxlength="50" required>
+ </label>
+<? elseif ($mode === 'new_course') : ?>
+ <div>
+ <input type="hidden" name="cmd" value="add_course">
+ <?=sprintf(_('Sie können nun einen leeren Kurs in der %s-Installation anlegen.'), $ilias->getName())?>
+ </div>
+<? elseif ($mode === 'assign_course') : ?>
+ <div>
+ <input type="hidden" name="cmd" value="assign_course">
+ <label>
+ <span><?= _('Veranstaltung wählen') ?></span>
+ <select name="ilias_course_id" required>
+ <option></option>
+ <? foreach ($studip_course_list as $ilias_course_id => $studip_course_name) : ?>
+ <option value="<?= htmlReady($ilias_course_id) ?>">
+ <?= htmlReady($studip_course_name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </div>
+<? elseif ($mode === 'assign_own_course') : ?>
+ <div>
+ <input type="hidden" name="cmd" value="assign_course">
+ <? if ($submit_text) : ?>
+ <label>
+ <span><?= _('ILIAS-Kurs wählen') ?></span>
+ <select name="ilias_course_id" required>
+ <option></option>
+ <? foreach ($studip_course_list as $ilias_course_id => $studip_course_name) : ?>
+ <option value="<?= htmlReady($ilias_course_id) ?>">
+ <?= htmlReady($studip_course_name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? else : ?>
+ <?= sprintf(
+ _('Es wurden keine Kurse in der %s-Installation gefunden, in denen Sie als Kursadministrator/-in eingetragen sind.'),
+ htmlReady($ilias->getName())
+ ) ?>
+ <? endif ?>
+ </div>
+<? elseif ($mode === 'search' || $mode === 'my_modules') : ?>
+ <table class="default">
+ <caption>
+ <? if ($mode === 'search') : ?>
+ <?= _('Gefundene Lernobjekte') ?>
+ <? elseif ($mode === 'my_modules') : ?>
+ <?= _('Meine Lernobjekte') ?>
+ <? endif ?>
+ </caption>
+ <colgroup>
+ <col style="width: 5%">
+ <col style="width: 65%">
+ <col style="width: 20%">
+ <col style="width: 10%">
+ </colgroup>
+ <thead>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </thead>
+ <tbody>
+ <? foreach ($ilias_modules as $module_id => $module) : ?>
+ <tr>
+ <td>
+ <?= Icon::create('learnmodule')->asImg([
+ 'title' => $module->getModuleTypeName(),
+ ]) ?>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for($module->getRoute('view_course'), compact('ilias_search', 'mode')) ?>" <?= $dialog ? 'data-dialog=""' : ''?>>
+ <?= htmlReady($module->getTitle()) ?>
+ </a>
+ </td>
+ <td><?= $module->getModuleTypeName() ?></td>
+ <td class="actions">
+ <?= ActionMenu::get()->addButton(
+ 'view',
+ _('Info'),
+ Icon::create('info-circle'),
+ [
+ 'title' => _('Info'),
+ 'formaction' => $controller->url_for($module->getRoute('view_course') .'?ilias_search='.htmlReady($ilias_search)),
+ 'data-dialog' => ''
+ ]
+ )->condition($edit_permission)->addButton(
+ 'add',
+ _('Hinzufügen'),
+ Icon::create('add'),
+ [
+ 'title' => _('Hinzufügen'),
+ 'formaction' => $controller->url_for($module->getRoute('add')),
+ 'data-dialog' => ''
+ ]
+ )->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? endif ?>
+ <footer data-dialog-button>
+ <? if ($ilias->isActive() && $submit_text) : ?>
+ <?= Studip\Button::create($submit_text, 'submit', ($dialog && $keep_dialog) ? ['data-dialog' => 'size=auto;reload-on-close'] : []) ?>
+ <? endif ?>
+ <?= Studip\Button::createCancel(_('Schließen'), 'cancel', $dialog ? ['data-dialog' => 'close'] : []) ?>
+ </footer>
+</form>
diff --git a/app/views/course/ilias_interface/edit_moduletitle.php b/app/views/course/ilias_interface/edit_moduletitle.php
new file mode 100755
index 0000000..5c3471f
--- /dev/null
+++ b/app/views/course/ilias_interface/edit_moduletitle.php
@@ -0,0 +1,11 @@
+<form class="default" action="<?= $controller->url_for('course/ilias_interface/edit_moduletitle') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <label>
+ <span><?= _('Seitentitel') ?></span>
+ <input type="text" name="ilias_interface_moduletitle" value="<?=$ilias_interface_moduletitle?>" size="50" maxlength="50" required>
+ </label>
+ <footer data-dialog-button>
+ <?= Studip\Button::create(_('Speichern'), 'submit') ?>
+ <?= Studip\Button::createCancel(_('Schließen'), 'cancel', $dialog ? ['data-dialog' => 'close'] : []) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/course/ilias_interface/edit_object_assignment.php b/app/views/course/ilias_interface/edit_object_assignment.php
new file mode 100755
index 0000000..d688975
--- /dev/null
+++ b/app/views/course/ilias_interface/edit_object_assignment.php
@@ -0,0 +1,30 @@
+<form class="default" action="<?= $controller->url_for('course/ilias_interface/edit_object_assignment/'.$ilias_index) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table>
+ <input type="hidden" name="ilias_module_id" value="<?=htmlReady($module_id)?>">
+ <tr>
+ <td>
+ <input type="radio" id="ilias_add_mode_reference" name="ilias_add_mode" value="reference" checked>
+ </td>
+ <td>
+ <label for="ilias_add_mode_reference">
+ <?=_('Fügt einen Link zu diesem Objekt im ILIAS-Kurs ein. Änderungen am ursprünglichen Lernobjekt wirken sich auf alle verlinkten Vorkommen des Objekts aus.')?>
+ </label>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <input type="radio" id="ilias_add_mode_copy" name="ilias_add_mode" value="copy">
+ </td>
+ <td>
+ <label for="ilias_add_mode_copy">
+ <?=_('Erstellt eine neue Instanz des Objekts. Das kopierte Objekt ist zunächst offline, Sie müssen das Objekt daher in ILIAS erst auf "online" stellen, damit es für Teilnehmende der Veranstaltung sichtbar wird. Diese Option ist z.B. für Tests geeignet, weil sich eine Test-Instanz nicht mehr ändern lässt, sobald Lernende daran teilgenommen haben.')?>
+ </label>
+ </td>
+ </tr>
+ </table>
+ <footer data-dialog-button>
+ <?= Studip\Button::create(_('Bestätigen'), 'submit') ?>
+ <?= Studip\Button::createCancel(_('Schließen'), 'cancel', $dialog ? ['data-dialog' => 'close'] : []) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/course/ilias_interface/index.php b/app/views/course/ilias_interface/index.php
new file mode 100755
index 0000000..9deab9f
--- /dev/null
+++ b/app/views/course/ilias_interface/index.php
@@ -0,0 +1,129 @@
+<form method="post">
+<? foreach($ilias_list as $ilias_index => $ilias) : ?>
+ <? if (!count($ilias->getCourseModules()) && !$courses[$ilias_index] && !$edit_permission) continue; ?>
+ <? if ($anker_target == $ilias_index) : ?>
+ <a name='anker'></a>
+ <? endif?>
+ <table class="default">
+ <caption>
+ <?= sprintf(_('Lernobjekte in %s'), htmlReady($ilias->getName()))?>
+ </caption>
+ <colgroup>
+ <col style="width: 5%">
+ <col style="width: 65%">
+ <col style="width: 20%">
+ <col style="width: 10%">
+ </colgroup>
+ <thead>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </thead>
+ <tbody>
+ <? if (count($ilias->getCourseModules())) : ?>
+ <? foreach ($ilias->getCourseModules() as $module_id => $module) : ?>
+ <tr>
+ <td><?=Icon::create('learnmodule', $module->is_offline ? Icon::ROLE_INACTIVE : Icon::ROLE_INFO, [
+ 'title' => $module->getModuleTypeName()
+ ])
+ ?></td>
+ <? if ($module->is_offline) : ?>
+ <td><?=$module->getTitle()?> <?=_('(offline)')?></td>
+ <? else : ?>
+ <td><a href="<?= $controller->url_for($module->getRoute('view_course'))?>" data-dialog="size=auto"><?=$module->getTitle()?></a></td>
+ <? endif ?>
+ <td><?=$module->getModuleTypeName()?></td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (! $module->is_offline) $actionMenu->addButton(
+ 'view',
+ _('Info'),
+ Icon::create('info-circle', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Info'),
+ 'formaction' => $controller->url_for($module->getRoute('view_course')),
+ 'data-dialog' => 'size=auto'
+ ])
+ ) ?>
+ <? if ($module->isAllowed('start')) $actionMenu->addButton(
+ 'start',
+ _('In ILIAS anzeigen'),
+ Icon::create('play', Icon::ROLE_CLICKABLE, [
+ 'title' => _('In ILIAS anzeigen'),
+ 'formaction' => $controller->url_for($module->getRoute('start')),
+ 'target' => '_blank',
+ 'rel' => 'noopener noreferrer'
+ ])
+ ) ?>
+ <? if ($module->isAllowed('edit')) $actionMenu->addButton(
+ 'edit',
+ _('In ILIAS bearbeiten'),
+ Icon::create('learnmodule+edit', Icon::ROLE_CLICKABLE, [
+ 'title' => _('In ILIAS bearbeiten'),
+ 'formaction' => $controller->url_for($module->getRoute('edit')),
+ 'target' => '_blank',
+ 'rel' => 'noopener noreferrer'
+ ])
+ ) ?>
+ <? if ($edit_permission && $module->isAllowed('delete')) $actionMenu->addButton(
+ 'remove',
+ _('Entfernen'),
+ Icon::create('learnmodule+decline', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Entfernen'),
+ 'formaction' => $controller->url_for($module->getRoute('remove')),
+ 'data-confirm' => $module->siblings_count < 2 ? sprintf(_('Dies ist die einzige Instanz des Objekts "%s". Durch das Entfernen aus dem Kurs wird das Objekt unwiderruflich gelöscht! Wollen Sie das Objekt wirklich löschen?'), htmlReady($module->getTitle())) : sprintf(_('Wollen Sie das Objekt "%s" jetzt entfernen?'), htmlReady($module->getTitle())),
+ 'target' => '_blank',
+ 'rel' => 'noopener noreferrer'
+ ])
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? elseif (!$courses[$ilias_index]) : ?>
+ <tr>
+ <td colspan="4">
+ <?= _('Es sind keine Lernobjekte mit dieser Veranstaltung verknüpft.')?>
+ </td>
+ </tr>
+ <? else : ?>
+ <tr>
+ <td><?=Icon::create('learnmodule', $course_objects[$ilias_index]->is_offline ? Icon::ROLE_INACTIVE : Icon::ROLE_INFO, [
+ 'title' => _('ILIAS-Kurs')
+ ])
+ ?></td>
+ <td>
+ <a href="<?= $controller->url_for('my_ilias_accounts/redirect/'.$ilias_index.'/start/'.$courses[$ilias_index].'/crs')?>" target="_blank"><?= sprintf(_('Kurs in %s'), $ilias->getName()).($course_objects[$ilias_index]->is_offline ? ' '._('(offline)') : '')?></a>
+ </td>
+ <td><?=_('ILIAS-Kurs')?></td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addButton(
+ 'start',
+ _('In ILIAS anzeigen'),
+ Icon::create('play', Icon::ROLE_CLICKABLE, [
+ 'title' => _('In ILIAS anzeigen'),
+ 'formaction' => $controller->url_for('my_ilias_accounts/redirect/'.$ilias_index.'/start/'.$courses[$ilias_index].'/crs'),
+ 'target' => '_blank',
+ 'rel' => 'noopener noreferrer'
+ ])
+ ) ?>
+ <? if ($edit_permission) $actionMenu->addButton(
+ 'remove',
+ _('Entfernen'),
+ Icon::create('learnmodule+decline', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Entfernen'),
+ 'formaction' => $controller->url_for('course/ilias_interface/remove_course/'.$ilias_index.'/'.$courses[$ilias_index]),
+ 'data-confirm' => sprintf(_('Verknüpfung zum Kurs in %s entfernen? Hierdurch werden auch die Verknüpfungen zu allen Objekten innerhalb des Kurses entfernt.'), $ilias->getName()),
+ 'target' => '_blank',
+ 'rel' => 'noopener noreferrer'
+ ])
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+<? endforeach ?>
+</form>
diff --git a/app/views/course/ilias_interface/view_object.php b/app/views/course/ilias_interface/view_object.php
new file mode 100755
index 0000000..3ca5c70
--- /dev/null
+++ b/app/views/course/ilias_interface/view_object.php
@@ -0,0 +1,23 @@
+<form class="default" action="<?= $controller->url_for($module->getRoute('view_course')) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="ilias_search" value="<?=htmlReady($ilias_search)?>">
+ <input type="hidden" name="ilias_module_id" value="<?=htmlReady($module_id)?>">
+ <input type="hidden" name="ilias_ref_id" value="<?=htmlReady($module_id)?>">
+ <?= $this->render_partial('my_ilias_accounts/_ilias_module.php') ?>
+ <footer data-dialog-button>
+ <? if ($ilias->isActive() && $mode && $edit_permission) : ?>
+ <?= Studip\LinkButton::create(_('Zurück'), $controller->url_for('course/ilias_interface/add_object/'.$mode.'/'.$ilias_index.'?ilias_search=' . $ilias_search), $dialog ? ['data-dialog' => 'size=auto'] : []) ?>
+ <?= Studip\LinkButton::create(_('Hinzufügen'), $controller->url_for($module->getRoute('add') .'?ilias_search=' . $ilias_search), $dialog ? ['data-dialog' => ''] : []) ?>
+ <? endif ?>
+ <? if ($ilias->isActive() && !$mode) : ?>
+ <? if ($edit_permission && $module->isAllowed('delete')) : ?>
+ <?= Studip\LinkButton::create(_('Entfernen'), $controller->url_for($module->getRoute('remove') . '?ilias_search=' . $ilias_search), ['data-confirm' => $module->siblings_count < 2 ? sprintf(_('Dies ist die einzige Instanz des Objekts "%s". Durch das Entfernen aus dem Kurs wird das Objekt unwiderruflich gelöscht! Wollen Sie das Objekt wirklich löschen?'), htmlReady($module->getTitle())) : sprintf(_('Wollen Sie das Objekt "%s" jetzt entfernen?'), htmlReady($module->getTitle()))]) ?>
+ <? endif ?>
+ <?= $module->isAllowed('start') ? Studip\LinkButton::create(_('Starten'), $controller->url_for($module->getRoute('start')), ['target' => '_blank', 'rel' => 'noopener noreferrer']) :'' ?>
+ <?= $module->isAllowed('edit') ? Studip\LinkButton::create(_('Bearbeiten'), $controller->url_for($module->getRoute('edit')), ['target' => '_blank', 'rel' => 'noopener noreferrer']) :'' ?>
+ <? endif ?>
+ <? if ($dialog) : ?>
+ <?= Studip\Button::createCancel(_('Schließen'), 'cancel', ['data-dialog' => 'close']) ?>
+ <? endif ?>
+ </footer>
+</form>
diff --git a/app/views/course/lti/add_link.php b/app/views/course/lti/add_link.php
new file mode 100644
index 0000000..dc479a2
--- /dev/null
+++ b/app/views/course/lti/add_link.php
@@ -0,0 +1,15 @@
+<form class="default" action="<?= $controller->link_for('course/lti/select_link') ?>" method="post">
+ <label>
+ <?= _('Auswahl des externen Tools') ?>
+ <select name="tool_id">
+ <? foreach ($tools as $tool): ?>
+ <option value="<?= $tool->id ?>"><?= htmlReady($tool->name) ?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Tool auswählen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/lti')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/lti/config.php b/app/views/course/lti/config.php
new file mode 100644
index 0000000..e999403
--- /dev/null
+++ b/app/views/course/lti/config.php
@@ -0,0 +1,20 @@
+<form class="default" action="<?= $controller->link_for('course/lti/save_config') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Einstellungen') ?>
+ </legend>
+
+ <label>
+ <span class="required">
+ <?= _('Titel des Reiters') ?>
+ </span>
+ <input type="text" name="title" value="<?= htmlReady($title) ?>" required>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/lti')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/lti/edit.php b/app/views/course/lti/edit.php
new file mode 100644
index 0000000..1df8d73
--- /dev/null
+++ b/app/views/course/lti/edit.php
@@ -0,0 +1,110 @@
+<form class="default" action="<?= $controller->link_for('course/lti/save/' . $lti_data->position) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Einstellungen') ?>
+ </legend>
+
+ <label>
+ <span class="required">
+ <?= _('Titel') ?>
+ </span>
+ <input type="text" name="title" value="<?= htmlReady($lti_data->title) ?>" required>
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description" class="add_toolbar wysiwyg"><?= wysiwygReady($lti_data->description) ?></textarea>
+ </label>
+
+ <label>
+ <?= _('Auswahl des externen Tools') ?>
+ <select class="config_tool" name="tool_id">
+ <? foreach ($tools as $tool): ?>
+ <option value="<?= $tool->id ?>"
+ <? if ($tool->allow_custom_url): ?>
+ data-url="<?= htmlReady($tool->launch_url) ?>"
+ <? endif ?>
+ <?= $lti_data->tool_id == $tool->id ? 'selected' : '' ?>><?= htmlReady($tool->name) ?></option>
+ <? endforeach ?>
+ <option value="0" <?= $lti_data && $lti_data->tool_id == 0 ? 'selected' : '' ?>><?= _('Zugangsdaten selbst eingeben...') ?></option>
+ </select>
+ </label>
+
+ <div class="config_custom_url">
+ <label>
+ <?= _('URL der Anwendung (optional)') ?>
+ <?= tooltipIcon(_('Sie können direkt auf eine URL in der Anwendung verlinken.')) ?>
+ <input type="text" name="custom_url" value="<?= htmlReady($lti_data->launch_url) ?>">
+ </label>
+ </div>
+
+ <div class="config_launch_url">
+ <label>
+ <?= _('URL der Anwendung') ?>
+ <?= tooltipIcon(_('Die Betreiber dieses Tools müssen Ihnen eine URL und Zugangsdaten (Consumer-Key und Consumer-Secret) mitteilen.')) ?>
+ <input type="text" name="launch_url" value="<?= htmlReady($lti_data->launch_url) ?>">
+ </label>
+
+ <label>
+ <?= _('Consumer-Key des LTI-Tools') ?>
+ <input type="text" name="consumer_key" value="<?= htmlReady($lti_data->options['consumer_key']) ?>">
+ </label>
+
+ <label>
+ <?= _('Consumer-Secret des LTI-Tools') ?>
+ <input type="text" name="consumer_secret" value="<?= htmlReady($lti_data->options['consumer_secret']) ?>">
+ </label>
+
+ <label>
+ <?= _('OAuth Signatur Methode des LTI-Tools') ?>
+ <select name="oauth_signature_method">
+ <option value="sha1">HMAC-SHA1</option>
+ <option value="sha256" <?=$lti_data->options['oauth_signature_method'] === 'sha256' ? 'selected' : '' ?>>HMAC-SHA256</option>
+ </select>
+ </label>
+
+ <label>
+ <input type="checkbox" name="send_lis_person" value="1" <?= $lti_data->options['send_lis_person'] ? ' checked' : '' ?>>
+ <?= _('Nutzerdaten an LTI-Tool senden') ?>
+ <?= tooltipIcon(_('Nutzerdaten dürfen nur an das externe Tool gesendet werden, wenn es keine Datenschutzbedenken gibt. Mit Setzen des Hakens bestätigen Sie, dass die Übermittlung der Daten zulässig ist.')) ?>
+ </label>
+ </div>
+
+ <label>
+ <input type="checkbox" name="document_target" value="iframe" <?= $lti_data->options['document_target'] == 'iframe' ? ' checked' : '' ?>>
+ <?= _('Anzeige im IFRAME auf der Seite') ?>
+ <?= tooltipIcon(_('Normalerweise wird das externe Tool in einem neuen Fenster angezeigt. Aktivieren Sie diese Option, wenn die Anzeige stattdessen in einem IFRAME erfolgen soll.')) ?>
+ </label>
+
+ <label>
+ <?= _('Zusätzliche LTI-Parameter') ?>
+ <?= tooltipIcon(_('Ein Wert pro Zeile, Beispiel: Review:Chapter=1.2.56')) ?>
+ <textarea name="custom_parameters"><?= htmlReady($lti_data->options['custom_parameters']) ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/lti')) ?>
+ </footer>
+</form>
+
+<script>
+ $('.config_tool').change(function() {
+ var url = $(this).find(':selected').data('url');
+
+ if ($(this).val() == 0) {
+ $('.config_launch_url').show();
+ } else {
+ $('.config_launch_url').hide();
+ }
+
+ if (url) {
+ $('.config_custom_url').find('input').attr('placeholder', url);
+ $('.config_custom_url').show();
+ } else {
+ $('.config_custom_url').hide();
+ }
+ }).trigger('change');
+</script>
diff --git a/app/views/course/lti/grades.php b/app/views/course/lti/grades.php
new file mode 100644
index 0000000..a200405
--- /dev/null
+++ b/app/views/course/lti/grades.php
@@ -0,0 +1,39 @@
+<table class="default">
+ <caption>
+ <?= _('Ergebnisse') ?>
+ </caption>
+
+ <thead>
+ <tr class="sortable">
+ <th class="<?= $desc ? 'sortdesc' : 'sortasc' ?>">
+ <a href="<?= $controller->link_for('course/lti/grades', ['desc' => !$desc]) ?>">
+ <?= _('Teilnehmende') ?>
+ </a>
+ </th>
+ <? foreach ($lti_data_array as $lti_data): ?>
+ <th style="text-align: right;">
+ <?= htmlReady($lti_data->title) ?>
+ </th>
+ <? endforeach ?>
+ </tr>
+ </thead>
+
+ <tbody>
+ <? foreach ($members as $member): ?>
+ <tr>
+ <td>
+ <?= htmlReady($member->nachname) ?>, <?= htmlReady($member->vorname) ?>
+ </td>
+ <? foreach ($lti_data_array as $lti_data): ?>
+ <td style="text-align: right;">
+ <? if ($grade = $lti_data->grades->findOneBy('user_id', $member->user_id)): ?>
+ <?= sprintf('%.0f%%', $grade->score * 100) ?>
+ <? else: ?>
+ &ndash;
+ <? endif ?>
+ </td>
+ <? endforeach ?>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/course/lti/grades_user.php b/app/views/course/lti/grades_user.php
new file mode 100644
index 0000000..8be7b02
--- /dev/null
+++ b/app/views/course/lti/grades_user.php
@@ -0,0 +1,33 @@
+<table class="default">
+ <caption>
+ <?= _('Ergebnisse') ?>
+ </caption>
+
+ <thead>
+ <tr>
+ <th>
+ <?= _('Abschnitt') ?>
+ </th>
+ <th style="text-align: right;">
+ <?= _('Bewertung') ?>
+ </th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <? foreach ($lti_data_array as $lti_data): ?>
+ <tr>
+ <td>
+ <?= htmlReady($lti_data->title) ?>
+ </td>
+ <td style="text-align: right;">
+ <? if ($grade = LtiGrade::find([$lti_data->id, $GLOBALS['user']->id])): ?>
+ <?= sprintf('%.0f%%', $grade->score * 100) ?>
+ <? else: ?>
+ &ndash;
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/course/lti/iframe.php b/app/views/course/lti/iframe.php
new file mode 100644
index 0000000..cd73efd
--- /dev/null
+++ b/app/views/course/lti/iframe.php
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+</head>
+<body onload="document.ltiLaunchForm.submit();">
+ <form name="ltiLaunchForm" method="post" action="<?= htmlReady($launch_url) ?>">
+ <? foreach ($launch_data as $key => $value): ?>
+ <input type="hidden" name="<?= htmlReady($key) ?>" value="<?= htmlReady($value, false) ?>">
+ <? endforeach ?>
+ <input type="hidden" name="oauth_signature" value="<?= $signature ?>">
+ <noscript>
+ <button><?= _('Anwendung starten') ?></button>
+ </noscript>
+ </form>
+</body>
+</html>
diff --git a/app/views/course/lti/index.php b/app/views/course/lti/index.php
new file mode 100644
index 0000000..3b2fb80
--- /dev/null
+++ b/app/views/course/lti/index.php
@@ -0,0 +1,67 @@
+<? if (empty($lti_data_array)): ?>
+ <?= MessageBox::info(_('Es wurden noch keine Inhalte angelegt.')) ?>
+<? endif ?>
+
+<? foreach ($lti_data_array as $lti_data): ?>
+ <? $launch_url = $lti_data->getLaunchURL() ?>
+ <? if ($launch_url): ?>
+ <? $lti_link = $controller->getLtiLink($lti_data) ?>
+ <? $launch_data = $lti_link->getBasicLaunchData() ?>
+ <? $signature = $lti_link->getLaunchSignature($launch_data) ?>
+ <? endif ?>
+
+ <article class="studip">
+ <header>
+ <h1><?= htmlReady($lti_data->title) ?></h1>
+
+ <? if ($edit_perm): ?>
+ <nav>
+ <form action="" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($lti_data->position > 0): ?>
+ <?= Icon::create('arr_2up', Icon::ROLE_SORT)->asInput([
+ 'formaction' => $controller->url_for('course/lti/move/' . $lti_data->position . '/up')
+ ]) ?>
+ <? endif ?>
+ <? if ($lti_data->position < count($lti_data_array) - 1): ?>
+ <?= Icon::create('arr_2down', Icon::ROLE_SORT)->asInput([
+ 'formaction' => $controller->url_for('course/lti/move/' . $lti_data->position . '/down')
+ ]) ?>
+ <? endif ?>
+
+ <?= Icon::create('edit')->asInput([
+ 'formaction' => $controller->url_for('course/lti/edit/' . $lti_data->position),
+ 'title' => _('Abschnitt bearbeiten'),
+ 'data-dialog' => ''
+ ]) ?>
+ <?= Icon::create('trash')->asInput([
+ 'formaction' => $controller->url_for('course/lti/delete/' . $lti_data->position),
+ 'title' => _('Abschnitt löschen'),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich den Abschnitt "%s" löschen?'), htmlReady($lti_data->title))
+ ]) ?>
+ </form>
+ </nav>
+ <? endif ?>
+ </header>
+
+ <section>
+ <?= formatReady($lti_data->description) ?>
+
+ <? if ($launch_url && $lti_data->options['document_target'] == 'iframe'): ?>
+ <iframe style="border: none; height: 640px; width: 100%;"
+ src="<?= $controller->link_for('course/lti/iframe', compact('launch_url', 'launch_data', 'signature')) ?>"></iframe>
+ <? endif ?>
+ </section>
+
+ <? if ($launch_url && $lti_data->options['document_target'] != 'iframe'): ?>
+ <footer>
+ <form class="default" action="<?= htmlReady($launch_url) ?>" method="post" target="_blank">
+ <? foreach ($launch_data as $key => $value): ?>
+ <input type="hidden" name="<?= htmlReady($key) ?>" value="<?= htmlReady($value, false) ?>">
+ <? endforeach ?>
+ <?= Studip\Button::create(_('Anwendung starten'), 'oauth_signature', ['value' => $signature]) ?>
+ </form>
+ </footer>
+ <? endif ?>
+ </article>
+<? endforeach ?>
diff --git a/app/views/course/lti/outcome.php b/app/views/course/lti/outcome.php
new file mode 100644
index 0000000..a077f26
--- /dev/null
+++ b/app/views/course/lti/outcome.php
@@ -0,0 +1,32 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+
+<imsx_POXEnvelopeResponse xmlns="http://www.imsglobal.org/lis/oms1p0/pox">
+ <imsx_POXHeader>
+ <imsx_POXResponseHeaderInfo>
+ <imsx_version>V1.0</imsx_version>
+ <imsx_messageIdentifier><?= htmlReady($message_id) ?></imsx_messageIdentifier>
+ <imsx_statusInfo>
+ <imsx_codeMajor><?= htmlReady($status_code) ?></imsx_codeMajor>
+ <imsx_severity><?= htmlReady($status_severity) ?></imsx_severity>
+ <imsx_description><?= htmlReady($description) ?></imsx_description>
+ <imsx_messageRefIdentifier><?= htmlReady($message_ref) ?></imsx_messageRefIdentifier>
+ </imsx_statusInfo>
+ </imsx_POXResponseHeaderInfo>
+ </imsx_POXHeader>
+ <imsx_POXBody>
+ <? if ($operation === 'readResultRequest'): ?>
+ <readResultResponse>
+ <result>
+ <resultScore>
+ <language>en</language>
+ <textString><?= htmlReady($score) ?></textString>
+ </resultScore>
+ </result>
+ </readResultResponse>
+ <? elseif ($operation === 'replaceResultRequest'): ?>
+ <replaceResultResponse/>
+ <? elseif ($operation === 'deleteResultRequest'): ?>
+ <deleteResultResponse/>
+ <? endif ?>
+ </imsx_POXBody>
+</imsx_POXEnvelopeResponse>
diff --git a/app/views/course/lvgselector/entry.php b/app/views/course/lvgselector/entry.php
new file mode 100644
index 0000000..09d26ec
--- /dev/null
+++ b/app/views/course/lvgselector/entry.php
@@ -0,0 +1,45 @@
+<?
+$id = htmlReady(implode('_', (array) $area->getId()));
+$name = htmlReady($area->getDisplayName());
+$expand_id = $area->hasChildren() ? $id : implode('_', (array) $area->getTrailParentId());
+?>
+<input class="lvgruppe_selection_add_<?= $id ?>"
+ data-id="<?= $id ?>" data-course_id="<?= htmlReady($course_id) ?>"
+ data-type="<?= get_class($area) ?>"
+ type="image"
+ name="lvgruppe_selection[add][<?= $id ?>]"
+ src="<?= Icon::create('arr_2left', 'sort')->asImagePath(); ?>"
+ title="<?= _('Diese LV-Gruppe zuordnen') ?>"
+ alt="<?= _('Diese LV-Gruppe zuordnen') ?>"
+ <?= (!$area->isAssignable() || $selection->includes($area))
+ ? 'style="visibility:hidden;"' : '' ?>>
+<? if (isset($show_link) && $show_link) : ?>
+ <a class="lvgruppe_selection_expand"
+ data-id="<?= htmlReady($expand_id) ?>" data-course_id="<?= htmlReady($course_id) ?>"
+ data-type="<?= get_class($area) ?>"
+ href="<?= URLHelper::getLink(isset($url) ? $url : '',
+ ['lvgruppe_selection[selected]' => htmlReady($expand_id),
+ 'lvgruppe_selection[type]' => get_class($area)]) ?>">
+ <?= $name ?>
+ </a>
+ <? if (isset($pathes) && count($pathes)) : ?>
+ <ul>
+ <? foreach ($pathes as $path) : ?>
+ <li style="background-color:inherit;padding-left:20px;color:#666666">
+ <?= htmlReady($path) ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+<? else : ?>
+ <?= $name ?>
+ <? if (isset($pathes) && count($pathes)) : ?>
+ <ul>
+ <? foreach ($pathes as $path) : ?>
+ <li style="background-color:inherit;padding-left:20px;color:#666666">
+ <?= htmlReady($path) ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+<? endif ?>
diff --git a/app/views/course/lvgselector/entry_trails.php b/app/views/course/lvgselector/entry_trails.php
new file mode 100644
index 0000000..b91802d
--- /dev/null
+++ b/app/views/course/lvgselector/entry_trails.php
@@ -0,0 +1,11 @@
+<? if (count($pathes)) : ?>
+<? foreach ($pathes as $path) : ?>
+ <li style="background-color:inherit;padding-left:20px;color:#666666">
+ <?= htmlReady($path) ?>
+ </li>
+<? endforeach; ?>
+<? else : ?>
+<li style="background-color:inherit;padding-left:20px;color:#666666">
+ <?= _('Keine Module in den Semestern der Veranstaltung verfügbar.'); ?>
+</li>
+<? endif; ?>
diff --git a/app/views/course/lvgselector/form.php b/app/views/course/lvgselector/form.php
new file mode 100644
index 0000000..86e2af9
--- /dev/null
+++ b/app/views/course/lvgselector/form.php
@@ -0,0 +1,64 @@
+<?
+# Lifter010: TODO
+?>
+<div id="lvgruppe_selection">
+ <input type="hidden" name="lvgruppe_selection[last_selected]" value="<?= htmlReady(implode('_', (array) $selection->getSelected()->getId())) ?>">
+ <input type="hidden" name="lvgruppe_selection[last_type]" value="<?= htmlReady(get_class($selection->getSelected())) ?>">
+ <input type="hidden" name="lvgruppe_selection[showall]" value="<?= (int) $selection->getShowAll() ?>">
+ <input type="submit" name="lvgruppe_selection[placeholder]" style="display:none;">
+
+
+ <div id="lvgruppe_selection_chosen">
+
+ <h3><?= _("Bestehende Zuordnungen:") ?></h3>
+
+ <? if ($selection->size()) : ?>
+ <div id="lvgruppe_selection_none" style="display:none;"><?= _("Bisher wurde noch keine Zuordnung vorgenommen") ?></div>
+ <? else: ?>
+ <div id="lvgruppe_selection_none"><?= _("Bisher wurde noch keine Zuordnung vorgenommen") ?></div>
+ <? endif ?>
+
+ <div id="lvgruppe_selection_at_least_one" style="display:none;">
+ <?= _("Sie können diesen Studienbereich nicht löschen, da eine Veranstaltung immer mindestens einem Studienbereich zugeordnet sein muss.") ?>
+ </div>
+
+ <?= $this->render_partial('course/lvgselector/selected_entries') ?>
+
+ </div>
+
+
+ <div id="lvgruppe_selection_selectables">
+ <h3><?= _('Bitte wählen') ?>:</h3>
+ <?= $this->render_partial('course/lvgselector/tree', compact('trail', 'subtree')) ?>
+
+ <h3><?=_("Suche:")?></h3>
+
+ <input type="text" name="lvgruppe_selection[search_key]" value="<?= htmlReady($this->selection->getSearchKey()) ?>">
+ <?= Icon::create('search', 'clickable')->asInput(false, ['name' => 'lvgruppe_selection[search_button]']); ?>
+
+ <? if ($selection->searched()) : ?>
+ <a href="<?= URLHelper::getLink(isset($url) ? $url : '',
+ ['lvgruppe_selection[rewind_button]' => 1,
+ 'lvgruppe_selection[last_selected]' => $selected,
+ 'lvgruppe_selection[showall]' => (int) $selection->getShowAll()]) ?>">
+ <?= Icon::create('refresh', 'clickable', [])->asImg(); ?>
+ </a>
+
+ <? if (!sizeof($selection->getSearchResult())) : ?>
+ <em><?= sprintf(_("Der Suchbegriff '%s' lieferte kein Ergebnis."), htmlReady($selection->getSearchKey())) ?></em>
+ <? else : ?>
+ <h3><?= _('Suchergebnisse') ?>:</h3>
+ <? TextHelper::reset_cycle(); $show_path = TRUE; $show_link = FALSE; ?>
+ <? foreach ($selection->getSearchResult() as $area) : ?>
+ <? // MVV: show LvGruppen with complete trails only ?>
+ <? $pathes = ModuleManagementModelTreeItem::getPathes($area->getTrails(['Modulteil', 'StgteilabschnittModul', 'StgteilAbschnitt', 'StgteilVersion', 'Studiengang'])); ?>
+ <? if (count($pathes)) : ?>
+ <div class="<?= TextHelper::cycle('odd', 'even') ?>">
+ <?= $this->render_partial('course/lvgselector/entry', compact('area', 'show_path', 'show_link', 'pathes')); ?>
+ </div>
+ <? endif; ?>
+ <? endforeach ?>
+ <? endif ?>
+ <? endif ?>
+ </div>
+</div>
diff --git a/app/views/course/lvgselector/index.php b/app/views/course/lvgselector/index.php
new file mode 100644
index 0000000..a16b425
--- /dev/null
+++ b/app/views/course/lvgselector/index.php
@@ -0,0 +1,100 @@
+<? if (!$locked) : ?>
+ <form action="<?= $controller->url_for('course/lvgselector/index/' . $course_id, $url_params) ?>" method="post">
+<? endif ?>
+<h1><?= _('Lehrveranstaltungsgruppen') ?></h1>
+<div id="assigned" data-ajax-url="<?= $ajax_url ?>" data-forward-url="<?= $no_js_url ?>">
+ <h2>
+ <span class="required">
+ <?= _('Bereits zugewiesen') ?>
+ </span>
+ </h2>
+ <ul class="css-tree">
+ <li class="lvgroup-tree-assigned-root keep-node" data-id="root">
+ <ul id="lvgroup-tree-assigned-selected">
+ <? foreach ($selection->getAreas() as $area) : ?>
+ <?= $this->render_partial('course/wizard/steps/lvgroups/lvgroup_entry', compact('area')) ?>
+ <? endforeach ?>
+ </ul>
+ </li>
+ </ul>
+ <? if (!$locked) : ?>
+ <div data-dialog-button class="hidden-no-js">
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ </div>
+ <? endif ?>
+</div>
+<? if (!$locked) : ?>
+ <div id="lvgroup-tree-open-nodes">
+ <? foreach ($open_lvg_nodes as $opennode): ?>
+ <input type="hidden" name="open_lvg_nodes[]" value="<?= $opennode; ?>">
+ <? endforeach; ?>
+ </div>
+ <div id="studyareas" data-ajax-url="<?= $ajax_url ?>"
+ data-forward-url="<?= $no_js_url ?>" data-no-search-result="<?=_('Es wurde kein Suchergebnis gefunden.') ?>">
+ <h2><?= _('Lehrveranstaltungsgruppen Suche') ?></h2>
+ <div>
+ <input type="text" style="width: auto;" size="40" name="search" id="lvgroup-tree-search"
+ value="<?= $searchterm ?>">
+ <span id="lvgroup-tree-search-start">
+ <?= Icon::create('search', 'clickable')->asInput(["name" => 'start_search', "onclick" => "return STUDIP.MVV.CourseWizard.searchTree()", "class" => $search_result?'hidden-no-js':'']) ?>
+ </span>
+ <span id="lvgroup-tree-search-reset" class="hidden-js">
+ <?= Icon::create('refresh', 'clickable')->asInput(["name" => 'reset_search', "onclick" => "return STUDIP.MVV.CourseWizard.resetSearch()", "class" => $search_result?'':' hidden-no-js']) ?>
+ </span>
+ </div>
+
+ <div id="lvgsearchresults" style="display: none;">
+ <h2><?= _('Suchergebnisse') ?></h2>
+ <ul class="collapsable css-tree">
+
+ </ul>
+ </div>
+ <h2><?= _('Alle Lehrveranstaltungsgruppen') ?></h2>
+ <ul class="collapsable css-tree">
+ <li class="lvgroup-tree-root tree-loaded keep-node">
+ <input type="checkbox" id="root" checked="checked"/>
+ <label for="root" class="undecorated">
+ <?= htmlReady(Config::get()->UNI_NAME_CLEAN) ?>
+ </label>
+ <ul>
+ <? $pos_id = 1; ?>
+ <? foreach ((array) $tree as $node) : ?>
+ <? $children = $node->getChildren(); ?>
+ <? if (count($children) || $node->isAssignable()) : ?>
+ <?= $this->render_partial('course/wizard/steps/lvgroups/_node',
+ ['node' => $node, 'pos_id' => $pos_id++,
+ 'open_nodes' => $open_lvg_nodes ?: [],
+ 'search_result' => $search_result ?: [],
+ 'children' => $children]) ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <? if ($open_lvg_nodes) : ?>
+ <input type="hidden" name="open_nodes" value="<?= json_encode($open_lvg_nodes) ?>">
+ <? endif ?>
+ <? if ($searchterm) : ?>
+ <input type="hidden" name="searchterm" value="<?= $searchterm ?>">
+ <? endif ?>
+ <script>
+ //<!--
+ $(function() {
+ var element = $('#lvgroup-tree-search');
+ element.on('keypress', function(e) {
+ if (e.keyCode == 13) {
+ if (element.val() != '') {
+ return STUDIP.MVV.CourseWizard.searchTree();
+ } else {
+ return STUDIP.MVV.CourseWizard.resetSearch();
+ }
+ }
+ });
+ });
+ //-->
+ </script>
+<? endif ?>
+<? if(!$locked) : ?>
+</form>
+<? endif ?>
diff --git a/app/views/course/lvgselector/locked_form.php b/app/views/course/lvgselector/locked_form.php
new file mode 100644
index 0000000..df68051
--- /dev/null
+++ b/app/views/course/lvgselector/locked_form.php
@@ -0,0 +1,23 @@
+<?
+# Lifter010: TODO
+?>
+<div id="lvgruppe_selection">
+ <em>
+ <?= _("Sie dürfen die Modulzuordnung dieser Veranstaltung nicht verändern.") ?>
+ <?= _("Diese Sperrung ist von einer Administratorin oder einem Administrator vorgenommen worden.") ?>
+ </em>
+ <div id="lvgruppe_selection_chosen" style="width: 50%;">
+ <h3><?= _("Bestehende Zuordnungen:") ?></h3>
+ <? if ($selection->size()) : ?>
+ <em id="lvgruppe_selection_none" style="display:none;"><?= _("Bisher wurde noch keine Zuordnung vorgenommen") ?></em>
+ <? else: ?>
+ <em id="lvgruppe_selection_none"><?= _("Bisher wurde noch keine Zuordnung vorgenommen") ?></em>
+ <? endif ?>
+ <ul id="lvgruppe_selection_selected">
+ <? foreach ($selection->getAreas() as $area) : ?>
+ <?= $this->render_partial('course/lvgselector/selected_entry', ['area' => $area]) ?>
+ <? endforeach ?>
+ </ul>
+ </div>
+</div>
+
diff --git a/app/views/course/lvgselector/selected_entries.php b/app/views/course/lvgselector/selected_entries.php
new file mode 100644
index 0000000..bf0df77
--- /dev/null
+++ b/app/views/course/lvgselector/selected_entries.php
@@ -0,0 +1,11 @@
+<?
+# Lifter010: TODO
+?>
+<ul id="lvgruppe_selection_selected">
+
+ <? foreach ($selection->getAreas() as $area) : ?>
+ <?= $this->render_partial('course/lvgselector/selected_entry', compact('area')) ?>
+ <? endforeach ?>
+
+</ul>
+
diff --git a/app/views/course/lvgselector/selected_entry.php b/app/views/course/lvgselector/selected_entry.php
new file mode 100644
index 0000000..b424e6e
--- /dev/null
+++ b/app/views/course/lvgselector/selected_entry.php
@@ -0,0 +1,28 @@
+<?
+$_id = htmlReady(implode('_', (array) $area->getId()));
+?>
+<li id="lvgruppe_selection_<?= $_id ?>">
+<? if (!$locked) : ?>
+ <input title="<?= _('Zuordnung entfernen') ?>"
+ data-id="<?= $_id ?>" data-course_id="<?= htmlReady($course_id) ?>"
+ style="vertical-align: text-top;"
+ type="image"
+ name="lvgruppe_selection[remove][<?= $_id ?>]"
+ src="<?= Icon::create('trash', 'clickable')->asImagePath(); ?>">
+<? endif; ?>
+ <span class="lvgruppe_selection_expand">
+ <?= htmlReady($area->getDisplayName()) ?>
+ <input title="<?= _('Alle Zuordnungen anzeigen') ?>"
+ data-id="<?= $_id ?>" data-course_id="<?= htmlReady($course_id) ?>"
+ style="vertical-align: text-top;"
+ type="image"
+ name="lvgruppe_selection[details][<?= $_id ?>]"
+ src="<?= Icon::create('info', 'clickable')->asImagePath() ?>">
+ </span>
+ <ul>
+ <? if (Request::isXhr()) : ?>
+ <?= $this->render_partial('course/lvgselector/entry_trails') ?>
+ <? endif; ?>
+ </ul>
+ <input type="hidden" name="lvgruppe_selection[areas][]" class="lvgruppe_selection_area" value="<?= $_id ?>">
+</li>
diff --git a/app/views/course/lvgselector/subtree.php b/app/views/course/lvgselector/subtree.php
new file mode 100644
index 0000000..f61463f
--- /dev/null
+++ b/app/views/course/lvgselector/subtree.php
@@ -0,0 +1,23 @@
+<?
+# Lifter010: TODO
+?>
+<ul>
+ <? foreach ($subtree->getChildren() as $child) : ?>
+ <li>
+ <?
+ $has_children = $child->hasChildren();
+ ?>
+
+ <div class="<?= TextHelper::cycle('odd', 'even') ?>">
+ <?= $this->render_partial('course/lvgselector/entry',
+ ['area' => $child,
+ 'show_link' => $has_children]) ?>
+ </div>
+
+ <? if ($selection->getShowAll() && $has_children) : ?>
+ <?= $this->render_partial('course/lvgselector/subtree', ['subtree' => $child]) ?>
+ <? endif ?>
+
+ </li>
+ <? endforeach ?>
+</ul>
diff --git a/app/views/course/lvgselector/tree.php b/app/views/course/lvgselector/tree.php
new file mode 100644
index 0000000..849c23c
--- /dev/null
+++ b/app/views/course/lvgselector/tree.php
@@ -0,0 +1,27 @@
+<?
+?>
+<input type="hidden" name="lvgruppe_selection[last_selected]" value="<?= htmlReady(implode('_', (array) $selection->getSelected()->getId())) ?>">
+<input type="hidden" name="lvgruppe_selection[last_type]" value="<?= htmlReady(get_class($selection->getSelected())) ?>">
+<?
+ $trail = $selection->getTrail();
+ $last = end($trail);
+?>
+
+<? foreach ($trail as $id => $area) : ?>
+ <ul>
+ <li class="trail_element">
+ <?= $this->render_partial('course/lvgselector/entry', ['area' => $area, 'show_link' => $area !== $last]) ?>
+
+ <? if ($area === $last) : ?>
+ <input type="image" name="lvgruppe_selection[showall_button]" title="<?= _('Alle Unterebenen einblenden') ?>" src="<?= Assets::image_path('sem_tree.gif') ?>">
+ <? endif ?>
+<? endforeach ?>
+
+<?= $this->render_partial('course/lvgselector/subtree',
+ ['subtree' => $selection->getSelected()]); ?>
+
+<? foreach ($trail as $id => $area) : ?>
+ </li>
+ </ul>
+<? endforeach ?>
+
diff --git a/app/views/course/management/index.php b/app/views/course/management/index.php
new file mode 100644
index 0000000..c7ab4bf
--- /dev/null
+++ b/app/views/course/management/index.php
@@ -0,0 +1,25 @@
+<ul class="boxed-grid">
+<? foreach (Navigation::getItem('/course/admin') as $name => $nav): ?>
+ <? if ($nav->isVisible() && $name != 'main'): ?>
+ <li>
+ <a href="<?= URLHelper::getLink($nav->getURL()) ?>">
+ <h3>
+ <? if ($nav->getImage()): ?>
+ <?= $nav->getImage()->asImg(false, $nav->getLinkAttributes()) ?>
+ <? endif; ?>
+ <?= htmlReady($nav->getTitle()) ?>
+ </h3>
+ <p>
+ <?= htmlReady($nav->getDescription()) ?>
+ </p>
+ </a>
+ </li>
+ <? endif; ?>
+<? endforeach; ?>
+<!--
+ this is pretty ugly but we need to spawn some empty elements so that the
+ last row of the flex grid won't be messed up if the boxes don't line up
+-->
+ <li></li><li></li><li></li>
+ <li></li><li></li><li></li>
+</ul>
diff --git a/app/views/course/management/lock.php b/app/views/course/management/lock.php
new file mode 100644
index 0000000..6d3d7cc
--- /dev/null
+++ b/app/views/course/management/lock.php
@@ -0,0 +1,26 @@
+<? if (!$GLOBALS['perm']->have_perm('root') && ($current_lock_rule['permission'] == 'admin' || $current_lock_rule['permission'] == 'root')) : ?>
+ <?=MessageBox::info(sprintf(_('Die eingestellte Sperrebene "%s" dürfen Sie nicht ändern.'), htmlReady($current_lock_rule['name'])))?>
+<? else : ?>
+ <form action="<?= $controller->link_for('course/management/set_lock_rule') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= PageLayout::getTitle() ?>
+ </legend>
+
+ <label>
+ <?= _('Sperrebene') ?>
+ <select name="lock_sem" id="lock_sem" aria-labelledby="<?= _('Sperrebene auswählen')?>">
+ <? foreach ($all_lock_rules as $lock_rule) : ?>
+ <option value="<?= $lock_rule['lock_id'] ?>" <?= $current_lock_rule->id == $lock_rule['lock_id'] ? 'selected' : '' ?>>
+ <?= htmlReady($lock_rule['name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ </footer>
+ </form>
+<? endif ?>
diff --git a/app/views/course/members/_studycourse.php b/app/views/course/members/_studycourse.php
new file mode 100644
index 0000000..ac1d380
--- /dev/null
+++ b/app/views/course/members/_studycourse.php
@@ -0,0 +1,21 @@
+<?php
+if ($count = count($studycourses)) {
+ $studycourse = $studycourses->first();
+ echo sprintf(
+ '%s (%s)',
+ htmlReady(trim($studycourse->studycourse_name . ' ' . $studycourse->degree_name)),
+ htmlReady($studycourse->semester)
+ );;
+ if ($count > 1) {
+ echo '[...]';
+ $course_res = implode("\n", $studycourses->limit(1, PHP_INT_MAX)->map(function ($item) {
+ return sprintf(
+ '- %s (%s)<br>',
+ htmlReady(trim($item->studycourse_name . ' ' . $item->degree_name)),
+ htmlReady($item->semester)
+ );
+ }));
+ echo tooltipHtmlIcon('<strong>' . _('Weitere Studiengänge') . '</strong><br>' . $course_res);
+ }
+}
+?>
diff --git a/app/views/course/members/accepted_list.php b/app/views/course/members/accepted_list.php
new file mode 100644
index 0000000..1d053c2
--- /dev/null
+++ b/app/views/course/members/accepted_list.php
@@ -0,0 +1,176 @@
+<? use \Studip\Button; ?>
+<br />
+<a name="users"></a>
+
+<form action="<?= $controller->url_for('course/members/edit_accepted/') ?>" method="post" data-dialog="size=50%">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default collapsable">
+ <caption>
+ <span class="actions">
+ <a href="<?= URLHelper::getLink('dispatch.php/messages/write', [
+ 'filter' => 'prelim',
+ 'emailrequest' => 1,
+ 'course_id' => $course_id,
+ 'default_subject' => $subject,
+ ]) ?>" data-dialog>
+ <?= Icon::create(
+ 'inbox',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(
+ _('Nachricht mit Mailweiterleitung an alle %s versenden'),
+ _('vorläufig akzeptierten Nutzer/-innen')
+ )
+ ]
+ ) ?>
+ </a>
+ </span>
+ <?= _('Vorläufig akzeptierte Teilnehmende') ?>
+ </caption>
+ <colgroup>
+ <? if (!$is_locked): ?>
+ <col width="20">
+ <? endif ?>
+ <col width="20">
+ <col>
+ <col width="15%">
+ <col width="35%">
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <? if (!$is_locked): ?>
+ <th>
+ <input aria-label="<?= sprintf(_('Alle %s auswählen'), _('vorläufig akzeptierten NutzerInnen')) ?>"
+ type="checkbox" name="all" value="1" data-proxyfor=":checkbox[name^=accepted]">
+ </th>
+ <? endif ?>
+ <th></th>
+ <th <?if ($sort_by === 'nachname' && $sort_status === 'accepted') printf('class="sort%s"', $order); ?>>
+ <? $order = $sort_status !== 'accepted' ? 'desc' : $order; ?>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=nachname&sort_status=accepted&order=%s&toggle=%s#users',
+ $order,
+ $sort_by === 'nachname'
+ )) ?>">
+ <?= _('Nachname, Vorname') ?>
+ </a>
+ </th>
+ <th <? if ($sort_by === 'mkdate' && $sort_status === 'accepted') printf('class="sort%s"', $order); ?>>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=mkdate&sort_status=accepted&order=%s&toggle=%s#accepted',
+ $order,
+ $sort_by === 'mkdate'
+ )) ?>">
+ <?= _('Anmeldedatum') ?>
+ </a>
+ </th>
+ <th><?=_('Studiengang')?></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $nr= 0; ?>
+ <? foreach ($accepted as $accept) : ?>
+ <? $fullname = $accept['fullname'];?>
+ <tr>
+ <? if (!$is_locked) : ?>
+ <td>
+ <input aria-label="<?= sprintf(_('%s auswählen'), _('Vorläufig akzeptierte/n NutzerIn')) ?>"
+ type="checkbox" name="accepted[<?= $accept['user_id'] ?>]" value="1"
+ <? if (isset($flash['checked']) && in_array($accept['user_id'], $flash['checked'])) echo 'checked'; ?>>
+ </td>
+ <? endif ?>
+ <td style="text-align: right"><?= sprintf('%02u', ++$nr) ?></td>
+ <td>
+ <a href="<?= $controller->url_for('profile?username=' . $accept['username']) ?>" <? if ($accept['mkdate'] >= $last_visitdate) echo 'class="new-member"'; ?>>
+ <?= Avatar::getAvatar($accept['user_id'], $accept['username'])->getImageTag(
+ Avatar::SMALL,
+ [
+ 'style' => 'margin-right: 5px',
+ 'title' => $fullname,
+ ]
+ ) ?>
+ <?= htmlReady($fullname) ?>
+ </a>
+ <? if ($accept['comment']): ?>
+ <?= tooltipHtmlIcon(sprintf(
+ '<strong>%s</strong><br>%s',
+ _('Bemerkung'),
+ htmlReady($accept['comment'])
+ )) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <? if (!empty($accept['mkdate'])) : ?>
+ <?= strftime('%x %X', $accept['mkdate'])?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= $this->render_partial('course/members/_studycourse.php', [
+ 'studycourses' => new SimpleCollection(UserStudyCourse::findByUser($accept['user_id']))
+ ]) ?>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/add_comment/' . $accept['user_id']),
+ _('Bemerkung hinzufügen'),
+ Icon::create('comment'),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? if ($user_id !== $accept['user_id']) : ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write',[
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'rec_uname' => $accept['username'],
+ 'default_subject' => $subject,
+ ]),
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create(
+ 'mail',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf('Nachricht mit Weiterleitung an %s senden', htmlReady($fullname))
+ ]
+ ),
+ ['data-dialog' => '']
+ ) ?>
+ <? endif?>
+ <? if (!$is_locked) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/cancel_subscription/singleuser/accepted/' . $accept['user_id']),
+ _('Aus Veranstaltung austragen'),
+ Icon::create(
+ 'door-leave',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(_('%s austragen'), htmlReady($fullname))
+ ]
+ )
+ ) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <? if (!$is_locked) : ?>
+ <tfoot>
+ <tr>
+ <td class="printhead" colspan="6">
+ <select name="action_accepted" id="action_accepted" aria-label="<?= _('Aktion ausführen') ?>">
+ <option value="">- <?= _('Aktion wählen') ?></option>
+ <option value="upgrade"><?= _('Akzeptieren') ?></option>
+ <option value="remove"><?= _('Austragen') ?></option>
+ <option value="message"><?=_('Nachricht senden')?></option>
+ <!--<option value="copy_to_course"><?= _('In Seminar verschieben/kopieren') ?></option>-->
+ </select>
+ <?= Button::create(_('Ausführen'), 'submit_accepted') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+</form>
diff --git a/app/views/course/members/add_comment.php b/app/views/course/members/add_comment.php
new file mode 100644
index 0000000..267cbb8
--- /dev/null
+++ b/app/views/course/members/add_comment.php
@@ -0,0 +1,19 @@
+<form class="default" action="<?= $controller->link_for('course/members/set_comment/' . $user->user_id)?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= PageLayout::getTitle() ?></legend>
+
+ <label>
+ <?= _('Bemerkung') ?>
+ <textarea name="comment" aria-label="<?=_('Bemerkung')?>" rows="8" maxlength="255" id="comment"><?=htmlReady($comment)?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('course/members')
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/course/members/add_dozent.php b/app/views/course/members/add_dozent.php
new file mode 100644
index 0000000..a4a508f
--- /dev/null
+++ b/app/views/course/members/add_dozent.php
@@ -0,0 +1,37 @@
+<h1><?= sprintf(_('%s hinzufügen'), htmlReady($decoratedStatusGroups['dozent'])) ?></h1>
+
+<form action="<?= $controller->url_for('course/members/set') ?>" method="post">
+<?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studipticket" value="<?= $studipticket ?>">
+ <table class="default">
+ <thead>
+ <tr>
+ <th colspan="2"><?= sprintf(_('%s suchen'), htmlReady($decoratedStatusGroups['dozent'])) ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <?=
+ QuickSearch::get('new_dozent', $search)
+ ->withButton(
+ [
+ 'reset_button_name' => 'reset_dozent',
+ 'search_button_name' => 'search_dozent'
+ ]
+ )->render();
+ ?>
+ <input type="hidden" name="seminar_id" value="<?= $course_id ?>">
+ </td>
+ <td>
+ <?= Studip\Button::createAccept(
+ _('Eintragen'),
+ 'add_dozent',
+ ['title' => sprintf(_("als %s eintragen"), htmlReady($decoratedStatusGroups['dozent']))]
+ ) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/members/index')) ?>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</form>
diff --git a/app/views/course/members/add_member.php b/app/views/course/members/add_member.php
new file mode 100644
index 0000000..8d597e4
--- /dev/null
+++ b/app/views/course/members/add_member.php
@@ -0,0 +1,99 @@
+<h1><?=sprintf(_('%s hinzufügen'), htmlReady($decoratedStatusGroups['autor']))?></h1>
+<form action="<?=$controller->url_for('course/members/set_autor')?>" method="post">
+<?= CSRFProtection::tokenTag() ?>
+ <table class="default collapsable">
+ <tbody>
+ <tr class="table_header header-row">
+ <th class="toggle-indicator" colspan="4">
+ <a class="toggler">
+ <?=sprintf(_('%s in die Veranstaltung hinzufügen'), htmlReady($decoratedStatusGroups['autor']))?>
+ </a>
+ </th>
+ </tr>
+ <tr>
+ <td style="width: 30%; text-align: left">
+ <?= sprintf(_('<strong>%s</strong> in die Veranstaltung eintragen'), htmlReady($decoratedStatusGroups['autor']))?>
+ </td>
+ <td style="width: 30%; text-align: left">
+ <?= QuickSearch::get("new_autor", $search)
+ ->withButton(['reset_button_name' => 'reset_autor', 'search_button_name' => 'search_autor'])
+ ->render();
+ ?>
+ <input type="hidden" name="cid" value="<?= $course_id ?>">
+ </td>
+ <td style="width: 20%; text-align: center">
+
+ </td>
+ <td style="width: 20%; text-align: right">
+ <?= Studip\Button::createAccept(
+ _('Eintragen'),
+ 'add_autor',
+ ['title' => sprintf(_("als %s eintragen"), $decoratedStatusGroups['autor'])]
+ ) ?>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</form>
+
+<form action="<?= $controller->url_for('course/members/set_autor_csv')?>" method="post" name="user">
+<?= CSRFProtection::tokenTag() ?>
+<table class="default collapsable">
+ <tbody class="collapsed">
+ <tr class="table_header header-row">
+ <th class="toggle-indicator" colspan="3">
+ <a class="toggler">
+ <?=_('Teilnehmendenliste übernehmen')?>
+ </a>
+ </th>
+ </tr>
+ <tr>
+ <td>
+ <?=_('Eingabeformat')?>:
+
+ <?= tooltipHtmlIcon(sprintf(_('In das Textfeld <strong>Teilnehmendenliste übernehmen</strong> können Sie eine Liste mit Namen von %s eingeben,
+ die in die Veranstaltung aufgenommen werden sollen. Wählen Sie in der Auswahlbox das gewünschte Format, in dem Sie die Namen eingeben möchten.<br />
+ <strong>Eingabeformat</strong><br/>
+ <strong>Nachname, Vorname &crarr;</strong><br />Geben Sie dazu in jede Zeile den Nachnamen und (optional) den Vornamen getrennt durch ein Komma oder ein Tabulatorzeichen ein.<br />
+ <strong>Nutzername &crarr;</strong><br />Geben Sie dazu in jede Zeile den Stud.IP Nutzernamen ein.'), htmlReady($status_groups['autor'])));?>
+ </td>
+ <td colspan="2">
+ <select name="csv_import_format">
+ <option value="realname"><?=_("Nachname, Vorname")?> &crarr;</option>
+ <option value="username"><?=_("Nutzername")?> &crarr;</option>
+ <? if(!empty($accessible_df)) : ?>
+ <? foreach ($accessible_df as $df) : ?>
+ <option value="<?=$df->getId()?>" <?=(Request::get('csv_import_format') == $df->getId()? 'selected="selected"': '')?>><?= htmlReady($df->getName())?> &crarr;</option>
+ <? endforeach?>
+ <? endif ?>
+ </select>
+ </td>
+ </tr>
+
+ <tr>
+ <td style="width: 30%">
+ <?= sprintf(
+ _('<strong>%s</strong> in die Veranstaltung eintragen'),
+ htmlReady($decoratedStatusGroups['autor'])
+ )?>
+ </td>
+ <td style="width: 50%">
+ <textarea name="csv_import" rows="6" cols="50"></textarea>
+ </td>
+ <td style="width: 20%; text-align: right">
+ <?= Studip\Button::createAccept(
+ _('Eintragen'),
+ 'add_member_list',
+ [
+ 'title' => sprintf(_("als %s eintragen"), htmlReady($decoratedStatusGroups['autor']))
+ ]
+ ) ?>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</form>
+
+<div style="text-align: right">
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/members/index')) ?>
+</div>
diff --git a/app/views/course/members/add_tutor.php b/app/views/course/members/add_tutor.php
new file mode 100644
index 0000000..95e9abc
--- /dev/null
+++ b/app/views/course/members/add_tutor.php
@@ -0,0 +1,34 @@
+<h1><?=sprintf(_('%s hinzufügen'), htmlReady($decoratedStatusGroups['tutor']))?></h1>
+
+<form action="<?=$controller->url_for('course/members/set')?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studipticket" value="<?=$studipticket?>">
+ <table class="default">
+ <thead>
+ <tr>
+ <th colspan="2">
+ <?=sprintf(_('%s suchen'), htmlReady($decoratedStatusGroups['tutor']))?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <?= QuickSearch::get('new_tutor', $search)
+ ->withButton(['reset_button_name' => 'reset_tutor',
+ 'search_button_name' => 'search_tutor'])
+ ->render(); ?>
+ <input type="hidden" name="seminar_id" value="<?= $course_id ?>">
+ </td>
+ <td>
+ <?= Studip\Button::createAccept(
+ _('Eintragen'),
+ 'add_tutor',
+ ['title' => sprintf(_('als %s eintragen'), htmlReady($decoratedStatusGroups['tutor']))]
+ ) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/members/index')) ?>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</form>
diff --git a/app/views/course/members/additional.php b/app/views/course/members/additional.php
new file mode 100644
index 0000000..d1af456
--- /dev/null
+++ b/app/views/course/members/additional.php
@@ -0,0 +1,34 @@
+<? if (!empty($aux['rows'])) : ?>
+ <form method="post" action="<?= $controller->url_for('course/members/store_additional')?>">
+ <?= CSRFProtection::tokenTag()?>
+ <table class="default hide_datafield_title">
+ <caption><?= _('Zusatzangaben bearbeiten') ?></caption>
+ <thead>
+ <tr>
+ <? foreach ($aux['head'] as $head): ?>
+ <th><?= htmlReady($head) ?></th>
+ <? endforeach; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($aux['rows'] as $entry): ?>
+ <tr>
+ <? foreach ($aux['head'] as $key => $value): ?>
+ <td><?= $key === 'name' ? htmlReady($entry[$key]) : $entry[$key] ?></td>
+ <? endforeach; ?>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="<?= count($aux['head']) ?>">
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </td>
+ </tr>
+ </tfoot>
+
+ </table>
+ </form>
+<? else : ?>
+ <?= MessageBox::info(_('Keine Zusatzangaben oder Teilnehmende vorhanden.')) ?>
+<? endif ?>
diff --git a/app/views/course/members/additional_input.php b/app/views/course/members/additional_input.php
new file mode 100644
index 0000000..89df041
--- /dev/null
+++ b/app/views/course/members/additional_input.php
@@ -0,0 +1,30 @@
+<form class="default" method="post">
+ <? if ($datafields) : ?>
+ <fieldset>
+ <legend>
+ <?= htmlReady($aux->name) ?>
+ </legend>
+
+ <p><?= formatReady($aux->description) ?></p>
+
+ <? foreach ($datafields as $field): ?>
+ <? if ($field->getTypedDatafield()->isVisible()): ?>
+ <? if ($field->getTypedDatafield()->isEditable()) : ?>
+ <? $editable = true; ?>
+ <? endif ?>
+ <?= $field->getTypedDatafield()->getHTML('aux'); ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </fieldset>
+
+ <? if ($editable): ?>
+ <footer>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </footer>
+ <? else: ?>
+ <?= MessageBox::info(_('Keine einstellbaren Zusatzdaten vorhanden')) ?>
+ <? endif; ?>
+ <? else : ?>
+ <?= MessageBox::info(_('Keine einstellbaren Zusatzdaten vorhanden')) ?>
+ <? endif; ?>
+</form>
diff --git a/app/views/course/members/autor_list.php b/app/views/course/members/autor_list.php
new file mode 100644
index 0000000..056477d
--- /dev/null
+++ b/app/views/course/members/autor_list.php
@@ -0,0 +1,225 @@
+<? use \Studip\Button; ?>
+<a name="autoren"></a>
+
+
+<form action="<?= $controller->url_for('course/members/edit_autor') ?>" method="post" data-dialog="">
+ <?= CSRFProtection::tokenTag() ?>
+ <table id="autor" class="default collapsable tablesorter">
+ <caption>
+ <? if ($is_tutor) : ?>
+ <span class="actions">
+ <a href="<?= URLHelper::getLink('dispatch.php/messages/write', [
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'who' => 'autor',
+ 'course_id' => $course_id,
+ 'default_subject' => $subject,
+ ]) ?>" data-dialog>
+ <?= Icon::create(
+ 'inbox',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(
+ _('Nachricht mit Mailweiterleitung an alle %s versenden'),
+ htmlReady($status_groups['autor']
+ )
+ )
+ ]) ?>
+ </a>
+ </span>
+ <? endif ?>
+ <?= htmlReady($status_groups['autor']) ?>
+ </caption>
+ <colgroup>
+ <col width="20">
+ <? if ($is_tutor) : ?>
+ <? if (!$is_locked) : ?>
+ <col width="20">
+ <? endif ?>
+ <col>
+ <col width="15%">
+ <col width="35%">
+ <? $cols = $cols_foot = 6; ?>
+ <? else : ?>
+ <col>
+ <? $cols = 3 ?>
+ <? endif ?>
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <? if ($is_tutor && !$is_locked) : ?>
+ <th>
+ <input aria-label="<?= sprintf(_('Alle %s auswählen'), htmlReady($status_groups['autor'])) ?>"
+ type="checkbox" name="all" value="1" data-proxyfor=":checkbox[name^=autor]">
+ </th>
+ <? endif ?>
+ <th></th>
+ <th <? if ($sort_by === 'nachname' && $sort_status === 'autor') printf('class="sort%s"', $order); ?>>
+ <? $order = $sort_status !== 'autor' ? 'desc' : $order; ?>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=nachname&sort_status=autor&order=%s&toggle=%s#autoren',
+ $order,
+ $sort_by === 'nachname'
+ )) ?>">
+ <?= _('Nachname, Vorname') ?>
+ </a>
+ </th>
+ <? if($is_tutor) :?>
+ <th <? if ($sort_by === 'mkdate' && $sort_status === 'autor') printf('class="sort%s"', $order); ?>>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=mkdate&sort_status=autor&order=%s&toggle=%s#autoren',
+ $order,
+ $sort_by === 'mkdate'
+ )) ?>">
+ <?= _('Anmeldedatum') ?>
+ </a>
+ </th>
+ <th><?= _('Studiengang') ?></th>
+ <? endif ?>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $nr = $autor_nr?>
+ <? foreach ($autoren as $autor) : ?>
+ <? $fullname = $autor['fullname']?>
+ <tr>
+ <? if ($is_tutor && !$is_locked) : ?>
+ <td>
+ <input aria-label="<?= sprintf(_('%s auswählen'), htmlReady($status_groups['autor'])) ?>"
+ type="checkbox" name="autor[<?= $autor['user_id'] ?>]" value="1"
+ <? if (isset($flash['checked']) && in_array($autor['user_id'], $flash['checked'])) echo 'checked'; ?>>
+ </td>
+ <? endif ?>
+ <td style="text-align: right"><?= sprintf('%02u', ++$nr) ?></td>
+ <td>
+ <a href="<?= $controller->url_for('profile?username=' . $autor['username']) ?>" <? if ($autor['mkdate'] >= $last_visitdate) echo 'class="new-member"'; ?>>
+ <?= Avatar::getAvatar($autor['user_id'], $autor['username'])->getImageTag(
+ Avatar::SMALL,
+ [
+ 'style' => 'margin-right: 5px',
+ 'title' => $fullname
+ ]
+ ) ?>
+ <?= htmlReady($fullname) ?>
+ <? if ($user_id === $autor['user_id'] && $autor['visible'] === 'no') : ?>
+ (<?= _('unsichtbar') ?>)
+ <? endif ?>
+ </a>
+ <? if ($is_tutor && $autor['comment']) : ?>
+ <?= tooltipHtmlIcon(sprintf(
+ '<strong>%s</strong><br>%s',
+ _('Bemerkung'),
+ htmlReady($autor['comment'])
+ )) ?>
+ <? endif ?>
+ </td>
+ <? if ($is_tutor) : ?>
+ <td>
+ <? if (!empty($autor['mkdate'])) : ?>
+ <?= strftime('%x %X', $autor['mkdate'])?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= $this->render_partial('course/members/_studycourse.php', [
+ 'studycourses' => new SimpleCollection(UserStudyCourse::findByUser($autor['user_id'])),
+ ]) ?>
+ </td>
+ <? endif ?>
+
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($is_tutor) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/add_comment/' . $autor['user_id']),
+ _('Bemerkung hinzufügen'),
+ Icon::create('comment'),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? endif ?>
+ <? if ($user_id !== $autor['user_id']) : ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write', [
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'rec_uname' => $autor['username'],
+ 'default_subject' => $subject,
+ ]),
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create(
+ 'mail',
+ Icon::ROLE_CLICKABLE, [
+ 'title' => sprintf(_('Nachricht mit Weiterleitung an %s senden'), htmlReady($fullname)),
+ ]),
+ ['data-dialog' => '']
+ ) ?>
+ <? else: ?>
+ <? $actionMenu->addLink(
+ '#',
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create('mail', Icon::ROLE_INACTIVE),
+ ['disabled' => true]
+ ) ?>
+ <? endif ?>
+ <? if ($is_tutor && !$is_locked) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/cancel_subscription/singleuser/autor/' . $autor['user_id']),
+ _('Aus Veranstaltung austragen'),
+ Icon::create(
+ 'door-leave',
+ Icon::ROLE_CLICKABLE,
+ ['title' => sprintf(_('%s austragen'), htmlReady($fullname))])
+ ) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? if ($invisibles > 0) : ?>
+ <tr>
+ <td colspan="<?= $cols ?>" class="blank"></td>
+ </tr>
+ <tr>
+ <td colspan="<?= $cols ?>">+ <?= sprintf(_('%u unsichtbare %s'), $invisibles, htmlReady($status_groups['autor'])) ?></td>
+ </tr>
+ <? endif ?>
+
+ </tbody>
+ <? if ($is_tutor && !$is_locked && count($autoren) > 0) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="<?= $cols_foot ?>">
+ <select name="action_autor" id="action_autor" aria-label="<?= _('Aktion ausführen') ?>">
+ <option value="">- <?= _('Aktion wählen') ?></option>
+ <? if($is_dozent) : ?>
+ <option value="upgrade">
+ <?= sprintf(_('Zu %s hochstufen'), htmlReady($status_groups['tutor'])) ?>
+ </option>
+ <? endif ?>
+ <option value="downgrade">
+ <?= sprintf(_('Zu %s herunterstufen'), htmlReady($status_groups['user'])) ?>
+ </option>
+ <? if ($to_waitlist_actions) : ?>
+ <option value="to_admission_first">
+ <?= _('An den Anfang der Warteliste verschieben') ?>
+ </option>
+ <option value="to_admission_last">
+ <?= _('Ans Ende der Warteliste verschieben') ?>
+ </option>
+ <? endif ?>
+ <option value="remove"><?= _('Austragen') ?></option>
+ <? if($is_dozent) : ?>
+ <option value="to_course">
+ <?= _('In andere Veranstaltung verschieben/kopieren') ?>
+ </option>
+ <? endif ?>
+ <option value="message"><?=_('Nachricht senden')?></option>
+ </select>
+ <?= Button::create(_('Ausführen'), 'submit_autor') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+</form>
diff --git a/app/views/course/members/awaiting_list.php b/app/views/course/members/awaiting_list.php
new file mode 100644
index 0000000..05c0472
--- /dev/null
+++ b/app/views/course/members/awaiting_list.php
@@ -0,0 +1,163 @@
+<br>
+<a name="awaiting"></a>
+<form action="<?= $controller->link_for('course/members/edit_awaiting') ?>" method="post" data-dialog="size=50%">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default collapsable ">
+ <caption>
+ <?= $waitingTitle ?>
+ <span class="actions">
+ <a href="<?= URLHelper::getLink('dispatch.php/messages/write', [
+ 'filter' => $waiting_type,
+ 'emailrequest' => 1,
+ 'course_id' => $course_id,
+ 'default_subject' => $subject,
+ ])?>" data-dialog>
+ <?= Icon::create('inbox')->asImg([
+ 'title' => _('Nachricht mit Mailweiterleitung an alle Wartenden versenden'),
+ ]) ?>
+ </a>
+ </span>
+ </caption>
+ <colgroup>
+ <? if (!$is_locked): ?>
+ <col width="20">
+ <? endif; ?>
+ <col width="20">
+ <col>
+ <col width="15%">
+ <col width="35%">
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <? if (!$is_locked) : ?>
+ <th>
+ <input aria-label="<?= _('NutzerInnen auswählen') ?>"
+ type="checkbox" name="all" value="1"
+ data-proxyfor=":checkbox[name^=awaiting]"
+ data-activates="#action_awaiting,button[name='submit_awaiting']">
+ </th>
+ <? endif ?>
+ <th></th>
+ <th <? if ($sort_by === 'nachname' && $sort_status === $waiting_type) printf('class="sort%s"', $order); ?>>
+ <a href="<?= URLHelper::getLink(sprintf(
+ "?sortby=nachname&sort_status={$waiting_type}&order=%s&toggle=%s#awaiting",
+ $order,
+ $sort_by === 'nachname'
+ )) ?>">
+ <?= _('Nachname, Vorname') ?>
+ </a>
+ </th>
+ <th style="text-align: center" <? if ($sort_by === 'position' && $sort_status === $waiting_type) printf('class="sort%s"', $order); ?>>
+ <? $order = $sort_status !== $waiting_type ? 'desc' : $order; ?>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=position&sort_status=%s&order=%s&toggle=%s#awaiting',
+ $waiting_type,
+ $order,
+ $sort_by === 'position'
+ )) ?>">
+ <? if ($waiting_type === 'awaiting'): ?>
+ <?= _('Position') ?>
+ <? else: ?>
+ <?= _('Priorität') ?>
+ <? endif; ?>
+ </a>
+ </th>
+ <th><?= _('Studiengang') ?></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $nr = 0 ?>
+ <? foreach ($awaiting as $waiting) : ?>
+ <? $fullname = $waiting['fullname'] ;?>
+ <tr>
+ <? if (!$is_locked) : ?>
+ <td>
+ <input aria-label="<?= _('NutzerIn auswählen') ?>" type="checkbox"
+ name="awaiting[<?= htmlReady($waiting['user_id']) ?>]" value="1"
+ <? if (isset($flash['checked']) && in_array($waiting['user_id'], $flash['checked'])) echo 'checked'; ?>>
+ </td>
+ <? endif ?>
+ <td style="text-align: right"><?= sprintf('%02d', ++$nr) ?></td>
+ <td>
+ <a href="<?= $controller->url_for('profile?username=' . $waiting['username']) ?>" <? if ($waiting['mkdate'] >= $last_visitdate) echo 'class="new-member"'; ?>>
+ <?= Avatar::getAvatar($waiting['user_id'], $waiting['username'])->getImageTag(Avatar::SMALL, [
+ 'style' => 'margin-right: 5px',
+ 'title' => htmlReady($fullname),
+ ]) ?>
+ <?= htmlReady($fullname) ?>
+ </a>
+ </td>
+ <td style="text-align: center">
+ <?= $waiting['position'] ?>
+ </td>
+ <td>
+ <?= $this->render_partial('course/members/_studycourse.php', [
+ 'studycourses' => new SimpleCollection(UserStudyCourse::findByUser($waiting['user_id']))
+ ]) ?>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($user_id !== $waiting['user_id']) : ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write', [
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'rec_uname' => $waiting['username'],
+ 'default_subject' => $subject,
+ ]),
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create(
+ 'mail',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(
+ _('Nachricht mit Weiterleitung an %s senden'),
+ htmlReady($fullname)
+ )
+ ]
+ ),
+ ['data-dialog' => '']
+ ) ?>
+ <? endif?>
+ <? if (!$is_locked) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/cancel_subscription/singleuser/' . $waiting_type . '/' . $waiting['user_id']),
+ _('Aus Veranstaltung austragen'),
+ Icon::create(
+ 'door-leave',
+ 'clickable',
+ ['title' => sprintf(_('%s austragen'), htmlReady($fullname))]
+ )
+ ) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <? if (!$is_locked) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <select name="action_awaiting" id="action_awaiting" aria-label="<?= _('Aktion ausführen') ?>">
+ <option value="">- <?= _('Aktion wählen') ?></option>
+ <option value="upgrade_autor">
+ <?= sprintf(_('Zu %s hochstufen'), htmlReady($status_groups['autor'])) ?>
+ </option>
+ <option value="upgrade_user">
+ <?= sprintf(_('Zu %s hochstufen'), htmlReady($status_groups['user'])) ?>
+ </option>
+ <option value="remove"><?= _('Austragen') ?></option>
+ <option value="message"><?=_('Nachricht senden')?></option>
+<!-- <option value="copy_to_sem"><?= _('In Seminar verschieben/kopieren') ?></option>-->
+ </select>
+ <input type="hidden" value="<?= htmlReady($waiting_type) ?>" name="waiting_type"/>
+ <?= \Studip\Button::create(_('Ausführen'), 'submit_awaiting') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+</form>
diff --git a/app/views/course/members/csv_manual_assignment.php b/app/views/course/members/csv_manual_assignment.php
new file mode 100644
index 0000000..fef01af
--- /dev/null
+++ b/app/views/course/members/csv_manual_assignment.php
@@ -0,0 +1,43 @@
+<h1><?=_('Manuelle Zuordnung')?></h1>
+<?= (isset($flash['error'])) ? MessageBox::error($flash['error']) : '' ?>
+<?= (isset($flash['success'])) ? MessageBox::success($flash['success']) : '' ?>
+<?= (isset($flash['info'])) ? MessageBox::info($flash['info']) : '' ?>
+<form action="<?= $controller->url_for('course/members/set_autor_csv')?>" method="post" name="user" class="default">
+<?= CSRFProtection::tokenTag() ?>
+<table class="default">
+ <thead>
+ <tr>
+ <th class="topic" colspan="2">
+ <?=sprintf(_('Folgende %s konnten <b>nicht eindeutig</b> zugewiesen werden. Bitte wählen Sie aus der jeweiligen Trefferliste:'), htmlReady($status_groups['autor']))?>
+ </th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <? foreach($flash['csv_mult_founds'] as $name => $csv_mult_found) : ?>
+ <tr>
+ <td style="width: 40%"><?=htmlReady(mila($name, 50));?></td>
+ <td>
+ <select name="selected_users[]">
+ <option value="---">--<?=_('bitte auswählen')?> --</option>
+ <? foreach ($csv_mult_found as $csv_found) : ?>
+ <? if ($csv_found['is_present']) : ?>
+ <? continue ?>
+ <? endif?>
+ <option value="<?=$csv_found['username']?>"><?=htmlReady(my_substr($csv_found['fullname'], 0, 50))?> (<?=$csv_found['username']?>) - <?=$csv_found['perms']?></option>
+ <? endforeach ?>
+ </select>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+
+ <tfoot data-dialog-button>
+ <tr>
+ <td colspan="2">
+ <?= Studip\Button::createAccept(_('Eintragen'))?>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+</form>
diff --git a/app/views/course/members/dozent_list.php b/app/views/course/members/dozent_list.php
new file mode 100644
index 0000000..2206fb0
--- /dev/null
+++ b/app/views/course/members/dozent_list.php
@@ -0,0 +1,119 @@
+<table class="default collapsable ">
+ <caption>
+ <? if ($is_tutor) : ?>
+ <span class="actions">
+ <a href="<?= URLHelper::getLink('dispatch.php/messages/write', [
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'who' => 'dozent',
+ 'course_id' => $course_id,
+ 'default_subject' => $subject
+ ]) ?>" data-dialog>
+ <?= Icon::create(
+ 'inbox',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(
+ _('Nachricht mit Mailweiterleitung an alle %s versenden'),
+ htmlReady($status_groups['dozent'])
+ )
+ ]
+ )->asImg() ?>
+ </a>
+ </span>
+ <? endif ?>
+ <?= htmlReady($status_groups['dozent']) ?>
+ </caption>
+ <colgroup>
+ <col width="<?= $is_tutor ? 40 : 20 ?>">
+ <col>
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <th></th>
+ <th <? if ($sort_by === 'nachname' && $sort_status === 'dozent') printf('class="sort%s"', $order); ?>>
+ <? $order = $sort_status !== 'dozent' ? 'desc' : $order; ?>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=nachname&sort_status=dozent&order=%s&toggle=%s',
+ $order, $sort_by === 'nachname'
+ )) ?>">
+ <?= _('Nachname, Vorname') ?>
+ </a>
+ </th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $nr = 0?>
+ <? foreach($dozenten as $dozent) : ?>
+ <? $fullname = $dozent['fullname'];?>
+ <tr>
+ <td style="text-align: right"><?= (++$nr < 10) ? sprintf('%02d', $nr) : $nr ?></td>
+ <td>
+ <a href="<?= $controller->url_for(sprintf('profile?username=%s',$dozent['username'])) ?>" <? if ($dozent['mkdate'] >= $last_visitdate) echo 'class="new-member"'; ?>>
+ <?= Avatar::getAvatar($dozent['user_id'], $dozent['username'])->getImageTag(Avatar::SMALL, [
+ 'style' => 'margin-right: 5px',
+ 'title' => $fullname,
+ ]) ?>
+ <?= htmlReady($fullname) ?>
+ </a>
+ <? if ($is_tutor && $dozent['comment']) : ?>
+ <?= tooltipHtmlIcon(sprintf(
+ '<strong>%s</strong><br>%s',
+ _('Bemerkung'),
+ htmlReady($dozent['comment'])
+ )) ?>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($is_tutor) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/add_comment/' . $dozent['user_id']),
+ _('Bemerkung hinzufügen'),
+ Icon::create('comment'),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? endif ?>
+ <? if($user_id !== $dozent['user_id']) : ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write',[
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'rec_uname' => $dozent['username'],
+ 'default_subject' => $subject,
+ ]),
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create(
+ 'mail',
+ Icon::ROLE_CLICKABLE,
+ ['title' => sprintf('Nachricht mit Weiterleitung an %s senden', htmlReady($fullname))]
+ ),
+ ['data-dialog' => '1']
+ ) ?>
+ <? else: ?>
+ <? $actionMenu->addLink(
+ '#',
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create('mail', Icon::ROLE_INACTIVE),
+ ['disabled' => true]
+ ) ?>
+ <? endif ?>
+ <? if (!$dozent_is_locked && $is_dozent && $user_id !== $dozent['user_id'] && count($dozenten) > 1) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/cancel_subscription/singleuser/dozent/' . $dozent['user_id']),
+ _('Aus Veranstaltung austragen'),
+ Icon::create(
+ 'door-leave',
+ Icon::ROLE_CLICKABLE,
+ ['title' => sprintf(_('%s austragen'), htmlReady($fullname))]
+ )
+ ) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/course/members/import_autorlist.php b/app/views/course/members/import_autorlist.php
new file mode 100644
index 0000000..d8c1255
--- /dev/null
+++ b/app/views/course/members/import_autorlist.php
@@ -0,0 +1,46 @@
+<? use Studip\Button, Studip\LinkButton;?>
+
+<form action="<?= $controller->url_for('course/members/set_autor_csv')?>" method="post" name="user" data-dialog class="default">
+<?= CSRFProtection::tokenTag() ?>
+ <h1>
+ <?=sprintf(_('%s hinzufügen'), htmlReady(get_title_for_status('autor', 1)))?>
+ </h1>
+ <fieldset>
+ <legend>
+ <?=_('Teilnehmendenliste übernehmen')?>
+ </legend>
+
+ <label>
+ <?=_('Eingabeformat')?>:
+
+ <?= tooltipHtmlIcon(sprintf(_('In das Textfeld <strong>Teilnehmendenliste übernehmen</strong> können Sie eine Liste mit Namen von %s eingeben,
+ die in die Veranstaltung aufgenommen werden sollen. Wählen Sie in der Auswahlbox das gewünschte Format, in dem Sie die Namen eingeben möchten.<br />
+ <strong>Eingabeformat</strong><br/>
+ <strong>Nachname, Vorname &crarr;</strong><br />Geben Sie dazu in jede Zeile den Nachnamen und (optional) den Vornamen getrennt durch ein Komma oder ein Tabulatorzeichen ein.<br />
+ <strong>Nutzername &crarr;</strong><br />Geben Sie dazu in jede Zeile den Stud.IP Nutzernamen ein.<br />
+ <strong>Email &crarr;</strong><br />Geben Sie dazu in jede Zeile die Email Adresse ein.'), htmlReady($status_groups['autor'])));?>
+
+ <select name="csv_import_format">
+ <option value="realname"><?=_("Nachname, Vorname")?> &crarr;</option>
+ <option value="username"><?=_("Nutzername")?> &crarr;</option>
+ <option value="email"><?=_("Email")?> &crarr;</option>
+ <? if(!empty($accessible_df)) : ?>
+ <? foreach ($accessible_df as $df) : ?>
+ <option value="<?=$df->getId()?>" <?=(Request::get('csv_import_format') == $df->getId()? 'selected="selected"': '')?>><?= htmlReady($df->getName())?> &crarr;</option>
+ <? endforeach?>
+ <? endif ?>
+ </select>
+ </label>
+
+ <label>
+ <?= sprintf(_('<strong>%s</strong> in die Veranstaltung eintragen'), htmlReady(get_title_for_status('autor', 1)))?></td>
+ <textarea name="csv_import" rows="6" cols="50"></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Button::createAccept(_('Eintragen'), 'add_member_list',
+ ['title' => sprintf(_("als %s eintragen"), htmlReady(get_title_for_status('autor', 1)))]) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/members/index')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/members/index.php b/app/views/course/members/index.php
new file mode 100644
index 0000000..2eef8b6
--- /dev/null
+++ b/app/views/course/members/index.php
@@ -0,0 +1,36 @@
+<? if (count($dozenten) > 0) : ?>
+ <?= $this->render_partial('course/members/dozent_list') ?>
+<? endif ?>
+
+<? if (count($tutoren) > 0) : ?>
+ <br />
+ <?= $this->render_partial('course/members/tutor_list') ?>
+<? endif ?>
+
+<? if ($is_tutor && $semAdmissionEnabled) : ?>
+ <p style="float: right">
+ <? //TODO?>
+ <strong><?= _('Teilnahmebeschränkte Veranstaltung') ?></strong> -
+ <?= _('max. Teilnehmendenanzahl') ?> <?= $course->admission_turnout ?>,
+ <?= _('davon belegt') ?>: <?= (count($autoren) + count($users) + count($accepted)) ?>
+ </p>
+ <div class="clear"></div>
+<? endif ?>
+
+<? if(count($autoren) >0) : ?>
+ <br />
+ <?= $this->render_partial('course/members/autor_list') ?>
+<? endif ?>
+
+<? if (count($users) > 0) : ?>
+ <br />
+ <?= $this->render_partial('course/members/user_list') ?>
+<? endif ?>
+
+<? if ($is_tutor && count($accepted) > 0) : ?>
+ <?= $this->render_partial('course/members/accepted_list') ?>
+<? endif ?>
+
+<? if ($is_tutor && count($awaiting) > 0) : ?>
+ <?= $this->render_partial('course/members/awaiting_list') ?>
+<? endif ?>
diff --git a/app/views/course/members/select_course.php b/app/views/course/members/select_course.php
new file mode 100644
index 0000000..249887d
--- /dev/null
+++ b/app/views/course/members/select_course.php
@@ -0,0 +1,32 @@
+<form class="default" action="<?= $controller->url_for('course/members/select_course') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Zielveranstaltung auswählen') ?></legend>
+
+ <label>
+ <?= _('Zielveranstaltung') ?>
+ <?= $search ?>
+
+ <br style="clear: both">
+ </label>
+
+ <label>
+ <?= _('Sollen die gewählten Personen in die Zielveranstaltung verschoben oder kopiert werden?') ?>
+ <select name="move">
+ <option value="1"><?= _('Verschieben') ?></option>
+ <option value="0"><?= _('Kopieren') ?></option>
+ </select>
+ </label>
+
+ <?php foreach ($users as $u) : ?>
+ <input type="hidden" name="users[]" value="<?= htmlReady($u) ?>"/>
+ <?php endforeach ?>
+
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Abschicken'), 'submit') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/course/members/tutor_list.php b/app/views/course/members/tutor_list.php
new file mode 100644
index 0000000..f11f971
--- /dev/null
+++ b/app/views/course/members/tutor_list.php
@@ -0,0 +1,186 @@
+<? use \Studip\Button; ?>
+
+<a name="tutoren"></a>
+<form action="<?= $controller->url_for('course/members/edit_tutor') ?>" method="post" data-dialog="size=50%">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default collapsable">
+ <caption>
+ <? if($is_tutor) : ?>
+ <span class="actions">
+ <a href="<?= URLHelper::getLink('dispatch.php/messages/write', [
+ 'filter' => 'send_sms_to_all',
+ 'who' => 'tutor',
+ 'emailrequest' => 1,
+ 'course_id' => $course_id,
+ 'default_subject' => $subject,
+ ]) ?>" data-dialog>
+ <?= Icon::create(
+ 'inbox',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(
+ _('Nachricht mit Mailweiterleitung an alle %s versenden'),
+ htmlReady( $status_groups['tutor'])
+ )
+ ]
+ ) ?>
+ </a>
+ </span>
+ <? endif ?>
+ <?= htmlReady($status_groups['tutor']) ?>
+ </caption>
+ <colgroup>
+ <? if ($is_dozent && !$tutor_is_locked) : ?>
+ <col width="20">
+ <? endif ?>
+ <col width="<?= (($is_tutor && !$is_dozent) || $tutor_is_locked) ? 40 : 20 ?>">
+ <col>
+ <? if ($is_dozent) : ?>
+ <col width="15%">
+ <col width="35%">
+ <? endif ?>
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <? if ($is_dozent && !$tutor_is_locked): ?>
+ <th>
+ <input aria-label="<?= sprintf(_('Alle %s auswählen'), htmlReady($status_groups['tutor'])) ?>"
+ type="checkbox" name="all" value="1" data-proxyfor=":checkbox[name^=tutor]">
+ </th>
+ <? endif ?>
+ <th></th>
+ <th <? if ($sort_by === 'nachname' && $sort_status === 'tutor') printf('class="sort%s"', $order); ?>>
+ <? $order = $sort_status !== 'tutor' ? 'desc' : $order; ?>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=nachname&sort_status=tutor&order=%s&toggle=%s#tutoren',
+ $order,
+ $sort_by === 'nachname'
+ )) ?>">
+ <?= _('Nachname, Vorname') ?>
+ </a>
+ </th>
+ <? if($is_dozent) : ?>
+ <th <? if ($sort_by === 'mkdate' && $sort_status === 'tutor') printf('class="sort%s"', $order); ?>>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=mkdate&sort_status=tutor&order=%s&toggle=%s#tutoren',
+ $order,
+ $sort_by === 'mkdate'
+ )) ?>">
+ <?= _('Anmeldedatum') ?>
+ </a>
+ </th>
+ <th><?=_('Studiengang')?></th>
+ <? endif ?>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $nr= 0; ?>
+ <? foreach ($tutoren as $tutor) : ?>
+ <? $fullname = $tutor['fullname'];?>
+ <tr>
+ <? if ($is_dozent && !$tutor_is_locked): ?>
+ <td>
+ <input aria-label="<?= sprintf(_('%s auswählen'), htmlReady($status_groups['tutor'])) ?>"
+ type="checkbox" name="tutor[<?= $tutor['user_id'] ?>]" value="1"
+ <? if (isset($flash['checked']) && in_array($tutor['user_id'], $flash['checked'])) echo 'checked'; ?>>
+ </td>
+ <? endif ?>
+ <td style="text-align: right"><?= sprintf('%02u', ++$nr) ?></td>
+ <td>
+ <a href="<?= $controller->url_for('profile?username=' . $tutor['username']) ?>" <? if ($tutor['mkdate'] >= $last_visitdate) echo 'class="new-member"'; ?>>
+ <?= Avatar::getAvatar($tutor['user_id'], $tutor['username'])->getImageTag(Avatar::SMALL, [
+ 'style' => 'margin-right: 5px',
+ 'title' => $fullname,
+ ]) ?>
+ <?= htmlReady($fullname) ?>
+ </a>
+ <? if ($is_tutor && $tutor['comment']) : ?>
+ <?= tooltipHtmlIcon(sprintf(
+ '<strong>%s</strong><br>%s',
+ _('Bemerkung'),
+ htmlReady($tutor['comment'])
+ )) ?>
+ <? endif ?>
+ </td>
+ <? if($is_dozent) : ?>
+ <td>
+ <? if (!empty($tutor['mkdate'])) : ?>
+ <?= strftime('%x %X', $tutor['mkdate'])?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= $this->render_partial('course/members/_studycourse.php', [
+ 'studycourses' => new SimpleCollection(UserStudyCourse::findByUser($tutor['user_id']))
+ ]) ?>
+ </td>
+ <? endif ?>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($is_tutor) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/add_comment/' . $tutor['user_id']),
+ _('Bemerkung hinzufügen'),
+ Icon::create('comment'),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? endif ?>
+ <? if ($user_id !== $tutor['user_id']) : ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write', [
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'rec_uname' => $tutor['username'],
+ 'default_subject' => $subject,
+ ]),
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create(
+ 'mail',
+ Icon::ROLE_CLICKABLE,
+ ['title' => sprintf(_('Nachricht mit Weiterleitung an %s senden'), htmlReady($fullname))]
+ ),
+ ['data-dialog' => '']
+ ) ?>
+ <? else: ?>
+ <? $actionMenu->addLink(
+ '#',
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create('mail', Icon::ROLE_INACTIVE),
+ ['disabled' => true]
+ ) ?>
+ <? endif ?>
+ <? if ($is_dozent && !$tutor_is_locked && $user_id !== $tutor['user_id'] && count($tutoren) >= 1) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/cancel_subscription/singleuser/tutor/' . $tutor['user_id']),
+ _('Aus Veranstaltung austragen'),
+ Icon::create(
+ 'door-leave',
+ 'clickable',
+ ['title' => sprintf(_('%s austragen'), htmlReady($fullname))]
+ )
+ ) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <? if ($is_dozent && !$tutor_is_locked): ?>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <select name="action_tutor" id="tutor_action" aria-label="<?= _('Aktion ausführen') ?>">
+ <option value="">- <?= _('Aktion auswählen') ?></option>
+ <option value="downgrade"><?= sprintf(_('Zu %s herunterstufen'), htmlReady($status_groups['autor'])) ?></option>
+ <option value="remove"><?= _('Austragen') ?></option>
+ <option value="message"><?=_('Nachricht senden')?></option>
+ <!--<option value="copy_to_course"><?= _('In Seminar verschieben/kopieren') ?></option>-->
+ </select>
+ <?= Button::create(_('Ausführen'), 'submit_autor') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+</form>
diff --git a/app/views/course/members/user_list.php b/app/views/course/members/user_list.php
new file mode 100644
index 0000000..675ca29
--- /dev/null
+++ b/app/views/course/members/user_list.php
@@ -0,0 +1,186 @@
+<? use Studip\Button; ?>
+<a name="users"></a>
+
+<form action="<?= $controller->url_for('course/members/edit_user') ?>" method="post" data-dialog>
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default collapsable">
+ <colgroup>
+ <? if($is_tutor) :?>
+ <col width="20">
+ <? endif ?>
+ <col width="20">
+ <col>
+ <? if($is_tutor) :?>
+ <col width="15%">
+ <col width="40%">
+ <? endif ?>
+ <col width="80">
+ </colgroup>
+ <caption>
+ <?= htmlReady($status_groups['user']) ?>
+ <? if($is_tutor) :?>
+ <span class="actions">
+ <a href="<?= URLHelper::getLink('dispatch.php/messages/write', [
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'who' => 'user',
+ 'course_id' => $course_id,
+ 'default_subject' => $subject,
+ ]) ?>" data-dialog>
+ <?= Icon::create(
+ 'inbox',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(
+ _('Nachricht mit Mailweiterleitung an alle %s versenden'),
+ htmlReady($status_groups['user'])
+ )
+ ]
+ ) ?>
+ </a>
+ </span>
+ <? endif ?>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <? if($is_tutor) :?>
+ <th>
+ <input aria-label="<?= sprintf(_('Alle %s auswählen'), htmlReady($status_groups['user'])) ?>"
+ type="checkbox" name="all" value="1" data-proxyfor=":checkbox[name^=user]">
+ </th>
+ <? endif ?>
+ <th></th>
+ <th <? if ($sort_by === 'nachname' && $sort_status === 'user') printf('class="sort%s"', $order); ?>>
+ <? $order = $sort_status !== 'user' ? 'desc' : $order; ?>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=nachname&sort_status=user&order=%s&toggle=%s#users',
+ $order,
+ $sort_by === 'nachname'
+ )) ?>">
+ <?= _('Nachname, Vorname') ?>
+ </a>
+ </th>
+ <? if($is_tutor) : ?>
+ <th <? if ($sort_by === 'mkdate' && $sort_status === 'user') printf('class="sort%s"', $order); ?>>
+ <a href="<?= URLHelper::getLink(sprintf(
+ '?sortby=mkdate&sort_status=user&order=%s&toggle=%s#users',
+ $order,
+ $sort_by === 'mkdate'
+ )) ?>">
+ <?= _('Anmeldedatum') ?>
+ </a>
+ </th>
+ <th><?=_('Studiengang')?></th>
+ <? endif ?>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $nr= 0; ?>
+ <? foreach ($users as $leser) : ?>
+ <? $fullname = $leser['fullname'];?>
+ <tr>
+ <? if($is_tutor) :?>
+ <td>
+ <input aria-label="<?= sprintf(_('%s auswählen'), htmlReady($status_groups['user'])) ?>"
+ type="checkbox" name="user[<?= $leser['user_id'] ?>]" value="1"
+ <? if (isset($flash['checked']) && in_array($leser['user_id'], $flash['checked'])) echo 'checked'; ?>>
+ </td>
+ <? endif ?>
+ <td style="text-align: right"><?= sprintf('%02u', ++$nr) ?></td>
+ <td>
+ <a href="<?= $controller->url_for('profile?username=' . $leser['username']) ?>" <? if ($leser['mkdate'] >= $last_visitdate) echo 'class="new-member"'; ?>>
+ <?= Avatar::getAvatar($leser['user_id'],$leser['username'])->getImageTag(Avatar::SMALL, [
+ 'style' => 'margin-right: 5px',
+ 'title' => $fullname,
+ ]); ?>
+ <?= htmlReady($fullname) ?>
+ </a>
+ </td>
+ <? if ($is_tutor) : ?>
+ <td>
+ <? if (!empty($leser['mkdate'])) : ?>
+ <?= strftime('%x %X', $leser['mkdate'])?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= $this->render_partial('course/members/_studycourse.php', [
+ 'studycourses' => new SimpleCollection(UserStudyCourse::findByUser($leser['user_id']))
+ ]) ?>
+ </td>
+ <? endif ?>
+ <td style="text-align: right">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($user_id !== $leser['user_id']) : ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write', [
+ 'filter' => 'send_sms_to_all',
+ 'emailrequest' => 1,
+ 'rec_uname' => $leser['username'],
+ 'default_subject' => $subject,
+ ]),
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create(
+ 'mail',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => sprintf(
+ _('Nachricht mit Weiterleitung an %s senden'),
+ htmlReady($fullname)
+ )
+ ]
+ ),
+ ['data-dialog' => '']
+ ) ?>
+ <? else: ?>
+ <? $actionMenu->addLink(
+ '#',
+ _('Nachricht mit Mailweiterleitung senden'),
+ Icon::create('mail', Icon::ROLE_INACTIVE),
+ ['disabled' => true]
+ ) ?>
+ <? endif ?>
+
+ <? if ($is_tutor) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/members/cancel_subscription/singleuser/user/' . $leser['user_id']),
+ _('Aus Veranstaltung austragen'),
+ Icon::create(
+ 'door-leave',
+ Icon::ROLE_CLICKABLE,
+ ['title' => sprintf(_('%s austragen'), htmlReady($fullname))]
+ )
+ ) ?>
+ <? endif ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <? if ($is_tutor) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <select name="action_user" id="user_action" aria-label="<?= _('Aktion ausführen') ?>">
+ <option value="">- <?= _('Aktion auswählen') ?></option>
+ <option value="upgrade">
+ <?= sprintf(_('Zu %s hochstufen'), htmlReady($status_groups['autor'])) ?>
+ </option>
+ <? if ($to_waitlist_actions) : ?>
+ <option value="to_admission_first"><?= _('An den Anfang der Warteliste verschieben') ?></option>
+ <option value="to_admission_last"><?= _('Ans Ende der Warteliste verschieben') ?></option>
+ <? endif ?>
+ <option value="remove"><?= _('Austragen') ?></option>
+ <? if($is_dozent) : ?>
+ <option value="to_course"><?= _('In andere Veranstaltung verschieben/kopieren') ?></option>
+ <? endif ?>
+ <option value="message"><?=_('Nachricht senden')?></option>
+ <!--<option value="copy_to_course"><?= _('In Seminar verschieben/kopieren') ?></option>-->
+ </select>
+ <?= Button::create(_('Ausführen'), 'submit_user') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+</form>
diff --git a/app/views/course/overview/index.php b/app/views/course/overview/index.php
new file mode 100644
index 0000000..8fc61b7
--- /dev/null
+++ b/app/views/course/overview/index.php
@@ -0,0 +1,81 @@
+<section class="contentbox">
+ <header>
+ <h1><?= _('Grunddaten') ?></h1>
+ </header>
+ <section>
+ <dl style="margin: 0;">
+ <? if (Context::get()->Untertitel != '') : ?>
+ <dt><?= _('Untertitel') ?></dt>
+ <dd>
+ <?= htmlReady(Context::get()->Untertitel) ?>
+ </dd>
+ <? endif ?>
+ <? if (!$studygroup_mode) : ?>
+ <dt><?= _('Zeit / Veranstaltungsort') ?></dt>
+ <dd>
+ <?= $times_rooms ?: _('Die Zeiten der Veranstaltung stehen nicht fest.') ?>
+ </dd>
+ <? if ($next_date) : ?>
+ <dt><?= _('Nächster Termin') ?></dt>
+ <dd><?= $next_date ?></dd>
+ <? else : ?>
+ <dt><?= _('Erster Termin') ?></dt>
+ <dd>
+ <? if ($first_date) : ?>
+ <?= $first_date ?>
+ <? else : ?>
+ <?= _('Die Zeiten der Veranstaltung stehen nicht fest.') ?>
+ <? endif ?>
+ </dd>
+ <? endif ?>
+ <dt><?= htmlReady(get_title_for_status('dozent', $num_dozenten)) ?></dt>
+ <dd><?= implode(', ', $show_dozenten) ?> </dd>
+ <? else : ?>
+ <? if ($sem->description) : ?>
+ <dt><?= _('Beschreibung') ?></dt>
+ <dd><?= formatLinks($sem->description) ?></dd>
+ <? endif ?>
+ <dt><?= _('Moderiert von') ?></dt>
+ <dd>
+ <ul class="list-csv">
+ <? foreach ($all_mods as $mod) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $mod['username']]) ?>">
+ <?= htmlready($mod['fullname']) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </dd>
+ <? endif ?>
+ </dl>
+ </section>
+</section>
+
+<?php
+
+// Anzeige von News
+echo $news;
+
+// Anzeige von Terminen
+echo $dates;
+
+// Anzeige von Umfragen
+echo $evaluations;
+
+echo $questionnaires;
+
+// display plugins
+
+if (!empty($plugins)) {
+ $layout = $GLOBALS['template_factory']->open('shared/content_box');
+ foreach ($plugins as $plugin) {
+ $template = $plugin->getInfoTemplate($course_id);
+
+ if ($template) {
+ echo $template->render(null, $layout);
+ $layout->clear_attributes();
+ }
+ }
+}
+echo Feedback::getHTML($course_id, 'Course');
diff --git a/app/views/course/plus/edittool.php b/app/views/course/plus/edittool.php
new file mode 100644
index 0000000..15635d3
--- /dev/null
+++ b/app/views/course/plus/edittool.php
@@ -0,0 +1,25 @@
+<form class="default" action="<?=$controller->link_for('/edittool/plugin_' . $tool->plugin_id)?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <label for="displayname">
+ <?=_('Name des Werkzeugs')?>
+ <input type="text" name="displayname" id="displayname" value="<?=htmlReady($tool->getDisplayname())?>">
+ </label>
+
+ <label><?=_('Sichtbarkeit')?></label>
+ <div class="hgroup">
+ <label for="permission_autor">
+ <?=_('Studierende')?>
+ <input type="radio" name="permission" id="permission_autor" value="autor" checked>
+ </label>
+ <label for="permission_tutor">
+ <?=_('Lehrende')?>
+ <input type="radio" name="permission" id="permission_tutor" value="tutor" <?= $tool->getVisibilityPermission() === 'tutor' ? 'checked' : '' ?>>
+ </label>
+ </div>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ </footer>
+</form>
diff --git a/app/views/course/plus/index.php b/app/views/course/plus/index.php
new file mode 100644
index 0000000..9cb224a
--- /dev/null
+++ b/app/views/course/plus/index.php
@@ -0,0 +1,268 @@
+<?php
+
+/*
+ * Copyright (c) 2012 Rasmus Fuhse <fuhse@data-quest.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+use Studip\Button, Studip\LinkButton;
+
+?>
+
+<form action="<?= URLHelper::getLink($save_url) ?>" method="post" class="default">
+<?= CSRFProtection::tokenTag() ?>
+<input name="uebernehmen" value="1" type="hidden">
+<table class="default nohover plus">
+<!-- <caption><?=_("Inhaltselemente")?></caption> -->
+<tbody>
+<?
+foreach ($available_modules as $category => $pluginlist) {
+ $visibility = "";
+ if ($_SESSION['plus']['displaystyle'] != 'category' && $category != 'Funktionen von A-Z') {
+ $visibility = "invisible";
+ }
+ if (isset($_SESSION['plus']) && !$_SESSION['plus']['Kategorie'][$category] && $category != 'Funktionen von A-Z') {
+ $visibility = "invisible";
+ }
+
+ ?>
+ <tr class="<?= $visibility; ?>">
+ <th colspan=3>
+ <?= htmlReady($category) ?>
+ </th>
+ </tr>
+
+ <? foreach ($pluginlist as $key => $val) {
+
+ if ($val['type'] == 'plugin') {
+ $plugin = $val['object'];
+ $plugin_activated = $plugin->isActivated();
+ $info = $plugin->getMetadata();
+
+ //Checkbox
+ $anchor = 'p_' . $plugin->getPluginId();
+ $cb_name = 'plugin_' . $plugin->getPluginId();
+ $cb_disabled = '';
+ $cb_checked = $plugin_activated ? "checked" : "";
+
+ $pluginname = $val['displayname'];
+ $URL = $plugin->isCorePlugin() ? $GLOBALS['ABSOLUTE_URI_STUDIP'] : $plugin->getPluginURL();
+ $pluginvisibility = $val['visibility'];
+ }
+ ?>
+
+ <tr id="<?= htmlReady($anchor);?>" class="<?= $visibility; ?> <?= $pre_check != null ? ' quiet' : '' ?>">
+ <td class="element" colspan=3>
+
+ <div class="plus_basic">
+
+ <!-- checkbox -->
+ <input type="checkbox"
+ id="<?= $pluginname ?>"
+ name="<?= $cb_name ?>"
+ data-moduleclass="<?= htmlReady($val['moduleclass']) ?>"
+ data-key="<?= htmlReady($val['modulkey']) ?>"
+ value="TRUE" <?= $cb_disabled ?> <?= $cb_checked ?>
+ onClick="STUDIP.Plus.setModule.call(this);">
+
+ <div class="element_header">
+
+ <!-- Name -->
+ <label for="<?= $pluginname ?>">
+ <strong><?= htmlReady($pluginname) ?></strong>
+ <? if ($cb_checked) : ?>
+ <?=Icon::create(
+ $pluginvisibility === 'autor' ? 'visibility-visible' : 'visibility-invisible',
+ Icon::ROLE_INFO,
+ ['title' => sprintf(_('%s für Studierende'), $pluginvisibility === 'autor' ? _('Sichtbar') : _('Unsichtbar'))]
+ )?>
+ <? endif ?>
+ </label>
+
+ </div>
+
+ <div class="element_description">
+
+ <!-- icon -->
+ <? if (isset($info['icon'])) : ?>
+ <? /* TODO: Plugins should use class "Icon" */ ?>
+ <? if (is_string($info['icon'])) : ?>
+ <img class="plugin_icon text-bottom" alt="" src="<?= $URL . "/" . $info['icon'] ?> ">
+ <? else: ?>
+ <?= $info['icon']->asImg(['class' => 'plugin_icon text-bottom', 'alt' => '']) ?>
+ <? endif ?>
+ <? endif ?>
+
+ <!-- shortdesc -->
+ <strong class="shortdesc">
+ <? if (isset($info['descriptionshort'])) : ?>
+ <? foreach (explode('\n', $info['descriptionshort']) as $descriptionshort) { ?>
+ <?= htmlReady($descriptionshort) ?>
+ <? } ?>
+ <? endif ?>
+ <? if (!isset($info['descriptionshort'])) : ?>
+ <? if (isset($info['summary'])) : ?>
+ <?= htmlReady($info['summary']) ?>
+ <? elseif (isset($info['description'])) : ?>
+ <?= htmlReady($info['description']) ?>
+ <? else: ?>
+ <?= _("Keine Beschreibung vorhanden.") ?>
+ <? endif ?>
+ <? endif ?>
+ </strong>
+ </div>
+
+
+ <? if ($plugin_activated) : ?>
+ <?php
+ $actionMenu = ActionMenu::get();
+
+ $actionMenu->addLink(
+ $controller->url_for('/edittool/' . $key),
+ _('Optionen bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE, ['size' => 20]),
+ ['data-dialog' => 'size=auto']
+ );
+ if (method_exists($plugin, 'deleteContent')) {
+ $actionMenu->addLink(
+ $controller->url_for('/index', ['deleteContent' => 1, 'name' => $key]),
+ _('Inhalte löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, ['size' => 20])
+ );
+ }
+ ?>
+ <div style="float: right">
+ <?= $actionMenu->render() ?>
+ </div>
+ <? endif ?>
+ </div>
+
+ <? if ($_SESSION['plus']['View'] == 'openall' || !isset($_SESSION['plus'])) { ?>
+
+ <div class="plus_expert hidden-tiny-down">
+
+ <div class="screenshot_holder">
+ <? if (isset($info['screenshot']) || isset($info['screenshots'])) :
+ if(isset($info['screenshots'])){
+ $title = $info['screenshots']['pictures'][0]['title'];
+ $source = $info['screenshots']['path'].'/'.$info['screenshots']['pictures'][0]['source'];
+ } else {
+ $fileext = end(explode(".", $info['screenshot']));
+ $title = str_replace("_"," ",basename($info['screenshot'], ".".$fileext));
+ $source = $info['screenshot'];
+ }
+ ?>
+
+ <a href="<?= $URL . "/" . $source ?>"
+ data-lightbox="<?= $pluginname ?>" data-title="<?= $title ?>">
+ <img class="big_thumb" src="<?= $URL . "/" . $source ?>"
+ alt="<?= $pluginname ?>"/>
+ </a>
+
+ <?
+ if (isset($info['additionalscreenshots']) || (isset($info['screenshots']) && count($info['screenshots']) > 1) ) {
+ ?>
+
+ <div class="thumb_holder">
+ <? if (isset($info['screenshots'])){
+ $counter = count($info['screenshots']['pictures']);
+ $cstart = 1;
+ } else {
+ $counter = count($info['additionalscreenshots']);
+ $cstart = 0;
+ } ?>
+
+ <? for ($i = $cstart; $i < $counter; $i++) {
+
+ if (isset($info['screenshots'])){
+ $title = $info['screenshots']['pictures'][$i]['title'];
+ $source = $info['screenshots']['path'].'/'.$info['screenshots']['pictures'][$i]['source'];
+ } else {
+ $fileext = end(explode(".", $info['additionalscreenshots'][$i]));
+ $title = str_replace("_"," ",basename($info['additionalscreenshots'][$i], ".".$fileext));
+ $source = $info['additionalscreenshots'][$i];
+ }
+
+ ?>
+
+ <a href="<?= $URL . "/" . $source ?>"
+ data-lightbox="<?= $pluginname ?>"
+ data-title="<?= $title ?>">
+ <img class="small_thumb"
+ src="<?= $URL . "/" . $source ?>"
+ alt="<?= $pluginname ?>"/>
+ </a>
+
+ <? } ?>
+
+ </div>
+
+ <? } ?>
+
+ <? endif ?>
+ </div>
+
+ <div class="descriptionbox">
+
+ <!-- tags -->
+ <? if (isset($info['keywords'])) : ?>
+ <ul class="keywords">
+ <? foreach (explode(';', $info['keywords']) as $keyword) {
+ echo '<li>' . htmlReady($keyword) . '</li>';
+ }?>
+ </ul>
+ <? endif ?>
+
+ <!-- longdesc -->
+ <? if (isset($info['descriptionlong'])) : ?>
+ <? foreach (explode('\n', $info['descriptionlong']) as $descriptionlong) { ?>
+ <p class="longdesc">
+ <?= htmlReady($descriptionlong) ?>
+ </p>
+ <? } ?>
+ <? endif ?>
+
+ <? if (!isset($info['descriptionlong']) && isset($info['summary'])) : ?>
+ <p class="longdesc">
+ <? if (isset($info['description'])) : ?>
+ <?= htmlReady($info['description']) ?>
+ <? else: ?>
+ <?= _("Keine Beschreibung vorhanden.") ?>
+ <? endif ?>
+ </p>
+ <? endif ?>
+
+ <? if (isset($info['homepage'])) : ?>
+ <p>
+ <strong><?= _('Weitere Informationen:') ?></strong>
+ <a href="<?= htmlReady($info['homepage']) ?>"><?= htmlReady($info['homepage']) ?></a>
+ </p>
+ <? endif ?>
+
+ <!-- helplink -->
+ <? if (isset($info['helplink'])) : ?>
+ <a class="helplink" href=" <?= htmlReady($info['helplink']) ?> ">...mehr</a>
+ <? endif ?>
+
+ </div>
+ </div>
+ <? } ?>
+ </td>
+ </tr>
+ <?
+ }
+} ?>
+</tbody>
+
+<tfoot>
+<tr class="hidden-js">
+ <td align="center" colspan="3">
+ <?= Button::create(_('An- / Ausschalten'), 'uebernehmen') ?>
+ </td>
+</tr>
+</tfoot>
+</table>
+</form>
diff --git a/app/views/course/plus/sorttools.php b/app/views/course/plus/sorttools.php
new file mode 100644
index 0000000..de57592
--- /dev/null
+++ b/app/views/course/plus/sorttools.php
@@ -0,0 +1,15 @@
+<section class="contentbox course-statusgroups" data-sortable="<?=$controller->url_for('/sorttools', ['order' => 1]) ?>">
+<? if ($sem->tools): ?>
+ <? foreach ($sem->tools as $tool): ?>
+ <?php if (!$tool->getStudipModule()) continue; ?>
+ <article class="draggable" id="<?= $tool->plugin_id ?>">
+ <header>
+ <span class="sg-sortable-handle"></span>
+ <h1><?= htmlready($tool->getDisplayName()) ?></h1>
+ </header>
+ </article>
+ <? endforeach ?>
+<? endif ?>
+</section>
+
+
diff --git a/app/views/course/room_requests/_request.php b/app/views/course/room_requests/_request.php
new file mode 100644
index 0000000..2ffa282
--- /dev/null
+++ b/app/views/course/room_requests/_request.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/_common/_request_info.php') ?>
diff --git a/app/views/course/room_requests/_request_edit_header.php b/app/views/course/room_requests/_request_edit_header.php
new file mode 100644
index 0000000..26c5541
--- /dev/null
+++ b/app/views/course/room_requests/_request_edit_header.php
@@ -0,0 +1,22 @@
+<? if ($direct_room_requests_only): ?>
+ <?= MessageBox::info(
+ _('Geben Sie bitte den gewünschten Raum an. Ihre Raumanfrage wird von der zuständigen Raumvergabe bearbeitet.'),
+ [_('<strong>Achtung:</strong> Geben Sie bitte immer die notwendige Sitzplatzanzahl mit an!')]
+ )?>
+<? else: ?>
+ <?= MessageBox::info(
+ _('Geben Sie den gewünschten Raum und/oder Raumeigenschaften an. Ihre Raumanfrage wird von der zuständigen Raumvergabe bearbeitet.'),
+ [_('<strong>Achtung:</strong> Um später einen passenden Raum für Ihre Veranstaltung zu bekommen, geben Sie bitte immer die gewünschten Eigenschaften mit an!')]
+ )?>
+<? endif ?>
+<section class="resources-grid">
+ <section class="contentbox">
+ <header><h1><?= _('Anfrage') ?></h1></header>
+ <section><?= htmlready($request->getTypeString(), 1, 1) ?></section>
+ </section>
+ <section class="contentbox">
+ <header><h1><?= _('Bearbeitungsstatus') ?></h1></header>
+ <section><?= htmlReady($request->getStatusText()) ?></section>
+ </section>
+</section>
+
diff --git a/app/views/course/room_requests/_request_form_footer.php b/app/views/course/room_requests/_request_form_footer.php
new file mode 100644
index 0000000..bfcd3e9
--- /dev/null
+++ b/app/views/course/room_requests/_request_form_footer.php
@@ -0,0 +1,28 @@
+<footer data-dialog-button>
+ <? if ($room_search_button) : ?>
+ <?= \Studip\Button::create(
+ _('Räume suchen'),
+ 'search_rooms',
+ [
+ 'title' => _('Startet die Suche von Räumen anhand der gewählten Eigenschaften.')
+ ]
+ ) ?>
+ <? endif ?>
+ <? if ($room_select_button) : ?>
+ <?= \Studip\Button::create(_('Raum auswählen'), 'select_room') ?>
+ <? endif ?>
+ <? if ($save_buttons) : ?>
+ <?= \Studip\Button::create(_('Speichern'), 'save_and_close') ?>
+ <? endif ?>
+ <? if ($select_properties_button) : ?>
+ <?= \Studip\Button::create(_('Eigenschaften wählen'), 'select_properties') ?>
+ <? endif ?>
+ <?= \Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->link_for('course/room_requests/index/' . $course_id),
+ [
+ 'title' => _('Abbrechen')
+ ]
+ ) ?>
+</footer>
+</form>
diff --git a/app/views/course/room_requests/_request_form_header.php b/app/views/course/room_requests/_request_form_header.php
new file mode 100644
index 0000000..cdfe7bc
--- /dev/null
+++ b/app/views/course/room_requests/_request_form_header.php
@@ -0,0 +1,4 @@
+<form method="post" name="room_request" class="default"
+ action="<?= $action ?>" <?= Request::isXhr() ? 'data-dialog="size=big"' : ''?>>
+ <input type="hidden" name="request_id" value="<?= htmlReady($request_id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
diff --git a/app/views/course/room_requests/index.php b/app/views/course/room_requests/index.php
new file mode 100644
index 0000000..5043e873
--- /dev/null
+++ b/app/views/course/room_requests/index.php
@@ -0,0 +1,144 @@
+<?php
+echo $flash['message'];
+?>
+
+<? if (count($room_requests)) : ?>
+ <table class="default">
+ <caption>
+ <?= _("Vorhandene Raumanfragen") ?>
+ </caption>
+ <colgroup>
+ <col style="width: 40%">
+ <col style="width: 20%">
+ <col>
+ <col style="width: 50px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Art der Anfrage') ?></th>
+ <th><?= _('Anfragender') ?></th>
+ <th><?= _('Bearbeitungsstatus') ?></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($room_requests as $rr): ?>
+ <tr>
+ <td>
+ <?= htmlReady($rr->getTypeString(), 1, 1) ?>
+ </td>
+ <td>
+ <?= htmlReady($rr->user ? $rr->user->getFullName() : '') ?>
+ </td>
+ <td>
+ <?= htmlReady($rr->getStatusText()) ?>
+ </td>
+ <td class="actions">
+ <a class="load-in-new-row"
+ href="<?= $controller->link_for('course/room_requests/info/' . $rr->id) ?>">
+ <?= Icon::create(
+ 'info',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => _('Weitere Informationen einblenden')
+ ]
+ ) ?>
+ </a>
+ <? $params = [] ?>
+ <? $dialog = []; ?>
+ <? if (Request::isXhr()) : ?>
+ <? $params['asDialog'] = true; ?>
+ <? $dialog['data-dialog'] = 'size=big' ?>
+ <? endif ?>
+
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/room_requests/request_summary/' . $rr->id, ['clear_cache' => 1]),
+ _('Diese Anfrage bearbeiten'),
+ Icon::create(
+ 'edit',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => _('Diese Anfrage bearbeiten')
+ ]
+ ),
+ $dialog
+ ) ?>
+
+ <?php
+ $user_has_permissions = false;
+ if ($rr->room && !$GLOBALS['perm']->have_perm('root')) {
+ $user_has_permissions = (
+ $rr->room->userHasPermission($current_user, 'admin') &&
+ (RoomRequest::countBySql(
+ "id = :request_id
+ AND closed = '0'
+ AND user_id = :user_id",
+ [
+ 'request_id' => $rr->id,
+ 'user_id' => $current_user->id
+ ]
+ ) > 0
+ )
+ );
+ } else {
+ $user_has_permissions = ResourceManager::userHasGlobalPermission($current_user, 'admin');
+ } ?>
+
+ <? if ($user_has_permissions && (int)$rr->closed === 0): ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL(
+ 'dispatch.php/resources/room_request/resolve/' . $rr->id,
+ [
+ 'reload-on-close' => 1,
+ 'single-request' => 1
+ ]
+ ),
+ _('Diese Anfrage selbst auflösen'),
+ Icon::create(
+ 'admin',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => _('Diese Anfrage selbst auflösen')
+ ]
+ ),
+ ['data-dialog' => '1']
+ ) ?>
+ <? endif ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/room_requests/delete/' . $rr->id),
+ _('Diese Anfrage löschen'),
+ Icon::create(
+ 'trash',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => _('Diese Anfrage löschen')
+ ]
+ )
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? if ($request_id == $rr->id) : ?>
+ <tr>
+ <td colspan="4">
+ <?= $this->render_partial('course/room_requests/_request.php', ['request' => $rr]); ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+<? else : ?>
+ <?= MessageBox::info(_('Zu dieser Veranstaltung sind noch keine Raumanfragen vorhanden.')) ?>
+<? endif ?>
+
+<? if (Request::isXhr()) : ?>
+ <div data-dialog-button>
+ <?= \Studip\LinkButton::createEdit(
+ _('Neue Raumanfrage erstellen'),
+ $controller->url_for('course/room_requests/new/' . $course_id, $url_params),
+ ['data-dialog' => 'size=big']
+ ) ?>
+ </div>
+<? endif ?> \ No newline at end of file
diff --git a/app/views/course/room_requests/new.php b/app/views/course/room_requests/new.php
new file mode 100644
index 0000000..18edbdc
--- /dev/null
+++ b/app/views/course/room_requests/new.php
@@ -0,0 +1,47 @@
+<form method="POST" class="default" name="new_room_request"
+ action="<?= $this->controller->link_for('course/room_requests/request_start') ?>"
+ <?= Request::isXhr() ? 'data-dialog="size=big"' : '' ?>>
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _("Raumanfrage erstellen") ?></legend>
+ <? if (count($options)): ?>
+ <label>
+ <?= _("Art der Raumanfrage:") ?>
+ <select id="new_room_request_type" name="range_str">
+ <? foreach ($options as $one) : ?>
+ <option value="<?= $one['value'] ?>">
+ <?= htmlReady($one['name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <div class="text-center" data-dialog-button>
+ </div>
+ <? else : ?>
+ <?= MessageBox::info(
+ _("In dieser Veranstaltung können keine weiteren Raumanfragen gestellt werden.")
+ ) ?>
+ <? endif ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if (count($options)): ?>
+ <?= Studip\Button::create(
+ _('Erstellen'),
+ 'create_room_request'
+ ) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->link_for('course/room_requests/index/' . $course_id)
+ ) ?>
+ <? else: ?>
+ <?= Studip\LinkButton::create(
+ _('Zurück zur Übersicht'),
+ $controller->link_for('course/room_requests/index/' . $course_id),
+ ['data-dialog' => 'size=big']
+ ) ?>
+ <? endif ?>
+ </footer>
+</form>
diff --git a/app/views/course/room_requests/request_select_properties.php b/app/views/course/room_requests/request_select_properties.php
new file mode 100644
index 0000000..15a335f
--- /dev/null
+++ b/app/views/course/room_requests/request_select_properties.php
@@ -0,0 +1,65 @@
+<? if (!$embedded) : ?>
+ <?= $this->render_partial(
+ 'course/room_requests/_request_form_header',
+ [
+ 'action' => $this->controller->link_for('course/room_requests/request_select_properties/' . $request_id),
+ 'request_id' => $request_id
+ ]
+ ) ?>
+ <?= $this->render_partial(
+ 'course/room_requests/_request_edit_header',
+ ['request' => $request]
+ ) ?>
+ <?= $this->render_partial(
+ 'course/room_requests/request_start',
+ ['embedded' => true]
+ ) ?>
+<? endif ?>
+
+<? if ($available_properties) : ?>
+ <? foreach ($available_properties as $property) : ?>
+ <?= $property->toHtmlInput(
+ $selected_properties[$property->name],
+ 'selected_properties[' . htmlReady($property->name) . ']',
+ true,
+ false
+ ) ?>
+ <? endforeach ?>
+<? endif ?>
+
+<label>
+ <?= _('Rüstzeit (in Minuten)') ?>
+ <input type="number" name="preparation_time"
+ value="<?= htmlReady($preparation_time) ?>"
+ min="0" max="<?= htmlReady($max_preparation_time) ?>">
+</label>
+
+<? if ($user_is_global_resource_admin) : ?>
+ <label>
+ <input type="checkbox" name="reply_lecturers" value="1"
+ <?= $reply_lecturers
+ ? 'checked="checked"'
+ : ''
+ ?>>
+ <?= _('Benachrichtigung bei Ablehnung der Raumanfrage auch an alle Lehrenden der Veranstaltung senden') ?>
+ </label>
+<? endif ?>
+
+
+ <label>
+ <?= _('Nachricht an die Raumvergabe') ?>
+ <textarea name="comment" cols="58" rows="4"
+ placeholder="<?= _('Weitere Wünsche oder Bemerkungen zur angefragten Raumbelegung') ?>"><?= htmlReady($comment) ?></textarea>
+ </label>
+
+<? if (!$embedded) : ?>
+ </div>
+ </section>
+ <?= $this->render_partial(
+ 'course/room_requests/_request_form_footer',
+ [
+ 'room_search_button' => true,
+ 'save_buttons' => true
+ ]
+ ) ?>
+<? endif ?>
diff --git a/app/views/course/room_requests/request_select_room.php b/app/views/course/room_requests/request_select_room.php
new file mode 100644
index 0000000..b3df281
--- /dev/null
+++ b/app/views/course/room_requests/request_select_room.php
@@ -0,0 +1,78 @@
+<? if (!$embedded) : ?>
+ <?= $this->render_partial(
+ 'course/room_requests/_request_form_header',
+ [
+ 'action' => $this->controller->link_for('course/room_requests/request_select_room/' . $request_id),
+ 'request_id' => $request_id
+ ]
+ ) ?>
+ <?= $this->render_partial(
+ 'course/room_requests/_request_edit_header',
+ ['request' => $request]
+ ) ?>
+ <?= $this->render_partial(
+ 'course/room_requests/request_start',
+ ['embedded' => true]
+ ) ?>
+ <? if (($category instanceof ResourceCategory) && !$direct_room_requests_only): ?>
+ <?= $this->render_partial(
+ 'course/room_requests/request_select_properties',
+ ['embedded' => true]
+ ) ?>
+ <? endif ?>
+<? endif ?>
+</div>
+
+<div>
+<? if ($available_rooms) : ?>
+ <section class="contentbox">
+ <header><h1><?= _('Passende Räume') ?></h1></header>
+ <section class="selectbox">
+ <fieldset>
+ <? foreach ($available_rooms as $room): ?>
+ <div class="flex-row">
+ <label class="horizontal">
+ <? if ($overlaps[$room->id] <= 0.0): ?>
+ <?= Icon::create('check-circle', Icon::ROLE_STATUS_GREEN)->asImg(
+ ['class' => 'text-bottom']
+ ) ?>
+ <? elseif ($overlaps[$room->id] >= 1.0): ?>
+ <?= Icon::create('decline-circle', Icon::ROLE_STATUS_RED)->asImg(
+ ['class' => 'text-bottom']
+ ) ?>
+ <? else: ?>
+ <?= Icon::create('exclaim-circle', Icon::ROLE_STATUS_YELLOW)->asImg(
+ ['class' => 'text-bottom']
+ ) ?>
+ <? endif ?>
+ <input type="radio" name="selected_room_id"
+ data-activates="button[type='submit'][name='select_room']"
+ value="<?= htmlReady($room->id) ?>">
+ <?= htmlReady(mb_substr($room->name, 0, 50)); ?>
+ <? if ($room->properties): ?>
+ <? $property_names = $room->getInfolabelPrperties()
+ ->pluck('fullname') ?>
+ <?= tooltipIcon(implode("\n", $property_names)) ?>
+ <? endif ?>
+ </label>
+ </div>
+ <? endforeach ?>
+ </fieldset>
+ </section>
+ </section>
+ <? else : ?>
+ <?= MessageBox::info(_('Es wurden keine passenden Räume gefunden!')) ?>
+ <? endif ?>
+ </div>
+</section>
+<? if (!$embedded) : ?>
+ <?= $this->render_partial(
+ 'course/room_requests/_request_form_footer',
+ [
+ 'room_search_button' => true,
+ 'room_select_button' => true,
+ 'save_buttons' => true,
+ 'select_properties_button' => false
+ ]
+ ) ?>
+<? endif ?>
diff --git a/app/views/course/room_requests/request_start.php b/app/views/course/room_requests/request_start.php
new file mode 100644
index 0000000..763ef5a
--- /dev/null
+++ b/app/views/course/room_requests/request_start.php
@@ -0,0 +1,85 @@
+<? if (!$embedded) : ?>
+ <?= $this->render_partial(
+ 'course/room_requests/_request_form_header',
+ [
+ 'action' => $this->controller->link_for('course/room_requests/request_start/' . $request_id),
+ 'request_id' => $request_id
+ ]
+ ) ?>
+ <?= $this->render_partial(
+ 'course/room_requests/_request_edit_header',
+ ['request' => $request]
+ ) ?>
+<? endif ?>
+<section class="resources-grid">
+ <div>
+ <fieldset>
+ <legend><?= _('Raum suchen') ?></legend>
+ <label>
+ <?= _('Raumname') ?>
+ <span class="flex-row">
+ <input type="text" name="room_name" value="<?= htmlReady($room_name) ?>">
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE)->asInput(
+ [
+ 'name' => 'search_by_name',
+ 'class' => 'text-bottom',
+ 'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+ ]
+ ) ?>
+ <? if ($room_name) : ?>
+ <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['title' => _('alle Angaben zurücksetzen')])->asInput(
+ [
+ 'type' => 'image',
+ 'class' => 'text-bottom',
+ 'name' => 'reset_category',
+ 'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+ ]
+ ) ?>
+ <? endif?>
+ </span>
+ </label>
+ <? if ($available_room_categories): ?>
+ <strong><p><?= _('Wünschbare Eigenschaften') ?></p></strong>
+ <label>
+ <?= _('Raumkategorie') ?>
+ <span class="flex-row">
+ <select name="category_id" <?= $category ? 'disabled' : '' ?>>
+ <option value=""><?= _('bitte auswählen') ?></option>
+ <? foreach ($available_room_categories as $rc): ?>
+ <option value="<?= htmlReady($rc->id) ?>"
+ <?= ($category_id == $rc->id)
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($rc->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? if ($category) : ?>
+ <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['title' => _('alle Angaben zurücksetzen')])->asInput(
+ [
+ 'type' => 'image',
+ 'class' => 'text-bottom',
+ 'name' => 'reset_category',
+ 'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+ ]
+ ) ?>
+ <? else : ?>
+ <?= Icon::create('accept', Icon::ROLE_CLICKABLE, ['title' => _('Raumtyp auswählen')])->asInput(
+ [
+ 'type' => 'image',
+ 'class' => 'text-bottom',
+ 'name' => 'select_properties',
+ 'value' => _('Raumtyp auswählen'),
+ 'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+ ]
+ ) ?>
+ <? endif ?>
+ </span>
+ </label>
+ <? endif ?>
+ <? if (!$embedded) : ?>
+ </fieldset>
+ </div>
+</section>
+<?= $this->render_partial('course/room_requests/_request_form_footer') ?>
+<? endif ?>
diff --git a/app/views/course/room_requests/request_summary.php b/app/views/course/room_requests/request_summary.php
new file mode 100644
index 0000000..360dbfa
--- /dev/null
+++ b/app/views/course/room_requests/request_summary.php
@@ -0,0 +1,102 @@
+<form method="post" name="room_request" class="default"
+ action="<?= $this->controller->link_for('course/room_requests/request_summary/' . $request_id) ?>">
+ <input type="hidden" name="request_id" value="<?= htmlReady($request_id) ?>">
+ <?= $this->render_partial(
+ 'course/room_requests/_request_edit_header',
+ ['request' => $request]
+ ) ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <section class="resources-grid">
+ <div>
+ <fieldset>
+ <legend><?= _('Ausgewählter Raum') ?></legend>
+ <? if ($selected_room): ?>
+ <input type="hidden" name="selected_room_id"
+ value="<?= htmlReady($selected_room->id) ?>">
+ <input type="hidden" name="confirmed_selected_room_id"
+ value="<?= htmlReady($selected_room->id) ?>">
+ <?= htmlReady($selected_room->name) ?>
+ <? if ($selected_room->properties): ?>
+ <? $property_names = $selected_room->properties
+ ->findBy('info_label', 1)
+ ->findBy('state', '', '!=')
+ ->pluck('fullname') ?>
+ <?= tooltipIcon(
+ implode("\n", $property_names)
+ ) ?>
+ <? endif ?>
+ <?= Studip\Button::create(
+ _('Anderen Raum wählen'),
+ 'select_other_room'
+ ) ?>
+ <? else: ?>
+ <?= MessageBox::info(
+ _('Es wurde kein konkreter Raum ausgewählt!')
+ ) ?>
+ <?= Studip\Button::create(
+ _('Eigenschaften neu wählen'),
+ 'select_properties'
+ ) ?>
+ <? endif ?>
+ <? if ($request->properties): ?>
+ <? foreach ($request->properties as $property): ?>
+ <? if (!in_array($property->name, ['seats'])): ?>
+ <dt><?= htmlReady($property->display_name) ?></dt>
+ <dd><?= htmlReady($property->__toString()) ?></dd>
+ <? endif ?>
+ <? endforeach ?>
+ <? endif ?>
+ <? if ($request->category): ?>
+ <dt><?= _('Gewünschter Raumtyp') ?>:</dt>
+ <dd><?= htmlReady($request->category->name) ?></dd>
+ <? endif ?>
+ <label>
+ <?= _('Erwartete Anzahl an Teilnehmenden') ?>:
+ <input type="number" name="seats"
+ value="<?= htmlReady($seats) ?>"
+ min="1">
+ </label>
+ <label>
+ <?= _('Rüstzeit (in Minuten)') ?>
+ <input type="number" name="preparation_time"
+ value="<?= htmlReady($preparation_time) ?>"
+ min="0" max="<?= htmlReady($max_preparation_time) ?>">
+ </label>
+ <? if ($user_is_global_resource_admin) : ?>
+ <label>
+ <input type="checkbox" name="reply_lecturers" value="1"
+ <?= $reply_lecturers
+ ? 'checked="checked"'
+ : ''
+ ?>>
+ <?= _('Benachrichtigung bei Ablehnung der Raumanfrage auch an alle Lehrenden der Veranstaltung senden') ?>
+ </label>
+ <? endif ?>
+ </fieldset>
+ </div>
+ <div>
+ <fieldset>
+ <legend><?= _('Nachricht an die Raumvergabe') ?></legend>
+ <textarea name="comment" cols="58" rows="4"
+ placeholder="<?= _('Weitere Wünsche oder Bemerkungen zur angefragten Raumbelegung') ?>"><?= htmlReady($comment) ?></textarea>
+ </fieldset>
+ </div>
+ </section>
+ <footer data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Speichern'),
+ 'save'
+ ) ?>
+ <?= \Studip\Button::create(
+ _('Speichern und zurück zur Übersicht'),
+ 'save_and_close'
+ ) ?>
+ <?= \Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->link_for('course/room_requests/index/' . $course_id),
+ [
+ 'title' => _('Abbrechen')
+ ]
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/course/scm/edit.php b/app/views/course/scm/edit.php
new file mode 100644
index 0000000..ca46f64
--- /dev/null
+++ b/app/views/course/scm/edit.php
@@ -0,0 +1,61 @@
+<p>
+ <?= _('Hier können Sie eine Seite mit Zusatzinformationen zu Ihrer '
+ . 'Veranstaltung gestalten. Sie können Links normal eingeben, diese '
+ . 'werden anschließend automatisch als Hyperlinks dargestellt.')
+ ?>
+</p>
+
+<form action="<?= $controller->edit($scm) ?>" method="post" data-secure class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Informationsseite') ?>
+ </legend>
+ <label>
+ <span class="required"><?= _('Titel') ?></span>
+ <?= I18N::input('tab_name', $scm->tab_name, [
+ 'required' => '',
+ 'id' => 'tab_name',
+ 'aria-label' => _('Titel der Informationsseite'),
+ 'placeholder' => _('Titel der Informationsseite'),
+ ]) ?>
+ </label>
+
+ <? if ($GLOBALS['SCM_PRESET']): ?>
+ <label>
+ <?= _('oder wählen Sie hier einen Namen aus:') ?>
+ <select name="tab_name_template" data-copy-to="input[name=tab_name]">
+ <option value="">- <?= _('Vorlagen') ?> -</option>
+ <? foreach ($GLOBALS['SCM_PRESET'] as $template): ?>
+ <option><?= htmlReady($template['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+
+ <label>
+ <?= _('Inhalt') ?>
+ <?= I18N::textarea('content', $scm->content, [
+ 'class' => 'add_toolbar wysiwyg size-l',
+ ]) ?>
+ </label>
+ </fieldset>
+
+<? if (!$scm->isNew()): ?>
+ <p>
+ <?= sprintf(_('Zuletzt geändert von %s am %s'),
+ ObjectdisplayHelper::link($scm->user),
+ strftime('%x, %X', $scm->chdate)) ?>
+ </p>
+<? endif; ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <? if ($first_entry): ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), URLHelper::getLink('seminar_main.php')) ?>
+ <? else: ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('course/scm/' . $scm->id)) ?>
+ <? endif; ?>
+ </footer>
+</form>
diff --git a/app/views/course/scm/index.php b/app/views/course/scm/index.php
new file mode 100644
index 0000000..8b45b23
--- /dev/null
+++ b/app/views/course/scm/index.php
@@ -0,0 +1,35 @@
+<article class="studip">
+ <header>
+ <h1>
+ <?= Icon::create('infopage', Icon::ROLE_INACTIVE)->asImg(['class' => 'text-top']) ?>
+ <?= htmlReady($scm->tab_name) ?>
+ </h1>
+ <nav>
+ <span>
+ <? if ($scm->user): ?>
+ <?= sprintf(_('Zuletzt geändert von %s am %s'), ObjectdisplayHelper::link($scm->user), strftime('%x, %X', $scm->chdate)) ?>
+ <? else: ?>
+ <?= $scm->chdate ? sprintf(_('Zuletzt geändert am %s'), strftime('%x, %X', $scm->chdate)) : '' ?>
+ <? endif; ?>
+ </span>
+ <? if ($priviledged): ?>
+ <a href="<?= $controller->edit($scm) ?>" title="<?= _('Bearbeiten') ?>" data-dialog>
+ <?= Icon::create('admin') ?>
+ </a>
+ <? if (count($scms) > 1): ?>
+ <? if ($scm->position != 0): ?>
+ <a href="<?= $controller->move($scm) ?>" title="<?= _('Diese Seite an die erste Position setzen') ?>">
+ <?= Icon::create('arr_2up') ?>
+ </a>
+ <? endif; ?>
+ <a href="<?= $controller->link_for('course/scm/' . $scm->id, ['verify' => 'delete']) ?>" title="<?= _('Diese Seite löschen') ?>">
+ <?= Icon::create('trash') ?>
+ </a>
+ <? endif; ?>
+ <? endif; ?>
+ </nav>
+ </header>
+ <section>
+ <?= ((string) $scm->content) ? formatReady($scm->content) : MessageBox::info(_('In diesem Bereich wurden noch keine Inhalte erstellt.')) ?>
+ </section>
+</article>
diff --git a/app/views/course/statusgroups/_askcancel_members.php b/app/views/course/statusgroups/_askcancel_members.php
new file mode 100644
index 0000000..7c03836
--- /dev/null
+++ b/app/views/course/statusgroups/_askcancel_members.php
@@ -0,0 +1,16 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_cancel_members') ?>" method="post">
+ <section>
+ <?= sprintf(ngettext('Soll %u Person wirklich aus %s ausgetragen werden?',
+ 'Sollen %u Personen wirklich aus %s ausgetragen werden?',
+ count($members)), count($members), htmlReady($course_title)) ?>
+ <?php foreach ($members as $m) : ?>
+ <input type="hidden" name="members[]" value="<?= $m ?>"/>
+ <?php endforeach ?>
+ </section>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Austragen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/_askdelete_groups.php b/app/views/course/statusgroups/_askdelete_groups.php
new file mode 100644
index 0000000..33ec794
--- /dev/null
+++ b/app/views/course/statusgroups/_askdelete_groups.php
@@ -0,0 +1,22 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_delete_groups') ?>" method="post">
+ <header>
+ <h1>
+ <?= ngettext('Soll die folgende Gruppe wirklich gelöscht werden?',
+ 'Sollen die folgenden Gruppen wirklich gelöscht werden?', count($groups)) ?>
+ </h1>
+ <ul>
+ <?php foreach ($groups as $g) : ?>
+ <li>
+ <input type="hidden" name="groups[]" value="<?= $g->id ?>">
+ <?= htmlReady($g->name) ?>
+ </li>
+ <?php endforeach ?>
+ </ul>
+ </header>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Löschen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/_askdelete_members.php b/app/views/course/statusgroups/_askdelete_members.php
new file mode 100644
index 0000000..5023ffd
--- /dev/null
+++ b/app/views/course/statusgroups/_askdelete_members.php
@@ -0,0 +1,17 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_delete_members',
+ $source_group->id) ?>" method="post">
+ <section>
+ <?= sprintf(ngettext('Soll %u Person wirklich aus %s entfernt werden?',
+ 'Sollen %u Personen wirklich aus %s entfernt werden?',
+ count($members)), count($members), htmlReady($source_group->name)) ?>
+ <?php foreach ($members as $m) : ?>
+ <input type="hidden" name="members[]" value="<?= $m ?>"/>
+ <?php endforeach ?>
+ </section>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Entfernen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/_copy_members.php b/app/views/course/statusgroups/_copy_members.php
new file mode 100644
index 0000000..d30308a
--- /dev/null
+++ b/app/views/course/statusgroups/_copy_members.php
@@ -0,0 +1,25 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_copy_members') ?>" method="post">
+ <label for="target_group">
+ <?= sprintf(ngettext(
+ 'In welche Gruppe soll die gewählte Person kopiert werden?',
+ 'In welche Gruppe sollen die %u gewählten Personen kopiert werden?',
+ count($members)),
+ count($members)) ?>
+ <select name="target_group">
+ <?php foreach ($target_groups as $g) : ?>
+ <option value="<?= $g->id ?>"><?= htmlReady($g->name) ?></option>
+ <?php endforeach ?>
+ </select>
+ </label>
+
+ <?php foreach ($members as $m) : ?>
+ <input type="hidden" name="members[]" value="<?= $m ?>"/>
+ <?php endforeach ?>
+ <input type="hidden" name="source" value="<?= $source_group ?>"/>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Kopieren'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/_edit_groups_selfassign.php b/app/views/course/statusgroups/_edit_groups_selfassign.php
new file mode 100644
index 0000000..d5c31d1
--- /dev/null
+++ b/app/views/course/statusgroups/_edit_groups_selfassign.php
@@ -0,0 +1,42 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_save_groups_selfassign') ?>" method="post">
+ <label>
+ <input type="checkbox" name="selfassign" value="1"<?= $selfassign == 1 ? ' checked' : '' ?>>
+ <?= _('Selbsteintrag erlaubt') ?>
+ <?= $selfassign == -1 ? '<br>(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="exclusive" value="1"<?= $exclusive == 1 ? ' checked' : '' ?>>
+ <?= _('Exklusiver Selbsteintrag (in nur eine Gruppe)') ?>
+ <?= $exclusive == -1 ? '<br>(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <label class="col-3" style="vertical-align: top">
+ <?= _('Selbsteintrag erlaubt ab') ?>
+ <input type="text" class="size-s" data-datetime-picker id="selfassign_start" size="20" name="selfassign_start" value="<?= $selfassign_start != -1 ?
+ $selfassign_start : '' ?>">
+ <?= $selfassign_start == -1 ? '(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <label class="col-3" style="vertical-align: top">
+ <?= _('Selbsteintrag erlaubt bis') ?>
+ <input type="text" class="size-s" data-datetime-picker='{">":"#selfassign_start"}' size="20" name="selfassign_end" value="<?= $selfassign_end != -1 ?
+ $selfassign_end : '' ?>">
+ <?= $selfassign_end == -1 ? '(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <?php foreach ($groups as $g) : ?>
+ <input type="hidden" name="groups[]" value="<?= $g->id ?>">
+ <?php endforeach ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
+<script type="text/javascript">
+ //<!--
+ STUDIP.Statusgroups.initInputs();
+ //-->
+</script>
diff --git a/app/views/course/statusgroups/_edit_groups_size.php b/app/views/course/statusgroups/_edit_groups_size.php
new file mode 100644
index 0000000..786ff56
--- /dev/null
+++ b/app/views/course/statusgroups/_edit_groups_size.php
@@ -0,0 +1,24 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_save_groups_size') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <label>
+ <?= _('Gruppengröße') ?>
+ <input type="number" name="size" value="<?= intval($size) ?>" min="0">
+ <?= $different_sizes ? '(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <?php foreach ($groups as $g) : ?>
+ <input type="hidden" name="groups[]" value="<?= $g->id ?>">
+ <?php endforeach ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
+<script type="text/javascript">
+ //<!--
+ STUDIP.Statusgroups.initInputs();
+ //-->
+</script>
diff --git a/app/views/course/statusgroups/_group.php b/app/views/course/statusgroups/_group.php
new file mode 100644
index 0000000..35f8a90
--- /dev/null
+++ b/app/views/course/statusgroups/_group.php
@@ -0,0 +1,142 @@
+<article class="<?= ContentBoxHelper::classes($group->id) ?> <? if ($group->id != 'nogroup' && $is_tutor && !$is_locked) echo 'draggable'; ?> <?= $open_group ? 'open' : '' ?>" id="<?= $group->id ?>">
+ <header>
+ <? if ($group->id != 'nogroup' && $is_tutor && !$is_locked) : ?>
+ <span class="sg-sortable-handle"></span>
+ <? endif ?>
+ <h1>
+ <?php if ($group->id != 'nogroup' && $is_tutor && !$is_locked) : ?>
+ <input aria-label="<?= _('Gruppe auswählen') ?>"
+ type="checkbox" name="groups[]"
+ class="groupselector" value="<?= $group->id ?>"
+ id="<?= $group->id ?>"/>
+ <?php endif ?>
+ <a href="<?= ContentBoxHelper::href($group->id) ?>" class="get-group-members"
+ data-group-id="<?= $group->id ?>"
+ data-get-members-url="<?= $controller->url_for('course/statusgroups/getgroup', $group->id) ?>">
+ <?= htmlReady($group->name) ?> (<?= $membercount .
+ ($group->size ? '/' . $group->size : '') ?>)
+ </a>
+ <?php if ($group->id != 'nogroup') : ?>
+ <a class="no-contentbox-link"
+ href="<?= $controller->url_for('course/statusgroups/groupinfo', $group->id) ?>"
+ data-dialog="size=auto">
+ <?= Icon::create('info-circle')->asImg([
+ 'title' => sprintf(_('Informationen zu %s'), $group->name)
+ ]) ?>
+ </a>
+ <?php endif ?>
+ </h1>
+ <nav>
+ <?php if ($is_autor && !$is_tutor && $group->id != 'nogroup' && $group->isMember($GLOBALS['user']->id)) : ?>
+ <a href="<?= $controller->link_for('messages/write', [
+ 'group_id' => $group->id,
+ 'default_subject' => htmlReady($course_title . ' (' . $group->name . ')'),
+ ]) ?>" data-dialog="size=auto">
+ <?= Icon::create('mail', 'clickable', ['title' => sprintf(
+ _('Nachricht an alle Mitglieder der Gruppe %s schicken'),
+ $group->name
+ ),
+ ]) ?>
+ </a>
+ <?php endif ?>
+ <?php if (!$GLOBALS['perm']->have_perm('admin')) : ?>
+ <?php if ($group->id != 'nogroup' && $joinable) : ?>
+ <a href="<?= $controller->url_for('course/statusgroups/join', $group->id) ?>">
+ <?= Icon::create('door-enter', 'clickable',
+ ['title' => sprintf(_('Mitglied von Gruppe %s werden'),
+ htmlReady($group->name))]) ?></a>
+ <?php elseif ($group->id != 'nogroup' && $group->selfassign &&
+ $group->selfassign_start > time()) : ?>
+ <?= Icon::create('door-enter', 'inactive',
+ ['title' => sprintf(_('Der Eintrag in diese Gruppe ist möglich ab %s.'),
+ date('d.m.Y H:i', $group->selfassign_start))]) ?>
+ <?php elseif ($group->id != 'nogroup' && $group->selfassign &&
+ $group->selfassign_end && $group->selfassign_end < time()) : ?>
+ <?= Icon::create('door-enter', 'inactive',
+ ['title' => sprintf(_('Der Eintrag in diese Gruppe war möglich bis %s.'),
+ date('d.m.Y H:i', $group->selfassign_end))]) ?>
+ <?php elseif ($group->id != 'nogroup' && $group->userMayLeave($GLOBALS['user']->id)) : ?>
+ <a href="<?= $controller->url_for('course/statusgroups/leave', $group->id) ?>" data-confirm="<?= sprintf(_('Aus Gruppe %s austragen'),htmlReady($group->name)) . '?' ?>">
+ <?= Icon::create('door-leave', 'attention',
+ ['title' => sprintf(_('Aus Gruppe %s austragen'),
+ htmlReady($group->name))]) ?></a>
+ <?php endif ?>
+ <?php endif ?>
+ <?php if ($is_tutor) : ?>
+ <?php if ($group->id != 'nogroup') : ?>
+ <?= ActionMenu::get()
+ ->addLink(
+ $controller->url_for('messages/write', [
+ 'group_id' => $group->id,
+ 'default_subject' => htmlReady($course_title . ' (' . $group->name . ')'),
+ ]),
+ _('Nachricht schicken'),
+ Icon::create('mail', 'clickable', [
+ 'title' => sprintf(
+ _('Nachricht an alle Mitglieder der Gruppe %s schicken'),
+ $group->name
+ ),
+ ]),
+ ['data-dialog' => 'size=auto']
+ )
+ ->condition(!($is_participants_locked || $is_locked))
+ ->addMultiPersonSearch(
+ MultiPersonSearch::get('add_statusgroup_member' . $group->id)
+ ->setTitle(sprintf(_('Personen zu Gruppe %s hinzufügen'), $group->name))
+ ->setLinkText(_('Personen hinzufügen'))
+ ->setSearchObject($memberSearch)
+ ->setDefaultSelectedUser($group->members->pluck('user_id'))
+ ->setDataDialogStatus(Request::isXhr())
+ ->setJSFunctionOnSubmit(Request::isXhr() ?
+ 'STUDIP.Dialog.close();' : false)
+ ->setExecuteURL($controller->url_for('course/statusgroups/add_member/' .
+ $group->id))
+ ->addQuickfilter(_('Veranstaltungsteilnehmende'),
+ $allmembers ? $allmembers->pluck('user_id') : [])
+ ->addQuickfilter(_('Teilnehmende ohne Gruppenzuordnung'),
+ $nogroupmembers)
+ )
+ ->conditionAll(!$is_locked)
+ ->addLink(
+ $controller->url_for('course/statusgroups/edit', $group->id),
+ _('Bearbeiten'),
+ Icon::create('edit', 'clickable', [
+ 'title' => sprintf(
+ _('Gruppe %s bearbeiten'),
+ $group->name
+ )
+ ]),
+ ['data-dialog' => '']
+ )
+ ->addLink(
+ $controller->url_for('course/statusgroups/delete', $group->id),
+ _('Löschen'),
+ Icon::create('trash', 'clickable', [
+ 'title' => sprintf(
+ _('Gruppe %s löschen'),
+ $group->name
+ )
+ ]),
+ ['data-confirm' => _('Soll die Gruppe wirklich gelöscht werden?')]
+ ) ?>
+ <?php else : ?>
+ <a href="<?= $controller->url_for('messages/write', [
+ 'filter' => 'not_grouped',
+ 'course_id' => $course_id,
+ 'default_subject' => htmlReady($course_title).' ('.htmlReady($group->name).')'
+ ]) ?>" data-dialog="size=auto;">
+ <?= Icon::create('mail', 'clickable', [
+ 'title' => _('Nachricht an alle nicht zugeordneten Personen schicken')
+ ])->asImg(20) ?></a>
+ <?php endif ?>
+ <?php endif ?>
+ </nav>
+ </header>
+ <section>
+ <article id="group-members-<?= $group->id ?>"<?= $load ? ' class="open"' : ''?>>
+ <?php if ($load) : ?>
+ <?= $this->render_partial('course/statusgroups/getgroup', compact('members is_tutor is_locked group order sort_by')) ?>
+ <?php endif ?>
+ </article>
+ </section>
+</article>
diff --git a/app/views/course/statusgroups/_member.php b/app/views/course/statusgroups/_member.php
new file mode 100644
index 0000000..a874e6b
--- /dev/null
+++ b/app/views/course/statusgroups/_member.php
@@ -0,0 +1,85 @@
+<? $user_fullname = $m->getUserFullname('full_rev') ?>
+<tr>
+<? if ($is_tutor && !$is_locked) : ?>
+ <td>
+ <input aria-label="<?= _('Mitglieder auswählen') ?>"
+ type="checkbox" name="group[<?= $group->id ?>][<?= $m->user_id ?>]"
+ class="groupmembers-<?= $group->id ?>" value="1">
+ </td>
+<? endif ?>
+ <td>
+ <?= str_pad($i, 2, '0', STR_PAD_LEFT) ?>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for('profile', ['username' => $m->username]) ?>">
+ <?= Avatar::getAvatar($m->user_id, $m->username)->getImageTag(Avatar::SMALL, [
+ 'style' => 'margin-right: 5px',
+ 'title' => $user_fullname,
+ ]) ?>
+ <?= htmlReady($user_fullname) ?>
+ <?php if ($user_id == $m->user_id && $m->visible == 'no') : ?>
+ (<?= _('unsichtbar') ?>)
+ <?php endif ?>
+ </a>
+ </td>
+<? if ($is_tutor) : ?>
+ <? if ($group->id !== 'nogroup'): ?>
+ <td>
+ <?= $m->mkdate ? strftime('%x %X', $m->mkdate) : '' ?>
+ </td>
+ <? endif; ?>
+ <td>
+ <?= $this->render_partial('course/members/_studycourse.php',
+ ['studycourses' => new SimpleCollection(UserStudyCourse::findByUser($m->user_id))]) ?>
+ </td>
+<? endif ?>
+ <td class="memberactions">
+ <? $actions = ActionMenu::get();
+ if ($is_tutor || $m->user_id !== $GLOBALS['user']->id) {
+ $actions->addLink(
+ $controller->url_for('messages/write', [
+ 'rec_uname' => $m->username,
+ 'default_subject' => $course_title,
+ ]),
+ _('Nachricht schicken'),
+ Icon::create('mail', 'clickable', [
+ 'title' => sprintf(_('Nachricht an %s schicken'), $user_fullname),
+ ]),
+ ['data-dialog' => 'size=auto']
+ );
+ }
+ if ($is_tutor) {
+ $actions->addLink(
+ $controller->url_for('course/statusgroups/move_member', $m->user_id, $group->id),
+ _('In eine andere Gruppe verschieben'),
+ Icon::create('person+move_right', 'clickable', [
+ 'title' => sprintf(
+ _('%s in eine andere Gruppe verschieben'),
+ $user_fullname
+ ),
+ ]),
+ ['data-dialog' => 'size=auto']
+ );
+ }
+ if ($group->id !== 'nogroup' && ($is_tutor || ($m->user_id === $GLOBALS['user']->id && $group->userMayLeave($GLOBALS['user']->id)))) {
+ $actions->addLink(
+ $controller->url_for('course/statusgroups/delete_member', $m->user_id, $group->id),
+ _('Aus der Gruppe entfernen'),
+ Icon::create('trash', 'clickable', [
+ 'title' => sprintf(
+ _('%s aus Gruppe %s entfernen'),
+ $user_fullname,
+ $group->name
+ ),
+ ]),
+ ['data-confirm' => sprintf(
+ _('Soll %s wirklich aus der Gruppe %s entfernt werden?'),
+ htmlReady($user_fullname),
+ htmlReady($group->name)
+ )]
+ );
+ }
+ echo $actions;
+ ?>
+ </td>
+</tr>
diff --git a/app/views/course/statusgroups/_move_members.php b/app/views/course/statusgroups/_move_members.php
new file mode 100644
index 0000000..e2ab7db
--- /dev/null
+++ b/app/views/course/statusgroups/_move_members.php
@@ -0,0 +1,25 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_move_members') ?>" method="post">
+ <label for="target_group">
+ <?= sprintf(ngettext(
+ 'In welche Gruppe soll die gewählte Person verschoben werden?',
+ 'In welche Gruppe sollen die %u gewählten Personen verschoben werden?',
+ count($members)),
+ count($members)) ?>
+ <select name="target_group">
+ <?php foreach ($target_groups as $g) : ?>
+ <option value="<?= $g->id ?>"><?= htmlReady($g->name) ?></option>
+ <?php endforeach ?>
+ </select>
+ </label>
+
+ <?php foreach ($members as $m) : ?>
+ <input type="hidden" name="members[]" value="<?= $m ?>"/>
+ <?php endforeach ?>
+ <input type="hidden" name="source" value="<?= $source_group ?>"/>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Verschieben'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/batch_action.php b/app/views/course/statusgroups/batch_action.php
new file mode 100644
index 0000000..10bec38
--- /dev/null
+++ b/app/views/course/statusgroups/batch_action.php
@@ -0,0 +1,28 @@
+<?php
+ if ($edit_size) {
+ echo $this->render_partial('course/statusgroups/_edit_groups_size', compact('groups'));
+ } elseif ($edit_selfassign) {
+ echo $this->render_partial('course/statusgroups/_edit_groups_selfassign', compact('groups'));
+ } elseif ($askdelete) {
+ echo $this->render_partial('course/statusgroups/_askdelete_groups', compact('groups'));
+ } elseif ($movemembers) {
+ echo $this->render_partial(
+ 'course/statusgroups/_move_members',
+ compact('target_groups', 'members', 'source_group')
+ );
+ } elseif ($copymembers) {
+ echo $this->render_partial(
+ 'course/statusgroups/_copy_members',
+ compact('target_groups', 'members', 'source_group')
+ );
+ } elseif ($deletemembers) {
+ echo $this->render_partial(
+ 'course/statusgroups/_askdelete_members',
+ compact('members', 'source_group')
+ );
+ } elseif ($cancelmembers) {
+ echo $this->render_partial(
+ 'course/statusgroups/_askcancel_members',
+ compact('members')
+ );
+ }
diff --git a/app/views/course/statusgroups/create_groups.php b/app/views/course/statusgroups/create_groups.php
new file mode 100644
index 0000000..c011b79
--- /dev/null
+++ b/app/views/course/statusgroups/create_groups.php
@@ -0,0 +1,146 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_create') ?>"
+ method="post" data-secure>
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Wie sollen Gruppen angelegt werden?') ?>
+ </legend>
+ <section>
+ <label>
+ <input type="radio" name="mode" value="numbering" checked
+ onclick="$('.numbering-data').show();$('.course-data').hide();">
+ <?= _('Erzeuge beliebig viele Gruppen mit Namenspräfix') ?>
+ </label>
+ <label>
+ <input type="radio" name="mode" value="coursedata"
+ onclick="$('.numbering-data').hide();$('.course-data').show();">
+ <?= _('Lege Gruppen zu bestehenden Veranstaltungsdaten an') ?>
+ </label>
+ </section>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Lege folgende Gruppen an') ?>
+ </legend>
+ <section class="numbering-data">
+ <label>
+ <span class="required">
+ <?= _('Anzahl anzulegender Gruppen') ?>
+ </span>
+ <input type="number" name="number" value="5" min="1">
+ </label>
+ </section>
+ <section class="numbering-data">
+ <label>
+ <input type="radio" name="numbering_type" value="1" checked>
+ <?= _('Numerische Nummerierung')?>
+ </label>
+ <label>
+ <input type="radio" name="numbering_type" value="2">
+ <?= _('Alphabetische Nummerierung')?>
+ </label>
+ </section>
+ <section class="numbering-data">
+ <label>
+ <?= _('Beginne Nummerierung bei') ?>
+ <input type="number" name="startnumber" value="1" min="0">
+ </label>
+ </section>
+ <section class="numbering-data">
+ <label class="numbering-data">
+ <span class="required">
+ <?= _('Namenspräfix') ?>
+ </span>
+ <input type="text" name="prefix" maxlength="200" value="<?= _('Gruppe') ?>">
+ </label>
+ </section>
+ <? if ($has_paper_related_topics): ?>
+ <section class="course-data">
+ <label>
+ <input type="radio" name="createmode" value="paper_related">
+ <?= _('Lege eine Gruppe pro Thema vom Typ "Hausarbeit/Referat" an') ?>
+ </label>
+ </section>
+ <? endif; ?>
+ <? if ($has_topics) : ?>
+ <section class="course-data">
+ <label>
+ <input type="radio" name="createmode" value="topics">
+ <?= _('Lege eine Gruppe pro Thema an') ?>
+ </label>
+ </section>
+ <? endif ?>
+ <? if ($has_cycles || $has_singledates) : ?>
+ <section class="course-data">
+ <label>
+ <input type="radio" name="createmode" value="dates">
+ <?= _('Lege eine Gruppe pro regelmäßiger Zeit/Einzeltermin an') ?>
+ </label>
+ </section>
+ <? endif ?>
+ <section class="course-data">
+ <label>
+ <input type="radio" name="createmode" value="lecturers">
+ <?= _('Lege eine Gruppe pro Lehrendem an') ?>
+ </label>
+ </section>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Voreinstellungen für alle anzulegenden Gruppen') ?>
+ </legend>
+ <section>
+ <label>
+ <?= _('Gruppengröße') ?>
+ <input type="number" name="size" value="0" min="0">
+ </label>
+ </section>
+ <section>
+ <label>
+ <input type="checkbox" name="makefolder" value="1">
+ <?= _('Dateiordner anlegen') ?>
+ </label>
+ </section>
+ <section>
+ <label>
+ <input type="checkbox" name="selfassign" value="1">
+ <?= _('Selbsteintrag') ?>
+ </label>
+ </section>
+ <section>
+ <label>
+ <input type="checkbox" name="exclusive" value="1">
+ <?= _('Selbsteintrag in nur eine Gruppe') ?>
+ </label>
+ </section>
+ <section class="col-3">
+ <label class="col-3">
+ <?= _('Selbsteintrag erlaubt ab') ?>
+ <input type="text" data-datetime-picker id="selfassign_start" size="20"
+ name="selfassign_start" value="<?= date('d.m.Y H:i') ?>">
+ </label>
+ </section>
+ <section class="col-3">
+ <label class="col-3">
+ <?= _('Selbsteintrag erlaubt bis') ?>
+ <input type="text" data-datetime-picker='{">":"#selfassign_start"}' size="20"
+ name="selfassign_end" value="">
+ </label>
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Anlegen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
+<script type="text/javascript" language="JavaScript">
+ //<!--
+ $('.course-data').hide();
+ STUDIP.Statusgroups.initInputs();
+ //-->
+</script>
diff --git a/app/views/course/statusgroups/edit.php b/app/views/course/statusgroups/edit.php
new file mode 100644
index 0000000..2cc8577
--- /dev/null
+++ b/app/views/course/statusgroups/edit.php
@@ -0,0 +1,117 @@
+<form class="default collapsable" action="<?= $controller->url_for('course/statusgroups/save', $group->id) ?>" method="post" data-secure>
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Einstellungen') ?>
+ </legend>
+
+ <label for="name" class="required">
+ <?= _('Name') ?>
+ </label>
+ <input type="text" name="name" size="75" maxlength="255" value="<?= htmlReady($group->name) ?>" required>
+
+ <label for="size">
+ <?= _('Gruppengröße') ?>
+ </label>
+ <input type="number" name="size" value="<?= intval($group->size) ?>" min="0">
+
+ <?php if ($group->isNew() || !$group->hasFolder()) : ?>
+ <label>
+ <input type="checkbox" name="makefolder" value="1">
+ <?= _('Dateiordner anlegen') ?>
+ </label>
+ <?php elseif ($group->hasFolder()) : ?>
+ <label>
+ <input type="checkbox" checked disabled>
+ <?= _('Zu dieser Gruppe gehört ein Dateiordner.') ?>
+ </label>
+ <?php endif ?>
+
+ <label>
+ <input type="checkbox" name="blubber" value="1"<?= BlubberStatusgruppeThread::findByStatusgruppe_id($group->id) ? " checked" : "" ?>>
+ <?= _('Blubber in der Gruppe erlauben') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="selfassign" value="1"<?= $group->selfassign ? ' checked' : '' ?>>
+ <?= _('Selbsteintrag erlaubt') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="exclusive" value="1"<?= $group->selfassign == 2 ? ' checked' : '' ?>>
+ <?= _('Exklusiver Selbsteintrag (in nur eine Gruppe)') ?>
+ </label>
+
+ <label class="col-3">
+ <?= _('Selbsteintrag erlaubt ab') ?>
+ <input class="size-s" type="text" size="20" name="selfassign_start" id="selfassign_start" value="<?= $group->selfassign_start ?
+ date('d.m.Y H:i', $group->selfassign_start) : '' ?>" data-datetime-picker>
+ </label>
+
+ <label class="col-3">
+ <?= _('Selbsteintrag erlaubt bis') ?>
+ <input class="size-s" type="text" size="20" name="selfassign_end" value="<?= $group->selfassign_end ?
+ date('d.m.Y H:i', $group->selfassign_end) : '' ?>" data-datetime-picker='{">":"#selfassign_start"}'>
+ </label>
+ </fieldset>
+
+ <h1>
+ <?= _('Zuordnung von Terminen') ?>
+ </h1>
+
+ <?php if ($cycles || $singledates) : ?>
+ <?php if ($cycles) : ?>
+ <fieldset class="collapsed">
+ <legend><?= _('Regelmäßige Zeiten') ?></legend>
+ <?php foreach ($cycles as $c) : ?>
+ <article class="<?= ContentBoxHelper::classes($c->id) ?>" id="<?= $c->id ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($c->id, ['contentbox_type' => 'news']) ?>">
+ <?= htmlReady($c->toString()) ?>
+ </a>
+ </h1>
+ </header>
+ <section>
+ <?php foreach ($c->dates as $d) : ?>
+ <label for="<?= $d->id ?>">
+ <input type="checkbox" name="dates[]" value="<?= $d->id ?>" id="<?= $d->id?>"
+ <?= $group->dates->find($d->id) ? ' checked' : '' ?>>
+ <?= htmlReady($d->getFullname()) ?>
+ </label>
+ <?php endforeach ?>
+ </section>
+ </article>
+ <?php endforeach ?>
+ </fieldset>
+ <?php endif ?>
+ <?php if ($singledates) : ?>
+ <fieldset class="collapsed">
+ <legend>
+ <?= _('Einzeltermine') ?>
+ </legend>
+ <?php foreach ($singledates as $s) : ?>
+ <label for="<?= $s->id ?>">
+ <input type="checkbox" name="dates[]" value="<?= $s->id ?>" id="<?= $s->id?>"
+ <?= $group->dates->find($s->id) ? ' checked' : '' ?>>
+ <?= htmlReady($s->getFullname()) ?>
+ </label>
+ <?php endforeach ?>
+ </fieldset>
+ <?php endif ?>
+ <?php else : ?>
+ <?= MessageBox::info(_('Diese Veranstaltung hat keine Termine.')); ?>
+ <?php endif ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
+<script type="text/javascript">
+ //<!--
+ STUDIP.Statusgroups.initInputs();
+ //-->
+</script>
diff --git a/app/views/course/statusgroups/getgroup.php b/app/views/course/statusgroups/getgroup.php
new file mode 100644
index 0000000..426fca4
--- /dev/null
+++ b/app/views/course/statusgroups/getgroup.php
@@ -0,0 +1,134 @@
+<? if (count($members)) : ?>
+ <table class="default">
+ <colgroup>
+ <col width="20">
+ <? if($is_tutor) : ?>
+ <? $cols = $group->id !== 'nogroup' ? 5 : 4 ?>
+ <? if (!$is_locked) : ?>
+ <col width="20">
+ <? $cols = 6 ?>
+ <? endif ?>
+ <col>
+ <? if ($group->id !== 'nogroup'): ?>
+ <col width="15%">
+ <? endif; ?>
+ <col width="35%">
+ <? else : ?>
+ <col>
+ <? $cols = 3 ?>
+ <? endif ?>
+
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <? if ($is_tutor && !$is_locked) : ?>
+ <th>
+ <input aria-label="<?= sprintf(_('Alle Mitglieder dieser Gruppe auswählen')) ?>"
+ type="checkbox" name="all" value="1"
+ data-proxyfor=":checkbox.groupmembers-<?= $group->id ?>"
+ data-activates=".memberactions-<?= $group->id ?> select,.memberactions-<?= $group->id ?> button">
+ </th>
+ <? endif ?>
+ <th></th>
+ <th <?= ($sort_by == 'nachname' && $sort_group == $group->id) ?
+ sprintf('class="sort%s"', $order) : '' ?>>
+ <a href="<?= URLHelper::getLink('#' . $group->id,
+ [
+ 'sortby' => 'nachname',
+ 'sort_group' => $group->id,
+ 'order' => $group->id && $sort_by == 'nachname' ?
+ ($order == 'desc' ? 'asc' : 'desc') : 'desc',
+ 'contentbox_open' => $group->id
+ ]) ?>">
+ <?=_('Nachname, Vorname')?>
+ </a>
+ </th>
+ <? if ($is_tutor) :?>
+ <? if ($group->id !== 'nogroup'): ?>
+ <th <?= ($sort_by == 'mkdate' && $sort_group == $group->id) ? sprintf('class="sort%s"', $order) : '' ?>>
+ <a href="<?= URLHelper::getLink('#' . $group->id,
+ [
+ 'sortby' => 'mkdate',
+ 'sort_group' => $group->id,
+ 'order' => $group->id && $sort_by == 'mkdate' ?
+ ($order == 'desc' ? 'asc' : 'desc') : 'desc',
+ 'contentbox_open' => $group->id
+ ]) ?>">
+ <?= _('Anmeldedatum') ?>
+ </a>
+ </th>
+ <? endif; ?>
+ <th>
+ <?= _('Studiengang') ?>
+ </th>
+ <? endif ?>
+ <th><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $i = 1; foreach ($members as $m) : ?>
+ <?= $this->render_partial(
+ 'course/statusgroups/_member',
+ ['m' => $m, 'i' => $i++, 'is_tutor' => $is_tutor, 'is_locked' => $is_locked]) ?>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <? if ($is_tutor) : ?>
+ <td colspan="<?= $cols ?>">
+ <? if (!$is_locked) : ?>
+ <div class="memberselect">
+ <label>
+ <input aria-label="<?= sprintf(_('Alle Mitglieder dieser Gruppe auswählen')) ?>"
+ type="checkbox" name="all" value="1"
+ data-proxyfor=":checkbox.groupmembers-<?= $group->id ?>"
+ data-activates=".memberactions-<?= $group->id ?> select,.memberactions-<?= $group->id ?> button">
+ <?= _('Alle Mitglieder dieser Gruppe auswählen') ?>
+ </label>
+ </div>
+ <div class="memberactions memberactions-<?= $group->id ?>">
+ <label>
+ <select name="members_action[<?= $group->id ?>]"
+ id="members-action-<?= $group->id ?>">
+ <option value="move"><?= _('In andere Gruppe verschieben') ?></option>
+ <option value="copy"><?= _('In andere Gruppe kopieren') ?></option>
+ <? if ($group->id != 'nogroup') : ?>
+ <option value="delete"><?= _('Aus dieser Gruppe entfernen') ?></option>
+ <? endif ?>
+ <option value="cancel"><?= _('Austragen aus der Veranstaltung') ?></option>
+ </select>
+ </label>
+ <input type="hidden" name="source" value="<?= $group->id ?>">
+ <?= Studip\Button::create(
+ _('Ausführen'),
+ "batch_members[{$group->id}]",
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ </div>
+ <? endif ?>
+ </td>
+ <? elseif (!$is_tutor) : ?>
+ <td colspan="<?= $cols ?>">
+ <?= sprintf(_('+ %u unsichtbare Personen'), $invisible) ?>
+ </td>
+ <? endif ?>
+ </tr>
+ </tfoot>
+ </table>
+<? elseif ($invisible > 0): ?>
+ <div class="statusgroup-no-members">
+ <?= sprintf(
+ ngettext(
+ 'Diese Gruppe hat %d unsichtbares Mitglied.',
+ 'Diese Gruppe hat %d unsichtbare Mitglieder.',
+ $invisible
+ ),
+ htmlReady($invisible)
+ ) ?>
+ </div>
+<? else : ?>
+ <div class="statusgroup-no-members">
+ <?= _('Diese Gruppe hat keine Mitglieder.') ?>
+ </div>
+<? endif ?>
diff --git a/app/views/course/statusgroups/groupinfo.php b/app/views/course/statusgroups/groupinfo.php
new file mode 100644
index 0000000..bbbf170
--- /dev/null
+++ b/app/views/course/statusgroups/groupinfo.php
@@ -0,0 +1,101 @@
+<header>
+ <h1><?= sprintf(_('Informationen zu %s'), htmlReady($group->name)) ?></h1>
+</header>
+<section>
+ <p>
+ <?= $group->size > 0 ?
+ formatReady(sprintf(_('Diese Gruppe ist auf **%u** Mitglieder beschränkt.'), $group->size)) :
+ formatReady(_('Die Größe dieser Gruppe ist **nicht beschränkt**.')) ?>
+ </p>
+
+ <?php if ($group->selfassign) : ?>
+ <?php if ($group->selfassign == 1) : ?>
+ <p>
+ <?= _('Die Teilnehmenden dieser Veranstaltung können sich ' .
+ 'selbst in beliebig viele der Gruppen eintragen, bei denen ' .
+ 'kein Exklusiveintrag aktiviert ist.') ?>
+ </p>
+ <?php elseif ($group->selfassign == 2) : ?>
+ <p>
+ <?= _('Die Teilnehmenden dieser Veranstaltung können sich ' .
+ 'in genau einer der Gruppen eintragen, bei denen der ' .
+ 'Exklusiveintrag aktiviert ist.') ?>
+ </p>
+ <?php endif ?>
+ <?php if ($group->selfassign_start && $group->selfassign_end) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Der Eintrag ist möglich **von %s bis %s**.'),
+ date('d.m.Y H:i', $group->selfassign_start),
+ date('d.m.Y H:i', $group->selfassign_end))) ?>
+ </p>
+ <?php elseif ($group->selfassign_start && !$group->selfassign_end) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Der Eintrag ist möglich **ab %s**.'),
+ date('d.m.Y H:i', $group->selfassign_start))) ?>
+ </p>
+ <?php elseif (!$group->selfassign_start && $group->selfassign_end) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Der Eintrag ist möglich **bis %s**.'),
+ date('d.m.Y H:i', $group->selfassign_end))) ?>
+ </p>
+ <?php endif ?>
+ <?php endif ?>
+
+ <?php if ($folder = $group->getFolder()) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Zu dieser Gruppe gehört ein [Dateiordner]%s .'),
+ URLHelper::getURL('dispatch.php/course/files/index/' . $folder->id, [
+ 'cid' => $course_id,
+ ]))) ?>
+ </p>
+ <?php endif ?>
+
+ <?php if ($thread = $group->blubberthread) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Zu dieser Gruppe gehört ein [Blubberthread]%s .'),
+ URLHelper::getURL('plugins.php/blubber/messenger/course/' . $thread->id, [
+ 'cid' => $course_id,
+ ]))) ?>
+ </p>
+ <?php endif ?>
+
+ <?php if ($group->dates->count() > 0) : ?>
+ <p>
+ <?= _('Zugeordnete Termine:') ?>
+ <ul>
+ <?php foreach ($group->dates as $d) : ?>
+ <li>
+ <?= htmlReady($d->toString()) ?>
+ </li>
+ <?php endforeach ?>
+ </ul>
+ </p>
+ <?php endif ?>
+
+ <?php if ($topics = $group->findTopics()) : ?>
+ <p>
+ <?= _('Zugeordnete Themen:') ?>
+ <ul>
+ <?php foreach ($topics as $t) : ?>
+ <li><?= htmlReady($t->title) ?></li>
+ <?php endforeach ?>
+ </ul>
+ </p>
+ <?php endif ?>
+
+ <?php if ($lecturers = $group->findLecturers()) : ?>
+ <p>
+ <?= sprintf(_('Zugeordnete %s:'), htmlReady(get_title_for_status('dozent', 2))) ?>
+ <ul>
+ <?php foreach ($lecturers as $l) : ?>
+ <li><?= htmlReady($l->getFullname()) ?></li>
+ <?php endforeach ?>
+ </ul>
+ </p>
+ <?php endif ?>
+</section>
+
+<footer data-dialog-button>
+ <?= Studip\LinkButton::createCancel(_('Schließen'),
+ $controller->url_for('course/statusgroups')) ?>
+</footer>
diff --git a/app/views/course/statusgroups/index.php b/app/views/course/statusgroups/index.php
new file mode 100644
index 0000000..2f75624
--- /dev/null
+++ b/app/views/course/statusgroups/index.php
@@ -0,0 +1,43 @@
+<form action="<?= $controller->url_for('course/statusgroups/batch_action') ?>" method="post">
+<section class="contentbox course-statusgroups" <? if ($is_tutor && !$is_locked) echo 'data-sortable="' . $controller->url_for('course/statusgroups/order') . '"'; ?>>
+ <header>
+ <h1><?= _('Teilnehmende nach Gruppen') ?></h1>
+ </header>
+ <?php foreach ($groups as $group) : ?>
+ <?= $this->render_partial('course/statusgroups/_group', [
+ 'group' => $group['group'],
+ 'membercount' => $group['membercount'],
+ 'members' => $group['members'],
+ 'joinable' => $group['joinable'],
+ 'invisible' => $group['invisible_users'],
+ 'load' => $open_groups ? true : $group['load'],
+ 'order' => $order,
+ 'sort_by' => $sort_by,
+ 'open_group' => $open_groups,
+ ]) ?>
+ <?php endforeach ?>
+ <?php if ((count($groups) > $ungrouped_count ? 2 : 1) && $is_tutor && !$is_locked) : ?>
+ <footer>
+ <div class="groupselection">
+ <label>
+ <input aria-label="<?= sprintf(_('Alle Gruppen auswählen')) ?>"
+ type="checkbox" name="allgroups" value="1"
+ data-proxyfor=":checkbox.groupselector"
+ data-activates="select#batch-groups-action,#batch-groups-submit">
+ <?= _('Alle Gruppen auswählen') ?>
+ </label>
+ </div>
+ <div class="groupactions">
+ <label>
+ <select name="groups_action" id="batch-groups-action" disabled>
+ <option value="edit_size"><?= _('Gruppengröße bearbeiten') ?></option>
+ <option value="edit_selfassign"><?= _('Selbsteintrag bearbeiten') ?></option>
+ <option value="write_message"><?= _('Nachricht schreiben') ?></option>
+ <option value="delete"><?= _('Löschen') ?></option>
+ </select>
+ </label>
+ <?= Studip\Button::create(_('Ausführen'), 'batch_groups', ['data-dialog' => 'size=auto', 'disabled' => '', 'id' => 'batch-groups-submit']) ?>
+ </div>
+ </footer>
+ <?php endif ?>
+</section>
diff --git a/app/views/course/statusgroups/joinables.php b/app/views/course/statusgroups/joinables.php
new file mode 100644
index 0000000..0ef22c2
--- /dev/null
+++ b/app/views/course/statusgroups/joinables.php
@@ -0,0 +1,18 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/join') ?>" method="post">
+ <section>
+ <label for="target_group">
+ <?= _('Welcher Gruppe möchten Sie beitreten?') ?>
+ <select name="target_group">
+ <?php foreach ($joinables as $g) : ?>
+ <option value="<?= $g->id ?>"><?= htmlReady($g->name) ?></option>
+ <?php endforeach ?>
+ </select>
+ </label>
+ </section>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Beitreten'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/move_member.php b/app/views/course/statusgroups/move_member.php
new file mode 100644
index 0000000..2cdd53a
--- /dev/null
+++ b/app/views/course/statusgroups/move_member.php
@@ -0,0 +1,2 @@
+<?= $this->render_partial('course/statusgroups/_move_members',
+ ['target_groups' => $target_groups, 'members' => $members, 'source_group' => $source_group]) ?>
diff --git a/app/views/course/study_areas/show.php b/app/views/course/study_areas/show.php
new file mode 100644
index 0000000..a56521c
--- /dev/null
+++ b/app/views/course/study_areas/show.php
@@ -0,0 +1,14 @@
+<? if (!$locked) : ?>
+ <form action="<?= $controller->url_for('course/study_areas/save/' . $course->id, $url_params) ?>" method="post">
+<? endif?>
+ <?= $tree ?>
+ <div style="text-align: center;">
+ <? if ($must_have_studyareas) : ?>
+ <?= _("Die Veranstaltung muss <b>mindestens einen</b> Studienbereich haben.") ?>
+ <? else : ?>
+ <?= _("Die Veranstaltung darf <b>keine</b> Studienbereiche haben.") ?>
+ <? endif ?>
+ </div>
+<? if(!$locked) : ?>
+ </form>
+<? endif ?>
diff --git a/app/views/course/studygroup/_choose_founders.php b/app/views/course/studygroup/_choose_founders.php
new file mode 100644
index 0000000..2e90379
--- /dev/null
+++ b/app/views/course/studygroup/_choose_founders.php
@@ -0,0 +1,43 @@
+<?
+# Lifter010: TODO
+?>
+<tr>
+ <? if(empty($flash['founders']) && empty($founders)) :?>
+ <td style='text-align:right; vertical-align:top;'><?= _("GruppengründerIn hinzufügen:") ?></td>
+ <td nowrap>
+ <div style="width: 49%; float: left;">
+ <? if (is_array($results_choose_founders)) : ?>
+ <select name="choose_founder">
+ <? foreach ($results_choose_founders as $user_id => $data) : ?>
+ <option value="<?= $user_id ?>"><?= htmlReady(my_substr($data['fullname']." (".$data['username'],0,35)) ?>) - <?= $data['perms'] ?></option>
+ <? endforeach; ?>
+ </select>
+ <?= Icon::create('accept', 'clickable', ['title' => _('NutzerIn hinzufügen')])->asInput(["type" => "image", "class" => "middle", "name" => "add_founder"]) ?>
+ <?= Icon::create('refresh', 'clickable', ['title' => _('neue Suche starten')])->asInput(["type" => "image", "class" => "middle", "name" => "new_search"]) ?>
+ <? if (sizeof($results_choose_founders) == 500) : ?>
+ <br><span style="color:red"><?= sprintf(_("Es werden nur die ersten %s Treffer angezeigt!"), 500) ?></span>
+ <? endif; ?>
+ <? else : ?>
+ <input type="text" name="search_for_founder">
+ <?= Icon::create('search', 'clickable', ['title' => _('Suchen')])->asInput(["type" => "image", "class" => "middle", "name" => "search_founder"]) ?>
+ <?= _("Geben Sie zur Suche den Vor-, Nach- oder Benutzernamen ein.") ?>
+ <? endif; ?>
+ </div>
+ </td>
+ <? else: ?>
+ <td style='text-align:right; vertical-align:top;'><?= _("Gruppengründer:") ?></td>
+ <td nowrap>
+ <div style="width: 49%; float: left;">
+ <? if (is_array($founders) && sizeof($founders) > 0) :
+ foreach ($founders as $user_id) :?>
+
+ <?= htmlReady(get_fullname($user_id, 'full_rev')) ?> (<?= get_username($user_id) ?>)
+ <input type="hidden" name="founders[]" value="<?= $user_id ?>">
+ <?= Icon::create('refresh', 'clickable', ['title' => _('NutzerIn entfernen')])->asInput(["type" => "image", "class" => "middle", "name" => "remove_founder"]) ?>
+ <br>
+ <? endforeach; ?>
+ <? endif; ?>
+ </div>
+ </td>
+ <? endif; ?>
+</tr>
diff --git a/app/views/course/studygroup/_feedback.php b/app/views/course/studygroup/_feedback.php
new file mode 100644
index 0000000..63c6b40
--- /dev/null
+++ b/app/views/course/studygroup/_feedback.php
@@ -0,0 +1,15 @@
+<?
+# Lifter010: TODO
+if ($errors = $flash['errors']) {
+ if ($flash['create']) {
+ echo MessageBox::error(_("Beim Anlegen der Studiengruppe traten folgende Fehler auf:"), $errors);
+ } elseif ($flash['edit']) {
+ echo MessageBox::error(_("Beim Bearbeiten der Studiengruppe traten folgende Fehler auf:"), $errors);
+ }
+}
+
+if ($messages = $flash['messages']) {
+ foreach ($messages as $type => $message_data) {
+ echo MessageBox::$type( $message_data['title'], $message_data['details']);
+ }
+}
diff --git a/app/views/course/studygroup/_members_gallery.php b/app/views/course/studygroup/_members_gallery.php
new file mode 100644
index 0000000..140a98b
--- /dev/null
+++ b/app/views/course/studygroup/_members_gallery.php
@@ -0,0 +1,32 @@
+<h3><?= htmlReady($title) ?></h3>
+
+<ul class="studygroup-gallery">
+<? foreach ($members as $user_id => $m) : ?>
+ <? $fullname = $m instanceof CourseMember ? $m->user->getFullname('no_title_rev') : $m['fullname']?>
+ <? ($last_visitdate <= $m['mkdate'] && $GLOBALS['perm']->have_studip_perm('tutor', $sem_id))
+ ? $options = ['style' => 'border: 3px solid rgb(255, 100, 100);border: 1px solid rgba(255, 0, 0, 0.5)']
+ : $options = [] ?>
+ <li>
+ <div>
+ <a href="<?= $controller->link_for('profile', ['username' => $m['username']]) ?>">
+ <?= Avatar::getAvatar($m['user_id'])->getImageTag(Avatar::MEDIUM, $options) ?>
+ </a>
+ </div>
+
+ <div>
+ <a href="<?= $controller->link_for('messages/write', ['rec_uname' => $m['username']]) ?>" data-dialog="size=50%">
+ <?= Icon::create('mail')->asImg(['title' => _('Nachricht schreiben')]) ?>
+ </a>
+ <? if ($GLOBALS['perm']->have_studip_perm('tutor', $sem_id)): ?>
+ <?= $this->render_partial('course/studygroup/_members_options.php', compact('m')) ?>
+ <? endif ?>
+ </div>
+
+ <div style="font-size: 0.8em;">
+ <a href="<?= $controller->link_for('profile', ['username' => $m['username']]) ?>">
+ <?= $fullname ? htmlReady($fullname) : _('unbekannt') ?>
+ </a>
+ </div>
+ </li>
+<? endforeach ?>
+</ul>
diff --git a/app/views/course/studygroup/_members_list.php b/app/views/course/studygroup/_members_list.php
new file mode 100644
index 0000000..470815a
--- /dev/null
+++ b/app/views/course/studygroup/_members_list.php
@@ -0,0 +1,92 @@
+<? if ($GLOBALS['perm']->have_studip_perm('tutor', $sem_id)): ?>
+<form action="<?= $controller->edit_members('bulk', $type) ?>" method="post">
+<? endif; ?>
+ <table class="default studygroupmemberlist sortable-table" id="studygroup-members-<?= $type ?>">
+ <colgroup>
+ <? if ($GLOBALS['perm']->have_studip_perm('tutor', $sem_id)): ?>
+ <col style="width: 24px">
+ <? endif; ?>
+ <col style="width: 40px">
+ <col>
+ <col style="width: 80px">
+ </colgroup>
+ <caption>
+ <?= $title ?>
+ </caption>
+ <thead>
+ <tr>
+ <? if ($GLOBALS['perm']->have_studip_perm('tutor', $sem_id)): ?>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="#studygroup-members-<?= $type ?> tbody :checkbox"
+ data-activates="#studygroup-members-<?= $type ?> tfoot .button">
+ </th>
+ <? endif; ?>
+ <th data-sort="false"></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="false" class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($members as $m): ?>
+ <? $fullname = $m instanceof CourseMember ? $m->user->getFullname('no_title_rev') : $m['fullname']?>
+ <tr <? if ($last_visitdate <= $m['mkdate'] && $GLOBALS['perm']->have_studip_perm('tutor', $sem_id)) echo 'class="new-member"'; ?>>
+ <? if ($GLOBALS['perm']->have_studip_perm('tutor', $sem_id)): ?>
+ <td>
+ <input type="checkbox" name="members[]" value="<?= htmlReady($m['username']) ?>">
+ </td>
+ <? endif; ?>
+ <td>
+ <a class="member-avatar"
+ href="<?= $controller->link_for('profile', ['username' => $m['username']]) ?>">
+ <?= Avatar::getAvatar($m['user_id'])
+ ->getImageTag(Avatar::SMALL, ['title' => $fullname]) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for('profile', ['username' => $m['username']]) ?>">
+ <?= htmlReady($fullname) ?>
+ </a>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->link_for('messages/write', ['rec_uname' => $m['username']]) ?>"
+ data-dialog="size=50%">
+ <?= Icon::create('mail')->asImg(['title' => _('Nachricht schreiben')]) ?>
+ </a>
+ <? if ($GLOBALS['perm']->have_studip_perm('tutor', $sem_id)) : ?>
+ <?= $this->render_partial('course/studygroup/_members_options.php', compact('m')) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <? if ($GLOBALS['perm']->have_studip_perm('tutor', $sem_id)): ?>
+ <tfoot>
+ <tr>
+ <td colspan="4">
+ <?= Studip\Button::create(_('Nachricht schreiben'), 'mail', [
+ 'data-dialog' => 'size=50%',
+ ]) ?>
+ <? if ($GLOBALS['perm']->have_studip_perm('dozent', $sem_id) && in_array($type, ['autor', 'tutor'])): ?>
+ <?= Studip\Button::create(_('Hochstufen'), 'promote', [
+ 'data-confirm' => _('Wollen Sie die markierten Personen wirklich hochstufen?'),
+ ]) ?>
+ <? endif; ?>
+ <? if ($GLOBALS['perm']->have_studip_perm('dozent', $sem_id) && in_array($type, ['tutor', 'moderator'])): ?>
+ <?= Studip\Button::create(_('Herunterstufen'), 'downgrade', [
+ 'data-confirm' => _('Wollen Sie die markierten Personen wirklich herunterstufen?'),
+ ]) ?>
+ <? endif; ?>
+ <? if ($type !== 'moderator'): ?>
+ <?= Studip\Button::create(_('Austragen'), 'remove', [
+ 'data-confirm' => _('Wollen Sie die markierten Personen wirklich auf der Studiengruppe entfernen?'),
+ ]) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+<? if ($GLOBALS['perm']->have_studip_perm('tutor', $sem_id)): ?>
+</form>
+<? endif; ?>
diff --git a/app/views/course/studygroup/_members_options.php b/app/views/course/studygroup/_members_options.php
new file mode 100644
index 0000000..01e7ed0
--- /dev/null
+++ b/app/views/course/studygroup/_members_options.php
@@ -0,0 +1,17 @@
+<? if ($GLOBALS['perm']->have_studip_perm('dozent', $sem_id) && $GLOBALS['perm']->have_studip_perm('tutor', $sem_id, $m['user_id'])) : ?>
+ <a href="<?= $controller->link_for('course/studygroup/edit_members/downgrade', $type, ['user' => $m['username']]) ?>" data-confirm="<?= _('Wollen Sie die Person wirklich runterstufen?') ?>">
+ <?= Icon::create('arr_2down')->asImg(['title' => _('Runterstufen')]) ?>
+ </a>
+<? endif ?>
+
+<? if ($GLOBALS['perm']->have_studip_perm('dozent', $sem_id) && !$GLOBALS['perm']->have_studip_perm('dozent', $sem_id, $m['user_id'])) : ?>
+ <a href="<?= $controller->link_for('course/studygroup/edit_members/promote', $type, ['user' => $m['username']]) ?>" data-confirm="<?= _('Wollen Sie die Person wirklich hochstufen?') ?>">
+ <?= Icon::create('arr_2up')->asImg(['title' => _('Hochstufen')])?>
+ </a>
+<? endif ?>
+
+<? if ($m['user_id'] !== $GLOBALS['user']->id && $GLOBALS['perm']->have_studip_perm('dozent', $sem_id)): ?>
+ <a href="<?= $controller->link_for('course/studygroup/edit_members/remove', ['user' => $m['username']]) ?>" data-confirm="<?= _('Wollen Sie die Person wirklich rauswerfen?') ?>">
+ <?= Icon::create('trash')->asImg(['title' => _('Rauswerfen')])?>
+ </a>
+<? endif; ?>
diff --git a/app/views/course/studygroup/_replace_founder.php b/app/views/course/studygroup/_replace_founder.php
new file mode 100644
index 0000000..8947fed
--- /dev/null
+++ b/app/views/course/studygroup/_replace_founder.php
@@ -0,0 +1,28 @@
+<section>
+ <?= _('GruppengründerInnen') ?>
+</section>
+
+<div class="hgroup">
+<? if (is_array($founders) && count($founders) > 0) : ?>
+ <ul>
+ <? foreach ($founders as $founder) : ?>
+ <li><?= htmlReady(get_fullname_from_uname($founder['username'])) ?></li>
+ <? endforeach; ?>
+ </ul>
+<? endif; ?>
+
+<? if (!empty($tutors)) :?>
+ <?= Icon::create('arr_2left', Icon::ROLE_SORT)->asInput([
+ 'title' => _('Als GruppengründerIn eintragen'),
+ 'class' => 'middle',
+ 'name' => 'replace_founder',
+ ]) ?>
+ <select name="choose_founder">
+ <? foreach($tutors as $uid => $tutor) : ?>
+ <option value="<?= htmlReady($uid) ?>">
+ <?= htmlReady($tutor['fullname']) ?>
+ </option>
+ <? endforeach ; ?>
+ </select>
+<? endif; ?>
+</div>
diff --git a/app/views/course/studygroup/details.php b/app/views/course/studygroup/details.php
new file mode 100644
index 0000000..d32fd98
--- /dev/null
+++ b/app/views/course/studygroup/details.php
@@ -0,0 +1,31 @@
+<article class="studip">
+ <header>
+ <h1><?= _('Grunddaten') ?></h1>
+ </header>
+ <section>
+ <dl style="margin: 0">
+ <? if ($studygroup->description): ?>
+ <dt><?= _('Beschreibung') ?></dt>
+ <dd><?= formatLinks($studygroup->description) ?></dd>
+ <? endif; ?>
+ <dt><?= _('Moderiert von') ?></dt>
+ <dd>
+ <ul class="list-csv">
+ <? foreach ($studygroup->getMembers(['dozent', 'tutor']) as $mod) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $mod['username']]) ?>">
+ <?= htmlready($mod['fullname']) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </dd>
+ </dl>
+ </section>
+</article>
+
+<div class="hidden-medium-up">
+<? foreach ($sidebarActions as $action) : ?>
+ <?= Studip\LinkButton::create($action->label, $action->url) ?>
+<? endforeach ?>
+</div>
diff --git a/app/views/course/studygroup/edit.php b/app/views/course/studygroup/edit.php
new file mode 100644
index 0000000..eaba1f7
--- /dev/null
+++ b/app/views/course/studygroup/edit.php
@@ -0,0 +1,54 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+
+<?= $this->render_partial("course/studygroup/_feedback") ?>
+
+<form action="<?= $controller->update() ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Studiengruppe bearbeiten') ?>
+ </legend>
+
+ <input type='submit' class="invisible" name="<?=_('Änderungen übernehmen') ?>" aria-hidden="true">
+ <label>
+ <span class="required"><?= _('Name') ?></span>
+ <input type='text' name='groupname' value="<?= htmlReady($sem->getName()) ?>">
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="groupdescription"><?= htmlReady($sem->description) ?></textarea>
+ </label>
+
+ <? if ($GLOBALS['perm']->have_studip_perm('dozent', $sem_id)) : ?>
+ <?= $this->render_partial('course/studygroup/_replace_founder', compact('tutors')) ?>
+ <? endif; ?>
+
+ <label>
+ <?= _('Zugang') ?>
+ <select name="groupaccess">
+ <option value="all" <? if (!$sem->admission_prelim) echo 'selected'; ?>>
+ <?= _('Offen für alle') ?>
+ </option>
+ <option value="invite" <? if ($sem->admission_prelim) echo 'selected'; ?>>
+ <?= _('Auf Anfrage') ?>
+ </option>
+ <? if (Config::get()->STUDYGROUPS_INVISIBLE_ALLOWED || !$sem->visible): ?>
+ <option value="invisible" <? if (!$sem->visible) echo 'selected'; ?> <? if (!Config::get()->STUDYGROUPS_INVISIBLE_ALLOWED) echo 'disabled'; ?>>
+ <?= _('Unsichtbar') ?>
+ </option>
+ <? endif; ?>
+ </select>
+ </label>
+
+ </fieldset>
+
+ <footer>
+ <?= Button::createAccept(_('Übernehmen'), ['title' => _("Änderungen übernehmen")]); ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), URLHelper::getURL('seminar_main.php')); ?>
+ </footer>
+</form>
diff --git a/app/views/course/studygroup/globalmodules.php b/app/views/course/studygroup/globalmodules.php
new file mode 100644
index 0000000..391a309
--- /dev/null
+++ b/app/views/course/studygroup/globalmodules.php
@@ -0,0 +1,80 @@
+<?php
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+
+/* * * * * * * * * * * *
+ * * * O U T P U T * * *
+ * * * * * * * * * * * */
+
+?>
+
+<?= $this->render_partial("course/studygroup/_feedback") ?>
+<? if (!$configured): ?>
+ <?= MessageBox::error(_('Keine Veranstaltungsart für Studiengruppen gefunden'), [
+ sprintf(
+ _('Die Standardkonfiguration für Studiengruppen in der Datei <b>%s</b> fehlt oder ist unvollständig.'),
+ 'config.inc.php'
+ )
+ ]) ?>
+<? endif ?>
+<? if (!Config::getInstance()->STUDYGROUPS_ENABLE):?>
+ <?= MessageBox::info(
+ _('Die Studiengruppen sind derzeit <b>nicht</b> aktiviert.')
+ . '<br>'
+ . _('Zum Aktivieren füllen Sie bitte das Formular aus und klicken Sie auf "Speichern".')
+ ) ?>
+<? else: ?>
+ <? if ($can_deactivate) : ?>
+ <?= MessageBox::info(_('Die Studiengruppen sind aktiviert.')) ?>
+ <form action="<?= $controller->deactivate() ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= Button::create(_("Deaktivieren"), 'deaktivieren') ?>
+ </form>
+ <? else: ?>
+ <?= MessageBox::info(_("Sie können die Studiengruppen nicht deaktivieren, solange noch welche in Stud.IP vorhanden sind!")) ?>
+ <? endif; ?>
+ <br>
+<? endif;?>
+<form class="default" action="<?= $controller->savemodules() ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <!-- Title -->
+ <fieldset>
+ <legend><?= _("Einrichtungszuordnung") ?></legend>
+ <label>
+ <?= _("Alle Studiengruppen werden folgender Einrichtung zugeordnet:") ?><br>
+ <select name="institute" class="nested-select">
+ <? if (!Config::getInstance()->STUDYGROUPS_ENABLE):?>
+ <option value="" class="is-placeholder">
+ <?= _('-- Bitte auswählen --') ?>
+ </option>
+ <? endif ?>
+ <? foreach ($institutes as $fak_id => $faculty) : ?>
+ <option value="<?= htmlReady($fak_id) ?>" class="nested-item-header"
+ <? if ($fak_id === $default_inst) echo 'selected'; ?>>
+ <?= htmlReady(my_substr($faculty['name'], 0, 60)) ?>
+ </option>
+ <? foreach ($faculty['childs'] as $inst_id => $inst_name) : ?>
+ <option value="<?= htmlReady($inst_id) ?>" class="nested-item"
+ <? if ($inst_id == $default_inst) echo 'selected'; ?>>
+ <?= htmlReady(my_substr($inst_name, 0, 60)) ?>
+ </option>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <!-- Title -->
+ <fieldset>
+ <legend><?= _('Nutzungsbedingungen') ?></legend>
+ <label>
+ <?= _('Geben Sie hier Nutzungsbedingungen für die Studiengruppen ein. '
+ . 'Diese müssen akzeptiert werden, bevor eine Studiengruppe angelegt werden kann.') ?>
+ <textarea name="terms"><?= htmlReady($terms) ?></textarea>
+ </label>
+ </fieldset>
+ <footer>
+ <?= Button::createAccept(_('Speichern'), 'speichern') ?>
+ </footer>
+</form>
diff --git a/app/views/course/studygroup/members.php b/app/views/course/studygroup/members.php
new file mode 100644
index 0000000..58a3b07
--- /dev/null
+++ b/app/views/course/studygroup/members.php
@@ -0,0 +1,161 @@
+<?= $this->render_partial('course/studygroup/_feedback', compact('anzahl', 'page', 'sem_id')) ?>
+
+<? if (count($moderators) > 0): ?>
+ <?= $this->render_partial("course/studygroup/_members_{$view}.php", [
+ 'title' => $sem_class['title_dozent_plural'] ?: _('Gruppenadministrator/-innen'),
+ 'sem_id' => $sem_id,
+ 'members' => $moderators,
+ 'moderator_list' => true,
+ 'type' => 'moderator',
+ ]) ?>
+<? endif ?>
+
+<? if (count($tutors) > 0): ?>
+ <?= $this->render_partial("course/studygroup/_members_{$view}.php", [
+ 'title' => $sem_class['title_tutor_plural'] ?: _('Moderator/-innen'),
+ 'sem_id' => $sem_id,
+ 'members' => $tutors,
+ 'type' => 'tutor',
+ ]) ?>
+<? endif ?>
+
+<? if (count($autors) > 0): ?>
+ <?= $this->render_partial("course/studygroup/_members_{$view}.php", [
+ 'title' => $sem_class['title_autor_plural'] ?: _('Mitglieder'),
+ 'sem_id' => $sem_id,
+ 'members' => $autors,
+ 'type' => 'autor',
+ ]) ?>
+<? endif ?>
+
+
+<? if ($rechte): ?>
+ <? if (count($accepted) > 0): ?>
+ <form action="<?= $controller->edit_members('bulk') ?>" method="post">
+ <table class="default sortable-table" id="studygroup-members">
+ <caption><?= _('Offene Mitgliedsanträge') ?></caption>
+ <colgroup>
+ <col style="width: 24px">
+ <col style="width: 40px">
+ <col>
+ <col style="width: 80px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th data-sort="false">
+ <input type="checkbox"
+ data-proxyfor="#studygroup-members tbody :checkbox"
+ data-activates="#studygroup-members tfoot .button">
+ </th>
+ <th data-sort="false"></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="false" class="actions">
+ <?= _('Aktionen') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($accepted as $p) : ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="members[]" value="<?= htmlReady($p['username']) ?>">
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $p->username]) ?>">
+ <?= Avatar::getAvatar($p['user_id'])->getImageTag(Avatar::SMALL) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $p->username]) ?>">
+ <?= htmlReady($p->user->getFullname('no_title_rev')) ?>
+ </a>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->edit_members('accept', ['user' => $p->username]) ?>">
+ <?= Icon::create('accept')->asImg(['title' => _('Eintragen')]) ?>
+ </a>
+
+ <a href="<?= $controller->edit_members('deny', ['user' => $p->username]) ?>" data-confirm="<?= _('Wollen Sie die Mitgliedschaft wirklich ablehnen?') ?>">
+ <?= Icon::create('trash')->asImg(['title' => _('Mitgliedschaft ablehnen')]) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="4">
+ <?= Studip\Button::create(_('Personen eintragen'), 'accept', [
+ 'data-confirm' => _('Wollen Sie die markierten Personen wirklich eintragen?'),
+ ]) ?>
+ <?= Studip\Button::create(_('Mitgliedschaften ablehnen'), 'deny', [
+ 'data-confirm' => _('Wollen Sie die Mitgliedschaften wirklich ablehnen?'),
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </form>
+ <? endif; ?>
+
+ <? if (count($invitedMembers) > 0) : ?>
+ <form action="<?= $controller->edit_members('bulk') ?>" method="post">
+ <table class="default sortable-table" id="studygroup-awaiting">
+ <caption><?= _('Verschickte Einladungen') ?></caption>
+ <colgroup>
+ <col style="width: 24px">
+ <col style="width: 40px">
+ <col>
+ <col style="width: 80px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th data-sort="false">
+ <input type="checkbox"
+ data-proxyfor="#studygroup-awaiting tbody :checkbox"
+ data-activates="#studygroup-awaiting tfoot .button">
+ </th>
+ <th data-sort="false"></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="false" class="actions">
+ <?= _('Aktionen') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($invitedMembers as $p): ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="members[]" value="<?= htmlReady($p['username']) ?>">
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile' , ['username' => $p['username']]) ?>">
+ <?= Avatar::getAvatar($p['user_id'])->getImageTag(Avatar::SMALL) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile' , ['username' => $p['username']]) ?>">
+ <?= htmlReady($p['fullname']) ?>
+ </a>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->edit_members('cancelInvitation', ['user' => $p['username']]) ?>" data-confirm="<?= _('Wollen Sie die Einladung wirklich löschen?') ?>">
+ <?= Icon::create('trash')->asImg(['title' => _('Einladung löschen')]) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="4">
+ <?= Studip\Button::create(_('Einladungen löschen'), 'cancel-invitations', [
+ 'data-confirm' => _('Wollen Sie die markierten Einladungen wirklich löschen?'),
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </form>
+ <? endif; ?>
+<? endif; ?>
diff --git a/app/views/course/timesrooms/_cancel_form.php b/app/views/course/timesrooms/_cancel_form.php
new file mode 100644
index 0000000..35e077b
--- /dev/null
+++ b/app/views/course/timesrooms/_cancel_form.php
@@ -0,0 +1,19 @@
+<?php
+// In den Controller
+$content = '';
+if ($termin instanceof CourseExDate && isset($termin->content)) {
+ $content = $termin->content;
+}
+?>
+<p>
+ <strong> <?= _('Wenn Sie die nicht stattfindenden Termine mit einem Kommentar versehen, werden die Ausfalltermine im Ablaufplan weiterhin dargestellt und auch im Terminkalender eingeblendet.') ?></strong>
+</p>
+
+<label for="cancel_comment">
+ <?= _('Kommentar') ?>
+ <textarea rows="5" id="cancel_comment" name="cancel_comment"><?= htmlReady($content) ?></textarea>
+</label>
+<label for="cancel_send_message" class="inline">
+ <input type="checkbox" id="cancel_send_message" name="cancel_send_message" value="1">
+ <?= _('Benachrichtigung über ausfallende Termine an alle Teilnehmenden verschicken') ?>
+</label>
diff --git a/app/views/course/timesrooms/_cycleRow.php b/app/views/course/timesrooms/_cycleRow.php
new file mode 100644
index 0000000..a7737ef
--- /dev/null
+++ b/app/views/course/timesrooms/_cycleRow.php
@@ -0,0 +1,148 @@
+<?php
+// In den Controller
+$is_exTermin = $termin instanceof CourseExDate;
+?>
+<tr>
+<? if (!$locked) : ?>
+ <td>
+ <label for="<?= htmlReady($termin->termin_id) ?>">
+ <input class="<?= $class_ids ?>" type="checkbox" id="<?= htmlReady($termin->termin_id) ?>"
+ value="<?= htmlReady($termin->termin_id) ?>"
+ <? if (is_array($checked_dates)): ?>
+ <? if (in_array($termin->termin_id, $checked_dates)) echo 'checked'; ?>
+ <? else: ?>
+ <? if (!$is_exTermin && $termin->date > time() && ($termin->date <= $current_semester->ende || $semester_filter !== 'all')) echo 'checked'; ?>
+ <? endif ?>
+ name="single_dates[]">
+ </label>
+ </td>
+<? endif ?>
+
+ <td class="<?= $termin->getRoom() !== null ? 'green' : 'red' ?>">
+ <? if ($is_exTermin) : ?>
+ <span class="is_ex_termin">
+ <?= htmlReady($termin->getFullname(CourseDate::FORMAT_VERBOSE)) ?>
+ </span>
+ <? elseif ($locked): ?>
+ <?= htmlReady($termin->getFullname(CourseDate::FORMAT_VERBOSE)) ?>
+ <? else: ?>
+ <a data-dialog
+ href="<?= $controller->url_for('course/timesrooms/editDate/' . $termin->termin_id, $linkAttributes) ?>">
+ <?= htmlReady($termin->getFullname(CourseDate::FORMAT_VERBOSE)) ?>
+ </a>
+ <? endif ?>
+ </td>
+
+ <td>
+ <? if (count($termin->dozenten) > 0): ?>
+ <ul class="list-unstyled list-csv <? if ($is_exTermin) echo 'is_ex_termin'; ?>">
+ <? foreach ($termin->dozenten as $dozent) : ?>
+ <li><?= $dozent instanceof User ? htmlReady($dozent->getFullname()) : '' ?></li>
+ <? endforeach ?>
+ </ul>
+ <? endif; ?>
+ </td>
+ <td>
+ <? if ($room_holiday = SemesterHoliday::isHoliday($termin->date, false)): ?>
+ <? $room_holiday = '<span' . ($is_exTermin ? ' class="is_ex_termin"' : '') . '>(' .
+ htmlReady($room_holiday['name']) . ')</span>' ?>
+ <? endif; ?>
+
+ <? if ($is_exTermin && ($comment = $termin->content)) : ?>
+ <span class="is_ex_termin" style="font-style: italic"><?= _('(fällt aus)') ?></span>
+ <?= tooltipIcon($termin->content, false) ?>
+ <? elseif ($name = SemesterHoliday::isHoliday($termin->date, false) && $is_exTermin): ?>
+ <?= $room_holiday ?>
+ <? elseif ($room = $termin->getRoom()) : ?>
+ <a href="<?= $room->getActionLink(
+ 'booking_plan',
+ [
+ 'defaultDate' => date('Y-m-d', $termin->date)
+ ]
+ ) ?>" data-dialog="size=big">
+ <?= htmlReady($room->getFullName()) ?>
+ </a>
+ <?= $room_holiday ?: '' ?>
+ <? elseif ($freeTextRoom = $termin->getRoomName()) : ?>
+ <?= sprintf('(%s)', formatReady($freeTextRoom)) ?>
+ <? else : ?>
+ <?= _('Keine Raumangabe') ?>
+ <?= $room_holiday ?: '' ?>
+ <? endif ?>
+
+ <? $room_request_exists = RoomRequest::existsByDate($termin->id, true) ?>
+ <? if ($room_request_exists): ?>
+ <? $msg_info = _('Für diesen Termin existiert eine Raumanfrage.') ?>
+ <?= tooltipIcon($msg_info) ?>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($is_exTermin): ?>
+ <? $actionMenu->addLink(
+ $controller->url_for(
+ 'course/timesrooms/cancel/' . $termin->id
+ . ($termin->metadate_id ? '/' . $termin->metadate_id : ''),
+ $linkAttributes
+ ),
+ _('Kommentare bearbeiten'),
+ Icon::create('edit', 'clickable', ['title' => _('Kommentar für diesen Termin bearbeiten')]),
+ ['data-dialog' => 'size=50%']
+ ) ?>
+
+ <? $params = [
+ 'type' => 'image',
+ 'class' => 'middle',
+ 'name' => 'delete_single_date',
+ 'data-confirm' => _('Diesen Termin wiederherstellen?'),
+ 'formaction' => $controller->url_for('course/timesrooms/undeleteSingle/' . $termin->id),
+ ]; ?>
+ <? if (Request::isXhr()) : ?>
+ <? $params['data-dialog'] = 'size=auto' ?>
+ <? endif ?>
+
+ <? $actionMenu->addButton(
+ 'delete_part',
+ _('Termin wiederherstellen'),
+ Icon::create('trash+decline', 'clickable', $params)
+ ) ?>
+
+ <? elseif (!$locked) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/timesrooms/editDate/' . $termin->id, $linkAttributes),
+ _('Termin bearbeiten'),
+ Icon::create('edit', 'clickable', ['title' => _('Diesen Termin bearbeiten')]),
+ ['data-dialog' => '']
+ ) ?>
+
+ <? $params = [
+ 'type' => 'image',
+ 'class' => 'middle',
+ 'name' => 'delete_single_date',
+ 'data-confirm' => _('Wollen Sie diesen Termin wirklich löschen / ausfallen lassen?')
+ . '<br>' . implode('<br>', array_map('htmlReady', $termin->getDeletionWarnings())),
+ 'formaction' => $controller->url_for(
+ 'course/timesrooms/deleteSingle/' . $termin->id,
+ ['cycle_id' => $termin->metadate_id] + $linkAttributes
+ ),
+ ]; ?>
+ <? if (Request::isXhr()) : ?>
+ <? $params['data-dialog'] = 'size=big' ?>
+ <? endif ?>
+
+ <? $actionMenu->addLink(
+ $controller->url_for(
+ 'course/timesrooms/stack',
+ [
+ 'single_dates[]' => $termin->termin_id,
+ 'method' => 'preparecancel'
+ ]
+ ),
+ _('Termin löschen'),
+ Icon::create('trash', 'clickable'),
+ ['data-dialog' => '1']
+ ) ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </td>
+</tr>
diff --git a/app/views/course/timesrooms/_irregularEvents.php b/app/views/course/timesrooms/_irregularEvents.php
new file mode 100644
index 0000000..71a8266
--- /dev/null
+++ b/app/views/course/timesrooms/_irregularEvents.php
@@ -0,0 +1,138 @@
+<?php
+// in den Controller
+$room_request_filter = function ($date) {
+ return $date->room_request
+ && !$date->room_request->isNew()
+ && $date->room_request->closed < 2;
+};
+?>
+
+<section class="contentbox timesrooms">
+ <header>
+ <h1>
+ <?= _('Unregelmäßige Termine / Blocktermine') ?>
+ </h1>
+ <? if(!$locked) : ?>
+ <nav>
+ <? $actionMenu = ActionMenu::get()?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/timesrooms/createSingleDate/' . $course->id, $linkAttributes),
+ _('Einzeltermin hinzufügen'),
+ Icon::create('date+add', 'clickable', ['title' => _('Einzeltermin hinzufügen')]),
+ ['data-dialog' => 'size=600']
+ ) ?>
+
+ <? $actionMenu->addLink(
+ $controller->url_for('course/block_appointments/index/' . $course->id, $linkAttributes),
+ _('Blocktermin hinzufügen'),
+ Icon::create('timetable+add', 'clickable', ['title' => _('Blocktermin hinzufügen')]),
+ ['data-dialog' => 'size=600']
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </nav>
+ <? endif ?>
+ </header>
+<? if (!empty($single_dates)): ?>
+ <form class="default collapsable" action="<?= $controller->url_for('course/timesrooms/stack', $linkAttributes) ?>"
+ <?= Request::isXhr() ? 'data-dialog="size=big"' : ''?> method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <? foreach ($single_dates as $semester_id => $termine) : ?>
+ <article id="singledate-<?= $semester_id ?>" class="<?= count($single_dates) === 1 ? 'open' : ContentBoxHelper::classes('singledate-' . $semester_id) ?>">
+ <header>
+ <h1>
+ <? if (!$locked): ?>
+ <input type="checkbox" class="date-proxy"
+ data-proxyfor="#singledate-<?= $semester_id ?> .ids-irregular">
+ <? endif ?>
+ <a href="<?= ContentBoxHelper::href('singledate-' . $semester_id) ?>">
+ <? if ($semester_id !== 'none'): ?>
+ <?= htmlReady(Semester::find($semester_id)->name) ?>
+ <? else: ?>
+ <?= _('Ohne Semester') ?>
+ <? endif ?>
+ </a>
+ </h1>
+ <section>
+ <span>
+ <?= sprintf(ngettext('%u Termin', '%u Termine', count($termine)),
+ count($termine)) ?>
+ </span>
+ <? if (Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS): ?>
+ <span>
+ | <strong><?= _('Einzel-Raumanfrage') ?></strong>:
+ <? if ($single_date_room_request_c > 0): ?>
+ <?= sprintf(_('%u noch offen'), $single_date_room_request_c) ?>
+ <? else: ?>
+ <?= _('keine offen') ?>
+ <? endif; ?>
+ </span>
+ <? endif; ?>
+ </section>
+ </header>
+ <section>
+ <table class="default nohover">
+ <colgroup>
+ <? if (!$locked) :?>
+ <col width="30px">
+ <? endif ?>
+ <col width="30%">
+ <col>
+ <col width="20%">
+ <col width="50px">
+ </colgroup>
+
+ <tbody>
+ <? foreach ($termine as $termin): ?>
+ <?= $this->render_partial('course/timesrooms/_cycleRow.php', [
+ 'termin' => $termin,
+ 'class_ids' => 'ids-irregular',
+ ]) ?>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ </section>
+ </article>
+ <? endforeach; ?>
+ <? if(!$locked) : ?>
+ <table class="default nohover">
+ <colgroup>
+ <col width="30px">
+ <col width="30%">
+ <col>
+ <col width="20%">
+ <col width="50px">
+ </colgroup>
+
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <label class="horizontal">
+ <input type="checkbox" data-proxyfor=".date-proxy"
+ data-activates=".actionForAllIrregular">
+ <?= _('Alle auswählen') ?>
+ </label>
+ </td>
+ <td colspan="3" class="actions">
+ <select name="method" class="datesBulkActions actionForAllIrregular">
+ <?= $this->render_partial('course/timesrooms/_stack_actions.php') ?>
+ </select>
+ <?= Studip\Button::create( _('Ausführen'), 'run', [
+ 'class' => 'actionForAllIrregular',
+ 'data-dialog' => 'size=big',
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+ </form>
+<? else: ?>
+ <section>
+ <p class="text-center">
+ <strong>
+ <?= _('Keine unregelmäßigen Termine vorhanden') ?>
+ </strong>
+ </p>
+ </section>
+<? endif; ?>
+</section>
diff --git a/app/views/course/timesrooms/_regularEvents.php b/app/views/course/timesrooms/_regularEvents.php
new file mode 100644
index 0000000..bfe18b2
--- /dev/null
+++ b/app/views/course/timesrooms/_regularEvents.php
@@ -0,0 +1,185 @@
+<section class="contentbox timesrooms">
+ <header>
+ <h1>
+ <?= _('Regelmäßige Termine') ?>
+ </h1>
+ <? if(!$locked) : ?>
+ <nav>
+ <a class="link-add"
+ href="<?= $controller->link_for('course/timesrooms/createCycle', $linkAttributes) ?>"
+ data-dialog="size=600"
+ title="<?= _('Regelmäßigen Termin hinzufügen') ?>">
+ <?= _('Regelmäßigen Termin hinzufügen') ?>
+ </a>
+ </nav>
+ <? endif ?>
+ </header>
+
+<? if (!empty($cycle_dates)) : ?>
+ <? foreach ($cycle_dates as $metadate_id => $cycle) : ?>
+
+ <form class="default collapsable" action="<?= $controller->url_for('course/timesrooms/stack/' . $metadate_id, $linkAttributes) ?>"
+ method="post" <?= Request::isXhr() ? 'data-dialog="size=big"' : ''?>>
+ <?= CSRFProtection::tokenTag() ?>
+
+ <article id="<?= $metadate_id ?>" class="<?= ContentBoxHelper::classes($metadate_id) ?>">
+ <header class="<?= $course->getCycleColorClass($metadate_id) ?>">
+ <h1>
+ <? if ($info = $course->getBookedRoomsTooltip($metadate_id)) : ?>
+ <?= tooltipHtmlIcon($info) ?>
+ <? elseif ($course->getCycleColorClass($metadate_id) === 'red'): ?>
+ <?= tooltipIcon(_('Keine Raumbuchungen vorhanden')) ?>
+ <? else: ?>
+ <?= tooltipIcon(_('Keine offenen Raumbuchungen')) ?>
+ <? endif; ?>
+ <a href="<?= ContentBoxHelper::href($metadate_id) ?>">
+ <?= htmlReady($cycle['cycle']->toString('long')) ?>
+ </a>
+ </h1>
+ <section>
+ <span>
+ <? if ($cycle_room_names[$cycle['cycle']->id]): ?>
+ <strong><?= _('Raum') ?>:</strong>
+ <?= htmlReady($cycle_room_names[$cycle['cycle']->id])?>
+ <? elseif (Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) : ?>
+ <? if (count($cycle['cycle']->room_requests) > 0): ?>
+ <? $room_request = $cycle['cycle']->room_requests[0] ?>
+ <? if ($room_request->closed <= '1'): ?>
+ <strong>
+ <?= sprintf(
+ _('Raum %s angefragt'),
+ htmlReady($cycle['cycle']->room_requests[0]->room->name)
+ ) ?>
+ </strong>
+ <? else: ?>
+ <strong><?= _('Bearbeitete Raumanfrage vorhanden!')?></strong>
+ <? endif ?>
+ <? else: ?>
+ <strong><?= _('Raumanfragen') ?></strong>:
+ <?= _('keine') ?>
+ <? endif ?>
+ <? endif ?>
+ </span>
+ <? if (Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) : ?>
+ <? $metadate = SeminarCycleDate::find($metadate_id) ?>
+ <? $open_requests = $metadate->countOpenRequestsForDates(); ?>
+ <span>
+ <strong><?= _('Einzel-Raumanfrage') ?></strong>:
+ <?= htmlReady(
+ $open_requests > 0
+ ? $open_requests
+ : _('keine offenen Anfragen')
+ ) ?>
+ </span>
+ <? endif ?>
+ </section>
+ <? if (!$locked) : ?>
+ <nav>
+ <? $actionMenu = ActionMenu::get()?>
+ <? $actionMenu->addLink(
+ $controller->url_for('course/timesrooms/createCycle/' . $metadate_id, $linkAttributes),
+ _('Diesen Zeitraum bearbeiten'),
+ Icon::create('edit', 'clickable', ['title' => _('Diesen Zeitraum bearbeiten'), 'style' => 'vertical-align: middle;']),
+ ['data-dialog' => 'size=600']
+ ) ?>
+ <? if (Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for(
+ 'course/room_requests/request_start/',
+ [
+ 'range' => 'cycle',
+ 'range_id' => $metadate_id
+ ]
+ ),
+ _('Raumanfrage erstellen'),
+ Icon::create(
+ 'room-request',
+ 'clickable',
+ [
+ 'title' => _('Raumanfrage erstellen'),
+ 'class' => 'text-align'
+ ]
+ ),
+ ['data-dialog' => 'size=big']
+ ) ?>
+ <? endif ?>
+ <? $actionMenu->addButton(
+ 'delete_cycle',
+ _('Diesen Zeitraum löschen'),
+ Icon::create('trash', 'clickable', ['title' => _('Diesen Zeitraum löschen')]),
+ ['formaction' => $controller->url_for('course/timesrooms/deleteCycle/' . $metadate_id, $linkAttributes),
+ 'data-confirm' => _('Soll dieser Zeitraum wirklich gelöscht werden?')]) ?>
+ <?= $actionMenu->render() ?>
+ </nav>
+ <? endif ?>
+ </header>
+ <section>
+ <table class="default nohover">
+ <colgroup>
+ <? if (!$locked) : ?>
+ <col width="30px">
+ <? endif ?>
+ <col width="30%">
+ <col>
+ <col width="20%">
+ <col width="50px">
+ </colgroup>
+ <? foreach ($cycle['dates'] as $semester_id => $termine) : ?>
+ <thead>
+ <tr>
+ <th colspan="<?= !$locked ? 5 : 4?>">
+ <label>
+ <? if(!$locked) : ?>
+ <input type="checkbox" class="date-proxy_<?= $metadate_id ?>"
+ data-proxyfor="#<?= $metadate_id ?>-<?= $semester_id ?> .ids-regular">
+ <? endif ?>
+ <?= htmlReady(Semester::find($semester_id)->name) ?>
+ </label>
+ </th>
+ </tr>
+ </thead>
+ <tbody id="<?= $metadate_id ?>-<?= $semester_id ?>">
+ <? foreach ($termine as $termin) : ?>
+ <?= $this->render_partial('course/timesrooms/_cycleRow.php',
+ ['termin' => $termin, 'class_ids' => 'ids-regular']) ?>
+ <? endforeach ?>
+ </tbody>
+ <? endforeach ?>
+ <? if(!$locked) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <label>
+ <input type="checkbox"
+ data-proxyfor=".date-proxy_<?= $metadate_id ?>"
+ data-activates=".actionForAllRegular_<?= $metadate_id ?>">
+ <?= _('Alle auswählen') ?>
+ </label>
+ </td>
+ <td colspan="3" class="actions">
+ <select name="method" class="datesBulkActions actionForAllRegular_<?= $metadate_id ?>">
+ <?= $this->render_partial('course/timesrooms/_stack_actions.php') ?>
+ </select>
+ <?= Studip\Button::create(_('Ausführen'), 'run', [
+ 'class' => 'actionForAllRegular_' . $metadate_id,
+ 'data-dialog' => 'size=big'
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+
+ </section>
+ </article>
+ </form>
+ <? endforeach; ?>
+
+<? else: ?>
+ <section>
+ <p class="text-center">
+ <strong><?= _('Keine regelmäßigen Termine vorhanden') ?></strong>
+ </p>
+ </section>
+<? endif; ?>
+</section>
diff --git a/app/views/course/timesrooms/_roomRequest.php b/app/views/course/timesrooms/_roomRequest.php
new file mode 100644
index 0000000..1244f55
--- /dev/null
+++ b/app/views/course/timesrooms/_roomRequest.php
@@ -0,0 +1,33 @@
+<?php
+$global_requests = $course->room_requests->filter(function (RoomRequest $request) {
+ return $request->closed < 2 && !$request->termin_id;
+});
+?>
+<section class="contentbox">
+ <header>
+ <h1>
+ <?= _('Raumanfrage für die gesamte Veranstaltung') ?>
+ </h1>
+
+ <nav>
+ <?= tooltipIcon(_('Hier können Sie für die gesamte Veranstaltung, also für alle regelmäßigen und unregelmäßigen Termine, '
+ . 'eine Raumanfrage erstellen.')) ?>
+ <a class="link-add" href="<?= $controller->url_for('course/room_requests/request_start',
+ array('cid' => $course->id, 'range_str' => 'course', 'origin' => 'course_timesrooms', 'create_room_request' => 1)) ?>"
+ data-dialog="size=big"
+ title="<?= _('Neue Raumanfrage für die Veranstaltung erstellen') ?>">
+ <?= _('Neue Raumanfrage') ?>
+ </a>
+ </nav>
+ </header>
+
+ <section>
+ <? if (count($global_requests) > 0): ?>
+ <p><?= _('Für diese Veranstaltung liegt eine offene Raumanfrage vor') ?></p>
+ <?= Studip\LinkButton::create(_('Raumanfragen anzeigen'),
+ URLHelper::getURL('dispatch.php/course/room_requests/index/' . $course->getId())) ?>
+ <? else: ?>
+ <p><?= _('Keine Raumanfrage vorhanden') ?></p>
+ <? endif; ?>
+ </section>
+</section>
diff --git a/app/views/course/timesrooms/_roomRequestInfo.php b/app/views/course/timesrooms/_roomRequestInfo.php
new file mode 100644
index 0000000..7bc3660
--- /dev/null
+++ b/app/views/course/timesrooms/_roomRequestInfo.php
@@ -0,0 +1,14 @@
+<?php
+$open_requests = $course->room_requests->filter(function (RoomRequest $request) {
+ return $request->closed < 2;
+});
+?>
+<? if (count($open_requests) > 0): ?>
+ <?= MessageBox::info(sprintf(ngettext(
+ 'Für diese Veranstaltung liegt eine offene Raumanfrage vor.',
+ 'Für diese Veranstaltung liegen %u offene Raumanfragen vor',
+ count($open_requests)
+ ), count($open_requests)) . '<br>'
+ . Studip\LinkButton::create(_('Raumanfragen anzeigen'),
+ URLHelper::getURL('dispatch.php/course/room_requests/index/' . $course->getId()))) ?>
+<? endif; ?>
diff --git a/app/views/course/timesrooms/_select_semester_range.php b/app/views/course/timesrooms/_select_semester_range.php
new file mode 100644
index 0000000..7b87b23
--- /dev/null
+++ b/app/views/course/timesrooms/_select_semester_range.php
@@ -0,0 +1,14 @@
+<form action="<?= $controller->url_for('course/timesrooms/index')?>" method="post" class="default" data-dialog="size=big">
+ <section>
+ <label class="undecorated">
+ <?= _('Semester auswählen') ?>
+ <select name="semester_filter" class="size-m">
+ <? foreach ($selectable_semesters as $item) : ?>
+ <option value="<?= $item['semester_id']?>" <?= $item['semester_id'] == $semester_filter ? 'selected' : ''?>><?= htmlReady($item['name'])?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <?= Studip\Button::createAccept(_('Auswählen'), 'select_sem')?>
+ </section>
+</form> \ No newline at end of file
diff --git a/app/views/course/timesrooms/_stack_actions.php b/app/views/course/timesrooms/_stack_actions.php
new file mode 100644
index 0000000..164e481
--- /dev/null
+++ b/app/views/course/timesrooms/_stack_actions.php
@@ -0,0 +1,6 @@
+<option value="edit"><?= _('Bearbeiten') ?></option>
+<option value="preparecancel"><?= _('Ausfallen lassen') ?></option>
+<option value="undelete"><?= _('Stattfinden lassen') ?></option>
+<? if (Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) : ?>
+ <option value="request"><?= _('Anfrage auf ausgewählte Termine stellen') ?> </option>
+<? endif ?>
diff --git a/app/views/course/timesrooms/cancel.php b/app/views/course/timesrooms/cancel.php
new file mode 100644
index 0000000..cdf41e3
--- /dev/null
+++ b/app/views/course/timesrooms/cancel.php
@@ -0,0 +1,9 @@
+<form action="<?= $controller->url_for('course/timesrooms/saveComment/' . $termin->id) ?>"
+ method="post" class="default" <?= Request::int('fromDialog') ? 'data-dialog="size=big"' : '' ?>>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('course/timesrooms/_cancel_form.php', compact('termin')) ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Übernehmen'), 'editDeletedSingleDate') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), '?#' . $termin_id) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/course/timesrooms/cancelStack.php b/app/views/course/timesrooms/cancelStack.php
new file mode 100644
index 0000000..a5aca01
--- /dev/null
+++ b/app/views/course/timesrooms/cancelStack.php
@@ -0,0 +1,15 @@
+<form method="post" action="<?= $controller->url_for('course/timesrooms/saveStack/' . $cycle_id, $linkAttributes) ?>"
+ class="default" data-dialog="size=big">
+ <input type="hidden" name="method" value="preparecancel">
+ <?= CSRFProtection::tokenTag()?>
+ <?= $this->render_partial('course/timesrooms/_cancel_form.php') ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Übernehmen'), 'cancel') ?>
+ <? if (Request::int('fromDialog')): ?>
+ <?= Studip\LinkButton::create(_('Zurück zur Übersicht'),
+ $controller->url_for('course/timesrooms/index'),
+ ['data-dialog' => 'size=big']) ?>
+ <? endif; ?>
+ </footer>
+</form>
diff --git a/app/views/course/timesrooms/createCycle.php b/app/views/course/timesrooms/createCycle.php
new file mode 100644
index 0000000..5e37175
--- /dev/null
+++ b/app/views/course/timesrooms/createCycle.php
@@ -0,0 +1,135 @@
+<form id="edit-cycle"
+ action="<?= $controller->url_for('course/timesrooms/' . ($cycle->isNew() ? 'saveCycle' : 'editCycle/' . $cycle->id), $linkAttributes) ?>"
+ class="default" method="post"
+ <?= Request::int('fromDialog') ? 'data-dialog="size=big"' : '' ?>>
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Regelmäßiger Termin') ?></legend>
+
+ <label class="col-2">
+ <?= _('Starttag') ?>
+ <select name="day">
+ <? foreach ([1, 2, 3, 4, 5, 6, 0] as $d): ?>
+ <option
+ value="<?= $d ?>" <?= (Request::int('day') === $d) || (!is_null($cycle->start_time) && $cycle->weekday == $d) || ($d == 1) ? 'selected' : ''?>>
+ <?= getWeekday($d, false) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label class="col-2">
+ <span class="required">
+ <?= _('Startzeit') ?>
+ </span>
+ <input class="size-s studip-timepicker" type="text" name="start_time"
+ value="<?= htmlReady(Request::get('start_time', mb_substr($cycle->start_time, 0, 5))) ?>"
+ required placeholder="HH:mm">
+ </label>
+
+ <label class="col-2">
+ <span class="required">
+ <?= _('Endzeit') ?>
+ </span>
+ <input class="size-s studip-timepicker" type="text" name="end_time"
+ value="<?= htmlReady(Request::get('end_time', mb_substr($cycle->end_time, 0, 5))) ?>"
+ required placeholder="HH:mm">
+ </label>
+
+ <label>
+ <?= _('Art') ?>
+ <select name="course_type" id="course_type" class="size-s">
+ <? foreach ($GLOBALS['TERMIN_TYP'] as $id => $value) : ?>
+ <option value="<?= $id ?>" <? if(Request::get('course_type') && Request::get('course_type') == $id) :?>selected="selected"<? endif?>><?= htmlReady($value['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <input type="text" name="description"
+ value="<?= htmlReady(Request::get('description', $cycle->description)) ?>">
+ </label>
+
+ <label>
+ <?= _('Turnus') ?>
+ <select name="cycle">
+ <option value="0" <?= (Request::int('cycle', $cycle->cycle) === 0) ? 'selected' : '' ?>>
+ <?= _('Wöchentlich') ?>
+ </option>
+ <option value="1" <?= (Request::int('cycle', $cycle->cycle) === 1) ? 'selected' : '' ?>>
+ <?= _('Zweiwöchentlich') ?>
+ </option>
+ <option value="2" <?= (Request::int('cycle', $cycle->cycle) === 2) ? 'selected' : '' ?>>
+ <?= _('Dreiwöchentlich') ?>
+ </option>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Startwoche') ?>
+ <select name="startWeek">
+ <!-- write down all Semesters as possible Start -->
+ <? if (isset($end_semester_weeks['start'])) : ?>
+ <? foreach ($end_semester_weeks['start'] as $end_sem_week) : ?>
+ <option value="<?= $end_sem_week['value'] ?>"
+ <?= (Request::get('startWeek', $cycle->week_offset) == $end_sem_week['value']) ? 'selected' : '' ?>>
+ <?= htmlReady($end_sem_week['label']) ?></option>
+ <? endforeach; ?>
+ <? endif; ?>
+
+ <!-- write down all weeks for all Semesters -->
+ <? foreach ($clean_weeks as $semester => $weeks) : ?>
+ <optgroup label="<?= htmlReady($semester) ?>">
+ <? foreach ($weeks as $value => $label) : ?>
+ <option value="<?= $value ?>"
+ <?= (Request::get('startWeek', $cycle->week_offset) == $value) ? 'selected' : '' ?>>
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach; ?>
+ </optgroup>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Endwoche') ?>
+ <select name="endWeek">
+ <? if (isset($end_semester_weeks['ende'])) : ?>
+ <? $selected = isset($cycle->end_offset) ? $cycle->end_offset : -1 ?>
+ <? foreach ($end_semester_weeks['ende'] as $end_sem_week) : ?>
+ <option value="<?= $end_sem_week['value'] ?>"
+ <?= (Request::get('endWeek', $selected) == $end_sem_week['value']) ? 'selected' : '' ?>>
+ <?= htmlReady($end_sem_week['label']) ?>
+ </option>
+ <? endforeach; ?>
+ <? endif; ?>
+
+ <? foreach ($clean_weeks as $semester => $weeks) : ?>
+ <optgroup label="<?= htmlReady($semester) ?>">
+ <? foreach ($weeks as $value => $label) : ?>
+ <option value="<?= $value ?>"
+ <?= (Request::get('endWeek', $selected) == $value) ? 'selected' : '' ?>>
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach; ?>
+ </optgroup>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('SWS Lehrende') ?>
+ <input type="text" name="teacher_sws" class="size-s"
+ value="<?= $cycle->sws ? htmlReady(Request::get('teacher_sws', $cycle->sws)) :'' ?>">
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save', ['data-dialog' => 'size=600']) ?>
+ <? if (Request::int('fromDialog')): ?>
+ <?= Studip\LinkButton::create(_('Zurück zur Übersicht'), $controller->url_for('course/timesrooms/index'), ['data-dialog' => 'size=big']) ?>
+ <? endif; ?>
+ </footer>
+</form>
diff --git a/app/views/course/timesrooms/createSingleDate.php b/app/views/course/timesrooms/createSingleDate.php
new file mode 100644
index 0000000..f5dafe3
--- /dev/null
+++ b/app/views/course/timesrooms/createSingleDate.php
@@ -0,0 +1,101 @@
+<form action="<?= $controller->url_for('course/timesrooms/saveSingleDate') ?>" method="post"
+ class="default" <?= Request::int('fromDialog') ? 'data-dialog="size=big"' : '' ?>>
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Einzeltermin anlegen') ?></legend>
+
+ <label class="col-2">
+ <?= _('Datum') ?>
+ <input class="has-date-picker size-s" type="text" name="date"
+ value="<?= htmlReady(Request::get('date')) ?>" required>
+ </label>
+ <label class="col-2">
+ <?= _('Startzeit') ?>
+ <input class="studip-timepicker size-s" type="text" name="start_time"
+ value="<?= htmlReady(Request::get('start_time')) ?>" required placeholder="HH:mm">
+ </label>
+ <label class="col-2">
+ <?= _('Endzeit') ?>
+ <input class="studip-timepicker size-s" type="text" name="end_time"
+ value="<?= htmlReady(Request::get('end_time')) ?>" required placeholder="HH:mm">
+ </label>
+
+ <label for="dateType">
+ <?= _('Art'); ?>
+ <select id="dateType" name="dateType">
+ <? foreach ($GLOBALS['TERMIN_TYP'] as $key => $val) : ?>
+ <option <?= Request::get('dateType') == $key ? 'selected' : '' ?>
+ value="<?= $key ?>"><?= htmlReady($val['name']) ?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <? if (Config::get()->RESOURCES_ENABLE
+ && ($selectable_rooms || $room_search)): ?>
+ <label>
+ <?= _('Raum') ?>
+ <? if ($room_search): ?>
+ <?= $room_search->render() ?>
+ <? else: ?>
+ <select name="room_id" style="width: calc(100% - 23px);">
+ <option value=""><?= _('<em>Keinen</em> Raum buchen') ?></option>
+ <? foreach ($selectable_rooms as $room): ?>
+ <option value="<?= htmlReady($room->id) ?>">
+ <?= htmlReady($room->name) ?>
+ <? if ($room->seats > 1) : ?>
+ <?= sprintf(_('(%d Sitzplätze)'), $room->seats) ?>
+ <? endif ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ </label>
+ <? endif ?>
+
+ <label for="freeRoomText">
+ <?= _('Freie Ortsangabe') ?>
+ <input value="<?= htmlReady(Request::get('freeRoomText')) ?>" id="freeRoomText"
+ name="freeRoomText" type="text" maxlength="255">
+ <? if (Config::get()->RESOURCES_ENABLE) : ?>
+ <small style="display: block"><?= _('(führt <em>nicht</em> zu einer Raumbuchung)') ?></small>
+ <? endif ?>
+ </label>
+
+ <? if (count($teachers)) : ?>
+ <label for="related_teachers"><?= _('Durchführende Lehrende') ?>
+ <? if (count($teachers) > 1) : ?>
+ <select id="related_teachers" name="related_teachers[]" multiple class="multiple">
+ <? foreach ($teachers as $dozent) : ?>
+ <option <?= in_array($dozent['user_id'], Request::getArray('related_teachers')) ? 'selected' : '' ?>
+ value="<?= $dozent['user_id'] ?>"><?= htmlReady($dozent['fullname']) ?></option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <p style="margin-left: 15px">
+ <? $dozent = array_pop($teachers) ?>
+ <?= htmlReady($dozent['fullname']) ?>
+ </p>
+ <? endif; ?>
+ </label>
+ <? endif; ?>
+
+
+ <? if (count($groups) > 0) : ?>
+ <label for="related_statusgruppen"><?= _('Beteiligte Gruppen') ?>
+ <select id="related_statusgruppen" name="related_statusgruppen[]" multiple class="multiple">
+ <? foreach ($groups as $group) : ?>
+ <option <?= in_array($group->getId(), Request::getArray('related_statusgruppen')) ? 'selected' : '' ?>
+ value="<?= $group->getId() ?>"><?= htmlReady($group['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save', ['data-dialog' => 'size=600']) ?>
+ <? if (Request::get('fromDialog')) : ?>
+ <?= Studip\LinkButton::create(_('Zurück zur Übersicht'), $controller->url_for('course/timesrooms/index'), ['data-dialog' => 'size=big']) ?>
+ <? endif ?>
+ </footer>
+</form>
diff --git a/app/views/course/timesrooms/editDate.php b/app/views/course/timesrooms/editDate.php
new file mode 100644
index 0000000..c5e3bf7
--- /dev/null
+++ b/app/views/course/timesrooms/editDate.php
@@ -0,0 +1,239 @@
+<form action="<?= $controller->url_for('course/timesrooms/saveDate/' . $date->termin_id) ?>"
+ method="post" class="default collapsable" <?= Request::int('fromDialog') ? 'data-dialog="size=big"' : '' ?>>
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset style="margin-top: 1ex">
+ <legend><?= _('Zeitangaben') ?></legend>
+ <label id="course_type" class=col-6>
+ <?= _('Art') ?>
+ <select name="course_type" id="course_type" class="size-s">
+ <? foreach ($GLOBALS['TERMIN_TYP'] as $id => $value) : ?>
+ <option value="<?= $id ?>"
+ <?= $date->date_typ == $id ? 'selected' : '' ?>>
+ <?= htmlReady($value['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <label class="col-2">
+ <?= _('Datum') ?>
+ <input class="has-date-picker size-s" type="text" name="date" required
+ value="<?= $date->date ? strftime('%d.%m.%Y', $date->date) : '' ?>">
+ </label>
+ <label class="col-2">
+ <?= _('Startzeit') ?>
+ <input class="studip-timepicker size-s" type="text" name="start_time" required placeholder="HH:mm"
+ value="<?= $date->date ? strftime('%H:%M', $date->date) : '' ?>">
+ </label>
+ <label class="col-2">
+ <?= _('Endzeit') ?>
+ <input class="studip-timepicker size-s" type="text" name="end_time" required placeholder="HH:mm"
+ value="<?= $date->end_time ? strftime('%H:%M', $date->end_time) : '' ?>">
+ </label>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Raumangaben') ?></legend>
+ <? if (Config::get()->RESOURCES_ENABLE
+ && ($selectable_rooms || $room_search)): ?>
+ <label>
+ <input style="display: inline;" type="radio" name="room" value="room"
+ id="room" <?= $date->room_booking->resource_id ? 'checked' : '' ?>
+ data-activates="input.preparation-time[name='preparation_time']">
+ <?= _('Raum direkt buchen') ?>
+ <span class="flex-row">
+ <? if ($room_search && !$only_bookable_rooms): ?>
+ <?= $room_search
+ ->setAttributes(['onFocus' => "jQuery('input[type=radio][name=room][value=room]').prop('checked', 'checked')"])
+ ->render() ?>
+ <? else: ?>
+ <? $selected_room_id = $date->room_booking->resource_id; ?>
+ <select name="room_id" onFocus="jQuery('input[type=radio][name=room][value=room]').prop('checked', 'checked')">
+ <? foreach ($selectable_rooms as $room): ?>
+ <option value="<?= htmlReady($room->id) ?>"
+ <?= $selected_room_id == $room->id
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($room->name) ?>
+ <? if ($room->seats > 1) : ?>
+ <?= sprintf(_('(%d Sitzplätze)'), $room->seats) ?>
+ <? endif ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ <? if (!$only_bookable_rooms) : ?>
+ <a href="<?= $controller->url_for(
+ 'course/timesrooms/editDate/' . $date->termin_id,
+ ['only_bookable_rooms' => '1']
+ ) ?>" <?= Request::isDialog() ? 'data-dialog="size=normal"' : '' ?>
+ title="<?= _('Nur buchbare Räume anzeigen') ?>">
+ <?= Icon::create('room-request')->asImg(
+ 20,
+ [
+ 'class' => 'text-bottom',
+ 'style' => 'margin-left: 0.2em; margin-top: 0.6em;',
+ ]
+ ) ?>
+ </a>
+ <? endif ?>
+ </span>
+ </label>
+ <label>
+ <?= _('Rüstzeit (in Minuten)') ?>
+ <input type="number" name="preparation_time"
+ class="preparation-time"
+ value="<?= htmlReady($preparation_time) ?>"
+ min="0" max="<?= htmlReady($max_preparation_time) ?>">
+ </label>
+ <? endif; ?>
+ <label class="horizontal">
+ <input type="radio" name="room" value="freetext" <?= $date->raum ? 'checked' : '' ?>
+ data-deactivates="input.preparation-time[name='preparation_time']">
+ <?= _('Freie Ortsangabe (keine Raumbuchung)') ?>
+ <input type="text"
+ name="freeRoomText_sd"
+ placeholder="<?= _('Freie Ortsangabe (keine Raumbuchung)') ?>"
+ value="<?= $date->raum ? htmlReady($date->raum) : '' ?>">
+ </label>
+
+ <label>
+ <input type="radio" name="room" value="noroom"
+ <?= (!empty($date->room_booking->resource_id) || !empty($date->raum) ? '' : 'checked') ?>
+ data-deactivates="input.preparation-time[name='preparation_time']">
+ <span style="display: inline-block;"><?= _('Kein Raum') ?></span>
+ </label>
+ <label>
+ <input type="radio" name="room" value="nochange" checked="checked"
+ data-deactivates="input.preparation-time[name='preparation_time']">
+ <?= _('Keine Änderungen an den Raumangaben vornehmen') ?>
+ <? if ($date->room_booking) :?>
+ <?=sprintf(_('(gebucht: %s)'), htmlReady($date->room_booking->room_name))?>
+ <? endif ?>
+ </label>
+
+ </fieldset>
+
+<? if (count($teachers) > 1): ?>
+ <fieldset class="collapsed studip-selection" data-attribute-name="assigned_teachers">
+ <legend><?= _('Durchführende Lehrende') ?></legend>
+
+ <section class="studip-selection-selected">
+ <h2><?= _('Zugewiesene Lehrende') ?></h2>
+
+ <ul>
+ <? foreach ($assigned_teachers as $teacher): ?>
+ <li data-selection-id="<?= htmlReady($teacher->user_id) ?>">
+ <input type="hidden" name="assigned_teachers[]"
+ value="<?= htmlReady($teacher->user_id) ?>">
+
+ <span class="studip-selection-image">
+ <?= Avatar::getAvatar($teacher->user_id)->getImageTag(Avatar::SMALL) ?>
+ </span>
+ <span class="studip-selection-label">
+ <?= htmlReady($teacher->getFullname()) ?>
+ </span>
+ </li>
+ <? endforeach; ?>
+ <li class="empty-placeholder">
+ <?= _('Kein spezieller Lehrender zugewiesen') ?>
+ </li>
+ </ul>
+ </section>
+
+ <section class="studip-selection-selectable">
+ <h2><?= _('Lehrende der Veranstaltung') ?></h2>
+
+ <ul>
+ <? foreach ($teachers as $teacher): ?>
+ <? if (!$assigned_teachers->find($teacher->user_id)): ?>
+ <li data-selection-id="<?= htmlReady($teacher->user_id) ?>" >
+ <span class="studip-selection-image">
+ <?= Avatar::getAvatar($teacher->user_id)->getImageTag(Avatar::SMALL) ?>
+ </span>
+ <span class="studip-selection-label">
+ <?= htmlReady($teacher->getUserFullname()) ?>
+ </span>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ <li class="empty-placeholder">
+ <?= sprintf(
+ _('Ihre Auswahl entspricht dem Zustand "%s" und wird beim Speichern zurückgesetzt'),
+ _('Kein spezieller Lehrender zugewiesen')
+ ) ?>
+ </li>
+ </ul>
+ </section>
+ </fieldset>
+<? endif; ?>
+
+<? if (count($groups) > 0): ?>
+ <fieldset class="collapsed studip-selection" data-attribute-name="assigned_groups">
+ <legend><?= _('Beteiligte Gruppen') ?></legend>
+
+ <section class="studip-selection-selected">
+ <h2><?= _('Zugewiesene Gruppen') ?></h2>
+
+ <ul>
+ <? foreach ($assigned_groups as $group) : ?>
+ <li data-selection-id="<?= htmlReady($group->id) ?>">
+ <input type="hidden" name="assigned_groups[]"
+ value="<?= htmlReady($group->id) ?>">
+
+ <span class="studip-selection-label">
+ <?= htmlReady($group->name) ?>
+ </span>
+ </li>
+ <? endforeach ?>
+ <li class="empty-placeholder">
+ <?= _('Keine spezielle Gruppe zugewiesen') ?>
+ </li>
+ </ul>
+ </section>
+
+ <section class="studip-selection-selectable">
+ <h2><?= _('Gruppen der Veranstaltung') ?></h2>
+
+ <ul>
+ <? foreach ($groups as $group): ?>
+ <? if (!$assigned_groups->find($group->id)): ?>
+ <li data-selection-id="<?= htmlReady($group->id) ?>" >
+ <span class="studip-selection-label">
+ <?= htmlReady($group->name) ?>
+ </span>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ <li class="empty-placeholder">
+ <?= _('Alle Gruppen wurden dem Termin zugewiesen') ?>
+ </li>
+ </ul>
+ </section>
+ </fieldset>
+<? endif; ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save_dates') ?>
+ <? if (Request::int('fromDialog')) : ?>
+ <?= Studip\LinkButton::create(_('Zurück zur Übersicht'),
+ $controller->url_for('course/timesrooms',
+ ['fromDialog' => 1, 'contentbox_open' => $date->metadate_id]),
+ ['data-dialog' => 'size=big']) ?>
+ <? endif ?>
+ <? if (Request::isXhr() && !$locked && Config::get()->RESOURCES_ENABLE && Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS): ?>
+ <? ?>
+ <?= Studip\LinkButton::create(
+ ($request_id ? _('Zur Raumanfrage wechseln') : _('Raumanfrage erstellen')),
+ (
+ $request_id
+ ? $controller->url_for(
+ 'course/room_requests/request_summary/' . $request_id
+ )
+ : $controller->url_for(
+ 'course/room_requests/request_start/' . $request_id,
+ array_merge($params, ['range_str' => 'date_' . $date->id,'origin' => 'course_timesrooms'])
+ )
+ ),
+ ['data-dialog' => 'size=big']) ?>
+ <? endif ?>
+ </footer>
+</form>
diff --git a/app/views/course/timesrooms/editSemester.php b/app/views/course/timesrooms/editSemester.php
new file mode 100644
index 0000000..35f11c2
--- /dev/null
+++ b/app/views/course/timesrooms/editSemester.php
@@ -0,0 +1,43 @@
+<form action="<?= $controller->url_for() ?>" method="post"
+ class="default" data-dialog>
+ <?=CSRFProtection::tokenTag()?>
+ <fieldset>
+ <legend><?= _('Semester ändern') ?></legend>
+
+ <label for="startSemester">
+ <?= _('Startsemester') ?>
+ <select name="startSemester" id="startSemester">
+ <? foreach ($semester as $sem) : ?>
+ <option
+ value="<?= $sem->semester_id ?>" <?= $sem->semester_id == $course->start_semester->semester_id ? 'selected' : '' ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label for="endSemester">
+ <?= _('Dauer') ?>
+ <select name="endSemester" id="endSemester">
+ <option value="0"
+ <?= $course->end_semester->id === $course->start_semester->id ? 'selected' : '' ?>>
+ <?= _('Ein Semester') ?></option>
+ <? foreach ($semester as $sem) : ?>
+ <? if ($sem->beginn >= $course->start_semester->beginn) : ?>
+ <option value="<?= $sem->semester_id ?>"
+ <?= (count($course->semesters) > 1) && $course->end_semester->id == $sem->id ? 'selected' : '' ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endif; ?>
+ <? endforeach; ?>
+ <option value="-1"
+ <?= $course->isOpenEnded() ? 'selected' : '' ?>>
+ <?= _('Unbegrenzt') ?></option>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer style="margin-top: 1ex" data-dialog-button>
+ <?= Studip\Button::createAccept(_('Semester speichern'), 'save') ?>
+ </footer>
+</form>
diff --git a/app/views/course/timesrooms/editStack.php b/app/views/course/timesrooms/editStack.php
new file mode 100644
index 0000000..c3ed18c
--- /dev/null
+++ b/app/views/course/timesrooms/editStack.php
@@ -0,0 +1,134 @@
+<form method="post" action="<?= $controller->url_for('course/timesrooms/saveStack/' . $cycle_id, $linkAttributes) ?>"
+ class="default collapsable" data-dialog="size=big">
+ <?= CSRFProtection::tokenTag()?>
+ <input type="hidden" name="method" value="edit">
+ <input type="hidden" name="checked_dates" value="<?= implode(',', $checked_dates) ?>">
+
+ <fieldset>
+ <legend><?= _('Raumangaben') ?></legend>
+ <? if (Config::get()->RESOURCES_ENABLE && (!empty($room_search) || !empty($selectable_rooms))): ?>
+ <section>
+ <input type="radio" name="action" value="room"
+ id="room">
+ <label style="display: inline-block; width: 50%; vertical-align: middle">
+ <? if (!empty($room_search)) : ?>
+ <?= $room_search
+ ->setAttributes(['onFocus' => "jQuery('input[type=radio][name=action][value=room]').prop('checked', 'checked')"])
+ ->render() ?>
+ <? else : ?>
+ <select name="room_id" style="display: inline-block; width: 50%;" onFocus="jQuery('input[type=radio][name=action][value=room]').prop('checked', 'checked')">
+ <option value="0">-- <?= _('Raum auswählen') ?> --</option>
+ <? foreach ($selectable_rooms as $room): ?>
+ <option value="<?= htmlReady($room->id)?>">
+ <?= htmlReady($room->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ <? if (!$only_bookable_rooms) : ?>
+ <?
+ $input_attr = [
+ 'class' => 'text-bottom',
+ 'style' => 'margin-left: 0.2em; margin-top: 0.6em;',
+ 'name' => 'only_bookable_rooms',
+ 'value' => '1',
+ 'title' => _('Nur buchbare Räume anzeigen')
+ ];
+ if (Request::isDialog()) {
+ $input_attr['data-dialog'] = 'size=big';
+ }
+ ?>
+ <?= Icon::create('room-request')->asInput(20, $input_attr) ?>
+ <? endif ?>
+ <div>
+ <?= _('Rüstzeit (in Minuten)') ?>
+ <input type="number" name="preparation_time"
+ class="preparation-time"
+ value="<?= htmlReady($preparation_time) ?>"
+ min="0" max="<?= htmlReady($max_preparation_time) ?>">
+ </div>
+ </label>
+ </section>
+
+ <? $placerholder = _('Freie Ortsangabe (keine Raumbuchung):') ?>
+ <? else : ?>
+ <? $placerholder = _('Freie Ortsangabe:') ?>
+ <? endif ?>
+ <section>
+ <input type="radio" name="action" value="freetext">
+ <label style="display: inline;">
+ <input type="text" name="freeRoomText" style="display: inline-block; width: 50%;" value="<?= $tpl['freeRoomText'] ?>"
+ placeholder="<?= $placerholder ?>"
+ onFocus="jQuery('input[type=radio][name=action][value=freetext]').prop('checked', 'checked')">
+ </label>
+ </section>
+ <? if (Config::get()->RESOURCES_ENABLE) : ?>
+ <label>
+ <input type="radio" name="action" value="noroom" style="display:inline">
+ <?= _('Kein Raum') ?>
+ </label>
+ <? endif ?>
+
+ <label>
+ <input type="radio" name="action" value="nochange" checked="checked">
+ <?= _('Keine Änderungen an den Raumangaben vornehmen') ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsed">
+ <legend><?= _('Terminangaben') ?></legend>
+ <label>
+ <?= _('Art') ?>
+ <select name="course_type" id="course_type">
+ <option value=""><?= _('-- Keine Änderung --') ?></option>
+ <? foreach ($GLOBALS['TERMIN_TYP'] as $id => $value) : ?>
+ <option value="<?= $id ?>"><?= htmlReady($value['name']) ?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsed">
+ <legend><?= _('Durchführende Lehrende') ?></legend>
+ <label>
+ <select name="related_persons_action" id="related_persons_action">
+ <option value="">-- <?= _('Aktion auswählen') ?> --</option>
+ <option value="add">...<?= _('hinzufügen') ?></option>
+ <option value="delete">...<?= _('entfernen') ?></option>
+ </select>
+ </label>
+
+ <select name="related_persons[]" id="related_persons" multiple>
+ <? foreach ($teachers as $teacher) : ?>
+ <option value="<?= htmlReady($teacher['user_id']) ?>"><?= htmlReady($teacher['fullname']) ?></option>
+ <? endforeach ?>
+ </select>
+ </fieldset>
+
+ <? if (count($gruppen)) : ?>
+ <fieldset class="collapsed">
+ <legend><?= _('Beteiligte Gruppen') ?></legend>
+ <label>
+ <select name="related_groups_action" id="related_groups_action">
+ <option value="">-- <?= _('Aktion auswählen') ?> --</option>
+ <option value="add">...<?= _('hinzufügen') ?></option>
+ <option value="delete">...<?= _('entfernen') ?></option>
+ </select>
+ </label>
+
+ <select id="related_groups" name="related_groups[]" multiple>
+ <? foreach ($gruppen as $gruppe) : ?>
+ <option value="<?= htmlReady($gruppe->statusgruppe_id) ?>"><?= htmlReady($gruppe->name) ?></option>
+ <? endforeach ?>
+ </select>
+ </fieldset>
+ <? endif ?>
+
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Änderungen speichern'), 'save') ?>
+ <? if (Request::int('fromDialog')) : ?>
+ <?= Studip\LinkButton::create(_('Zurück zur Übersicht'), $controller->url_for('course/timesrooms/index'), ['data-dialog' => 'size=big']) ?>
+ <? endif ?>
+ </footer>
+</form>
diff --git a/app/views/course/timesrooms/index.php b/app/views/course/timesrooms/index.php
new file mode 100644
index 0000000..48c8315
--- /dev/null
+++ b/app/views/course/timesrooms/index.php
@@ -0,0 +1,32 @@
+<? if ($show['roomRequest']) : ?>
+ <!--Raumanfragen-->
+ <?= $this->render_partial('course/timesrooms/_roomRequestInfo.php') ?>
+<? endif; ?>
+
+<? if (Request::isXhr()): ?>
+ <?= $this->render_partial('course/timesrooms/_select_semester_range.php') ?>
+<? endif ?>
+
+<? if ($show['regular']) : ?>
+ <!--Regelmäßige Termine-->
+ <?= $this->render_partial('course/timesrooms/_regularEvents.php') ?>
+<? endif; ?>
+
+<? if ($show['irregular']) : ?>
+ <!--Unregelmäßige Termine-->
+ <?= $this->render_partial('course/timesrooms/_irregularEvents') ?>
+<? endif; ?>
+
+<? if ($show['roomRequest']) : ?>
+ <!--Raumanfrage-->
+ <?= $this->render_partial('course/timesrooms/_roomRequest.php') ?>
+<? endif; ?>
+
+<? if (Request::isXhr() && !$locked && Config::get()->RESOURCES_ENABLE && Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS): ?>
+ <div data-dialog-button>
+ <?= Studip\LinkButton::create(_('Raumanfrage erstellen'),
+ $controller->url_for('course/room_requests/request_start',
+ ['cid' => $course->id, 'range_str' => 'course', 'origin' => 'admin_courses']),
+ ['data-dialog' => 'size=big']) ?>
+ </div>
+<? endif; ?>
diff --git a/app/views/course/topics/_topiclist.php b/app/views/course/topics/_topiclist.php
new file mode 100644
index 0000000..90b45ed
--- /dev/null
+++ b/app/views/course/topics/_topiclist.php
@@ -0,0 +1,6 @@
+<? foreach ($topics as $topic) : ?>
+<label>
+ <input type="checkbox" name="topic[<?= htmlReady($topic->getId()) ?>]" value="1" checked>
+ <?= htmlReady($topic['title']) ?>
+</label>
+<? endforeach ?>
diff --git a/app/views/course/topics/copy.php b/app/views/course/topics/copy.php
new file mode 100644
index 0000000..d0f97ef
--- /dev/null
+++ b/app/views/course/topics/copy.php
@@ -0,0 +1,39 @@
+<form action="<?= URLHelper::getLink("dispatch.php/course/topics/copy") ?>" method="post" class="default">
+ <fieldset>
+ <legend><?= _('Themen auswählen') ?></legend>
+ <script>
+ STUDIP.Topics = {
+ loadTopics: function (seminar_id) {
+ jQuery.ajax({
+ 'url': STUDIP.URLHelper.getURL("dispatch.php/course/topics/fetch_topics"),
+ 'data': { 'seminar_id': seminar_id },
+ 'dataType': "json",
+ 'success': function (json) {
+ jQuery("#topiclist").html(json.html);
+ }
+ });
+ return true;
+ }
+ };
+ </script>
+
+ <label>
+ <?= _('Veranstaltung') ?>
+
+ <?= QuickSearch::get("copy_from", $courseSearch)
+ ->fireJSFunctionOnSelect("STUDIP.Topics.loadTopics")
+ ->render() ?>
+ </label>
+
+ <div id="topiclist">
+ <? if (Request::option("seminar_id")) : ?>
+ <?= $this->render_partial("_topiclist.php", ['topics' => CourseTopic::findBySeminar_id(Request::option("seminar_id"))]) ?>
+ <? endif ?>
+ </div>
+
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= \Studip\Button::create(_("Kopieren"), 'copy') ?>
+ </footer>
+</form>
diff --git a/app/views/course/topics/edit.php b/app/views/course/topics/edit.php
new file mode 100644
index 0000000..43a5c74
--- /dev/null
+++ b/app/views/course/topics/edit.php
@@ -0,0 +1,94 @@
+<? $date_ids = $topic->dates->pluck("termin_id") ?>
+<form action="<?= URLHelper::getLink("dispatch.php/course/topics") ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <input type="hidden" name="issue_id" value="<?=htmlReady($topic->getId()) ?>">
+ <input type="hidden" name="open" value="<?=htmlReady($topic->getId()) ?>">
+ <input type="hidden" name="edit" value="1">
+
+ <fieldset>
+ <legend><?= _('Thema bearbeiten') ?></legend>
+
+ <label for="topic_title">
+ <span class="required"><?= _("Titel") ?></span>
+ <input type="text" name="title" id="topic_title" value="<?= htmlReady($topic['title']) ?>" required>
+ </label>
+
+
+ <label for="topic_description">
+ <?= _("Beschreibung") ?>
+
+ <textarea class="add_toolbar wysiwyg size-l" name="description" id="topic_description"><?= wysiwygReady($topic['description']) ?></textarea>
+ <? if (Request::isAjax()) : ?>
+ <script>jQuery('.add_toolbar').addToolbar();</script>
+ <? endif ?>
+ </label>
+
+ <? if ($documents_activated) : ?>
+ <label>
+ <? $folder = $topic->folders->first() ?>
+ <? if ($folder) : ?>
+ <?= Icon::create('accept', 'accept')->asImg(['class' => "text-bottom"]) ?>
+ <?= _("Dateiordner vorhanden ") ?>
+ <? else : ?>
+ <input type="checkbox" name="folder" id="topic_folder">
+ <?= _("Dateiordner anlegen") ?>
+ <? endif ?>
+ </label>
+ <? endif ?>
+
+ <? if ($forum_activated) : ?>
+ <label>
+ <? if ($topic->forum_thread_url) : ?>
+ <?= Icon::create('accept', 'accept')->asImg(['class' => "text-bottom"]) ?>
+ <?= _("Forenthema vorhanden ") ?>
+ <? else : ?>
+ <input type="checkbox" name="forumthread" id="topic_forumthread">
+ <?= _("Forenthema anlegen") ?>
+ <? endif ?>
+ </label>
+ <? endif ?>
+
+ <h2><?= _("Termine") ?></h2>
+ <? foreach ($dates as $date) : ?>
+ <label>
+ <input type="checkbox" name="date[<?= $date->getId() ?>]" value="1" class="text-bottom"<?= in_array($date->getId(), $date_ids) ? " checked" : "" ?>>
+ <?= Icon::create('date', 'info')->asImg(['class' => "text-bottom"]) ?>
+ <?= (floor($date['date'] / 86400) !== floor($date['end_time'] / 86400)) ? date("d.m.Y, H:i", $date['date'])." - ".date("d.m.Y, H:i", $date['end_time']) : date("d.m.Y, H:i", $date['date'])." - ".date("H:i", $date['end_time']) ?>
+ <? $localtopics = $date->topics ?>
+ <? if (count($localtopics)) : ?>
+ (
+ <? foreach ($localtopics as $key => $localtopic) : ?>
+ <a href="<?= URLHelper:: getLink("dispatch.php/course/topics/index", ['open' => $localtopic->getId()]) ?>">
+ <?= Icon::create('topic', 'clickable')->asImg(['class' => "text-bottom"]) ?>
+ <?= htmlReady($localtopic['title']) ?>
+ </a>
+ <? endforeach ?>
+ )
+ <? endif ?>
+ </label>
+ <? endforeach ?>
+
+ <h2><?= _('Hausarbeit/Referat') ?></h2>
+ <label>
+ <input type="checkbox" name="paper_related" value="1"
+ <? if ($topic->paper_related) echo 'checked'; ?>>
+ <?= _('Thema behandelt eine Hausarbeit oder ein Referat') ?>
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <div class="button-group">
+ <?= \Studip\Button::createAccept(_("Speichern")) ?>
+
+ <? if (!$topic->isNew()) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Löschen'),
+ $controller->url_for('course/topics/delete/' . $topic->getId()),
+ ['data-confirm' => _('Wirklich löschen?')]
+ ) ?>
+ <? endif ?>
+ </div>
+ </footer>
+</form>
+
+<br>
diff --git a/app/views/course/topics/index.php b/app/views/course/topics/index.php
new file mode 100644
index 0000000..79b74a2
--- /dev/null
+++ b/app/views/course/topics/index.php
@@ -0,0 +1,124 @@
+<? if (count($topics) > 0) : ?>
+<table class="default withdetails">
+ <colgroup>
+ <col width="50%">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _("Thema") ?></th>
+ <th><?= _("Termine") ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($topics as $key => $topic) : ?>
+ <tr class="<?= Request::get("open") === $topic->getId() ? "open" : "" ?>">
+ <td>
+ <a href="#" name="<?=$topic->getId()?>" onClick="jQuery(this).closest('tr').toggleClass('open'); return false;">
+ <? if ($topic->paper_related): ?>
+ <?= Icon::create('glossary')->asImg(array_merge(
+ ['class' => 'text-top'],
+ tooltip2(_('Thema behandelt eine Hausarbeit oder ein Referat'))
+ )) ?>
+ <? endif; ?>
+ <?= htmlReady($topic['title']) ?>
+ </a>
+ </td>
+ <td>
+ <ul class="clean">
+ <? foreach ($topic->dates as $date) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink("dispatch.php/course/dates/details/".$date->getId()) ?>" data-dialog="size=auto">
+ <?= Icon::create('date', 'clickable')->asImg(['class' => "text-bottom"]) ?>
+ <?= htmlReady($date->getFullName()) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </td>
+ </tr>
+ <tr class="details nohover">
+ <td colspan="2">
+ <div class="detailscontainer">
+ <table class="default nohover">
+ <tbody>
+ <tr>
+ <td><strong><?= _("Beschreibung") ?></strong></td>
+ <td><?= formatReady($topic['description']) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _("Materialien") ?></strong></td>
+ <td>
+ <? $material = false ?>
+ <ul class="clean">
+ <? $folder = $topic->folders->first() ?>
+ <? if ($documents_activated && $folder) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/course/files/index/' . $folder->id
+ ) ?>">
+ <?= $folder->getTypedFolder()->getIcon('clickable')->asImg(['class' => "text-bottom"]) ?>
+ <?= _("Dateiordner") ?>
+ </a>
+ </li>
+ <? $material = true ?>
+ <? endif ?>
+
+ <? if ($forum_activated && ($link_to_thread = $topic->forum_thread_url)) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink($link_to_thread) ?>">
+ <?= Icon::create('forum', 'clickable')->asImg(['class' => "text-bottom"]) ?>
+ <?= _("Thema im Forum") ?>
+ </a>
+ </li>
+ <? $material = true ?>
+ <? endif ?>
+ </ul>
+ <? if (!$material) : ?>
+ <?= _("Keine Materialien zu dem Thema vorhanden") ?>
+ <? endif ?>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div style="text-align: center;">
+ <? if ($GLOBALS['perm']->have_studip_perm("tutor", Context::getId())) : ?>
+ <?= \Studip\LinkButton::createEdit(_('Bearbeiten'),
+ $controller->url_for('course/topics/edit/' . $topic->getId()), [
+ 'data-dialog' => ''
+ ]) ?>
+
+ <?= Studip\LinkButton::create(
+ _('Löschen'),
+ $controller->url_for('course/topics/delete/' . $topic->getId()),
+ ['data-confirm' => _('Wirklich löschen?')]
+ ) ?>
+
+ <? if (!$cancelled_dates_locked && $topic->dates->count()) : ?>
+ <?= \Studip\LinkButton::create(_("Alle Termine ausfallen lassen"), URLHelper::getURL("dispatch.php/course/cancel_dates", ['issue_id' => $topic->getId()]), ['data-dialog' => '']) ?>
+ <? endif ?>
+ <? if ($key > 0) : ?>
+ <form action="<?=$controller->link_for()?>" method="post" style="display: inline;">
+ <input type="hidden" name="move_up" value="<?= $topic->getId() ?>">
+ <input type="hidden" name="open" value="<?= $topic->getId() ?>">
+ <?= \Studip\Button::createMoveUp(_("nach oben verschieben")) ?>
+ </form>
+ <? endif ?>
+ <? if ($key < count($topics) - 1) : ?>
+ <form action="<?=$controller->link_for()?>" method="post" style="display: inline;">
+ <input type="hidden" name="move_down" value="<?= $topic->getId() ?>">
+ <input type="hidden" name="open" value="<?= $topic->getId() ?>">
+ <?= \Studip\Button::createMoveDown(_("nach unten verschieben")) ?>
+ </form>
+ <? endif ?>
+ <? endif ?>
+ </div>
+ </div>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+<? else : ?>
+ <? PageLayout::postInfo(_('Keine Themen vorhanden.')) ?>
+<? endif ?>
diff --git a/app/views/course/wizard/ajax.php b/app/views/course/wizard/ajax.php
new file mode 100644
index 0000000..f8e4421
--- /dev/null
+++ b/app/views/course/wizard/ajax.php
@@ -0,0 +1 @@
+<?= $result ?> \ No newline at end of file
diff --git a/app/views/course/wizard/step.php b/app/views/course/wizard/step.php
new file mode 100644
index 0000000..6df4594
--- /dev/null
+++ b/app/views/course/wizard/step.php
@@ -0,0 +1,29 @@
+<? if ($content) : ?>
+ <form class="default course-wizard-step-<?= $stepnumber ?>" action="<?= $controller->url_for('course/wizard/process', $stepnumber, $temp_id) ?>" method="post" data-secure>
+ <fieldset>
+ <?= $content ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <input type="hidden" name="step" value="<?= $stepnumber ?>">
+ <? if (!$first_step): ?>
+ <?= Studip\Button::create(
+ _('Zurück'),
+ 'back',
+ $dialog ? ['data-dialog' => 'size=50%'] : []
+ ) ?>
+ <? endif; ?>
+ <?= Studip\Button::create(
+ _('Weiter'),
+ 'next',
+ $dialog ? ['data-dialog' => 'size=50%'] : []
+ ) ?>
+ </footer>
+ </form>
+<? else : ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Zurück zu meiner Veranstaltungsübersicht'),
+ $controller->url_for($GLOBALS['perm']->have_perm('admin') ? 'admin/courses' : 'my_courses'),
+ ['data-dialog-button' => '']
+ ) ?>
+<? endif ?>
diff --git a/app/views/course/wizard/steps/advancedbasicdata/index.php b/app/views/course/wizard/steps/advancedbasicdata/index.php
new file mode 100644
index 0000000..f5060b0
--- /dev/null
+++ b/app/views/course/wizard/steps/advancedbasicdata/index.php
@@ -0,0 +1,26 @@
+<?= $this->render_partial('basicdata/index.php', ['value' => $value]) ?>
+
+<section>
+ <label for="wizard-subtitle">
+ <?= _('Untertitel') ?>
+ </label>
+ <?= I18N::input('subtitle', $values['subtitle'], ['id' => 'wizard-subtitle', 'size' => 75, 'maxlength' => 254]) ?>
+</section>
+<section>
+ <label for="wizard-kind">
+ <?= _('Veranstaltungsart') ?>
+ </label>
+ <?= I18N::input('kind', $values['kind'], ['id' => 'wizard-kind', 'size' => 75, 'maxlength' => 254]) ?>
+</section>
+<section>
+ <label for="wizard-ects">
+ <?= _('ECTS-Punkte') ?>
+ </label>
+ <input type="text" name="ects" id="wizard-ects" size="20" maxlength="32" value="<?= htmlReady($values['ects']) ?>"/>
+</section>
+<section>
+ <label for="wizard-maxmembers">
+ <?= _('max. Teilnehmendenzahl') ?>
+ </label>
+ <input type="number" name="maxmembers" id="wizard-maxmember" min="0" value="<?= htmlReady($values['maxmembers']) ?>"/>
+</section>
diff --git a/app/views/course/wizard/steps/basicdata/_institute.php b/app/views/course/wizard/steps/basicdata/_institute.php
new file mode 100644
index 0000000..50543cf
--- /dev/null
+++ b/app/views/course/wizard/steps/basicdata/_institute.php
@@ -0,0 +1,5 @@
+<div class="institute">
+ <input type="hidden" name="participating[<?= $inst->id ?>]" value="1" id="<?= $inst->id ?>"/>
+ <?= htmlReady($inst->name) ?>
+ <?= Icon::create('trash', 'clickable')->asInput(["name" => 'remove_participating['.$inst->id.']', "onclick" => "return STUDIP.CourseWizard.removeParticipatingInst('".$inst->id."')"]) ?>
+</div>
diff --git a/app/views/course/wizard/steps/basicdata/_user.php b/app/views/course/wizard/steps/basicdata/_user.php
new file mode 100644
index 0000000..320ec7c
--- /dev/null
+++ b/app/views/course/wizard/steps/basicdata/_user.php
@@ -0,0 +1,5 @@
+<div class="<?= $class ?>">
+ <input type="hidden" name="<?= $inputname ?>[<?= $user->id ?>]" value="1" id="<?= $user->id ?>"/>
+ <?= htmlReady($user->getFullname('full_rev')) ?> (<?= htmlReady($user->username) ?>)
+ <?= Icon::create('trash', 'clickable')->asInput(["name" => 'remove_'.$class.'['.$user->id.']', "onclick" => "return STUDIP.CourseWizard.removePerson('".$user->id."')"]) ?>
+</div>
diff --git a/app/views/course/wizard/steps/basicdata/index.php b/app/views/course/wizard/steps/basicdata/index.php
new file mode 100644
index 0000000..cc97058
--- /dev/null
+++ b/app/views/course/wizard/steps/basicdata/index.php
@@ -0,0 +1,179 @@
+<legend>
+ <?= _('Grunddaten') ?>
+</legend>
+<section>
+ <label for="wizard-coursetype" class="required">
+ <?= _('Typ') ?>
+ </label>
+ <select name="coursetype" id="wizard-coursetype">
+ <?php foreach ($types as $class => $subtypes) { ?>
+ <optgroup label="<?= htmlReady($class) ?>">
+ <?php foreach ($subtypes as $type) { ?>
+ <option value="<?= $type['id'] ?>"<?= $type['id'] == $values['coursetype'] ? ' selected="selected"' : '' ?>>
+ <?= htmlReady($type['name']) ?>
+ </option>
+ <?php } ?>
+ </optgroup>
+ <?php } ?>
+ </select>
+</section>
+<section>
+ <label for="wizard-start-time" class="required">
+ <?= _('Semester') ?>
+ </label>
+ <select name="start_time" id="wizard-start-time" >
+ <?php foreach (array_reverse($semesters) as $semester) { ?>
+ <? ($values['start_time'] < time()) ? (($semester->beginn <= time() && time() <= $semester->ende) ? $values['start_time'] = $semester->beginn : '' ): '' ?>
+ <option value="<?= $semester->beginn ?>"<?= $semester->beginn == $values['start_time'] ? ' selected="selected"' : '' ?>>
+ <?= htmlReady($semester->name) ?>
+ </option>
+ <?php } ?>
+ </select>
+</section>
+<section>
+ <label for="wizard-name" class="required">
+ <?= _('Veranstaltungstitel') ?>
+ </label>
+ <?= I18N::input('name', $values['name'], ['id' => 'wizard-name', 'size' => 75, 'maxlength' => 255]) ?>
+</section>
+<section>
+ <? $course_number_format_config = Config::get()->getMetadata('COURSE_NUMBER_FORMAT'); ?>
+ <label for="wizard-number">
+ <?= _('Veranstaltungsnummer') ?>
+ <?= $course_number_format_config['comment'] ? tooltipIcon($course_number_format_config['comment']) : '' ?>
+ </label>
+ <? $course_number_format = Config::get()->COURSE_NUMBER_FORMAT; ?>
+ <input type="text" name="number" id="wizard-number" size="20" maxlength="99" value="<?= htmlReady($values['number']) ?>"
+ <? if ($course_number_format) : ?>pattern="<?= htmlReady($course_number_format) ?>" <? endif ?>/>
+</section>
+<section>
+ <label for="wizard-description">
+ <?= _('Beschreibung') ?>
+ </label>
+ <?= I18N::textarea('description', $values['description'], ['id' => 'wizard-description', 'cols' => 75, 'rows' => 4]) ?>
+</section>
+<section>
+ <label for="wizard-home-institute" class="required">
+ <?= _('Heimateinrichtung') ?>
+ </label>
+ <select name="institute" id="wizard-home-institute" class="nested-select">
+ <?php
+ $fak_id = '';
+ foreach ($institutes as $inst) :
+ if ($inst['is_fak']) {
+ $fak_id = $inst['Institut_id'];
+ }
+ ?>
+ <option value="<?= $inst['Institut_id'] ?>"<?=
+ $inst['Institut_id'] == $values['institute'] ? ' selected="selected"' : '' ?> class="<?=
+ $inst['is_fak'] ? 'faculty' : ($inst['fakultaets_id'] == $fak_id ? 'sub_institute' : 'institute') ?>">
+ <?= htmlReady($inst['Name']) ?>
+ </option>
+ <?php endforeach ?>
+ </select>
+ <?= Icon::create('arr_2right', 'sort')->asInput(["name" => 'select_institute', "value" => '1', "class" => 'hidden-js']) ?>
+</section>
+<section>
+ <label for="part_inst_id_1">
+ <?= _('Beteiligte Einrichtungen') ?>
+ </label>
+ <div id="wizard-instsearch">
+ <?= $instsearch ?>
+ </div>
+ <?php if ($values['part_inst_id_parameter']) : ?>
+ <?= Icon::create('arr_2down', 'sort')->asInput(["name" => 'add_part_inst', "value" => '1']) ?>
+ <?php endif ?>
+</section>
+<section>
+ <div id="wizard-participating">
+ <div class="description<?= count($values['participating']) ? '' : ' hidden-js' ?>">
+ <?= _('bereits zugeordnet:') ?>
+ </div>
+ <?php foreach ($values['participating'] as $id => $assigned) : ?>
+ <?php if ($inst = Institute::find($id)) : ?>
+ <?= $this->render_partial('basicdata/_institute',
+ ['class' => 'institute', 'inst' => $inst]) ?>
+ <?php endif ?>
+ <?php endforeach ?>
+ </div>
+</section>
+
+<section >
+ <label for="lecturer_id_2" class="required">
+ <?= _('Lehrende') ?>
+ </label>
+ <div id="wizard-lecturersearch">
+ <?= $lsearch ?>
+ </div>
+ <?php if ($values['lecturer_id_parameter']) : ?>
+ <?= Icon::create('arr_2down', 'sort')->asInput(["name" => 'add_lecturer', "value" => '1']) ?>
+ <?php endif ?>
+</section>
+<section>
+ <div id="wizard-lecturers" data-ajax-url="<?= $ajax_url ?>" data-default-enabled="<?= $default_deputies_enabled ?>">
+ <div class="description<?= count($values['lecturers']) ? '' : ' hidden-js' ?>">
+ <?= _('bereits zugeordnet:') ?>
+ </div>
+ <?php foreach ($values['lecturers'] as $id => $assigned) : ?>
+ <?php if ($user = User::find($id)) : ?>
+ <?= $this->render_partial('basicdata/_user',
+ ['class' => 'lecturer', 'inputname' => 'lecturers', 'user' => $user]) ?>
+ <?php endif ?>
+ <?php endforeach ?>
+ </div>
+</section>
+
+<?php if ($dsearch) : ?>
+<section>
+ <label for="deputy_id_3">
+ <?= _('Vertretungen') ?>
+ </label>
+ <div id="wizard-deputysearch">
+ <?= $dsearch ?>
+ </div>
+ <?php if ($values['deputy_id_parameter']) : ?>
+ <?= Icon::create('arr_2down', 'sort')->asInput(["name" => 'add_deputy', "value" => '1']) ?>
+ <?php endif ?>
+</section>
+<section>
+ <div id="wizard-deputies">
+ <div class="description<?= count($values['deputies']) ? '' : ' hidden-js' ?>">
+ <?= _('bereits zugeordnet:') ?>
+ </div>
+ <?php foreach ($values['deputies'] as $id => $assigned) : ?>
+ <?php if ($user = User::find($id)) : ?>
+ <?php if (!in_array($id, array_keys($values['lecturers']))) : ?>
+ <?= $this->render_partial('basicdata/_user',
+ ['class' => 'deputy', 'inputname' => 'deputies', 'user' => $user]) ?>
+ <?php endif ?>
+ <?php endif ?>
+ <?php endforeach ?>
+ </div>
+</section>
+<?php endif ?>
+
+<section for="tutor_id_parameter">
+ <label for="tutor_id_2">
+ <?= _('Tutor/-in') ?>
+ </label>
+ <div id="wizard-tutorsearch">
+ <?= $tsearch ?>
+ </div>
+ <?php if ($values['tutor_id_parameter']) : ?>
+ <?= Icon::create('arr_2down', 'sort')->asInput(["name" => 'add_tutor', "value" => '1']) ?>
+ <?php endif ?>
+</section>
+
+<section>
+ <div id="wizard-tutors">
+ <div class="description<?= count($values['tutors']) ? '' : ' hidden-js' ?>">
+ <?= _('bereits zugeordnet:') ?>
+ </div>
+ <?php foreach ($values['tutors'] as $id => $assigned) : ?>
+ <?php if ($user = User::find($id)) : ?>
+ <?= $this->render_partial('basicdata/_user',
+ ['class' => 'tutor', 'inputname' => 'tutors', 'user' => $user]) ?>
+ <?php endif ?>
+ <?php endforeach ?>
+ </div>
+</section>
diff --git a/app/views/course/wizard/steps/basicdata/index_studygroup.php b/app/views/course/wizard/steps/basicdata/index_studygroup.php
new file mode 100644
index 0000000..5d7dc44
--- /dev/null
+++ b/app/views/course/wizard/steps/basicdata/index_studygroup.php
@@ -0,0 +1,79 @@
+<legend>
+ <?= _('Grunddaten') ?>
+</legend>
+
+<label class="col-3">
+ <span class="required"><?= _('Name') ?></span>
+ <input type="text" name="name" id="wizard-name" maxlength="254" value="<?= $values['name'] ?>" required/>
+</label>
+
+<? if(count($types) > 1) : ?>
+ <label class="col-3">
+ <span class="required"><?= _('Typ') ?></span>
+ <select name="coursetype" id="wizard-coursetype">
+ <?php foreach ($types as $class => $subtypes) : ?>
+ <optgroup label="<?= htmlReady($class) ?>">
+ <?php foreach ($subtypes as $type) : ?>
+ <option value="<?= $type['id'] ?>"<?= $type['id'] == $values['coursetype'] ? ' selected="selected"' : '' ?>>
+ <?= htmlReady($type['name']) ?>
+ </option>
+ <?php endforeach ?>
+ </optgroup>
+ <?php endforeach ?>
+ </select>
+ </label>
+<? else : ?>
+ <? $type = array_shift(array_values($types)) ?>
+ <input type="hidden" name="coursetype" value="<?= htmlReady($type[0]['id']) ?>">
+<? endif ?>
+
+
+<label class="col-3">
+ <?= _('Beschreibung') ?>
+ <textarea name="description" id="wizard-description"
+ rows="4"><?= htmlReady($values['description'])?></textarea>
+</label>
+
+
+<label class="col-3">
+ <span class="required"><?= _('Zugang') ?></span>
+
+ <select name="access" id="wizard-access">
+ <option value="all"
+ <?= $values['access'] == 'all' ? 'selected' : ''?>>
+ <?= _('offen für alle') ?>
+ </option>
+ <option value="invite"
+ <?= $values['access'] == 'invite' ? 'selected' : ''?>>
+ <?= _('auf Anfrage') ?>
+ </option>
+ <?php if (Config::get()->STUDYGROUPS_INVISIBLE_ALLOWED) : ?>
+ <option value="invisible"
+ <?= $values['access'] == 'invisible' ? 'selected' : ''?>>
+ <?= _('unsichtbar') ?>
+ </option>
+ <?php endif ?>
+ </select>
+</label>
+
+
+<label><span class="required"><?= _('Nutzungsbedingungen')?></span></label>
+
+<? if ($GLOBALS['perm']->have_perm('admin')) : ?>
+ <p style="font-weight: bold;">
+ <?= _('Ich habe die eingetragenen Personen darüber informiert, dass in Ihrem Namen eine Studiengruppe angelegt wird und versichere, dass Sie mit folgenden Nutzungsbedingungen einverstandenen sind:') ?>
+ </p>
+<? endif ?>
+<?= formatReady(Config::Get()->STUDYGROUP_TERMS) ?>
+
+<label>
+ <input type="checkbox" name="accept" id="wizard-accept" required>
+ <?= _('Einverstanden') ?>
+</label>
+
+<input type="hidden" name="institute" value="<?= $values['institute'] ?>"/>
+<input type="hidden" name="start_time" value="<?= $values['start_time'] ?>"/>
+<input type="hidden" name="studygroup" value="1"/>
+<?php foreach ($values['lecturers'] as $id => $assigned) : ?>
+ <input type="hidden" name="lecturers[<?= $id ?>]" value="1"/>
+<?php endforeach ?>
diff --git a/app/views/course/wizard/steps/lvgroups/_node.php b/app/views/course/wizard/steps/lvgroups/_node.php
new file mode 100644
index 0000000..8b159bd
--- /dev/null
+++ b/app/views/course/wizard/steps/lvgroups/_node.php
@@ -0,0 +1,42 @@
+<? if (!$search_result || in_array($node->id, $search_result)) : ?>
+<? $id = $node->id . '-' . $pos_id; ?>
+ <? if (!count($children)) : ?>
+ <li><?= _('Keine Module verfügbar') ?></li>
+ <? else : ?>
+ <li class="lvgroup-tree-<?= htmlReady($id) ?> keep-node" data-id="<?= $id ?>" data-type="<?= get_class($node) ?>">
+ <? if ($node->isAssignable()) : ?>
+ <?= Icon::create('arr_2left', 'sort')->asInput(["name" => 'assign[' . $node->id . ']', "onclick" => "return STUDIP.MVV.CourseWizard.assignNode('" . $node->id . "')", "style" => in_array($id, $selection->getLvGruppenIDs()) ? 'display: none;' : '']) ?>
+ <?= htmlReady($node->getDisplayname()) ?>
+ <? else : ?>
+ <input type="checkbox" id="<?= htmlReady($id) ?>"<?= (in_array($id, $open_nodes)) ? ' checked="checked"' : '' ?>/>
+ <label onclick="return STUDIP.MVV.CourseWizard.getTreeChildren('<?= htmlReady($id) ?>', true, '<?= htmlReady(get_class($node)) ?>')"
+ for="<?= htmlReady($id) ?>" class="undecorated">
+ <a href="<?= URLHelper::getLink($no_js_url,
+ ['open_node' => $id, 'open_nodes' => json_encode($open_nodes)]) ?>">
+ <?= htmlReady($node->getDisplayname()) ?>
+ </a>
+ </label>
+ <input type="hidden" name="open_nodes[]" value="<?= $id; ?>">
+ <ul>
+ <? if (in_array($id, $open_nodes)) : ?>
+ <? $i = 1; ?>
+ <? if (!count($children)) : ?>
+ <li><?= _('Keine Module verfügbar') ?></li>
+ <? else : ?>
+ <? foreach ($children as $child) : ?>
+ <? $children = $child->getChildren(); ?>
+ <? if (count($children) || $child->isAssignable()) : ?>
+ <?= $this->render_partial('lvgroups/_node',
+ ['node' => $child, 'stepnumber' => $stepnumber,
+ 'pos_id' => $pos_id . '_' . $i++, 'open_nodes' => $open_nodes ?: [],
+ 'search_result' => $search_result ?: [],
+ 'children' => $children]) ?>
+ <? endif; ?>
+ <? endforeach ?>
+ <? endif; ?>
+ <? endif; ?>
+ </ul>
+ <? endif; ?>
+ </li>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/course/wizard/steps/lvgroups/index.php b/app/views/course/wizard/steps/lvgroups/index.php
new file mode 100644
index 0000000..a23bbe9
--- /dev/null
+++ b/app/views/course/wizard/steps/lvgroups/index.php
@@ -0,0 +1,93 @@
+<legend>
+ <?= _('Lehrveranstaltungsgruppen') ?>
+</legend>
+<div id="assigned" data-ajax-url="<?= $ajax_url ?>" data-forward-url="<?= $no_js_url ?>">
+ <h2>
+ <span class="required">
+ <?= _('Bereits zugewiesen') ?>
+ </span>
+ </h2>
+ <ul class="css-tree">
+ <li class="lvgroup-tree-assigned-root keep-node" data-id="root">
+ <ul id="lvgroup-tree-assigned-selected">
+ <? foreach ($selection->getAreas() as $area) : ?>
+ <?= $this->render_partial('lvgroups/lvgroup_entry', compact('area')) ?>
+ <? endforeach; ?>
+ </ul>
+ </li>
+ </ul>
+</div>
+<? if (!$values['locked']) : ?>
+
+ <div id="lvgroup-tree-open-nodes">
+ <? foreach ($open_lvg_nodes as $opennode) : ?>
+ <input type="hidden" name="open_lvg_nodes[]" value="<?= $opennode; ?>">
+ <? endforeach; ?>
+ </div>
+
+ <div id="studyareas" data-ajax-url="<?= $ajax_url ?>"
+ data-forward-url="<?= $no_js_url ?>" data-no-search-result="<?=_('Es wurde kein Suchergebnis gefunden.') ?>">
+ <h2><?= _('Lehrveranstaltungsgruppen Suche') ?></h2>
+ <div>
+ <input type="text" size="40" style="width: auto;" name="search" id="lvgroup-tree-search"
+ value="<?= $values['searchterm'] ?>">
+ <span id="lvgroup-tree-search-start">
+ <?= Icon::create('search', 'clickable')->asInput(["name" => 'start_search', "onclick" => "return STUDIP.MVV.CourseWizard.searchTree()", "class" => $search_result?'hidden-no-js':'']) ?>
+ </span>
+ <span id="lvgroup-tree-search-reset" class="hidden-js">
+ <?= Icon::create('refresh', 'clickable')->asInput(["name" => 'reset_search', "onclick" => "return STUDIP.MVV.CourseWizard.resetSearch()", "class" => $search_result?'':' hidden-no-js']) ?>
+ </span>
+ </div>
+
+ <div id="lvgsearchresults" style="display: none;">
+ <h2><?= _('Suchergebnisse') ?></h2>
+ <ul class="collapsable css-tree">
+
+ </ul>
+ </div>
+ <h2><?= _('Alle Lehrveranstaltungsgruppen') ?></h2>
+ <ul class="collapsable css-tree">
+ <li class="lvgroup-tree-root tree-loaded keep-node">
+ <input type="checkbox" id="root" checked="checked"/>
+ <label for="root" class="undecorated">
+ <?= htmlReady(Config::get()->UNI_NAME_CLEAN) ?>
+ </label>
+ <ul>
+ <? $pos_id = 1; ?>
+ <? foreach ((array) $tree as $node) : ?>
+ <? $children = $node->getChildren() ?>
+ <? if (count($children)) : ?>
+ <?= $this->render_partial('lvgroups/_node',
+ ['node' => $node, 'pos_id' => $pos_id++,
+ 'open_nodes' => $open_lvg_nodes ?: [],
+ 'search_result' => $search_result ?: [],
+ 'children' => $node->getChildren()]) ?>
+ <? endif ?>
+ <? endforeach; ?>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <? if ($values['open_lvg_nodes']) : ?>
+ <input type="hidden" name="open_nodes" value="<?= json_encode($values['open_lvg_nodes']) ?>"/>
+ <? endif; ?>
+ <? if ($values['searchterm']) : ?>
+ <input type="hidden" name="searchterm" value="<?= $values['searchterm'] ?>"/>
+ <? endif; ?>
+ <script>
+ //<!--
+ $(function() {
+ var element = $('#lvgroup-tree-search');
+ element.on('keypress', function(e) {
+ if (e.keyCode == 13) {
+ if (element.val() != '') {
+ return STUDIP.MVV.CourseWizard.searchTree();
+ } else {
+ return STUDIP.MVV.CourseWizard.resetSearch();
+ }
+ }
+ });
+ });
+ //-->
+ </script>
+<? endif; ?>
diff --git a/app/views/course/wizard/steps/lvgroups/lvgroup_entry.php b/app/views/course/wizard/steps/lvgroups/lvgroup_entry.php
new file mode 100644
index 0000000..09d2405
--- /dev/null
+++ b/app/views/course/wizard/steps/lvgroups/lvgroup_entry.php
@@ -0,0 +1,23 @@
+<?
+# Lifter010: TODO
+$_id = htmlReady(implode('_', (array) $area->getId()));
+?>
+<li id="lvgroup-tree-assigned-<?= $_id ?>" class="<?= TextHelper::cycle('odd', 'even') ?>">
+<? if (!$locked) : ?>
+ <?= Icon::create('trash', 'clickable')->asInput(["name" => 'lvgruppe_selection[remove]['.$_id.']', "onclick" => "return STUDIP.MVV.CourseWizard.removeLVGroup('".$_id."')", "class" => '',
+ "data-id" => $_id, "data-course_id" => htmlReady($course_id)]) ?>
+<? endif; ?>
+ <span class="lvgruppe_selection_expand">
+ <?= htmlReady($area->getDisplayName()) ?>
+ <?= Icon::create('info', 'clickable')->asInput(["name" => 'lvgruppe_selection[details]['.$_id.']',
+ "onclick" => "return STUDIP.MVV.CourseWizard.showDetails('".$_id."')", "class" => '',
+ "data-id" => $_id, "data-course_id" => htmlReady($course_id)]) ?>
+
+ </span>
+ <? if(isset($selection_details) && key_exists($_id, $selection_details)): ?>
+ <ul id="lvgruppe_selection_detail_<?= $_id ?>"><?= $selection_details[$_id] ?></ul>
+ <? else: ?>
+ <ul id="lvgruppe_selection_detail_<?= $_id ?>" style="display:none;"></ul>
+ <? endif; ?>
+ <input type="hidden" name="lvgruppe_selection[areas][]" class="lvgruppe_selection_area" value="<?= $_id ?>">
+</li>
diff --git a/app/views/course/wizard/steps/lvgroups/lvgroup_searchentry.php b/app/views/course/wizard/steps/lvgroups/lvgroup_searchentry.php
new file mode 100644
index 0000000..e4af01c
--- /dev/null
+++ b/app/views/course/wizard/steps/lvgroups/lvgroup_searchentry.php
@@ -0,0 +1,19 @@
+<?
+# Lifter010: TODO
+$_id = htmlReady(implode('_', (array) $area->getId()));
+?>
+<li id="lvgruppe_search_<?= $_id ?>" class="<?= TextHelper::cycle('odd', 'even') ?>">
+
+<? if (!$inlist) : ?>
+ <?= Icon::create('arr_2left', 'sort')->asInput(["name" => 'assign['.$_id.']', "onclick" => "return STUDIP.MVV.CourseWizard.assignNode('".$_id."')",
+ "class" => in_array($_id,$values['studyareas']?:[])?'hidden-no-js':'']) ?>
+<? endif; ?>
+ <?/* <span class="lvgruppe_selection_expand">*/?>
+ <?= htmlReady($area->getDisplayName()) ?>
+ <?= Icon::create('info', 'clickable')->asInput(["name" => 'lvgruppe_search[details]['.$_id.']',
+ "onclick" => "return STUDIP.MVV.CourseWizard.showSearchDetails('".$_id."')", "class" => '',
+ "data-id" => $_id, "data-course_id" => htmlReady($course_id)]) ?>
+ <?/*
+ </span>*/?>
+
+</li>
diff --git a/app/views/course/wizard/steps/studyareas/_assigned_node.php b/app/views/course/wizard/steps/studyareas/_assigned_node.php
new file mode 100644
index 0000000..459cddd
--- /dev/null
+++ b/app/views/course/wizard/steps/studyareas/_assigned_node.php
@@ -0,0 +1,12 @@
+<li class="sem-tree-assigned-<?= $element['id'] ?>">
+ <?= htmlReady($element['name']) ?>
+ <?php if (!$values['locked'] && $element['assignable'] && in_array($element['id'], $studyareas ?: [])) : ?>
+ <?= Icon::create('trash', 'clickable')->asInput(["name" => 'unassign['.$element['id'].']', "onclick" => "return STUDIP.CourseWizard.unassignNode('".$element['id']."')"]) ?>
+ <input type="hidden" name="studyareas[]" value="<?= $element['id'] ?>"/>
+ <?php endif ?>
+ <ul>
+ <?php foreach ($element['children'] as $c) : ?>
+ <?= $this->render_partial('studyareas/_assigned_node', ['element' => $c]) ?>
+ <?php endforeach ?>
+ </ul>
+</li> \ No newline at end of file
diff --git a/app/views/course/wizard/steps/studyareas/_node.php b/app/views/course/wizard/steps/studyareas/_node.php
new file mode 100644
index 0000000..75e37c2
--- /dev/null
+++ b/app/views/course/wizard/steps/studyareas/_node.php
@@ -0,0 +1,30 @@
+<?php if (!$search_result || in_array($node->id, $search_result)) : ?>
+<li class="sem-tree-<?= htmlReady($node->id) ?> keep-node" data-id="<?= $node->id ?>">
+ <?php if ($node->isAssignable()) : ?>
+ <?= Icon::create('arr_2left', 'sort')->asInput(["name" => 'assign['.$node->id.']', "onclick" => "return STUDIP.CourseWizard.assignNode('".$node->id."')", "class" => in_array($node->id,$values['studyareas']?:[])?'hidden-no-js':'', "style" => in_array($node->id,$values['studyareas']?:[])?'display:none':false]) ?>
+ <?php endif ?>
+ <?php if ($node->hasChildren()) : ?>
+ <input type="checkbox" id="<?= htmlReady($node->id) ?>"<?= (in_array($node->id, $open_nodes) && $node->parent_id != $values['open_node']) ? ' checked="checked"' : '' ?>/>
+ <label onclick="return STUDIP.CourseWizard.getTreeChildren('<?= htmlReady($node->sem_tree_id) ?>', true)"
+ for="<?= htmlReady($node->id) ?>" class="undecorated">
+ <a href="<?= URLHelper::getLink($no_js_url,
+ ['open_node' => $node->id]) ?>">
+ <?php endif ?>
+ <?= htmlReady($node->name) ?>
+ <?php if ($node->hasChildren()) : ?>
+ </a>
+ </label>
+ <ul>
+ <?php if ($node->hasChildren() && in_array($node->id, $open_nodes) && $node->_parent->id != $values['open_node']) : ?>
+ <?php foreach ($node->getChildren() as $child) : ?>
+ <?= $this->render_partial('studyareas/_node',
+ ['node' => $child, 'stepnumber' => $stepnumber,
+ 'temp_id' => $temp_id, 'values' => $values,
+ 'open_nodes' => $open_nodes ?: [],
+ 'search_result' => $search_result ?: []]) ?>
+ <?php endforeach ?>
+ <?php endif ?>
+ </ul>
+ <?php endif ?>
+</li>
+<?php endif ?>
diff --git a/app/views/course/wizard/steps/studyareas/index.php b/app/views/course/wizard/steps/studyareas/index.php
new file mode 100644
index 0000000..18c46a6
--- /dev/null
+++ b/app/views/course/wizard/steps/studyareas/index.php
@@ -0,0 +1,89 @@
+<legend>
+ <?= _('Studienbereiche') ?>
+</legend>
+<div id="assigned">
+ <h2>
+ <span class="required">
+ <?= _('Bereits zugewiesen') ?>
+ </span>
+ </h2>
+ <ul class="css-tree">
+ <li class="sem-tree-assigned-root keep-node" data-id="root"<?=
+ $assigned ? ' class="hidden-no-js hidden-js"' : '' ?>>
+ <?= htmlReady(Config::get()->UNI_NAME_CLEAN) ?>
+ <ul>
+ <?php foreach ($assigned as $element) : ?>
+ <?= $element->name ?>
+ <?= $this->render_partial('studyareas/_assigned_node',
+ ['element' => $element, 'studyareas' => $values['studyareas']]) ?>
+ <?php endforeach ?>
+ </ul>
+ </li>
+ </ul>
+ <? if (!$stepnumber && !$values['locked']) : ?>
+ <div data-dialog-button class="hidden-no-js">
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ </div>
+ <? endif ?>
+</div>
+<? if (!$values['locked']) : ?>
+ <div id="studyareas" data-ajax-url="<?= $ajax_url ?>"
+ data-forward-url="<?= $no_js_url ?>" data-no-search-result="<?=_('Es wurde kein Suchergebnis gefunden.') ?>">
+ <h2><?= _('Alle Studienbereiche') ?></h2>
+ <div>
+ <input style="width:auto" type="text" size="40" name="search" id="sem-tree-search"
+ value="<?= $values['searchterm'] ?>"/>
+ <span id="sem-tree-search-start">
+ <?= Icon::create('search', 'clickable')->asInput(["name" => 'start_search', "onclick" => "return STUDIP.CourseWizard.searchTree()", "class" => $search_result?'hidden-no-js':'']) ?>
+ </span>
+ <span id="sem-tree-search-reset" class="hidden-js">
+ <?= Icon::create('refresh', 'clickable')->asInput(["name" => 'reset_search', "onclick" => "return STUDIP.CourseWizard.resetSearch()", "class" => $search_result?'':' hidden-no-js']) ?>
+ </span>
+ </div>
+ <div id="sem-tree-assign-all" class="hidden-js hidden-no-js">
+ <a href="" onclick="return STUDIP.CourseWizard.assignAllNodes()">
+ <?= Icon::create('arr_2left', 'sort')->asImg() ?>
+ <?= _('Alle Suchergebnisse zuweisen') ?>
+ </a>
+ </div>
+ <ul class="collapsable css-tree">
+ <li class="sem-tree-root tree-loaded keep-node">
+ <input type="checkbox" id="root" checked="checked">
+ <label for="root" class="undecorated">
+ <?= htmlReady(Config::get()->UNI_NAME_CLEAN) ?>
+ </label>
+ <ul>
+ <?php foreach ($tree as $node) : ?>
+ <?= $this->render_partial('studyareas/_node',
+ ['node' => $node, 'stepnumber' => $stepnumber,
+ 'temp_id' => $temp_id, 'values' => $values,
+ 'open_nodes' => $open_nodes ?: [],
+ 'search_result' => $search_result ?: []]) ?>
+ <?php endforeach ?>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <?php if ($values['open_node']) : ?>
+ <input type="hidden" name="open_node" value="<?= $values['open_node'] ?>"/>
+ <?php endif ?>
+ <?php if ($values['searchterm']) : ?>
+ <input type="hidden" name="searchterm" value="<?= $values['searchterm'] ?>"/>
+ <?php endif ?>
+ <script>
+ //<!--
+ $(function() {
+ var element = $('#sem-tree-search');
+ element.on('keypress', function(e) {
+ if (e.keyCode == 13) {
+ if (element.val() != '') {
+ return STUDIP.CourseWizard.searchTree();
+ } else {
+ return STUDIP.CourseWizard.resetSearch();
+ }
+ }
+ });
+ });
+ //-->
+ </script>
+<? endif ?>
diff --git a/app/views/course/wizard/summary.php b/app/views/course/wizard/summary.php
new file mode 100644
index 0000000..57ca726
--- /dev/null
+++ b/app/views/course/wizard/summary.php
@@ -0,0 +1,52 @@
+<form class="default" action="<?= $controller->url_for('course/wizard/process', $stepnumber, $temp_id) ?>" method="post">
+<fieldset>
+ <legend><?= _('Anlegen der Veranstaltung') ?></legend>
+
+<? if ($dialog) : ?>
+ <?= MessageBox::info(
+ _('Sie haben alle benötigten Daten angegeben und können nun die Veranstaltung anlegen.')
+ ) ?>
+<? else : ?>
+ <?= MessageBox::info(
+ _('Sie haben alle benötigten Daten angegeben und können nun die Veranstaltung anlegen.')
+ . ' ' .
+ _('Der nächste Schritt führt Sie gleich in den Verwaltungsbereich '
+ . 'der neu angelegten Veranstaltung, wo Sie weitere Daten hinzufügen können.')
+ ) ?>
+<? endif ?>
+
+<? if ($source_course) : ?>
+ <section>
+ <label>
+ <input type="checkbox" checked name="copy_basic_data" value="1">
+ <?= sprintf(
+ _('Alle Grunddaten der Ursprungsveranstaltung (%s) kopieren'),
+ sprintf(
+ '<a data-dialog href="%s">%s</a>',
+ URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $source_course->id]),
+ htmlReady($source_course->getFullname())
+ )
+ ) ?>
+ </label>
+ </section>
+<? endif ?>
+
+ <section>
+ <input type="hidden" name="step" value="<?= $stepnumber ?>">
+ <? if ($dialog) : ?>
+ <input type="hidden" name="dialog" value="1">
+ <? endif ?>
+ </section>
+</fieldset>
+
+ <footer data-dialog-button>
+ <? if ($_SESSION['coursewizard'][$this->temp_id]['batchcreate']) : ?>
+ <? foreach ($_SESSION['coursewizard'][$this->temp_id]['batchcreate'] as $key => $value) : ?>
+ <input type="hidden" name="batchcreate[<?= $key ?>]" value="<?= $value ?>">
+ <? endforeach ?>
+ <? endif ?>
+ <?= Studip\Button::create(_('Zurück'), 'back',
+ $dialog ? ['data-dialog' => 'size=50%'] : []) ?>
+ <?= Studip\Button::createAccept(_('Veranstaltung anlegen'), 'create') ?>
+ </footer>
+</form>
diff --git a/app/views/dialog/confirm_dialog.php b/app/views/dialog/confirm_dialog.php
new file mode 100644
index 0000000..e57dd97
--- /dev/null
+++ b/app/views/dialog/confirm_dialog.php
@@ -0,0 +1,13 @@
+<script id="confirm_dialog" type="text/html">
+<div class="modaloverlay">
+ <div class="messagebox">
+ <div class="content">
+ <%- question %>
+ </div>
+ <div class="buttons">
+ <a class="accept button" href="<%- confirm %>"><?= _('Ja') ?></a>
+ <?= Studip\LinkButton::createCancel(_('Nein'), "javascript:STUDIP.Dialogs.closeConfirmDialog();") ?>
+ </div>
+ </div>
+</div>
+</script> \ No newline at end of file
diff --git a/app/views/elearning/my_accounts.php b/app/views/elearning/my_accounts.php
new file mode 100644
index 0000000..83719ff
--- /dev/null
+++ b/app/views/elearning/my_accounts.php
@@ -0,0 +1,48 @@
+<?php use Studip\Button, Studip\LinkButton; ?>
+ <h2><?=_('Meine Lernmodule und Benutzer-Accounts')?></h2>
+ <? foreach($cms_list as $cms_index => $cms_data) : ?>
+ <? if ($cms_anker_target == $cms_index) : ?>
+ <a name='anker'></a>
+ <? endif?>
+ <?=ELearningUtils::getCMSHeader($cms_data['name'])?>
+ <br>
+ <?=ELearningUtils::getHeader(_("Mein Benutzeraccount"))?>
+ <? if ($cms_data['account_form']) : ?>
+ <?=$cms_data['account_form']?>
+ <? else : ?>
+ <? if ($cms_data['show_account_form'] AND $cms_data['user']) : ?>
+ <?=ELearningUtils::getMyAccountForm('', $cms_index)?>
+ <? elseif ($cms_data['show_account_form']) : ?>
+ <?=ELearningUtils::getMyAccountForm(sprintf(_("Sie haben im System %s bisher keinen Benutzer-Account."), htmlReady($cms_data['name'])), $cms_index)?>
+ <? endif ?>
+ <? if ($cms_data['user'] AND $cms_data['start_link']) : ?>
+ <div class="messagebox messagebox_info" style="background-image: none; padding-left: 15px">
+ <?=_('Hier gelangen Sie direkt zur Startseite im angebundenen System:')?>
+ <a href="<?= URLHelper::getScriptLink($cms_data['start_link']) ?>" target="_blank" rel="noopener noreferrer">
+ <?= htmlReady($cms_data['name']) ?>
+ </a>
+ </div>
+ <br>
+ <? endif ?>
+ <?=ELearningUtils::getHeader(_('Meine Lernmodule'))?>
+ <? if (count($cms_data['modules'])) : ?>
+ <? foreach ($cms_data['modules'] as $module_html) : ?>
+ <?=$module_html?>
+ <? endforeach ?>
+ <? else : ?>
+ <table border="0" cellspacing="0" cellpadding="6">
+ <tr>
+ <td>
+ <?=sprintf(_("Sie haben im System %s keine eigenen Lernmodule."), htmlReady($cms_data['name']))?><br>
+ <br>
+ </td>
+ </tr>
+ </table>
+ <? endif ?>
+ <br>
+ <br>
+ <?=$cms_data['new_module_form']?>
+ <? endif ?>
+ <?=ELearningUtils::getCMSFooter($cms_data['logo'])?>
+ <br>
+ <? endforeach ?>
diff --git a/app/views/evaluation/_actions.php b/app/views/evaluation/_actions.php
new file mode 100644
index 0000000..45bf032
--- /dev/null
+++ b/app/views/evaluation/_actions.php
@@ -0,0 +1,4 @@
+<?= Icon::create('pause', 'clickable')->asImg() ?>
+<?= Icon::create('community+remove', 'clickable')->asImg() ?>
+<?= Icon::create('admin', 'clickable')->asImg() ?>
+<?= Icon::create('trash', 'clickable')->asImg() ?> \ No newline at end of file
diff --git a/app/views/evaluation/_admin_list_vote.php b/app/views/evaluation/_admin_list_vote.php
new file mode 100644
index 0000000..a98335b
--- /dev/null
+++ b/app/views/evaluation/_admin_list_vote.php
@@ -0,0 +1,27 @@
+<? foreach ($votes as $vote): ?>
+ <tr>
+ <td>
+ <?= htmlReady($vote->title) ?>
+ </td>
+ <td>
+ <?= ObjectdisplayHelper::link($vote->author) ?>
+ </td>
+ <td>
+ <?= strftime("%d.%m.%Y %T", $vote->startdate) ?>
+ </td>
+ <td>
+ <? if ($vote->stopdate): ?>
+ <?= strftime("%d.%m.%Y %T", $vote->stopdate) ?>
+ <? else: ?>
+ <? if ($vote->timespan): ?>
+ <?= strftime("%d.%m.%Y %T", $vote->startdate + $vote->timespan) ?>
+ <? else: ?>
+ <?= _('Unbegrenzt') ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ <td class="actions">
+ <?= $this->render_partial("vote/_actions.php", ['vote' => $vote]) ?>
+ </td>
+ </tr>
+<? endforeach; ?> \ No newline at end of file
diff --git a/app/views/evaluation/_buttons.php b/app/views/evaluation/_buttons.php
new file mode 100644
index 0000000..b5a3b33
--- /dev/null
+++ b/app/views/evaluation/_buttons.php
@@ -0,0 +1,22 @@
+<? if (!$controller->showResult($vote)): ?>
+ <? if ($vote->isRunning() && !$nobody) : ?>
+ <?= Studip\Button::create(_('Abstimmen'), 'vote', ['value' => $vote->id]) ?>
+ <? endif ?>
+ <?= Studip\LinkButton::create(_('Ergebnisse'), ContentBoxHelper::href($vote->id, ['preview[]' => $vote->id])) ?>
+<? else: ?>
+ <?= Studip\LinkButton::create(_('Ergebnisse ausblenden'), ContentBoxHelper::href($vote->id, ['preview' => 0])) ?>
+ <?= Request::get('sort')
+ ? Studip\LinkButton::create(_('Nicht sortieren'), ContentBoxHelper::href($vote->id, ['preview[]' => $vote->id, 'sort' => 0]))
+ : Studip\LinkButton::create(_('Sortieren'), ContentBoxHelper::href($vote->id, ['preview[]' => $vote->id, 'sort' => 1]))
+ ?>
+ <? if ($vote->changeable && $vote->state == 'active' && !$nobody): ?>
+ <?= Studip\LinkButton::create(_('Antwort ändern'), ContentBoxHelper::href($vote->id, ['change' => 1])) ?>
+ <? endif; ?>
+ <? if (!$vote->anonymous && ($admin || $vote->namesvisibility)): ?>
+ <? if (Request::get('revealNames') === $vote->id) : ?>
+ <?= Studip\LinkButton::create(_('Namen ausblenden'), ContentBoxHelper::href($vote->id, ['revealNames' => null])) ?>
+ <? else : ?>
+ <?= Studip\LinkButton::create(_('Namen zeigen'), ContentBoxHelper::href($vote->id, ['revealNames' => $vote->id])); ?>
+ <? endif; ?>
+ <? endif; ?>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/evaluation/_evaluation.php b/app/views/evaluation/_evaluation.php
new file mode 100644
index 0000000..82c6fd1
--- /dev/null
+++ b/app/views/evaluation/_evaluation.php
@@ -0,0 +1,57 @@
+<? $is_new = ($evaluation->chdate >= object_get_visit($evaluation->id, 'eval', false, false)) && ($evaluation->author_id != $GLOBALS['user']->id);
+?>
+<article class="studip toggle <?=($is_new ? 'new' : '')?>" id="<?= $evaluation->id ?>" data-visiturl="<?=URLHelper::getScriptLink('dispatch.php/vote/visit')?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::switchhref($evaluation->id, ['contentbox_type' => 'eval']) ?>">
+ <?= htmlReady($evaluation->title) ?>
+ </a>
+ </h1>
+ <nav>
+ <a href="<?= $evaluation->author ? URLHelper::getLink('dispatch.php/profile', ['username' => $evaluation->author->username]) : '' ?>">
+ <?= $evaluation->author ? htmlReady($evaluation->author->getFullName()) : '' ?>
+ </a> |
+ <?= strftime("%d.%m.%Y", $evaluation->mkdate) ?>
+ <? if ($admin): ?>
+ <a title="<?= _("Evaluation bearbeiten") ?>" href="<?= URLHelper::getLink('admin_evaluation.php', ['openID' => $evaluation->id, 'rangeID' => $range_id]) ?>">
+ <?= Icon::create('admin', 'clickable')->asImg() ?>
+ </a>
+ <? if (!$evaluation->enddate || $evaluation->enddate > time()): ?>
+ <a title="<?= _("Evaluation stoppen") ?>" href="<?= URLHelper::getLink('admin_evaluation.php', ['evalID' => $evaluation->id, 'evalAction' => 'stop']) ?>">
+ <?= Icon::create('pause', 'clickable')->asImg() ?>
+ </a>
+ <? else: ?>
+ <a title="<?= _("Evaluation fortsetzen") ?>" href="<?= URLHelper::getLink('admin_evaluation.php', ['evalID' => $evaluation->id, 'evalAction' => 'continue']) ?>">
+ <?= Icon::create('play', 'clickable')->asImg() ?>
+ </a>
+ <? endif; ?>
+ <a title="<?= _("Evaluation löschen") ?>" href="<?= URLHelper::getLink('admin_evaluation.php', ['evalID' => $evaluation->id, 'evalAction' => 'delete_request']) ?>">
+ <?= Icon::create('trash', 'clickable')->asImg() ?>
+ </a>
+ <a title="<?= _("Evaluation exportieren") ?>" href="<?= URLHelper::getLink('admin_evaluation.php', ['evalID' => $evaluation->id, 'evalAction' => 'export_request']) ?>">
+ <?= Icon::create('export', 'clickable')->asImg() ?>
+ </a>
+ <a title="<?= _("Evaluation auswerten") ?>" href="<?= URLHelper::getLink('eval_summary.php', ['eval_id' => $evaluation->id]) ?>">
+ <?= Icon::create('vote', 'clickable')->asImg() ?>
+ </a>
+ <? endif; ?>
+ </nav>
+ </header>
+ <section>
+ <?= formatReady($evaluation->text); ?>
+ </section>
+ <section>
+ <?= \Studip\LinkButton::create(_('Anzeigen'), URLHelper::getURL('show_evaluation.php', ['evalID' => $evaluation->id]), ['data-dialog' => '', 'target' => '_blank']) ?>
+ </section>
+ <footer>
+ <p>
+ <?= _('Teilnehmende') ?>: <?= $evaluation->getNumberOfVotes() ?>
+ </p>
+ <p>
+ <?= _('Anonym') ?>: <?= $evaluation->anonymous ? _('Ja') : _('Nein') ?>
+ </p>
+ <p>
+ <?= _('Endzeitpunkt') ?>: <?= $evaluation->enddate ? strftime('%d.%m.%y, %H:%M', $evaluation->enddate) : _('Unbekannt') ?>
+ </p>
+ </footer>
+</article>
diff --git a/app/views/evaluation/display.php b/app/views/evaluation/display.php
new file mode 100644
index 0000000..35d3178
--- /dev/null
+++ b/app/views/evaluation/display.php
@@ -0,0 +1,27 @@
+<? if ($admin || $evaluations): ?>
+<article class="studip">
+ <header>
+ <h1>
+ <?= Icon::create('vote', 'info')->asImg(); ?>
+ <?= _('Evaluationen') ?>
+ </h1>
+ <nav>
+ <? if ($admin): ?>
+ <a href="<?= URLHelper::getLink('admin_evaluation.php', ['rangeID' => $range_id]) ?>">
+ <?= Icon::create('edit', 'clickable')->asImg(); ?>
+ </a>
+ <? endif; ?>
+ </nav>
+ </header>
+
+ <? if (!$evaluations): ?>
+ <section>
+ <?= _('Keine Evaluationen vorhanden. Um neue Umfragen zu erstellen, klicken Sie rechts auf das Bearbeiten-Zeichen.') ?>
+ </section>
+ <? else: ?>
+ <? foreach ($evaluations as $evaluation): ?>
+ <?= $this->render_partial('evaluation/_evaluation.php', ['evaluation' => $evaluation]); ?>
+ <? endforeach; ?>
+ <? endif; ?>
+</article>
+<? endif; ?>
diff --git a/app/views/event_log/admin.php b/app/views/event_log/admin.php
new file mode 100644
index 0000000..7ee7bed
--- /dev/null
+++ b/app/views/event_log/admin.php
@@ -0,0 +1,50 @@
+<p><?= _('Sie können hier einen Teil der Logging-Funktionen direkt verändern.') ?></p>
+
+<table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ <th><?= _('Template') ?></th>
+ <th><?= _('Anzahl') ?></th>
+ <th><?= _('Aktiv?') ?></th>
+ <th><?= _('Ablaufzeit') ?></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($log_actions as $log_action): ?>
+ <tr>
+ <td><?= htmlReady($log_action['name']) ?></td>
+ <td>
+ <?= htmlReady($log_action['description']) ?>
+ </td>
+ <td>
+ <?= htmlReady($log_action['info_template']) ?>
+ </td>
+ <td>
+ <?= $log_action['log_count'] ?>
+ </td>
+ <td>
+ <? if ($log_action['active']): ?>
+ <?= Icon::create('accept', Icon::ROLE_STATUS_GREEN) ?>
+ <? else: ?>
+ <?= Icon::create('decline', Icon::ROLE_STATUS_RED) ?>
+ <? endif ?>
+ </td>
+ <td style="white-space: nowrap;">
+ <? if ($log_action['expires'] > 0): ?>
+ <?= $log_action['expires'] / 86400 ?> <?= _('Tage') ?>
+ <? else: ?>
+ <?= Icon::create('decline', Icon::ROLE_STATUS_RED) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <a href="<?= $controller->edit($log_action['action_id']) ?>" data-dialog="size=auto">
+ <?= Icon::create('edit') ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/event_log/edit.php b/app/views/event_log/edit.php
new file mode 100644
index 0000000..ed6410a
--- /dev/null
+++ b/app/views/event_log/edit.php
@@ -0,0 +1,45 @@
+<form action="<?= $controller->save($action) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= sprintf(_('Log-Aktion %s bearbeiten'), htmlReady($action->name)) ?>
+ </legend>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <input type="text" name="description"
+ value="<?= htmlReady(Request::get('description', $action->description)) ?>">
+ </label>
+
+ <label>
+ <?= _('Template') ?>
+ <input required type="text" name="info_template"
+ value="<?= htmlReady(Request::get('info_template', $action->info_template)) ?>">
+ </label>
+
+ <label>
+ <input type="checkbox" name="active" value="1"
+ <? if (Request::int('active', $action->active)) echo 'checked'; ?>>
+ <?= _('Aktiv') ?>
+ </label>
+
+ <label>
+ <?= _('Ablaufzeit in Tagen') ?>
+ (<?= _('optional') ?>, <?= _('0 = keine Ablaufzeit') ?>)
+ <input type="number" class="size-s" name="expires" min="0"
+ value="<?= Request::int('expires', floor($action->expires / 86400)) ?>">
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save', [
+ 'data-dialog' => 'reload-on-close',
+ ]) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->adminURL()
+ ) ?>
+ </footer>
+
+</form>
diff --git a/app/views/event_log/show.php b/app/views/event_log/show.php
new file mode 100644
index 0000000..4eeac33
--- /dev/null
+++ b/app/views/event_log/show.php
@@ -0,0 +1,135 @@
+<form action="<?= $controller->show() ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Anzeige der Log-Events') ?></legend>
+
+ <label class="col-2">
+ <?= _('Aktionen filtern') ?>
+ <select name="action_id" class="nested-select" required>
+ <option value="all"><?= _('Alle Aktionen') ?></option>
+ <? foreach ($log_actions as $group => $actions): ?>
+ <option value="" class="nested-item-header" disabled>
+ <?= _('Gruppe') ?> <?= htmlReady($group) ?>
+ </option>
+ <? foreach ($actions as $id => $description): ?>
+ <option value="<?= htmlReady($id) ?>" <? if ($id === $action_id) echo 'selected'; ?> class="nested-item">
+ <?= htmlReady($description) ?>
+ </option>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label class="col-2">
+ <?= _('Darstellung') ?>
+ <select name="format">
+ <option value="compact" <? if ($format === 'compact') echo 'selected'; ?>>
+ <?= _('Kompakt') ?>
+ </option>
+ <option value="detail" <? if ($format === 'detail') echo 'selected'; ?>>
+ <?= _('Details') ?>
+ </option>
+ </select>
+ </label>
+
+ <label class="col-2">
+ <?= _('Art der Einträge') ?><br>
+ <select name="type" <? if (isset($objects)) echo 'disabled'; ?>>
+ <? foreach ($types as $name => $title): ?>
+ <option value="<?= htmlReady($name) ?>" <? if ($type === $name) echo 'selected'; ?>>
+ <?= htmlReady($title) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <? if (isset($objects)): ?>
+ <input type="hidden" name="type" value="<?= htmlReady($type) ?>">
+ <input type="hidden" name="search" value="<?= htmlReady($search) ?>">
+
+ <label class="col-3">
+ <?= _('Eintrag auswählen') ?>
+ <div class="hgroup">
+ <select name="object_id">
+ <? foreach ($objects as $object): ?>
+ <option value="<?= htmlReady($object[0]) ?>" <? if ($object[0] === $object_id) echo 'selected'; ?>>
+ <?= htmlReady($object[1]) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+
+ <a href="<?= $controller->show(['action_id' => $action_id]) ?>">
+ <?= Icon::create('decline')->asImg(['title' => _('neue Suche')]) ?>
+ </a>
+ </div>
+ </label>
+ <? else : ?>
+ <label class="col-3">
+ <?= _('Suchen') ?>
+ <input type="text" name="search"
+ placeholder="<?= _('Veranstaltung / Einrichtung / ... ') ?>">
+ </label>
+ <? endif ?>
+
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::create(_('Anzeigen')) ?>
+ </footer>
+
+ <? if (isset($log_events)): ?>
+ <br>
+ <table class="default">
+ <colgroup>
+ <col style="width: 20ex">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Zeit') ?></th>
+ <th><?= _('Info') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($log_events) === 0): ?>
+ <tr>
+ <td colspan="2">
+ <?= _('keine Einträge gefunden') ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($log_events as $log_event): ?>
+ <tr>
+ <td>
+ <?= strftime('%x %X', $log_event['time']) ?>
+ </td>
+ <td>
+ <?= $log_event['info'] ?>
+ <? if ($format === 'detail' && $log_event['detail']): ?>
+ <br>
+ <?= _('Info:') ?>
+ <?= htmlReady($log_event['detail']) ?>
+ <? endif ?>
+ <? if ($format === 'detail' && $log_event['debug']): ?>
+ <br>
+ <?= _('Debug:') ?>
+ <?= htmlReady($log_event['debug']) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <? if ($num_entries > 50): ?>
+ <tfoot>
+ <tr>
+ <td colspan="2" class="actions">
+ <?= Pagination::create($num_entries, $page, 50)->asButtons() ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+ <? endif ?>
+
+</form>
diff --git a/app/views/fachabschluss/abschluesse/abschluss.php b/app/views/fachabschluss/abschluesse/abschluss.php
new file mode 100644
index 0000000..c0efb7d
--- /dev/null
+++ b/app/views/fachabschluss/abschluesse/abschluss.php
@@ -0,0 +1,47 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? $perm = MvvPerm::get($abschluss) ?>
+<form class="default" action="<?= $controller->url_for('/abschluss/' . $abschluss->getId()) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label>
+ <?= _('Name') ?>
+ <?= MvvI18N::input('name', $abschluss->name, ['maxlength' => '255', 'required' => ''])->checkPermission($abschluss) ?>
+ </label>
+ <label>
+ <?= _('Kurzname') ?>
+ <?= MvvI18N::input('name_kurz', $abschluss->name_kurz, ['maxlength' => '50'])->checkPermission($abschluss) ?>
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <?= MvvI18N::textarea('beschreibung', $abschluss->beschreibung, ['class' => 'add_toolbar ui-resizable wysiwyg'])->checkPermission($abschluss) ?>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Abschluss-Kategorie wählen') ?></legend>
+ <? if ($perm->haveFieldPerm('category_assignment')) : ?>
+ <label><?= _('Abschluss-Kategorie') ?></label>
+ <select id="abschluss_kategorie" name="kategorie_id" size="1">
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($abschluss_kategorien as $kategorie) : ?>
+ <option
+ <?= ($kategorie->getId() === $abschluss->kategorie_id ? 'selected ' : '') ?>value="<?= $kategorie->getId() ?>"><?= htmlReady($kategorie->name) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? else : ?>
+ <?= htmlReady(AbschlussKategorie::get($abschluss->kategorie_id)->getDisplayName()) ?>
+ <? endif; ?>
+ </fieldset>
+ <footer data-dialog-button>
+ <? if ($abschluss->isNew()) : ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Abschluss anlegen')]) ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('/index'), ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/fachabschluss/abschluesse/details.php b/app/views/fachabschluss/abschluesse/details.php
new file mode 100644
index 0000000..0628d1b
--- /dev/null
+++ b/app/views/fachabschluss/abschluesse/details.php
@@ -0,0 +1,28 @@
+<td colspan="4">
+ <table class="default">
+ <colgroup>
+ <col>
+ <col style="width: 1%;">
+ </colgroup>
+ <? foreach ($abschluss->getFaecher() as $fach) : ?>
+ <? if (count($perm_institutes) === 0
+ || count(array_intersect($perm_institutes, $fach->getFachbereiche()->pluck('institut_id')))) : ?>
+ <tr>
+ <td>
+ <?= htmlReady($fach->name) ?>
+ </td>
+ <td class="actions">
+ <? if (MvvPerm::havePermWrite($fach)) : ?>
+ <a data-dialog href="<?= $controller->url_for('/fach/' . $fach->id) ?>">
+ <?= Icon::create('edit', 'clickable', ['title' => _('Fach bearbeiten')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? endforeach; ?>
+ </table>
+</td>
+
+
+
diff --git a/app/views/fachabschluss/abschluesse/index.php b/app/views/fachabschluss/abschluesse/index.php
new file mode 100644
index 0000000..e541257
--- /dev/null
+++ b/app/views/fachabschluss/abschluesse/index.php
@@ -0,0 +1,76 @@
+<form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <table class="default collapsable">
+ <caption>
+ <?= _('Abschlüsse mit verwendeten Fächern') ?>
+ <span class="actions"><? printf(ngettext('%s Abschluss', '%s Abschlüsse', $count), $count) ?></span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('/index', _('Abschluss'), 'name') ?>
+ <?= $controller->renderSortLink('/index', _('Abschluss-Kategorie'), 'kategorie_name', ['style' => 'width: 30%;']) ?>
+ <?= $controller->renderSortLink('/index', ('Fächer'), 'count_faecher', ['style' => 'width: 5%;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($abschluesse as $abschluss) : ?>
+ <tbody class="<?= $abschluss->count_faecher ? '' : 'empty' ?> <?= ($abschluss_id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <? if ($abschluss->count_faecher) : ?>
+ <a class="mvv-load-in-new-row" href="<?= $controller->url_for('/details/' . $abschluss->id) ?>"><?= htmlReady($abschluss->name) ?> </a>
+ <? else: ?>
+ <?= htmlReady($abschluss->name) ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide"><?= htmlReady($abschluss->kategorie_name) ?></td>
+ <td style="text-align: center;" class="dont-hide"><?= $abschluss->count_faecher ?></td>
+ <td class="dont-hide actions" style="white-space: nowrap;">
+ <? if (MvvPerm::havePermWrite($abschluss)) : ?>
+ <a href="<?=$controller->url_for('/abschluss/' . $abschluss->id)?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE, tooltip2(_('Abschluss bearbeiten')))->asImg(); ?>
+ </a>
+ <? endif; ?>
+ <? if (MvvPerm::havePermCreate($abschluss)) : ?>
+ <? if (!$abschluss->count_faecher) : ?>
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE, tooltip2(_('Abschluss löschen')))->asInput(
+ [
+ 'formaction' => $controller->url_for('/delete/' . $abschluss->id),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie wirklich den Abschluss "%s" löschen?'),
+ htmlReady($abschluss->name)
+ ),
+ 'name' => 'delete'
+ ]); ?>
+ <? else : ?>
+ <?= Icon::create('trash', Icon::ROLE_INACTIVE, tooltip2(_('Abschluss kann nicht glöscht werden')))->asImg(); ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? if ($abschluss_id === $abschluss->id) : ?>
+ <?= $this->render_partial('fachabschluss/abschluesse/details', compact('abschluss')) ?>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="4" style="text-align: right;">
+ <?php
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_abschluesse=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render('shared/pagechooser');
+ ?>
+
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</form>
diff --git a/app/views/fachabschluss/faecher/details.php b/app/views/fachabschluss/faecher/details.php
new file mode 100644
index 0000000..c9201a5
--- /dev/null
+++ b/app/views/fachabschluss/faecher/details.php
@@ -0,0 +1,23 @@
+<td colspan="3">
+ <table class="default">
+ <colgroup>
+ <col>
+ <col style="width: 40%">
+ <col style="width: 1%">
+ </colgroup>
+ <?php $abschluesse = $fach->getAbschluesse()?>
+ <? foreach ($abschluesse as $abschluss) : ?>
+ <tr>
+ <td><?= htmlReady($abschluss->getDisplayName()) ?></td>
+ <td><?= htmlReady($abschluss->category->getDisplayName()) ?></td>
+ <td class="actions">
+ <? if (MvvPerm::havePermWrite($abschluss)) : ?>
+ <a data-dialog href="<?= $controller->url_for('/abschluss/' . $abschluss->id) ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE, ['title' => _('Abschluss bearbeiten')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </table>
+</td>
diff --git a/app/views/fachabschluss/faecher/details_fachbereich.php b/app/views/fachabschluss/faecher/details_fachbereich.php
new file mode 100644
index 0000000..a13def0
--- /dev/null
+++ b/app/views/fachabschluss/faecher/details_fachbereich.php
@@ -0,0 +1,22 @@
+<td colspan="2">
+ <table class="default">
+ <colgroup>
+ <col>
+ <col style="width: 1%">
+ </colgroup>
+ <? foreach ($faecher as $fach) : ?>
+ <tr>
+ <td class="label-cell">
+ <?= htmlReady($fach->name) ?>
+ </td>
+ <td class="actions">
+ <? if (MvvPerm::havePermWrite($fach)) : ?>
+ <a href="<?= $controller->url_for('/fach/' . $fach->id) ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE, ['title' => _('Fach bearbeiten')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </table>
+</td>
diff --git a/app/views/fachabschluss/faecher/fach.php b/app/views/fachabschluss/faecher/fach.php
new file mode 100644
index 0000000..f05b9d5
--- /dev/null
+++ b/app/views/fachabschluss/faecher/fach.php
@@ -0,0 +1,110 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+
+<? $perm = MvvPerm::get($fach) ?>
+<form class="default" action="<?= $controller->url_for('/fach/', $fach->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset class="collapsable">
+ <legend>
+ <?= _('Grunddaten') ?>
+ </legend>
+
+ <label>
+ <?= _('Name') ?>
+ <?= MvvI18N::input('name', $fach->name, ['maxlength' => '255', 'required' => ''])->checkPermission($fach) ?>
+ </label>
+ <label>
+ <?= _('Kurzname') ?>
+ <?= MvvI18N::input('name_kurz', $fach->name_kurz, ['maxlength' => '50'])->checkPermission($fach) ?>
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <?= MvvI18N::textarea('beschreibung', $fach->beschreibung, ['class' => 'add_toolbar ui-resizable wysiwyg'])->checkPermission($fach) ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Verantwortliche Einrichtung') ?>
+ </legend>
+
+ <? if ($perm->haveFieldPermDepartments(MvvPerm::PERM_WRITE)) : ?>
+ <?= $search_institutes->render(); ?>
+ <? if (Request::submitted('search_institutes')) : ?>
+ <?= Icon::create(
+ 'refresh',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'name' => 'reset_institutes',
+ 'data-qs_id' => $search_institutes_id
+ ]
+ )->asInput(); ?>
+ <? else : ?>
+ <?= Icon::create(
+ 'search',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'name' => 'search_dokumente',
+ 'data-qs_id' => $search_institutes_id,
+ 'data-qs_name' => $search_institutes->getId(),
+ 'class' => 'mvv-qs-button'
+ ]
+ )->asInput(); ?>
+ <? endif; ?>
+ <? endif; ?>
+ <ul id="institut_target" class="mvv-assigned-items mvv-institute sortable">
+ <? if ($perm->haveFieldPermDepartments(MvvPerm::PERM_WRITE)) : ?>
+ <li class="mvv-item-list-placeholder"<?= (count($fach->departments) ? ' style="display: none;"' : '') ?>><?= _('Bitte mindestens eine verantwortliche Einrichtung hinzufügen.') ?></li>
+ <? elseif (!count($fach->getFachbereiche())) : ?>
+ <li class="mvv-item-list-placeholder"><?= _('Es wurde noch keine verantwortliche Einrichtung angegeben.') ?></li>
+ <? endif; ?>
+ <? foreach ($fach->getFachbereiche() as $fachbereich) : ?>
+ <li id="fachbereiche_<?= $fachbereich->getId() ?>" class="sort_items">
+ <div class="mvv-item-list-text">
+ <? if ($fachbereich) : ?>
+ <?= htmlReady($fachbereich->getDisplayName()) ?>
+ <? else: ?>
+ <?= _('Unbekannte Einrichtung') ?>
+ <? endif; ?>
+ </div>
+ <? if ($perm->haveFieldPerm('institut_id', MvvPerm::PERM_WRITE)): ?>
+ <div class="mvv-item-list-buttons">
+ <a href="#"
+ class="mvv-item-remove"><?= Icon::create('trash', Icon::ROLE_CLICKABLE, ['title' => _('Einrichtung entfernen')])->asImg(); ?></a>
+ </div>
+ <? endif; ?>
+ <input type="hidden" name="institut_items[]" value="<?= $fachbereich->getId() ?>">
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Zusätzliche Angaben') ?>
+ </legend>
+ <label><?= _('Schlagworte') ?>
+ <? if ($perm->haveFieldPerm('schlagworte')) : ?>
+ <textarea cols="60" rows="5" name="schlagworte" id="schlagworte"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($fach->schlagworte) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="schlagworte" id="schlagworte"
+ class="ui-resizable"><?= htmlReady($fach->schlagworte) ?></textarea>
+ <? endif; ?>
+ <?= _('Hier können zusätzlich Schlagworte angegeben werden, die in der Suche berücksichtigt werden.') ?>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if ($fach->isNew()) : ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Fach anlegen')]) ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('/index'), ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/fachabschluss/faecher/fachbereiche.php b/app/views/fachabschluss/faecher/fachbereiche.php
new file mode 100644
index 0000000..dce4d98
--- /dev/null
+++ b/app/views/fachabschluss/faecher/fachbereiche.php
@@ -0,0 +1,29 @@
+<table class="default collapsable">
+ <colgroup>
+ <col>
+ <col style="width: 5%;">
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('fachabschluss/faecher/fachbereiche/', _('Fachbereich'), 'name') ?>
+ <?= $controller->renderSortLink('fachabschluss/faecher/fachbereiche/', _('Fächer'), 'faecher', ['style' => 'text-align: center;']) ?>
+ </tr>
+ </thead>
+ <? foreach ($fachbereiche as $fachbereich): ?>
+ <? if ($fachbereich['faecher']) : ?>
+ <tbody class="<?= ($fachbereich_id === $fachbereich['institut_id'] ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details_fachbereich/' . $fachbereich['institut_id']) ?>"><?= htmlReady($fachbereich['name']) ?></a>
+ </td>
+ <td style="text-align: center;" class="dont-hide"><?= htmlReady($fachbereich['faecher']) ?> </td>
+ </tr>
+ <? if ($fachbereich_id === $fachbereich['institut_id']) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('fachabschluss/faecher/details_fachbereich', compact('fach')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endif; ?>
+ <? endforeach ?>
+</table>
diff --git a/app/views/fachabschluss/faecher/index.php b/app/views/fachabschluss/faecher/index.php
new file mode 100644
index 0000000..6710ec4
--- /dev/null
+++ b/app/views/fachabschluss/faecher/index.php
@@ -0,0 +1,74 @@
+<form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <table class="default collapsable">
+ <caption>
+ <?= _('Fächer mit verwendeten Abschlüssen') ?>
+ <span class="actions"><? printf(ngettext('%s Fach', '%s Fächer', $count), $count) ?></span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('/index', _('Fach'), 'name') ?>
+ <?= $controller->renderSortLink('/index', _('Abschlüsse'), 'count_abschluesse', ['style' => 'width: 10%; text-align: center;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($faecher as $fach): ?>
+ <tbody class="<?= $fach->count_abschluesse ? '' : 'empty' ?> <?= ($fach_id === $fach->id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <? if ($fach->count_abschluesse) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details/' . $fach->id) ?>"><?= htmlReady($fach->name) ?></a>
+ <? else: ?>
+ <?= htmlReady($fach->name) ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide" style="text-align: center;"><?= $fach->count_abschluesse ?> </td>
+ <td class="dont-hide actions" style="white-space: nowrap;">
+ <? if (MvvPerm::havePermWrite($fach)) : ?>
+ <a href="<?= $controller->url_for('/fach/' . $fach->id) ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE, ['title' => _('Fach bearbeiten')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ <? if (MvvPerm::havePermCreate($fach)) : ?>
+ <? if ($fach->count_abschluesse == 0): ?>
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE, tooltip2(_('Fach löschen')))->asInput(
+ [
+ 'formaction' => $controller->url_for('/delete/' . $fach->id),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich das Fach "%s" löschen?'), htmlReady($fach->name)),
+ 'name' => 'delete'
+ ]); ?>
+ <? else : ?>
+ <?= Icon::create('trash', Icon::ROLE_INACTIVE, tooltip2(_('Fach kann nicht glöscht werden')))->asImg(); ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? if ($fach_id === $fach->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('fachabschluss/faecher/details', compact('fach')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach ?>
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="3" style="text-align: right;">
+ <?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_faecher=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render('shared/pagechooser');
+ ?>
+
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</form>
diff --git a/app/views/fachabschluss/kategorien/details.php b/app/views/fachabschluss/kategorien/details.php
new file mode 100644
index 0000000..5bcb954
--- /dev/null
+++ b/app/views/fachabschluss/kategorien/details.php
@@ -0,0 +1,16 @@
+<td colspan="4">
+ <table id="abschluesse_<?= $kategorie->id ?>" class="default sortable">
+ <? foreach ($kategorie->abschluesse as $abschluss) : ?>
+ <? if (count($perm_institutes) === 0
+ || array_intersect($perm_institutes, array_keys($abschluss->getAssignedInstitutes()))) : ?>
+ <tbody id="<?= $kategorie->id . '_' . $abschluss->id ?>"<?= MvvPerm::haveFieldPermPosition('AbschlussZuord', MvvPerm::PERM_WRITE) ? ' class="sort_items"' : '' ?>>
+ <tr class="header-row">
+ <td>
+ <?= htmlReady($abschluss->name) ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif; ?>
+ <? endforeach; ?>
+ </table>
+</td> \ No newline at end of file
diff --git a/app/views/fachabschluss/kategorien/index.php b/app/views/fachabschluss/kategorien/index.php
new file mode 100644
index 0000000..893f3ca
--- /dev/null
+++ b/app/views/fachabschluss/kategorien/index.php
@@ -0,0 +1,75 @@
+<?= $this->controller->jsUrl() ?>
+<form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <table id="abschluss_kategorien" class="default sortable collapsable">
+ <thead>
+ <tr>
+ <th>
+ <?= _('Name') ?>
+ </th>
+ <th style="text-align: center; width: 5%;">
+ <?= _('Abschlüsse') ?>
+ </th>
+ <th style="text-align: center; width: 5%;">
+ <?= _('Materialien') ?>
+ </th>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? if(count($abschluss_kategorien)) : ?>
+ <? foreach ($abschluss_kategorien as $kategorie) : ?>
+ <? $perm = MvvPerm::get($kategorie) ?>
+ <? $abschluesse = $kategorie->abschluesse; ?>
+ <tbody id="<?= $kategorie->id ?>"
+ class="<?= count($abschluesse) ? '' : 'empty' ?> collapsed<?= $perm->haveFieldPerm('position') ? ' sort_items' : '' ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <? if (count($abschluesse) < 1): ?>
+ <?= htmlReady($kategorie->name) ?>
+ <? else: ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details/' . $kategorie->id) ?>"><?= htmlReady($kategorie->name) ?> </a>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide" style="text-align: center;">
+ <?= $kategorie->count_abschluesse ?>
+ </td>
+ <td class="dont-hide" style="text-align: center;">
+ <?= $kategorie->count_dokumente ?>
+ </td>
+ <td style="white-space: nowrap;" class="dont-hide actions">
+ <? if ($perm->havePermWrite()) : ?>
+ <a href="<?= $controller->url_for('/kategorie/' . $kategorie->id) ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE, tooltip2(_('Abschluss-Kategorie bearbeiten')))->asImg(); ?>
+ </a>
+ <? endif; ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <? if (count($abschluesse) < 1) : ?>
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE, tooltip2(_('Abschluss-Kategorie löschen')))->asInput(
+ [
+ 'formaction' => $controller->url_for('/delete', $kategorie->id),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich die Abschluss-Kategorie "%s" löschen?'), htmlReady($kategorie->name)),
+ 'name' => 'delete'
+ ]); ?>
+ <? else : ?>
+ <?= Icon::create('trash', Icon::ROLE_INACTIVE, tooltip2(_('Löschen nicht möglich')))->asImg(); ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? if ($kategorie_id === $kategorie->id) : ?>
+ <?= $this->render_partial('fachabschluss/kategorien/details', compact('kategorie')) ?>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+ <? else : ?>
+ <tbody>
+ <tr>
+ <td colspan="4" style="text-align: center">
+ <?= _('Es wurden noch keine Abschluss-Kategorien angelegt.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif?>
+ </table>
+</form>
diff --git a/app/views/fachabschluss/kategorien/kategorie.php b/app/views/fachabschluss/kategorien/kategorie.php
new file mode 100644
index 0000000..2fa9efa
--- /dev/null
+++ b/app/views/fachabschluss/kategorien/kategorie.php
@@ -0,0 +1,59 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+<script>
+ STUDIP.MVV.PARENT_ID = '<?= $abschluss_kategorie->getId() ?>';
+ STUDIP.MVV.OBJECT_TYPE = 'AbschlussKategorie';
+</script>
+<? $perm = MvvPerm::get($abschluss_kategorie) ?>
+<form class="default"
+ action="<?= $controller->url_for('fachabschluss/kategorien/kategorie/' . $abschluss_kategorie->getId()) ?>"
+ method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset class="collapsable">
+ <legend><?= _('Grunddaten') ?></legend>
+ <label>
+ <?= _('Name') ?>
+ <?= MvvI18N::input(
+ 'name',
+ $abschluss_kategorie->name,
+ ['maxlength' => '255', 'required' => '']
+ )->checkPermission($abschluss_kategorie) ?>
+ <label>
+ <?= _('Kurzname') ?>
+ <?= MvvI18N::input(
+ 'name_kurz',
+ $abschluss_kategorie->name_kurz,
+ ['maxlength' => '50']
+ )->checkPermission($abschluss_kategorie) ?>
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <?= MvvI18N::textarea(
+ 'beschreibung',
+ $abschluss_kategorie->beschreibung, ['class' => 'add_toolbar ui-resizable wysiwyg']
+ )->checkPermission($abschluss_kategorie) ?>
+ </label>
+ </fieldset>
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Dokumente'); ?>
+ </legend>
+ <?= $this->render_partial('materialien/files/range', array('perm_dokumente' => $perm->haveFieldPerm('document_assignments', MvvPerm::PERM_CREATE))) ?>
+ </fieldset>
+ <footer data-dialog-buttons>
+ <? if ($abschluss_kategorie->isNew()) : ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Abschluss-Kategorie anlegen')]) ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('fachabschluss/kategorien'),
+ ['title' => _('zurück zur Übersicht')]
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/file/_file_aside.php b/app/views/file/_file_aside.php
new file mode 100644
index 0000000..47f33f3
--- /dev/null
+++ b/app/views/file/_file_aside.php
@@ -0,0 +1,62 @@
+<aside id="file_aside">
+ <div class="file-icon">
+ <?= $file->getIcon(Icon::ROLE_INFO) ?>
+ </div>
+
+ <table class="default nohover">
+ <caption><?= htmlReady($file->getFilename()) ?></caption>
+ <tbody>
+ <tr>
+ <td><?= _('Größe') ?></td>
+ <? $size = $file->getSize() ?>
+ <td><?= $size !== null ? relSize($file->getSize(), false) : "-" ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Downloads') ?></td>
+ <td><?= htmlReady($file->getDownloads()) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Erstellt') ?></td>
+ <td><?= date('d.m.Y H:i', $file->getMakeDate()) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Geändert') ?></td>
+ <td><?= date('d.m.Y H:i', $file->getLastChangeDate()) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Besitzer/-in') ?></td>
+ <td>
+ <? $user_id = $file->getUserId() ?>
+ <? if ($user_id) : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => get_username($user_id)]) ?>">
+ <?= htmlReady($file->getUserName()) ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($file->getUserName()) ?>
+ <? endif ?>
+ </td>
+ </tr>
+
+ <? $content_terms_of_use = $file->getTermsOfUse() ?>
+
+ <? if ($content_terms_of_use) : ?>
+ <tr>
+ <td colspan="2">
+ <h3><?=_('Hinweis zur Nutzung und Weitergabe:')?></h3>
+ <?= Icon::create($content_terms_of_use->icon, Icon::ROLE_INFO)->asImg(20) ?>
+ <article><?= htmlReady($content_terms_of_use->student_description) ?></article>
+
+ <? if ($content_terms_of_use->download_condition) : ?>
+ <h3><?= _('Bedingung zum Herunterladen') ?></h3>
+ <p>
+ <?= htmlReady(ContentTermsOfUse::describeCondition(
+ $content_terms_of_use->download_condition
+ )) ?>
+ </p>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+</aside>
diff --git a/app/views/file/_folder_aside.php b/app/views/file/_folder_aside.php
new file mode 100644
index 0000000..e6ef8ed
--- /dev/null
+++ b/app/views/file/_folder_aside.php
@@ -0,0 +1,37 @@
+<aside id="folder_aside">
+ <div class="folder-icon"><?= $folder->getIcon('info') ?></div>
+
+ <table class="default nohover">
+ <caption><?= htmlReady($folder->name) ?></caption>
+ <tbody>
+ <? if ($folder->mkdate) : ?>
+ <tr>
+ <td><?= _('Erstellt') ?></td>
+ <td><?= date('d.m.Y H:i', $folder->mkdate) ?></td>
+ </tr>
+ <? endif ?>
+ <? if ($folder->chdate) : ?>
+ <tr>
+ <td><?= _('Geändert') ?></td>
+ <td><?= date('d.m.Y H:i', $folder->chdate) ?></td>
+ </tr>
+ <? endif ?>
+ <tr>
+ <td><?= _('Besitzer/-in') ?></td>
+ <td>
+ <? if ($folder->owner): ?>
+ <?= htmlReady($folder->owner->getFullName()) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Anz. Dateien') ?></td>
+ <td><?= number_format($folder_file_amount, 0, ',', '.') ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Größe') ?></td>
+ <td><?= relsize($folder_size, false) ?></td>
+ </tr>
+ </tbody>
+ </table>
+</aside>
diff --git a/app/views/file/_terms_of_use_select.php b/app/views/file/_terms_of_use_select.php
new file mode 100644
index 0000000..525162f
--- /dev/null
+++ b/app/views/file/_terms_of_use_select.php
@@ -0,0 +1,49 @@
+<?php
+if (!$selected_terms_of_use_id) {
+ $selected_terms_of_use_id = ContentTermsOfUse::findDefault()->id;
+}
+?>
+<? if ($content_terms_of_use_entries) : ?>
+ <div style="margin-bottom: 1ex;">
+ <?= _('Bereitgestellte Dateien können heruntergeladen und ggf. weiterverbreitet werden.
+ Dabei ist das Urheberrecht sowohl beim Hochladen der Datei als auch bei der Nutzung
+ zu beachten. Bitte geben Sie daher an, um welche Art von Bereitstellung es sich handelt.
+ Diese Angabe dient mehreren Zwecken: Beim Herunterladen wird ein Hinweis angezeigt,
+ welche Nutzung der Datei zulässig ist. Beim Hochladen stellt die Angabe eine
+ Entscheidungshilfe dar, damit Sie sichergehen können, dass die Datei tatsächlich
+ bereitgestellt werden darf.') ?>
+ </div>
+ <fieldset class="select_terms_of_use">
+ <? foreach ($content_terms_of_use_entries as $content_terms_of_use_entry) : ?>
+ <input type="radio" name="content_terms_of_use_id"
+ value="<?= htmlReady($content_terms_of_use_entry->id) ?>"
+ id="content_terms_of_use-<?= htmlReady($content_terms_of_use_entry->id) ?>"
+ <? if ($content_terms_of_use_entry->id == $selected_terms_of_use_id) echo 'checked'; ?>>
+
+ <label for="content_terms_of_use-<?= htmlReady($content_terms_of_use_entry->id) ?>">
+ <div class="icon">
+ <? if ($content_terms_of_use_entry['icon']) : ?>
+ <? if (filter_var($content_terms_of_use_entry['icon'], FILTER_VALIDATE_URL)): ?>
+ <img src="<?= htmlReady($content_terms_of_use_entry['icon']) ?>" width="32" height="32">
+ <? else : ?>
+ <?= Icon::create($content_terms_of_use_entry['icon'], Icon::ROLE_CLICKABLE)->asImg(32) ?>
+ <? endif ?>
+ <? endif ?>
+ </div>
+ <div class="text">
+ <?= htmlReady($content_terms_of_use_entry->name) ?>
+ </div>
+ <?= Icon::create('arr_1down', Icon::ROLE_CLICKABLE)->asImg(24, ['class' => 'arrow']) ?>
+ <?= Icon::create('check-circle', Icon::ROLE_CLICKABLE)->asImg(32, ['class' => 'check']) ?>
+ </label>
+
+ <? if (trim($content_terms_of_use_entry->description)): ?>
+ <div class="terms_of_use_description">
+ <div class="description">
+ <?= formatReady($content_terms_of_use_entry->description ?: _('Keine Beschreibung')) ?>
+ </div>
+ </div>
+ <? endif ?>
+ <? endforeach ?>
+ </fieldset>
+<? endif; ?>
diff --git a/app/views/file/add_files_window.php b/app/views/file/add_files_window.php
new file mode 100644
index 0000000..bdfbca5
--- /dev/null
+++ b/app/views/file/add_files_window.php
@@ -0,0 +1,100 @@
+<?php
+$options = [];
+if (Request::get('to_plugin')) {
+ $options['to_plugin'] = Request::get('to_plugin');
+}
+if (Request::get('from_plugin')) {
+ $options['from_plugin'] = Request::get('from_plugin');
+}
+if (Request::get('to_folder_id')) {
+ $options['to_folder_id'] = Request::get('to_folder_id');
+}
+if ($folder_id) {
+ $options['to_folder_id'] = $folder_id;
+}
+
+?>
+<div class="files_source_selector" data-folder_id="<?= htmlReady($folder_id) ?>" <? if ($hidden) echo ' style="display: none;"'; ?>>
+ <h2 class="dialog-subtitle"><?= _('Quelle auswählen') ?></h2>
+ <div class="file_select_possibilities">
+ <? if (($range instanceof Course) && !$range->getSemClass()['studygroup_mode'] && $GLOBALS['perm']->have_studip_perm('tutor', $range->id) && $GLOBALS['LIBRARY_CATALOGS'] && $show_library_functions) : ?>
+ <div>
+ <a class="important-item" data-dialog="size=medium-43"
+ href="<?= $controller->link_for('file/add_from_library/' . $folder_id)?>">
+ <div class="icon">
+ <?= Icon::create('literature')->asImg(50) ?>
+ <div><?= _('Bibliothek') ?></div>
+ </div>
+ <div class="description">
+ <strong><?= _('Originaldokument aus Bibliotheksverzeichnissen einbinden') ?></strong>
+ <div><?= htmlReady($library_search_description) ?></div>
+ </div>
+ </a>
+ </div>
+ <? endif ?>
+ <div>
+ <a href="#" onclick="jQuery('.file_selector input[type=file]').first().click(); return false;">
+ <?= Icon::create('computer')->asImg(50) ?>
+ <?= _('Mein Computer') ?>
+ </a>
+ <a href="<?= $controller->link_for('file/add_url/' . $folder_id, array_merge($options, ['from_plugin' => ""])) ?>" data-dialog>
+ <?= Icon::create('globe')->asImg(50) ?>
+ <?= _('Webadresse') ?>
+ </a>
+ <a href="<?= $controller->link_for('file/choose_file/' . Folder::findTopFolder($GLOBALS['user']->id)->getId(), array_merge($options, ['from_plugin' => ""])) ?>" data-dialog>
+ <?= Icon::create('files')->asImg(50) ?>
+ <?= _('Persönlicher Dateibereich') ?>
+ </a>
+ <a href="<?= $controller->link_for('file/choose_file_from_course/' . htmlReady($folder_id), array_merge($options, ['from_plugin' => ""])) ?>" data-dialog>
+ <?= Icon::create('seminar')->asImg(50) ?>
+ <?= _('Meine Veranstaltungen') ?>
+ </a>
+ <? if (($range instanceof Course) && $GLOBALS['perm']->have_studip_perm('tutor', $range->id) && $show_library_functions) : ?>
+ <a href="<?= $controller->link_for('library_file/select_type/' . htmlReady($folder_id)) ?>"
+ data-dialog="size=auto">
+ <?= Icon::create('literature')->asImg(50) ?>
+ <?= _('Literatur') ?>
+ </a>
+ <? endif ?>
+ <? if (Config::get()->OERCAMPUS_ENABLED && $GLOBALS['perm']->have_perm(Config::get()->OERCAMPUS_PUBLIC_STATUS)) : ?>
+ <a href="<?= $controller->link_for('oer/addfile/choose_file', array_merge($options, ['from_plugin' => ""])) ?>"
+ data-dialog="height=800">
+ <?= Icon::create('service', Icon::ROLE_CLICKABLE)->asImg(50) ?>
+ <?= htmlReady(Config::get()->OER_TITLE) ?>
+ </a>
+ <? endif ?>
+ <? foreach (PluginManager::getInstance()->getPlugins('FilesystemPlugin') as $plugin) : ?>
+ <? if ($plugin->isSource()) : ?>
+ <? $nav = $plugin->getFileSelectNavigation() ?>
+ <? if ($nav): ?>
+ <a href="<?= $controller->link_for('file/choose_file/', array_merge($options, ['from_plugin' => get_class($plugin)])) ?>" data-dialog>
+ <?= $nav->getImage()->asImg(50) ?>
+ <?= htmlReady($nav->getTitle()) ?>
+ </a>
+ <? endif; ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </div>
+ </div>
+ <div>
+ <?=sprintf(_('Sie dürfen Dateien bis zu einer Größe von %s in diesem Bereich einstellen.'), '<b>' . relsize($upload_type['file_size']) . '</b>')?>
+ </div>
+ <? if (count($upload_type['file_types']) && $upload_type['type'] == 'allow') : ?>
+ <div>
+ <?=sprintf(_('Sie dürfen die Dateitypen %s nicht hochladen!'), '<b>' . join(',', $upload_type['file_types']) . '</b>')?>
+ </div>
+ <? endif ?>
+ <? if (count($upload_type['file_types']) && $upload_type['type'] == 'deny') : ?>
+ <div>
+ <?=sprintf(_('Sie dürfen nur die Dateitypen %s hochladen!'), '<b>' . join(',', $upload_type['file_types']) . '</b>')?>
+ </div>
+ <? endif ?>
+ <form style="display: none;" class="file_selector">
+
+ <input type="file" name="files[]" multiple onchange="STUDIP.Files.upload(this.files);">
+ </form>
+</div>
+
+<div style="display: none;">
+ <?= _('Soll die hochgeladene ZIP-Datei entpackt werden?') ?>
+</div>
diff --git a/app/views/file/add_from_library.php b/app/views/file/add_from_library.php
new file mode 100644
index 0000000..12291da
--- /dev/null
+++ b/app/views/file/add_from_library.php
@@ -0,0 +1,177 @@
+<? if ($search_id && !$result_set) : ?>
+ <? if ($library_plugins) : ?>
+ <?= MessageBox::info(_('Zu Ihrer Suche wurden keine Ergebnisse gefunden! Sie können ihre letzte Suchanfrage mit einer Mitteilung an die Bibliothek zur Klärung und Anfrage von Unterstützung senden.')) ?>
+ <? else : ?>
+ <?= MessageBox::info(_('Zu Ihrer Suche wurden keine Ergebnisse gefunden!')) ?>
+ <? endif ?>
+ <p>
+ <?= _('Sie können ihre letzte Suchanfrage mit einer Mitteilung an die Bibliothek zur Klärung und Anfrage von Unterstützung senden.')?>
+ </p>
+<? endif ?>
+<form class="default" method="post" data-dialog="size=medium-43"
+ action="<?= $controller->link_for('file/add_from_library/' . $folder_id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Dokument in Bibliothek suchen') ?></legend>
+ <div class="form-columns">
+ <div class="column">
+ <label>
+ <?= _('Titel') ?>
+ <input type="text" name="title" value="<?= htmlReady($title) ?>">
+ </label>
+ <label>
+ <?= _('Autor') ?>
+ <input type="text" name="author" value="<?= htmlReady($author) ?>">
+ </label>
+ <label>
+ <?= _('Jahr') ?>
+ <input type="text" name="year" value="<?= htmlReady($year) ?>">
+ </label>
+ </div>
+ <div class="column">
+ <label>
+ <?= _('Nummer (ISBN/ISSN/...)') ?>
+ <input type="text" name="number" value="<?= htmlReady($number) ?>">
+ </label>
+ <label>
+ <?= _('Zeitschrift') ?>
+ <input type="text" name="publication" value="<?= htmlReady($publication) ?>">
+ </label>
+ <label>
+ <?= _('Signatur') ?>
+ <input type="text" name="signature" value="<?= htmlReady($signature) ?>">
+ </label>
+ </div>
+ </div>
+ <label>
+ <input type="radio" name="order_by" value="relevance"
+ <?= $order_by == LibrarySearch::ORDER_BY_RELEVANCE
+ ? 'checked="checked"' : '' ?>>
+ <?= _('Sortierung nach Relevanz') ?>
+ </label>
+ <label>
+ <input type="radio" name="order_by" value="year"
+ <?= $order_by == LibrarySearch::ORDER_BY_YEAR
+ ? 'checked="checked"' : '' ?>>
+ <?= _('Sortierung nach Jahr') ?>
+ </label>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Suchen'), 'search') ?>
+ </div>
+ </fieldset>
+</form>
+<? if ($result_set): ?>
+ <? $last_result_number = (($page + 1) * $page_size);
+ if ($last_result_number > $total_results) {
+ $last_result_number = $total_results;
+ }
+ ?>
+ <h2 class="search-result-info">
+ <?= sprintf(
+ _('Ihre Suchergebnisse (%1$d - %2$d von %3$d)'),
+ ($page * $page_size) + 1,
+ $last_result_number,
+ $total_results
+ ) ?>
+ </h2>
+ <form class="default" method="post" data-dialog="size=medium-43"
+ action="<?= $controller->link_for('file/add_from_library/' . $folder_id) ?>">
+ <? foreach ($result_set as $result) : ?>
+ <?
+ $result_id = $result->getId();
+ ?>
+ <input type="radio" name="result_id" value="<?= htmlReady($result_id) ?>"
+ id="result_<?= htmlReady($result_id) ?>"
+ class="hidden-checkbox">
+ <label for="result_<?= htmlReady($result_id) ?>">
+ <section class="contentbox">
+ <header>
+ <span class="title no-overflow"><?= $result->getIcon()->asImg() ?> <?= $result->getTitle('long-comma') ?></span>
+ <nav>
+ <?= Icon::create('accept', 'status-green')->asImg(
+ 20,
+ ['class' => 'hidden-checkbox-checked-icon']
+ ) ?>
+ </nav>
+ </header>
+ <section class="hidden-content">
+ <dl>
+ <dt><?= _('Titel') ?></dt>
+ <dd><?= htmlReady($result->getTitle()) ?></dd>
+ <dt><?= _('Typ') ?></dt>
+ <dd><?= htmlReady($result->getType('display_name')) ?></dd>
+ <? if ($result->csl_data['issued'] || $result->csl_data['publisher']) : ?>
+ <dt><?= _('Veröffentlicht') ?></dt>
+ <dd><?= htmlReady($result->csl_data['publisher'] . ' ' . $result->getIssueDate(true)) ?></dd>
+ <? endif ?>
+ <? if (!empty($result->csl_data['medium'])) : ?>
+ <dt><?= _('Medium') ?></dt>
+ <dd><?= htmlReady($result->csl_data['medium']) ?></dd>
+ <? endif ?>
+ <? if ($result->csl_data['author']) : ?>
+ <dt><?= _('Erstellt von') ?></dt>
+ <dd><?= htmlReady($result->getAuthorNames()) ?></dd>
+ <? endif ?>
+ <? if (!empty($result->csl_data['URL'])) : ?>
+ <dt><?= _('URL') ?></dt>
+ <dd><a target="_blank" href="<?= htmlReady($result->csl_data['URL']) ?>"><?= htmlReady($result->csl_data['URL']) ?></a></dd>
+ <? endif ?>
+ <? if ($result->catalog) : ?>
+ <dt><?= _('Katalog') ?></dt>
+ <? if ($result->opac_link) : ?>
+ <dd><a target="_blank" title="<?=_('Im OPAC anzeigen')?>" href="<?=$result->opac_link?>"><?= htmlReady($result->catalog) ?></a></dd>
+ <? else : ?>
+ <dd><?= htmlReady($result->catalog) ?></dd>
+ <? endif ?>
+ <? endif ?>
+ </dl>
+ <? if ($result->csl_data['abstract']) : ?>
+ <div><?= htmlReady($result->csl_data['abstract']) ?></div>
+ <? endif ?>
+ </section>
+ </section>
+ </label>
+ <? endforeach ?>
+ <?= Pagination::create(
+ $total_results, $page, $page_size
+ )->asDialog('size=medium-43')->asLinks($pagination_link_closure) ?>
+ <div data-dialog-button>
+ <input type="hidden" name="search_id"
+ value="<?= htmlReady($search_id) ?>">
+ <?= \Studip\Button::create(
+ _('Zum Dateibereich hinzufügen'),
+ 'add_to_file_area'
+ ) ?>
+ <? if ($library_plugins) : ?>
+ <? $plugin = $library_plugins[0] ?>
+ <input type="hidden" name="plugin_id"
+ value="<?= htmlReady($plugin->getPluginId()) ?>">
+ <?= \Studip\Button::create(
+ _('Bibliotheksanfrage erstellen'),
+ 'create_library_request'
+ ) ?>
+ <? endif ?>
+ </div>
+ </form>
+<? endif ?>
+<? if ($library_plugins) : ?>
+ <section class="big-help-box">
+ <?= Icon::create('support')->asImg(96, ['class' => 'icon']) ?>
+ <div class="text">
+ <strong><?= _('Passendes Dokument nicht gefunden?') ?></strong>
+ <p><?= _('Gerne unterstützen wir Sie bei der Suche nach Dokumenten.') ?></p>
+ <form class="default" method="post" data-dialog="size=medium-43"
+ action="<?= $controller->link_for('file/add_from_library/' . $folder_id) ?>">
+ <? $plugin = $library_plugins[0] ?>
+ <input type="hidden" name="search_id"
+ value="<?= htmlReady($search_id) ?>">
+ <input type="hidden" name="plugin_id"
+ value="<?= htmlReady($plugin->getPluginId()) ?>">
+ <?= \Studip\Button::create(
+ _('Bibliotheksanfrage erstellen'),
+ 'create_library_request'
+ ) ?>
+ </form>
+ </div>
+ </section>
+<? endif ?>
diff --git a/app/views/file/add_url.php b/app/views/file/add_url.php
new file mode 100644
index 0000000..620a1a5
--- /dev/null
+++ b/app/views/file/add_url.php
@@ -0,0 +1,43 @@
+<form action="<?= $controller->link_for('/add_url/' . $top_folder->id) ?>" method="post" data-dialog class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Datei aus dem Internet verlinken') ?></legend>
+ <label>
+ <?= _('Webadresse') ?>
+ <input type="text" name="url" placeholder="https://..." required
+ value="<?= htmlReady(Request::get('url')) ?>">
+ </label>
+ <label>
+ <?= _('Gewünschter Dateiname') ?>
+ <input type="text" name="name" placeholder="<?= _('Beispielname.pdf') ?>"
+ value="<?= htmlReady(Request::get('name')) ?>">
+ </label>
+
+ <label>
+ <?= _('Zugriffsart') ?>
+ </label>
+ <label>
+ <input type="radio" name="access_type" value="redirect"
+ <? if (Request::option('access_type') !== 'proxy') echo 'checked'; ?>>
+ <?= _('Direktlink')?>
+ </label>
+ <label>
+ <input type="radio" name="access_type" value="proxy"
+ <? if (Request::option('access_type') === 'proxy') echo 'checked'; ?>>
+ <?= _('Link über Proxy')?>
+ </label>
+ <?= $this->render_partial('file/_terms_of_use_select.php', [
+ 'content_terms_of_use_entries' => $content_terms_of_use_entries,
+ 'selected_terms_of_use_id' => $content_terms_of_use_id,
+ ]) ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Zurück'),
+ $controller->url_for('/add_files_window/' . Request::option('to_folder_id'), $options),
+ ['data-dialog' => '']
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/file/choose_destination.php b/app/views/file/choose_destination.php
new file mode 100644
index 0000000..ae3f808
--- /dev/null
+++ b/app/views/file/choose_destination.php
@@ -0,0 +1,100 @@
+<?php
+$options = array_filter([
+ 'from_plugin' => Request::get('from_plugin'),
+ 'to_folder_id' => Request::get('to_folder_id'),
+ 'copymode' => Request::get('copymode', $copymode),
+ 'isfolder' => Request::get('isfolder'),
+ 'fileref_id' => Request::getArray('fileref_id') ?: $fileref_id,
+ 'direct_parent' => true,
+], function ($value) {
+ return $value !== null;
+});
+?>
+
+<form action="#" method="post" class="files_source_selector" data-dialog <? if ($hidden) echo ' style="display: none;"'; ?>>
+ <input type="hidden" name="webkitbugfix" value="1">
+<? foreach ($options as $key => $value): ?>
+ <?= addHiddenFields($key, $value) ?>
+<? endforeach; ?>
+
+<? if ($options['copymode'] === 'move') : ?>
+ <?= _('Ziel zum Verschieben auswählen') ?>
+<? elseif ($options['copymode'] === 'copy') : ?>
+ <?= _('Ziel zum Kopieren auswählen') ?>
+<? elseif ($options['copymode'] === 'upload') : ?>
+ <?= _('Wohin soll hochgeladen werden?') ?>
+<? endif ?>
+
+ <div class="file_select_possibilities">
+ <div>
+ <? if (isset($parent_folder) && ($parent_folder->isWritable($GLOBALS['user']->id) || count($parent_folder->getSubfolders()))): ?>
+ <div class="clickable">
+ <?= Icon::create('folder-parent', Icon::ROLE_CLICKABLE)->asInput(50, ['formaction' => $controller->url_for('/choose_folder/' . $parent_folder->getId()), 'to_plugin' => $options['from_plugin']]) ?>
+ <button
+ class="undecorated"
+ formaction="<?= $controller->link_for('/choose_folder/' . $parent_folder->getId()) ?>" <? if ($options['from_plugin']): ?> name="to_plugin" value="<?= htmlReady($options['from_plugin']) ?>"<? endif; ?>>
+ <?= _('Aktueller Ordner') ?>
+ </button>
+ </div>
+ <? endif ?>
+ <div class="clickable">
+ <?= Icon::create('files')->asInput(50, ['formaction' => $controller->url_for('/choose_folder/' . Folder::findTopFolder($GLOBALS['user']->id)->getId())]) ?>
+ <button
+ class="undecorated"
+ formaction="<?= $controller->link_for('/choose_folder/' . Folder::findTopFolder($GLOBALS['user']->id)->getId()) ?>">
+
+ <?= _('Persönlicher Dateibereich') ?>
+ </button>
+ </div>
+
+ <div class="clickable">
+ <?= Icon::create('seminar')->asinput(50, ['formaction' => $controller->url_for('/choose_folder_from_course')]) ?>
+ <button class="undecorated"
+ formaction="<?= $controller->link_for('/choose_folder_from_course') ?>">
+ <?= _('Meine Veranstaltungen') ?>
+ </button>
+ </div>
+
+ <div class="clickable">
+ <?= Icon::create('institute')->asInput(50, ['formaction' => $controller->url_for('/choose_folder_from_institute')]) ?>
+ <button class="undecorated"
+ formaction="<?= $controller->link_for('/choose_folder_from_institute') ?>">
+ <?= _('Meine Einrichtungen') ?>
+ </button>
+ </div>
+
+ <? foreach (PluginManager::getInstance()->getPlugins('FilesystemPlugin') as $plugin) : ?>
+ <? if ($plugin->isPersonalFileArea()) : ?>
+ <? $nav = $plugin->getFileSelectNavigation() ?>
+ <? if ($nav) : ?>
+ <div class="clickable">
+ <?= $nav->getImage()->asInput(50, ['formaction' => $controller->url_for('/choose_folder'), 'name' => 'to_plugin', 'value' => get_class($plugin)]) ?>
+ <button formaction="<?= $controller->link_for('/choose_folder') ?>"
+ type="submit"
+ class="undecorated"
+ name="to_plugin"
+ value="<?= htmlReady(get_class($plugin)) ?>">
+ <?= htmlReady($nav->getTitle()) ?>
+ </button>
+ </div>
+ <? endif ?>
+ <? endif ?>
+ <? endforeach ?>
+ </div>
+ </div>
+
+
+<? if (!Request::isDialog()) : ?>
+ <?
+ if ($parent_folder) {
+ $cancelUrl = (in_array($parent_folder->range_type, ['course', 'institute']) ? $parent_folder->range_type . '/' : '') . 'files/index/' . $parent_folder->getId();
+ } else {
+ $cancelUrl = 'files_dashboard';
+ }
+ ?>
+
+ <div>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for($cancelUrl)) ?>
+ </div>
+<? endif ?>
+</form>
diff --git a/app/views/file/choose_file.php b/app/views/file/choose_file.php
new file mode 100644
index 0000000..4cf0e47
--- /dev/null
+++ b/app/views/file/choose_file.php
@@ -0,0 +1,177 @@
+<?php
+$options = [];
+if (Request::get('from_plugin')) {
+ $options['from_plugin'] = Request::get('from_plugin');
+}
+if (Request::get('to_plugin')) {
+ $options['to_plugin'] = Request::get('to_plugin');
+}
+if (Request::get('to_folder_id')) {
+ $options['to_folder_id'] = Request::get('to_folder_id');
+}
+?>
+
+<div style="text-align: center; margin-bottom: 20px;">
+ <?= _('Kopieren nach') ?>
+ <?= Icon::create('folder-full', Icon::ROLE_INFO)->asImg(20, ['class' => 'text-bottom']) ?>
+ <?= htmlReady($to_folder_name) ?>
+</div>
+
+<? if ($filesystemplugin && $filesystemplugin->hasSearch()) : ?>
+ <form action="<?= $controller->url_for('file/choose_file/' . $top_folder->parent_id) ?>" class="default" data-dialog style="margin-bottom: 50px;" id="file_search">
+ <? foreach ($options as $key => $value) : ?>
+ <input type="hidden" name="<?= htmlReady($key) ?>" value="<?= htmlReady($value) ?>">
+ <? endforeach; ?>
+ <? $request_parameter = Request::getArray('parameter') ?>
+ <input type="text" name="search" value="<?= htmlReady(Request::get('search')) ?>"
+ placeholder="<?= _('Suche nach ...') ?>" style="max-width: 100%">
+
+ <? foreach ((array) $filesystemplugin->getSearchParameters() as $parameter) : ?>
+ <label>
+ <? if ($parameter['type'] === 'text'): ?>
+ <?= htmlReady($parameter['label']) ?>
+ <input type="text" name="parameter[<?= htmlReady($parameter['name']) ?>]"
+ value="<?= htmlReady($request_parameter[$parameter['name']]) ?>"
+ placeholder="<?= htmlReady($parameter['placeholder']) ?>">
+ <? elseif ($parameter['type'] === 'select'): ?>
+ <?= htmlReady($parameter['label']) ?>
+ <select name="parameter[<?= htmlReady($parameter['name']) ?>]">
+ <? foreach ($parameter['options'] as $index => $option) : ?>
+ <option value="<?= htmlReady($index) ?>" <? if ($index === $request_parameter[$parameter['name']]) echo 'selected'; ?>>
+ <?= htmlReady($option) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? elseif ($parameter['type'] === 'checkbox'): ?>
+ <input type="checkbox" name="parameter[<?= htmlReady($parameter['name']) ?>]" value="1"
+ <? if ($request_parameter[$parameter['name']]) echo 'checked'; ?>>
+ <?= htmlReady($parameter['label']) ?>
+ <? endif; ?>
+ </label>
+ <? endforeach; ?>
+ </form>
+
+<? endif; ?>
+
+<? if ($top_folder): ?>
+<table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Name') ?></th>
+ </tr>
+ </thead>
+<? if ($top_folder->parent_id && ($top_folder->parent_id !== $top_folder->id)) : ?>
+ <tbody>
+ <tr>
+ <td colspan="2">
+ <a href="<?= $controller->url_for('file/choose_file/' . $top_folder->parent_id, $options) ?>" title="<?= _('Ein Verzeichnis nach oben wechseln') ?>" data-dialog>
+ <?= _('Ein Verzeichnis nach oben wechseln') ?>
+ </a>
+ </td>
+ </tr>
+ </tbody>
+<? endif ?>
+<? if (count($top_folder->getSubfolders()) + count($top_folder->getFiles()) === 0): ?>
+ <tbody>
+ <tr>
+ <td colspan="2" class="empty">
+ <?= _('Dieser Ordner ist leer') ?>
+ </td>
+ </tr>
+ </tbody>
+<? else : ?>
+ <tbody>
+ <? foreach ($top_folder->getSubfolders() as $subfolder) : ?>
+ <? if (!$subfolder->isVisible($GLOBALS['user']->id)) continue; ?>
+ <tr>
+ <td class="document-icon" data-sort-value="0">
+ <? if ($subfolder->isReadable($GLOBALS['user']->id)) : ?>
+ <a href="<?= $controller->link_for('file/choose_file/' . $subfolder->id, $options) ?>" data-dialog>
+ <? endif ?>
+ <? if ($is_empty): ?>
+ <?= Icon::create('folder-empty')->asImg(24) ?>
+ <? else: ?>
+ <?= Icon::create('folder-full')->asImg(24) ?>
+ <? endif; ?>
+ <? if ($subfolder->isReadable($GLOBALS['user']->id)) : ?>
+ </a>
+ <? endif ?>
+ </td>
+ <td>
+ <? if ($subfolder->isReadable($GLOBALS['user']->id)) : ?>
+ <a href="<?= $controller->link_for('file/choose_file/' . $subfolder->id, $options) ?>" data-dialog>
+ <?= htmlReady($subfolder->name) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($subfolder->name) ?>
+ <? endif ?>
+ <? if ($subfolder->description): ?>
+ <small class="responsive-hidden"><?= htmlReady($subfolder->description) ?></small>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <? if (count($top_folder->getFiles())) : ?>
+ <tbody>
+ <? foreach ($top_folder->getFiles() as $file) : ?>
+ <tr>
+ <td class="document-icon" data-sort-value="1">
+ <? if ($file->isDownloadable()): ?>
+ <form action="<?= $controller->link_for('file/choose_file/' . $top_folder->id, $options) ?>" method="post" data-dialog>
+ <input type="hidden" name="file_id" value="<?= htmlReady($file->getId()) ?>">
+ <a href="#" onclick="jQuery(this).closest('form').submit(); return false;">
+ <?= FileManager::getIconForMimeType($file->getMimetype())->asImg(24) ?>
+ </a>
+ </form>
+ <? else: ?>
+ <?= FileManager::getIconForMimeType($file->getMimetype(), Icon::ROLE_INACTIVE)->asImg(24) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <? if ($file->isDownloadable()) : ?>
+ <form action="<?= $controller->link_for('file/choose_file/' . $top_folder->id, $options) ?>" method="post" data-dialog>
+ <input type="hidden" name="file_id" value="<?= htmlReady($file->getId()) ?>">
+ <a href="#" onclick="jQuery(this).closest('form').submit(); return false;">
+ <?= htmlReady($file->getFilename()) ?>
+ <? if ($file->getDescription()) : ?>
+ <div style="color: grey; font-size: 0.8em;"><?= htmlReady($file->getDescription()) ?></div>
+ <? endif ?>
+ </a>
+ </form>
+ <? else: ?>
+ <?= htmlReady($file->getFilename()) ?>
+ <? if ($file->getDescription()): ?>
+ <div style="color: grey; font-size: 0.8em;"><?= htmlReady($file->getDescription()) ?></div>
+ <? endif ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <? endif ?>
+<? endif ?>
+</table>
+<? endif ?>
+
+<?php
+$options = [];
+if (Request::get('to_plugin')) {
+ $options['to_plugin'] = Request::get('to_plugin');
+}
+?>
+<footer data-dialog-button>
+ <?= Studip\LinkButton::create(
+ _('Zurück'),
+ $controller->url_for('/add_files_window/' . Request::get('to_folder_id'), $options),
+ ['data-dialog' => 1]
+ ) ?>
+<? if ($filesystemplugin && $filesystemplugin->hasSearch()) : ?>
+ <?= Studip\Button::create(
+ _('Suche starten'),
+ 'startsearch',
+ ['form' => 'file_search']
+ ) ?>
+<? endif ?>
+</footer>
diff --git a/app/views/file/choose_file_from_course.php b/app/views/file/choose_file_from_course.php
new file mode 100644
index 0000000..a018497
--- /dev/null
+++ b/app/views/file/choose_file_from_course.php
@@ -0,0 +1,66 @@
+<?php
+$options = [];
+if (Request::get('to_plugin')) {
+ $options['to_plugin'] = Request::get('to_plugin');
+}
+if (Request::get('from_plugin')) {
+ $options['from_plugin'] = Request::get('from_plugin');
+}
+if (Request::get('range_type')) {
+ $options['range_type'] = Request::get('range_type');
+}
+?>
+
+<? if ($GLOBALS['perm']->have_perm('admin')) : ?>
+ <form id="filechooser_course_search"
+ action="<?= $controller->link_for('file/choose_file_from_course/' . $folder_id) ?>"
+ data-dialog>
+ <?= QuickSearch::get('course_id', new StandardSearch('AnySeminar_id'))
+ ->fireJSFunctionOnSelect("function () { jQuery('#filechooser_course_search').submit(); }")
+ ->setInputStyle('width: calc(100% - 40px); margin: 20px;')
+ ->render() ?>
+ </form>
+<? else : ?>
+ <table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Bild') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Semester') ?></th>
+ <th class="actions"><?= _('Zum Dateibereich') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($courses as $course) : ?>
+ <tr>
+ <td class="avatar">
+ <a href="<?= $controller->link_for('file/choose_file_from_course/' . $folder_id, array_merge($options, ['course_id' => $course->id])) ?>" data-dialog>
+ <?= CourseAvatar::getAvatar($course->id)->getImageTag(Avatar::MEDIUM, ['style' => 'width: 50px; height: 50px;']) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for('file/choose_file_from_course/' . $folder_id, array_merge($options, ['course_id' => $course->id])) ?>" data-dialog>
+ <?= htmlReady($course->getFullname()) ?>
+ </a>
+ </td>
+ <td>
+ <?= htmlReady($course->start_semester->name) ?>
+ </td>
+ <td class="actions">
+ <a href="<?= $controller->link_for('file/choose_file_from_course/' . $folder_id, array_merge($options, ['course_id' => $course->id])) ?>" data-dialog>
+ <?= Icon::create('folder-full', Icon::ROLE_CLICKABLE)->asImg(30) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+<? endif; ?>
+
+<footer data-dialog-button>
+ <?= Studip\LinkButton::create(
+ _('Zurück'),
+ $controller->url_for('/add_files_window/' . Request::get('to_folder_id'), $options),
+ ['data-dialog' => '']
+ ) ?>
+</footer>
diff --git a/app/views/file/choose_folder.php b/app/views/file/choose_folder.php
new file mode 100644
index 0000000..f76f27e
--- /dev/null
+++ b/app/views/file/choose_folder.php
@@ -0,0 +1,211 @@
+<?php
+$options = array_filter([
+ 'to_plugin' => Request::get('to_plugin'),
+ 'from_plugin' => Request::get('from_plugin'),
+ 'fileref_id' => Request::getArray('fileref_id'),
+ 'isfolder' => Request::get('isfolder'),
+ 'copymode' => Request::get('copymode'),
+], function ($value) {
+ return $value !== null;
+});
+
+$headings = [
+ 'copy' => _('Kopieren nach'),
+ 'move' => _('Verschieben nach'),
+ 'upload' => _('Hochladen nach'),
+];
+$buttonLabels = [
+ 'copy' => _('Hierher kopieren'),
+ 'move' => _('Hierher verschieben'),
+ 'upload' => _('Hierher hochladen'),
+];
+?>
+
+<div style="text-align: center; margin-bottom: 20px;">
+ <?= $headings[$options['copymode']] ?>
+ <?= Icon::create('folder-full', Icon::ROLE_INFO)->asImg(20, ['class' => 'text-bottom']) ?>
+ <?= htmlReady($top_folder_name) ?>
+</div>
+
+<? /*if ($filesystemplugin && $filesystemplugin->hasSearch()) : ?>
+ <form action="<?= $controller->url_for('/choose_file/' . $top_folder->parent_id) ?>" method="get" class="default" style="margin-bottom: 50px;">
+ <? foreach ($options as $key => $value) : ?>
+ <input type="hidden" name="<?= htmlReady($key) ?>" value="<?= htmlReady($value) ?>">
+ <? endforeach ?>
+ <? $request_parameter = Request::getArray("parameter") ?>
+ <input type="text" name="search" value="<?= htmlReady(Request::get("search")) ?>" placeholder="<?= _("Suche nach ...") ?>" style="max-width: 100%;">
+
+ <? foreach ((array) $filesystemplugin->getSearchParameters() as $parameter) : ?>
+ <label>
+ <? switch ($parameter['type']) {
+ case "text": ?>
+ <?= htmlReady($parameter['label']) ?>
+ <input type="text" name="parameter[<?= htmlReady($parameter['name']) ?>]" value="<?= htmlReady($request_parameter[$parameter['name']]) ?>" placeholder="<?= htmlReady($parameter['placeholder']) ?>">
+ <? break ?>
+ <? case "select": ?>
+ <?= htmlReady($parameter['label']) ?>
+ <select name="parameter[<?= htmlReady($parameter['name']) ?>]">
+ <? foreach ($parameter['options'] as $index => $option) : ?>
+ <option value="<?= htmlReady($index) ?>"<?= ($index === $request_parameter[$parameter['name']] ? " selected" : "") ?>><?= htmlReady($option) ?></option>
+ <? endforeach ?>
+ </select>
+ <? break ?>
+ <? case "checkbox": ?>
+ <input type="checkbox" name="parameter[<?= htmlReady($parameter['name']) ?>]" value="1"<?= $request_parameter[$parameter['name']] ? " checked" : "" ?>>
+ <?= htmlReady($parameter['label']) ?>
+ <? break ?>
+ <? } ?>
+ </label>
+ <? endforeach ?>
+ </form>
+
+<? endif*/ ?>
+
+<form action="#" method="post">
+<? foreach ($options as $key => $value): ?>
+ <?= addHiddenFields($key, $value) ?>
+<? endforeach; ?>
+
+<? if ($top_folder) : ?>
+ <table class="default">
+ <thead>
+ <tr>
+ <th width="25px"><?= _('Typ') ?></th>
+ <th><?= _('Name') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (($top_folder->parent_id || $top_folder instanceof VirtualFolderType) && $top_folder->parent_id !== $top_folder->getId()) : ?>
+ <tr>
+ <td colspan="2">
+ <!-- neu -->
+ <button formaction="<?= $controller->link_for('/choose_folder/' . $top_folder->parent_id) ?>" class="undecorated" data-dialog>
+ <small><?= _('Ein Verzeichnis nach oben wechseln') ?></small>
+ </button>
+ </td>
+ </tr>
+ <? endif ?>
+ <? if ($top_folder->is_empty): ?>
+ <tr>
+ <td colspan="2" class="empty">
+ <?= _('Dieser Ordner ist leer') ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($top_folder->getSubfolders() as $subfolder) : ?>
+ <? if (!$subfolder->isVisible($GLOBALS['user']->id)) continue; ?>
+ <? if ($subfolder->isWritable($GLOBALS['user']->id)): ?>
+ <tr>
+ <td class="document-icon" data-sort-value="0">
+ <!-- neu -->
+ <button formaction="<?= $controller->link_for('/choose_folder/' . $subfolder->getId()) ?>" class="undecorated" data-dialog>
+ <? if ($subfolder->is_empty): ?>
+ <?= Icon::create('folder-empty')->asImg(24) ?>
+ <? else: ?>
+ <?= Icon::create('folder-full')->asImg(24) ?>
+ <? endif; ?>
+ </button>
+ </td>
+ <td>
+ <!-- neu -->
+ <button formaction="<?= $controller->link_for('/choose_folder/' . $subfolder->getId()) ?>" class="undecorated" data-dialog>
+ <?= htmlReady($subfolder->name) ?>
+ </button>
+
+ <? if ($subfolder->description): ?>
+ <small class="responsive-hidden">
+ <?= htmlReady($subfolder->description) ?>
+ </small>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? else : ?>
+ <tr>
+ <td class="document-icon" data-sort-value="0">
+ <? if ($subfolder->is_empty): ?>
+ <?= Icon::create('folder-empty+decline', Icon::ROLE_INFO)->asImg(24) ?>
+ <? else: ?>
+ <?= Icon::create('folder-full+decline', Icon::ROLE_INFO)->asImg(24) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= htmlReady($subfolder->name) ?>
+ <? if ($subfolder->description): ?>
+ <small class="responsive-hidden">
+ <?= htmlReady($subfolder->description) ?>
+ </small>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? endif; ?>
+
+<?php
+switch ($top_folder->range_type) {
+ case 'user':
+ $check = true;
+ break;
+ case 'course':
+ case 'institute':
+ $check = CoreDocuments::checkActivation($top_folder->range_id);
+ break;
+ default:
+ $check = is_numeric($top_folder->range_type);
+ break;
+}
+?>
+
+<? if (!$check): ?>
+ <? if ($top_folder->range_type == 'course') : ?>
+ <?= MessageBox::error(_('Der Dateibereich ist für diese Veranstaltung nicht aktiviert.')) ?>
+ <? elseif($top_folder->range_type == 'institute'): ?>
+ <?= MessageBox::error(_('Der Dateibereich ist für diese Einrichtung nicht aktiviert.')) ?>
+ <? endif; ?>
+<? endif; ?>
+
+<footer data-dialog-button>
+<? if ($check && $top_folder->isWritable($GLOBALS['user']->id) && !in_array($top_folder->getId(), $options['fileref_id'])): ?>
+ <?
+ if ($options['copymode'] === 'upload') {
+ $buttonOptions = [
+ 'data-dialog' => 'size=auto',
+ 'onclick' => 'STUDIP.Files.openAddFilesWindow("'.$top_folder->getId().'"); return false;',
+ ];
+ } else {
+ $buttonOptions = [];
+ }
+ ?>
+
+ <!-- neu -->
+
+ <?= Studip\Button::createAccept(
+ $buttonLabels[$options['copymode']] ?: _('Auswählen'),
+ $buttonOptions + [
+ 'formaction' => $controller->url_for('files/copyhandler/' . $top_folder->getId()),
+ ]
+ ) ?>
+<? endif; ?>
+
+<? if (Request::get('direct_parent')): ?>
+ <!-- neu -->
+ <?= Studip\Button::create(_('Zurück'), [
+ 'formaction' => $controller->url_for('/choose_destination/' . $options['copymode']),
+ 'data-dialog' => 'size=auto',
+ ]) ?>
+<? elseif ($top_folder->range_type === 'course') : ?>
+ <!-- neu -->
+ <?= Studip\Button::create(_('Zurück'), [
+ 'formaction' => $controller->url_for('/choose_folder_from_course'),
+ 'data-dialog' => '',
+ ]) ?>
+<? elseif($top_folder->range_type === 'institute'): ?>
+ <!-- neu -->
+ <?= Studip\Button::create(_('Zurück'), [
+ 'formaction' => $controller->url_for('/choose_folder_from_institute'),
+ 'data-dialog' => '',
+ ]) ?>
+<? endif; ?>
+</footer>
diff --git a/app/views/file/choose_folder_from_course.php b/app/views/file/choose_folder_from_course.php
new file mode 100644
index 0000000..375c2c4
--- /dev/null
+++ b/app/views/file/choose_folder_from_course.php
@@ -0,0 +1,74 @@
+<?php
+$options = array_filter([
+ 'to_plugin' => Request::get('to_plugin'),
+ 'from_plugin' => Request::get('from_plugin'),
+ 'range_type' => Request::get('range_type'),
+ 'fileref_id' => Request::getArray('fileref_id'),
+ 'isfolder' => Request::get('isfolder'),
+ 'copymode' => Request::get('copymode'),
+], function ($value) {
+ return $value !== null;
+});
+?>
+
+<script>
+jQuery(function ($) {
+ $('#folderchooser_course_search select option').on('click', function () {
+ $('#folderchooser_course_search').submit();
+ });
+});
+</script>
+
+<? if ($GLOBALS['perm']->have_perm('admin')) : ?>
+<form id="folderchooser_course_search" method="post"
+ action="<?= $controller->link_for('file/choose_folder_from_course') ?>"
+ data-dialog>
+ <?= QuickSearch::get('course_id', new StandardSearch('AnySeminar_id'))
+ ->fireJSFunctionOnSelect("function () { jQuery('#folderchooser_course_search').submit(); }")
+ ->setInputStyle('width: calc(100% - 40px); margin: 20px;')
+ ->render() ?>
+<? else : ?>
+<form action="#" method="post" data-dialog>
+ <table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Bild') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Semester') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($courses as $course) : ?>
+ <tr>
+ <td>
+ <!-- neu -->
+ <button formaction="<?= $controller->link_for('file/choose_folder_from_course') ?>" name="course_id" value="<?= htmlReady($course->id) ?>" class="undecorated">
+ <?= CourseAvatar::getAvatar($course->id)->getImageTag(Avatar::MEDIUM, ['style' => 'width: 50px; height: 50px;']) ?>
+ </button>
+ </td>
+ <td>
+ <!-- neu -->
+ <button formaction="<?= $controller->link_for('file/choose_folder_from_course') ?>" name="course_id" value="<?= htmlReady($course->id) ?>" class="undecorated">
+ <?= htmlReady($course->getFullname()) ?>
+ </button>
+ </td>
+ <td>
+ <?= htmlReady($course->start_semester->name) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+<? endif; ?>
+
+<? foreach ($options as $key => $value): ?>
+ <?= addHiddenFields($key, $value) ?>
+<? endforeach; ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::create(_('Zurück'), [
+ 'formaction' => $controller->url_for('file/choose_destination/' . $options['copymode']),
+ 'data-dialog' => 'size=auto'
+ ]) ?>
+ </footer>
+</form>
diff --git a/app/views/file/choose_folder_from_institute.php b/app/views/file/choose_folder_from_institute.php
new file mode 100644
index 0000000..266859c
--- /dev/null
+++ b/app/views/file/choose_folder_from_institute.php
@@ -0,0 +1,75 @@
+<?php
+$options = array_filter([
+ 'to_plugin' => Request::get('to_plugin'),
+ 'from_plugin' => Request::get('from_plugin'),
+ 'range_type' => Request::get('range_type'),
+ 'fileref_id' => Request::getArray('fileref_id'),
+ 'isfolder' => Request::get('isfolder'),
+ 'copymode' => Request::get('copymode'),
+], function ($value) {
+ return $value !== null;
+});
+?>
+
+<? if ($GLOBALS['perm']->have_perm("admin")) : ?>
+<form id="folderchooser_institute_search" method="post"
+ action="<?= $controller->link_for('/choose_folder_from_institute') ?>"
+ data-dialog>
+ <?= QuickSearch::get('Institut_id', $instsearch)
+ ->fireJSFunctionOnSelect("function () { jQuery('#folderchooser_institute_search').submit(); }")
+ ->setInputStyle('width: calc(100% - 40px); margin: 20px;')
+ ->render()
+ ?>
+<? else : ?>
+<form action="#" method="post" data-dialog>
+ <table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Bild') ?></th>
+ <th><?= _('Name') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach (Institute::getMyInstitutes($GLOBALS['user']->id) as $institut) : ?>
+ <tr>
+ <td>
+ <input type="image" class="undecorated"
+ style="width: 50px; height: 50px;"
+ formaction="<?= $controller->link_for('file/choose_folder_from_institute') ?>"
+ name="Institut_id"
+ value="<?= htmlReady($institut['Institut_id']) ?>"
+ src="<?= htmlReady(
+ InstituteAvatar::getAvatar($institut['Institut_id'])->getUrl(Avatar::MEDIUM)
+ ) ?>">
+ </td>
+ <td>
+ <button formaction="<?= $controller->link_for('file/choose_folder_from_institute') ?>" name="Institut_id" value="<?= htmlReady($institut['Institut_id']) ?>" class="undecorated">
+ <?= htmlReady($institut['Name']) ?>
+ </button>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+<? endif; ?>
+
+<? foreach ($options as $key => $value): ?>
+ <?= addHiddenFields($key, $value) ?>
+<? endforeach; ?>
+
+ <footer data-dialog-button>
+ <!-- neu -->
+ <?= Studip\Button::create(_('Zurück'), [
+ 'formaction' => $controller->url_for('/choose_destination/' . $options['copymode']),
+ 'data-dialog' => 'size=auto',
+ ]) ?>
+ </footer>
+</form>
+
+<script>
+jQuery(function () {
+ $('#folderchooser_institute_search select option').on('click', function () {
+ $('#folderchooser_institute_search').submit();
+ });
+});
+</script>
diff --git a/app/views/file/edit.php b/app/views/file/edit.php
new file mode 100644
index 0000000..f2a3a65
--- /dev/null
+++ b/app/views/file/edit.php
@@ -0,0 +1,56 @@
+<div id="file_edit_window">
+ <?= $this->render_partial('file/_file_aside.php', compact('file_ref')) ?>
+
+ <div id="file_management_forms">
+ <form method="post" data-dialog class="default"
+ action="<?= $controller->link_for('/edit/' . $file_ref->id, ['from_plugin' => $from_plugin]) ?>">
+
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Datei bearbeiten') ?></legend>
+
+ <label>
+ <?= _('Name') ?>
+ <input id="edit_file_name" type="text" name="name"
+ value="<?= htmlReady($name) ?>">
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description" placeholder="<?= _('Optionale Beschreibung') ?>"><?= htmlReady($description); ?></textarea>
+ </label>
+ </fieldset>
+
+ <?= $this->render_partial('file/_terms_of_use_select.php', [
+ 'content_terms_of_use_entries' => $content_terms_of_use_entries,
+ 'selected_terms_of_use_id' => $content_terms_of_use->id,
+ ]) ?>
+
+ <footer data-dialog-button>
+ <? if ($show_force_button): ?>
+ <?= Studip\Button::createAccept(_('Trotzdem speichern'), 'force_save') ?>
+ <? else: ?>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ <? endif ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for((in_array($folder->range_type, ['course', 'institute']) ? $folder->range_type . '/' : '') . 'files/index/' . $folder->id)
+ ) ?>
+ </footer>
+ </form>
+ </div>
+</div>
+
+<script>
+ //On focus on the edit file name input field, the whole file name but the
+ //extension shall be selected. This can't be done with jQuery directly!
+
+ jQuery('#edit_file_name').focus(function() {
+ //select the whole file name, but the file extension
+ var text = $(this).val(),
+ //get start position of extension:
+ extension_start_pos = text.lastIndexOf('.');
+
+ $(this).setSelection(0, extension_start_pos);
+ });
+
+</script>
diff --git a/app/views/file/edit_folder.php b/app/views/file/edit_folder.php
new file mode 100644
index 0000000..c5c8fe4
--- /dev/null
+++ b/app/views/file/edit_folder.php
@@ -0,0 +1,25 @@
+<div id="file_edit_window">
+ <?= $this->render_partial('file/_folder_aside.php') ?>
+ <div id="file_management_forms">
+ <form method="post" class="default"
+ action="<?= $controller->url_for('/edit_folder/' . $folder->getId()) ?>"
+ data-dialog="reload-on-close"
+ >
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('file/new_edit_folder_form.php') ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'edit') ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for((in_array($folder->range_type, ['course', 'institute']) ? $folder->range_type . '/' : '') . 'files/index/' . $folder->parent_id)
+ ) ?>
+ </footer>
+ </form>
+ </div>
+</div>
+
+<script>
+ // On focus the whole folder name shall be selected.
+ // The input field with id edit_folder_name is in the view new_edit_folder_form!
+ jQuery('#edit_folder_name').select();
+</script>
diff --git a/app/views/file/edit_license.php b/app/views/file/edit_license.php
new file mode 100644
index 0000000..0ca27b2
--- /dev/null
+++ b/app/views/file/edit_license.php
@@ -0,0 +1,26 @@
+<form action="<?= $controller->link_for('file/edit_license', $origin_folder_id) ?>"
+ method="post" class="default" data-dialog="reload-on-close">
+<input type="hidden" name="re_location" value="<?= htmlReady($re_location) ?>">
+<? foreach ($file_refs as $file_ref) : ?>
+ <input type="hidden" name="file_refs[]" value="<?= htmlReady($file_ref->id) ?>">
+<? endforeach ?>
+
+ <? if ($show_description_field): ?>
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description" placeholder="<?= _('Optionale Beschreibung') ?>"></textarea>
+ </label>
+ <? endif ?>
+ <?= $this->render_partial('file/_terms_of_use_select.php', [
+ 'content_terms_of_use_entries' => $licenses,
+ 'selected_terms_of_use_id' => $file_ref->content_terms_of_use_id
+ ]) ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Lizenzauswahl abbrechen'),
+ $controller->url_for((in_array($folder->range_type, ['course', 'institute']) ? $folder->range_type . '/' : '') . 'files/index/' . $folder->id)
+ ) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/file/edit_urlfile.php b/app/views/file/edit_urlfile.php
new file mode 100644
index 0000000..41e7a6c
--- /dev/null
+++ b/app/views/file/edit_urlfile.php
@@ -0,0 +1,73 @@
+<div id="file_edit_window">
+ <?= $this->render_partial('file/_file_aside.php', compact('file_ref')) ?>
+
+ <div id="file_management_forms">
+ <form method="post" data-dialog class="default"
+ action="<?= $controller->link_for('/edit_urlfile/' . $file_ref->id, ['from_plugin' => $from_plugin]) ?>">
+
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Datei bearbeiten') ?></legend>
+
+ <label>
+ <?= _('Name') ?>
+ <input id="edit_file_name" type="text" name="name"
+ value="<?= htmlReady($name) ?>">
+ </label>
+
+ <label>
+ <?= _('URL') ?>
+ <input id="edit_file_url" type="text" name="url"
+ value="<?= htmlReady($file_ref->file['metadata']['url']) ?>">
+ </label>
+
+ <label>
+ <?= _('Zugriffsart') ?>
+ </label>
+ <label>
+ <input type="radio" name="access_type" value="redirect"
+ <? if ($file_ref->file['metadata']['access_type'] === "redirect") echo 'checked'; ?>>
+ <?= _('Direktlink')?>
+ </label>
+ <label>
+ <input type="radio" name="access_type" value="proxy"
+ <? if ($file_ref->file['metadata']['access_type'] === "proxy") echo 'checked'; ?>>
+ <?= _('Link über Proxy')?>
+ </label>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description" placeholder="<?= _('Optionale Beschreibung') ?>"><?= htmlReady($description); ?></textarea>
+ </label>
+ </fieldset>
+
+ <?= $this->render_partial('file/_terms_of_use_select.php', [
+ 'content_terms_of_use_entries' => $content_terms_of_use_entries,
+ 'selected_terms_of_use_id' => $content_terms_of_use_id,
+ ]) ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'save') ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for((in_array($folder->range_type, ['course', 'institute']) ? $folder->range_type . '/' : '') . 'files/index/' . $folder->id)
+ ) ?>
+ </footer>
+ </form>
+ </div>
+</div>
+
+<script>
+ //On focus on the edit file name input field, the whole file name but the
+ //extension shall be selected. This can't be done with jQuery directly!
+
+ jQuery('#edit_file_name').focus(function() {
+ //select the whole file name, but the file extension
+ var text = $(this).val(),
+ //get start position of extension:
+ extension_start_pos = text.lastIndexOf('.');
+
+ $(this).setSelection(0, extension_start_pos);
+ });
+
+</script>
diff --git a/app/views/file/file_details.php b/app/views/file/file_details.php
new file mode 100644
index 0000000..356043f
--- /dev/null
+++ b/app/views/file/file_details.php
@@ -0,0 +1,55 @@
+<div id="file_details_window">
+ <?= $this->render_partial('file/_file_aside.php') ?>
+
+ <div id="preview_container">
+ <? if ($file_info_template instanceof Flexi_Template) : ?>
+ <?= $file_info_template->render() ?>
+ <? endif ?>
+ <h3><?=_('Pfad')?></h3>
+ <article>
+ <? foreach (array_values($fullpath) as $i => $one_folder) : ?>
+ <? if ($i): ?>/<? endif; ?>
+ <a href="<?= FileManager::getFolderLink($one_folder) ?>">
+ <?= htmlReady($one_folder->name) ?>
+ </a>
+ <? endforeach; ?>
+ </article>
+
+ <? if ($file->getDescription()) : ?>
+ <h3><?= _('Beschreibung') ?></h3>
+ <article>
+ <?= htmlReady($file->getDescription() ?: _('Keine Beschreibung vorhanden.'), true, true) ?>
+ </article>
+ <? endif ?>
+ <?= Feedback::getHTML($file->getId(), 'FileRef') ?>
+ </div>
+</div>
+
+<footer data-dialog-button>
+ <?
+ $file_action_buttons = $file->getInfoDialogButtons(compact('from_plugin'));
+ ?>
+ <? if ($previous_file_ref_id): ?>
+ <?= Studip\LinkButton::create(
+ _('<< Vorherige Datei'),
+ $controller->url_for(
+ "file/details/{$previous_file_ref_id}",
+ ['from_plugin' => $from_plugin, 'file_navigation' => $include_navigation]
+ ),
+ ['data-dialog' => '']
+ ) ?>
+ <? endif ?>
+ <? if ($next_file_ref_id): ?>
+ <?= Studip\LinkButton::create(
+ _('Nächste Datei >>'),
+ $controller->url_for(
+ "file/details/{$next_file_ref_id}",
+ ['from_plugin' => $from_plugin, 'file_navigation' => $include_navigation]
+ ),
+ ['data-dialog' => '']
+ ) ?>
+ <? endif ?>
+ <? foreach ($file_action_buttons as $button) : ?>
+ <?= $button ?>
+ <? endforeach ?>
+</footer>
diff --git a/app/views/file/folder_details.php b/app/views/file/folder_details.php
new file mode 100644
index 0000000..5bd6574
--- /dev/null
+++ b/app/views/file/folder_details.php
@@ -0,0 +1,38 @@
+<?php
+$folder_template = $folder->getDescriptionTemplate();
+?>
+<div id="file_edit_window">
+ <?= $this->render_partial('file/_folder_aside.php') ?>
+
+ <div id="file_management_forms">
+ <h3><?= _('Ordnertyp') ?></h3>
+ <article><?= htmlReady($folder->getTypeName()) ?></article>
+ <? if (!empty($folder_template)) : ?>
+ <h3><?= _('Beschreibung') ?></h3>
+ <article>
+ <? if ($folder_template instanceof Flexi_Template): ?>
+ <?= $folder_template->render() ?>
+ <? else: ?>
+ <?= $folder_template ?>
+ <? endif; ?>
+ </article>
+ <? endif; ?>
+ </div>
+</div>
+
+<footer data-dialog-button>
+<? if ($folder->isEditable($GLOBALS['user']->id)) : ?>
+ <?= Studip\LinkButton::create(
+ _('Bearbeiten'),
+ $controller->url_for('file/edit_folder/' . $folder->getId()),
+ ['data-dialog' => '']
+ ) ?>
+<? endif; ?>
+<? if ($folder->isVisible($GLOBALS['user']->id)) : ?>
+
+ <?= \Studip\LinkButton::create(
+ _('Ordner öffnen'),
+ $controller->url_for('file/open_folder/' . $folder->getId())
+ ) ?>
+<? endif; ?>
+</footer>
diff --git a/app/views/file/link.php b/app/views/file/link.php
new file mode 100644
index 0000000..bc860a6
--- /dev/null
+++ b/app/views/file/link.php
@@ -0,0 +1 @@
+TODO! \ No newline at end of file
diff --git a/app/views/file/new_edit_folder_form.php b/app/views/file/new_edit_folder_form.php
new file mode 100644
index 0000000..2c7a801
--- /dev/null
+++ b/app/views/file/new_edit_folder_form.php
@@ -0,0 +1,55 @@
+<fieldset>
+ <legend>
+ <?= _('Ordnereigenschaften') ?>
+ </legend>
+ <label>
+ <?= _('Name') ?>
+ <input id="edit_folder_name" type="text" name="name" placeholder="<?= _('Name') ?>" value="<?= htmlReady($name) ?>">
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description" class="wysiwyg" placeholder="<?= _('Optionale Beschreibung') ?>"><?= htmlReady($description); ?></textarea>
+ </label>
+</fieldset>
+
+<? if (!is_a($folder, 'VirtualFolderType')): ?>
+ <fieldset class="select_terms_of_use">
+ <legend>
+ <?= _('Ordnertyp auswählen') ?>
+ </legend>
+ <? foreach ($folder_types as $folder_type) : ?>
+ <input type="radio" name="folder_type"
+ value="<?= htmlReady($folder_type['class']) ?>"
+ id="folder-type-<?= htmlReady($folder_type['class']) ?>"
+ <? if ($folder_type['class'] === get_class($folder)) echo 'checked'; ?>>
+ <label for="folder-type-<?= htmlReady($folder_type['class']) ?>">
+ <div class="icon">
+ <? if ($folder_type['icon']) : ?>
+ <?= $folder_type['icon']->asImg(32) ?>
+ <? endif ?>
+ </div>
+ <div class="text">
+ <?= htmlReady($folder_type['name']) ?>
+ <? if ($template = $folder_type['instance']->getDescriptionTemplate()): ?>
+ <?= tooltipIcon($template instanceof Flexi_Template ? $template->render() : $template, false, true) ?>
+ <? endif; ?>
+
+ </div>
+ <?= Icon::create('arr_1down')->asImg(24, ['class' => 'arrow']) ?>
+ <?= Icon::create('check-circle')->asImg(32, ['class' => 'check']) ?>
+ </label>
+ <? if ($folder_type['class'] === get_class($folder)) : ?>
+ <? $folder_template = $folder->getEditTemplate() ?>
+ <? else : ?>
+ <? $folder_template = $folder_type['instance']->getEditTemplate() ?>
+ <? endif; ?>
+ <? if ($folder_template) : ?>
+ <div class="terms_of_use_description">
+ <div class="description">
+ <?= $folder_template->render() ?>
+ </div>
+ </div>
+ <? endif; ?>
+ <? endforeach; ?>
+</fieldset>
+<? endif ?>
diff --git a/app/views/file/new_folder.php b/app/views/file/new_folder.php
new file mode 100644
index 0000000..7af34d7
--- /dev/null
+++ b/app/views/file/new_folder.php
@@ -0,0 +1,16 @@
+<form method="post" class="default" data-dialog="reload-on-close" action="<?= $controller->link_for('file/new_folder/' . $parent_folder_id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('file/new_edit_folder_form.php', [
+ 'name' => $name,
+ 'description' => $description,
+ 'folder_types' => $folder_types,
+ 'new_folder_form' => true,
+ ]) ?>
+ <footer data-dialog-button>
+ <? if ($show_confirmation_button): ?>
+ <?= Studip\Button::createAccept(_('Trotzdem erstellen'), 'force_creation') ?>
+ <? else: ?>
+ <?= Studip\Button::createAccept(_('Erstellen'), 'create') ?>
+ <? endif ?>
+ </footer>
+</form>
diff --git a/app/views/file/unzipquestion.php b/app/views/file/unzipquestion.php
new file mode 100644
index 0000000..a7e82b1
--- /dev/null
+++ b/app/views/file/unzipquestion.php
@@ -0,0 +1,15 @@
+<form action="<?= $controller->url_for('file/unzipquestion') ?>" method="post" data-dialog>
+
+<? foreach ($file_refs as $file_ref): ?>
+ <input type="hidden" name="file_refs[]" value="<?= htmlReady($file_ref->id) ?>">
+<? endforeach ?>
+
+ <?= Icon::create('unit-test', Icon::ROLE_INACTIVE)->asImg(120, ['style' => 'display: block; margin-left: auto; margin-right: auto;']) ?>
+
+ <?= _('Soll diese ZIP-Datei entpackt werden?') ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::create(_('Entpacken'), 'unzip') ?>
+ <?= Studip\Button::create(_('Nicht Entpacken'), 'dontunzip') ?>
+ </footer>
+</form>
diff --git a/app/views/file/update.php b/app/views/file/update.php
new file mode 100644
index 0000000..ba88f9d
--- /dev/null
+++ b/app/views/file/update.php
@@ -0,0 +1,40 @@
+<form action="<?= $controller->link_for('file/update/' . $file->getId(), ['from_plugin' => $from_plugin]) ?>"
+ enctype="multipart/form-data" method="post" class="default">
+
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Neue Dateiversion') ?></legend>
+ <label class="file-upload">
+ <?= sprintf(
+ _('Bitte die neue Version der Datei %s auswählen.'),
+ htmlReady($file->getFilename())
+ ) ?>
+ <input type="file" name="file">
+ </label>
+ <label>
+ <input type="checkbox" name="update_filename" value="1">
+ <?= _('Dateinamen aus neuer Dateiversion übernehmen.') ?>
+ </label>
+ <? if ($file_ref) : ?>
+ <? $count = count($file_ref->file->refs) ?>
+ <? if ($count > 1) : ?>
+ <label>
+ <input type="checkbox" name="update_all_instances" value="1">
+ <?= sprintf(_('Alle weiteren %u Vorkommen aktualisieren.'), $count - 1) ?>
+ </label>
+ <? endif ?>
+ <? endif ?>
+
+
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Aktualisieren'), 'confirm') ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for(
+ (in_array($folder->range_type, ['course', 'institute']) ? $folder->range_type . '/' : '')
+ . 'files/index/' . $folder->parent_id
+ )
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/file/upload_window.php b/app/views/file/upload_window.php
new file mode 100644
index 0000000..5c2bc2e
--- /dev/null
+++ b/app/views/file/upload_window.php
@@ -0,0 +1,18 @@
+<div class="file_uploader">
+ <div class="file_upload_window">
+ <div class="errorbox" style="display: none;">
+ <?= MessageBox::error('<span class="errormessage"></span>')?>
+ </div>
+ <ul class="filenames clean"></ul>
+ <div class="uploadbar uploadbar-outer">
+ <div class="uploadbar uploadbar-inner">
+ <?= Icon::create('upload', Icon::ROLE_INFO_ALT)->asImg(30) ?>
+ <?= Icon::create('ufo', Icon::ROLE_INFO_ALT)->asImg(30, ['class' => 'ufo']) ?>
+ </div>
+
+ <?= Icon::create('upload')->asImg(30) ?>
+
+ <span class="upload-progress"></span>
+ </div>
+ </div>
+</div>
diff --git a/app/views/files/_fileref_tr.php b/app/views/files/_fileref_tr.php
new file mode 100644
index 0000000..06fe18c
--- /dev/null
+++ b/app/views/files/_fileref_tr.php
@@ -0,0 +1,93 @@
+<?php
+$permissions = [];
+if ($file->isEditable($GLOBALS['user']->id)) {
+ $permissions[] = 'w';
+}
+if ($file->isDownloadable($GLOBALS['user']->id)) {
+ $permissions[] = 'dr';
+}
+?>
+<tr class="<? if ($file->getLastChangeDate() > $last_visitdate && ($file->getUserId() !== $GLOBALS['user']->id)) echo 'new'; ?>"
+ id="fileref_<?= htmlReady($table_id) ?>_<?= htmlReady($file->getId()) ?>"
+ role="row"
+ data-permissions="<?= implode($permissions) ?>">
+ <? if ($show_bulk_checkboxes) : ?>
+ <td>
+ <? if ($file->isDownloadable($GLOBALS['user']->id)) : ?>
+ <input type="checkbox"
+ class="studip-checkbox"
+ name="ids[]"
+ id="file_checkbox_<?= htmlReady($table_id) ?>_<?= htmlReady($file->getId()) ?>"
+ value="<?= htmlReady($file->getId()) ?>"
+ <?= in_array($file->getId(), (array) $marked_element_ids) ? 'checked' : '' ?>>
+ <label for="file_checkbox_<?= htmlReady($table_id) ?>_<?= htmlReady($file->getId()) ?>"></label>
+ <? endif ?>
+ </td>
+ <? endif ?>
+ <td class="document-icon" data-sort-value="<?= crc32($file->getMimeType()) ?>">
+ <? if ($file->isDownloadable($GLOBALS['user']->id)) : ?>
+ <a href="<?= htmlReady($file->getDownloadURL()) ?>" target="_blank" rel="noopener noreferrer">
+ <?= $file->getIcon(Icon::ROLE_CLICKABLE)->asImg(24) ?>
+ </a>
+ <? else : ?>
+ <?= $file->getIcon(Icon::ROLE_INACTIVE)->asImg(24) ?>
+ <? endif ?>
+ </td>
+ <td data-sort-value="<?= htmlReady($file->getFilename()) ?>">
+ <? if ($file->isDownloadable($GLOBALS['user']->id)) : ?>
+ <a href="<?= $controller->link_for("file/details/{$file->getId()}", ['file_navigation' => '1']) ?>" data-dialog>
+ <?= htmlReady($file->getFilename()) ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($file->getFilename()) ?>
+ <? endif ?>
+
+ <?php $terms = $file->getTermsOfUse() ?>
+ <? if ($terms && !$terms->isDownloadable($topFolder->range_id, $topFolder->range_type, false)) : ?>
+ <?= Icon::create('lock-locked', Icon::ROLE_INFO)->asImg(['title' => _('Das Herunterladen dieser Datei ist nur eingeschränkt möglich.')]) ?>
+ <? endif ?>
+ </td>
+ <? $size = $file->getSize() ?>
+ <td title="<?= number_format($size, 0, ',', '.') . ' Byte' ?>" data-sort-value="<?= htmlReady($size) ?>" class="responsive-hidden">
+ <? if ($size !== null) : ?>
+ <?= relSize($size, false) ?>
+ <? endif ?>
+ </td>
+ <? if ($show_downloads) : ?>
+ <? $downloads = $file->getDownloads() ?>
+ <td data-sort-value="<?= htmlReady($downloads) ?>" class="responsive-hidden">
+ <?= htmlReady($downloads) ?>
+ </td>
+ <? endif ?>
+ <? $author_name = $file->getUserName() ?>
+ <td data-sort-value="<?= htmlReady($author_name) ?>" class="responsive-hidden">
+ <? if ($file->getUser() && $file->getUser()->id !== $GLOBALS['user']->id) : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $file->getUser()->username) ?>">
+ <?= htmlReady($author_name) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($author_name) ?>
+ <? endif; ?>
+ </td>
+ <? $chdate = $file->getLastChangeDate() ?>
+ <td title="<?= strftime('%x %X', $chdate) ?>" data-sort-value="<?= htmlReady($chdate) ?>" class="responsive-hidden">
+ <?= $chdate ? reltime($chdate) : "" ?>
+ </td>
+ <? foreach ($current_folder->getAdditionalColumns() as $index => $column_name) : ?>
+ <td class="responsive-hidden"
+ data-sort-value="<?= htmlReady($file->getAdditionalColumnOrderWeigh($index)) ?>">
+ <? $content = $file->getContentForAdditionalColumn($index) ?>
+ <? if ($content) : ?>
+ <?= is_a($content, "Flexi_Template") ? $content->render() : $content ?>
+ <? endif ?>
+ </td>
+ <? endforeach ?>
+ <td class="actions">
+ <?
+ $actionMenu = $file->getActionMenu();
+ if ($actionMenu) {
+ echo $actionMenu->render();
+ }
+ ?>
+ </td>
+</tr>
diff --git a/app/views/files/_files_thead.php b/app/views/files/_files_thead.php
new file mode 100644
index 0000000..7769a96
--- /dev/null
+++ b/app/views/files/_files_thead.php
@@ -0,0 +1,48 @@
+<colgroup>
+ <? if ($show_bulk_checkboxes) : ?>
+ <col width="30px" data-filter-ignore>
+ <? endif ?>
+ <col width="20px" data-filter-ignore>
+ <col>
+ <col width="100px" class="responsive-hidden" data-filter-ignore>
+ <? if ($show_downloads) : ?>
+ <col width="100px" class="responsive-hidden" data-filter-ignore>
+ <? endif; ?>
+ <col width="150px" class="responsive-hidden">
+ <col width="120px" class="responsive-hidden" data-filter-ignore>
+ <col width="80px" data-filter-ignore>
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <? if ($show_bulk_checkboxes) : ?>
+ <th data-sort="false">
+ <input type="checkbox"
+ class="studip-checkbox"
+ <?= $table_id
+ ? 'data-proxyfor="table.documents[data-table_id=\'' . htmlReady($table_id) . '\'] tbody :checkbox"'
+ : 'data-proxyfor="table.documents tbody :checkbox"'
+ ?>
+ <?= $table_id
+ ? 'data-activates="table.documents[data-table_id=\'' . htmlReady($table_id) . '\'] tfoot .multibuttons .button"'
+ : 'data-activates="table.documents tfoot .multibuttons .button"'
+ ?>
+ id="all_files_checkbox_<?= htmlReady($table_id) ?>">
+ <label for="all_files_checkbox_<?= htmlReady($table_id) ?>"></label>
+ </th>
+ <? endif ?>
+ <th data-sort="htmldata"><?= _('Typ') ?></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="htmldata" class="responsive-hidden"><?= _('Größe') ?></th>
+ <? if ($show_downloads) : ?>
+ <th data-sort="htmldata" class="responsive-hidden"><?= _('Downloads') ?></th>
+ <? endif ?>
+ <th data-sort="text" class="responsive-hidden"><?= _('Autor/-in') ?></th>
+ <th data-sort="htmldata" class="responsive-hidden"><?= _('Datum') ?></th>
+ <? if ($topFolder) : ?>
+ <? foreach ($topFolder->getAdditionalColumns() as $index => $column_name) : ?>
+ <th data-sort="htmldata" class="responsive-hidden"><?=htmlReady($column_name) ?></th>
+ <? endforeach ?>
+ <? endif ?>
+ <th data-sort="false"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
diff --git a/app/views/files/_flat_tfoot.php b/app/views/files/_flat_tfoot.php
new file mode 100644
index 0000000..b18eda9
--- /dev/null
+++ b/app/views/files/_flat_tfoot.php
@@ -0,0 +1,58 @@
+<?
+$writable = $writable || false;
+if ($topFolder) {
+ $writable = $topFolder->isWritable($GLOBALS['user']->id);
+}
+$table_selector = 'table.documents';
+if ($table_id) {
+ $table_selector .= '[data-table_id="' . htmlReady($table_id) . '"]';
+}
+?>
+<tfoot>
+ <tr>
+ <td colspan="<?= $show_downloads ? 8 : 7 ?>">
+ <span class="multibuttons">
+ <?= Studip\Button::create(_('Herunterladen'), 'download', [
+ 'data-activates-condition' => $table_selector . ' tr[data-permissions*=d] :checkbox:checked'
+ ]) ?>
+ <? if ($writable): ?>
+ <?= Studip\Button::create(
+ _('Lizenz ändern'),
+ 'change_license',
+ [
+ 'formaction' => $controller->url_for('file/edit_license/bulk'),
+ 'data-dialog' => '',
+ 'data-activates-condition' => $table_selector . ' tr[data-permissions*=w] :checkbox:checked'
+ ]
+ ) ?>
+ <?= Studip\Button::create(_('Verschieben'), 'move', [
+ 'formaction' => $controller->url_for('file/choose_destination/move/bulk'),
+ 'data-dialog' => '',
+ 'data-activates-condition' => $table_selector . ' tr[data-permissions*=w] :checkbox:checked'
+ ]) ?>
+ <? endif ?>
+ <?= Studip\Button::create(_('Kopieren'), 'copy', [
+ 'formaction' => $controller->url_for('file/choose_destination/copy/bulk'),
+ 'data-dialog' => ''
+ ]) ?>
+ <? if ($writable): ?>
+ <?= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Soll die Auswahl wirklich gelöscht werden?'),
+ 'data-activates-condition' => $table_selector . ' tr[data-permissions*=w] :checkbox:checked'
+ ]) ?>
+ <? endif ?>
+ </span>
+ <? if (is_array($pagination)) : ?>
+ <div class="pagination-wrapper">
+ <?
+ $page = $pagination[0];
+ $amount = $pagination[1];
+ $page_size = $pagination[2];
+ $link_closure = $pagination[3];
+ ?>
+ <?= Pagination::create($amount, $page, $page_size)->asLinks($link_closure) ?>
+ </div>
+ <? endif ?>
+ </td>
+ </tr>
+</tfoot>
diff --git a/app/views/files/_folder_tr.php b/app/views/files/_folder_tr.php
new file mode 100644
index 0000000..a45fbba
--- /dev/null
+++ b/app/views/files/_folder_tr.php
@@ -0,0 +1,126 @@
+<?php
+if (!$controllerpath) {
+ $controllerpath = 'files/index';
+ if ($topFolder->range_type !== 'user') {
+ $controllerpath = $topFolder->range_type . '/' . $controllerpath;
+ }
+}
+$is_readable = $folder->isReadable($GLOBALS['user']->id);
+$owner = User::find($folder->user_id) ?: new User();
+
+$permissions = [];
+if ($is_readable) {
+ $permissions[] = 'r';
+}
+if ($folder->isEditable($GLOBALS['user']->id)) {
+ $permissions[] = 'w';
+}
+if ($folder->isReadable($GLOBALS['user']->id)) {
+ $permissions[] = 'd';
+}
+?>
+
+<tr id="row_folder_<?= $folder->id ?>" data-permissions="<?= implode($permissions) ?>">
+ <td>
+ <? if ($is_readable) : ?>
+ <input type="checkbox"
+ name="ids[]"
+ class="studip-checkbox"
+ id="file_checkbox_<?= $folder->id ?>"
+ value="<?= $folder->id ?>"
+ <? if (in_array($folder->getId(), (array)$marked_element_ids)) echo 'checked'; ?>>
+ <label for="file_checkbox_<?= $folder->id ?>"></label>
+ <? endif?>
+ </td>
+ <td class="document-icon" data-sort-value="<?=crc32(get_class($folder))?>">
+ <a href="<?= $controller->link_for($controllerpath . '/' . $folder->getId()) ?>">
+ <?= $folder->getIcon('clickable')->asImg(26) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for($controllerpath . '/' . $folder->getId()) ?>">
+ <?= htmlReady($folder->name) ?>
+ </a>
+ </td>
+ <? // -number + file count => directories should be sorted apart from files ?>
+ <td data-sort-value="-1000000" class="responsive-hidden"></td>
+<? if ($show_downloads): ?>
+ <td data-sort-value="-1000000" class="responsive-hidden"></td>
+<? endif; ?>
+ <td data-sort-value="<?= htmlReady($owner->getFullName('no_title_rev')) ?>" class="responsive-hidden">
+ <? if ($owner->id !== $GLOBALS['user']->id) : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $owner->username) ?>">
+ <?= htmlReady($owner->getFullName('no_title_rev')) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($owner->getFullName('no_title_rev')) ?>
+ <? endif; ?>
+ </td>
+ <td title="<?= strftime('%x %X', $folder->mkdate) ?>" data-sort-value="<?= $folder->mkdate ?>" class="responsive-hidden">
+ <?= $folder->mkdate ? reltime($folder->mkdate) : "" ?>
+ </td>
+ <? foreach ($topFolder->getAdditionalColumns() as $index => $column_name) : ?>
+ <td class="responsive-hidden"
+ data-sort-value="<?= htmlReady($folder->getAdditionalColumnOrderWeigh($index)) ?>">
+ <? $content = $folder->getContentForAdditionalColumn($index) ?>
+ <? if ($content) : ?>
+ <?= is_a($content, "Flexi_Template") ? $content->render() : $content ?>
+ <? endif ?>
+ </td>
+ <? endforeach ?>
+ <td class="actions">
+ <?php
+ $actionMenu = ActionMenu::get();
+ $actionMenu->addLink(
+ $controller->url_for('file/details/' . $folder->getId()),
+ _('Info'),
+ Icon::create('info-circle', 'clickable', ['size' => 20]),
+ ['data-dialog' => '1']
+ );
+ if ($folder->isEditable($GLOBALS['user']->id)) {
+ $actionMenu->addLink(
+ $controller->url_for('file/edit_folder/' . $folder->getId()),
+ _('Ordner bearbeiten'),
+ Icon::create('edit', 'clickable', ['size' => 20]),
+ ['data-dialog' => '1']
+ );
+ }
+ if ($folder->isReadable($GLOBALS['user']->id) && $GLOBALS['user']->id !== 'nobody') {
+ $actionMenu->addLink(
+ $controller->url_for('file/download_folder/' . $folder->getId()),
+ _('Ordner herunterladen'),
+ Icon::create('download', 'clickable', ['size' => 20])
+ );
+ }
+ if ($folder->isEditable($GLOBALS['user']->id)) {
+ $actionMenu->addLink(
+ $controller->url_for('file/choose_destination/move/' . $folder->getId(), ['isfolder' => 1]),
+ _('Ordner verschieben'),
+ Icon::create('folder-empty+move_right', 'clickable', ['size' => 20]),
+ ['data-dialog' => 'size=auto']
+ );
+ $actionMenu->addLink(
+ $controller->url_for('file/choose_destination/copy/' . $folder->getId(), ['isfolder' => 1]),
+ _('Ordner kopieren'),
+ Icon::create('folder-empty+add', 'clickable', ['size' => 20]),
+ ['data-dialog' => 'size=auto']
+ );
+ if (Feedback::isActivated() && Feedback::hasCreatePerm($course->id)) {
+ $actionMenu->addLink(
+ $controller->url_for('course/feedback/create_form/' . $folder->getId() . '/Folder'),
+ _('Neues Feedback-Element'),
+ Icon::create('star+add', Icon::ROLE_CLICKABLE, ['size' => 20]),
+ ['data-dialog' => '1']
+ );
+ }
+ $actionMenu->addLink(
+ $controller->url_for('file/delete_folder/' . $folder->getId()),
+ _('Ordner löschen'),
+ Icon::create('trash', 'clickable', ['size' => 20]),
+ ['onclick' => "return STUDIP.Dialog.confirmAsPost('" . sprintf(_('Soll der Ordner "%s" wirklich gelöscht werden?'), jsReady($folder->name)) . "', this.href);"]
+ );
+ }
+ ?>
+ <?= $actionMenu->render() ?>
+ </td>
+</tr>
diff --git a/app/views/files/_overview.php b/app/views/files/_overview.php
new file mode 100644
index 0000000..0cc0da0
--- /dev/null
+++ b/app/views/files/_overview.php
@@ -0,0 +1,107 @@
+<form class="default" method="get" action="<?= $controller->link_for('files_dashboard/search') ?>">
+ <?= $this->render_partial('files_dashboard/_input-group-search') ?>
+</form>
+
+<? if ($all_files) : ?>
+ <?
+ $tfoot_link = [
+ 'text' => sprintf(
+ ngettext('Insgesamt %d Datei', 'Insgesamt %d Dateien', $all_files_c),
+ $all_files_c
+ ),
+ 'href' => $controller->link_for('files/overview', ['view' => 'all_files'])
+ ];
+ ?>
+ <div class="vue-file-table"
+ data-topfolder="<?= htmlReady(json_encode($vue_topfolder)) ?>"
+ data-files="<?= htmlReady(json_encode($all_files)) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <files-table :showdownloads="<?= $show_download_column ? "true" : "false" ?>"
+ :files="files"
+ :topfolder="topfolder"
+ enable_table_filter="false"
+ table_title="<?= _('Alle Dateien') ?>"
+ :show_bulk_actions="false"
+ :tfoot_link="<?= htmlReady(json_encode($tfoot_link)) ?>"
+ ></files-table>
+ </div>
+<? endif ?>
+
+<? if ($uploaded_files) : ?>
+ <?
+ $tfoot_link = [
+ 'text' => sprintf(
+ ngettext('Insgesamt %d Datei', 'Insgesamt %d Dateien', $uploaded_files_c),
+ $uploaded_files_c
+ ),
+ 'href' => $controller->link_for('files/overview', ['view' => 'my_uploaded_files'])
+ ];
+ ?>
+ <div class="vue-file-table"
+ data-topfolder="<?= htmlReady(json_encode($vue_topfolder)) ?>"
+ data-files="<?= htmlReady(json_encode($uploaded_files)) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <files-table :showdownloads="<?= $show_download_column ? "true" : "false" ?>"
+ :files="files"
+ :topfolder="topfolder"
+ enable_table_filter="false"
+ table_title="<?= _('Persönlichr Dateibereich') ?>"
+ :show_bulk_actions="false"
+ :tfoot_link="<?= htmlReady(json_encode($tfoot_link)) ?>"
+ ></files-table>
+ </div>
+<? endif ?>
+
+<? if ($public_files) : ?>
+ <?
+ $tfoot_link = [
+ 'text' => sprintf(
+ ngettext('Insgesamt %d Datei', 'Insgesamt %d Dateien', $public_files_c),
+ $public_files_c
+ ),
+ 'href' => $controller->link_for('files/overview', ['view' => 'my_public_files'])
+ ];
+ ?>
+ <div class="vue-file-table"
+ data-topfolder="<?= htmlReady(json_encode($vue_topfolder)) ?>"
+ data-files="<?= htmlReady(json_encode($public_files)) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <files-table :showdownloads="<?= $show_download_column ? "true" : "false" ?>"
+ :files="files"
+ :topfolder="topfolder"
+ enable_table_filter="false"
+ table_title="<?= _('Meine öffentlichen Dateien') ?>"
+ :show_bulk_actions="false"
+ :tfoot_link="<?= htmlReady(json_encode($tfoot_link)) ?>"
+ ></files-table>
+ </div>
+<? endif ?>
+
+<? if ($uploaded_unlic_files) : ?>
+ <?
+ $tfoot_link = [
+ 'text' => sprintf(
+ ngettext('Insgesamt %d Datei', 'Insgesamt %d Dateien', $uploaded_unlic_files_c),
+ $uploaded_unlic_files_c
+ ),
+ 'href' => $controller->link_for('files/overview', ['view' => 'my_uploaded_files_unknown_license'])
+ ];
+ ?>
+ <div class="vue-file-table"
+ data-topfolder="<?= htmlReady(json_encode($vue_topfolder)) ?>"
+ data-files="<?= htmlReady(json_encode($uploaded_unlic_files)) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <files-table :showdownloads="<?= $show_download_column ? "true" : "false" ?>"
+ :files="files"
+ :topfolder="topfolder"
+ enable_table_filter="false"
+ table_title="<?= _('Meine Dateien mit ungeklärter Lizenz') ?>"
+ :show_bulk_actions="false"
+ :tfoot_link="<?= htmlReady(json_encode($tfoot_link)) ?>"
+ ></files-table>
+ </div>
+<? endif ?>
+
+<? if ($no_files) : ?>
+ <?= MessageBox::info(_('Es sind keine Dateien vorhanden, die für Sie zugänglich sind!')) ?>
+<? endif ?>
diff --git a/app/views/files/all_files.php b/app/views/files/all_files.php
new file mode 100644
index 0000000..a4f00d0
--- /dev/null
+++ b/app/views/files/all_files.php
@@ -0,0 +1,51 @@
+<nav>
+ <? if ($previous_page) : ?>
+ <a href="<?= $controller->link_for('files/all_files', ['page' => $previous_page]) ?>">
+ <?= Icon::create('arr_2left') ?>
+ </a>
+ <? endif ?>
+ <? if ($next_page) : ?>
+ <a href="<?= $controller->link_for('files/all_files', ['page' => $next_page]) ?>">
+ <?= Icon::create('arr_2right') ?>
+ </a>
+ <? endif ?>
+</nav>
+<table class="default documents sortable-table" data-sortlist="[[5, 1]]" data-shiftcheck>
+ <? if ($previous_page || $next_page) : ?>
+ <caption><?= htmlReady(sprintf(_('Alle Dateien, Seite %d'), $page)) ?></caption>
+ <? else : ?>
+ <caption><?= _('Alle Dateien') ?></caption>
+ <? endif ?>
+ <?= $this->render_partial(
+ 'files/_files_thead.php',
+ [
+ 'show_downloads' => $show_download_column,
+ 'show_bulk_checkboxes' => true
+ ]
+ ) ?>
+ <?= $this->render_partial(
+ 'files/_flat_tfoot',
+ [
+ 'show_downloads' => $show_downloads,
+ 'writable' => true,
+ 'pagination' => [$page, $file_ref_c, $page_size]
+ ]
+ ) ?>
+ <tbody class="files">
+ <? foreach ($new_files as $file_ref) : ?>
+ <?
+ $folder = $file_ref->folder;
+ if ($folder instanceof Folder) {
+ $folder = $folder->getTypedFolder();
+ }
+ ?>
+ <?= $this->render_partial('files/_fileref_tr', [
+ 'file_ref' => $file_ref,
+ 'current_folder' => $folder,
+ 'controllerpath' => $controllerpath,
+ 'show_downloads' => $show_download_column,
+ 'show_bulk_checkboxes' => true
+ ]) ?>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/files/configure.php b/app/views/files/configure.php
new file mode 100644
index 0000000..5ab6eea
--- /dev/null
+++ b/app/views/files/configure.php
@@ -0,0 +1,8 @@
+<div class="file_select_possibilities">
+<? foreach ($configure_urls as $url) : ?>
+ <a href="<?= htmlReady($url['url']) ?>" data-dialog>
+ <?= $url['icon']->asImg(50) ?>
+ <?= htmlReady($url['name']) ?>
+ </a>
+<? endforeach ?>
+</div>
diff --git a/app/views/files/flat.php b/app/views/files/flat.php
new file mode 100644
index 0000000..7702767
--- /dev/null
+++ b/app/views/files/flat.php
@@ -0,0 +1,101 @@
+<?php
+$show_downloads = in_array(Config::get()->DISPLAY_DOWNLOAD_COUNTER, ['always', 'flat']);
+$vue_files = [];
+foreach ($files as $file) {
+ if ($file->isVisible($GLOBALS['user']->id)) {
+ $vue_files[] = FilesystemVueDataManager::getFileVueData($file, $file->getFolderType(), $last_visitdate);
+ }
+}
+$vue_files = array_values(SimpleCollection::createFromArray($vue_files)->orderBy('chdate desc')->toArray());
+
+$topFolder = new StandardFolder();
+$vue_topFolder = [
+ 'description' => $topFolder->getDescriptionTemplate(),
+ 'additionalColumns' => $topFolder->getAdditionalColumns(),
+ 'buttons' => null
+];
+if (is_a($vue_topFolder['description'], "Flexi_Template")) {
+ $vue_topFolder['description'] = $vue_topFolder['description']->render();
+}
+$vue_topFolder['buttons'] = '<span class="multibuttons">';
+$vue_topFolder['buttons'] .= Studip\Button::create(_('Herunterladen'), 'download', [
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=d] :checkbox:checked'
+]);
+if ($topFolder->isWritable($GLOBALS['user']->id)) {
+ $vue_topFolder['buttons'] .= Studip\Button::create(_('Verschieben'), 'move', [
+ 'formaction' => $controller->url_for('file/choose_destination/move/bulk'),
+ 'data-dialog' => 'size=auto',
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=w] :checkbox:checked'
+ ]);
+}
+$vue_topFolder['buttons'] .= Studip\Button::create(_('Kopieren'), 'copy', [
+ 'formaction' => $controller->url_for('file/choose_destination/copy/bulk'),
+ 'data-dialog' => 'size=auto',
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=r] :checkbox:checked'
+]);
+if ($topFolder->isWritable($GLOBALS['user']->id)) {
+ $vue_topFolder['buttons'] .= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Soll die Auswahl wirklich gelöscht werden?'),
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=w] :checkbox:checked'
+ ]);
+}
+$vue_topFolder['buttons'] .= '</span>';
+foreach ($topFolder->getAdditionalActionButtons() as $button) {
+ $vue_topFolder['buttons'] .= $button;
+}
+?>
+<form id="files_table_form"
+ method="post"
+ action="<?= htmlReady($form_action) ?>"
+ data-files="<?= htmlReady(json_encode($vue_files)) ?>"
+ data-topfolder="<?= htmlReady(json_encode((array) $vue_topFolder)) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <files-table :showdownloads="<?= $show_downloads ? "true" : "false" ?>"
+ :breadcrumbs="breadcrumbs"
+ :files="files"
+ :folders="folders"
+ :topfolder="topfolder"
+ enable_table_filter="<?= $enable_table_filter ? 'true' : 'false' ?>"
+ table_title="<?= htmlReady($table_title) ?>"
+ pagination="<?= htmlReady($pagination_html) ?>"
+ :initial_sort="{sortedBy:'chdate',sortDirection:'desc'}"
+ ></files-table>
+</form>
+
+<? ob_start(); ?>
+<? if ($enable_table_filter) : ?>
+<div align="center">
+<input class="tablesorterfilter" placeholder="<?= _('Name oder Autor/-in') ?>" data-column="2,4" type="search" style="width: 100%; margin-bottom: 5px;"><br>
+</div>
+<? endif ?>
+<?
+if ($show_default_sidebar) {
+ if ($enable_table_filter) {
+ $content = ob_get_clean();
+ $widget = new SidebarWidget();
+ $widget->setTitle(_('Filter'));
+ $widget->addElement(new WidgetElement($content));
+ Sidebar::get()->addWidget($widget);
+ } else {
+ ob_get_clean();
+ }
+
+ $views = new ViewsWidget();
+ $views->addLink(
+ _('Ordneransicht'),
+ $controller->url_for(($range_type ? $range_type . '/' : '') . 'files/index'),
+ null,
+ [],
+ 'index'
+ );
+ $views->addLink(
+ _('Alle Dateien'),
+ $controller->url_for(($range_type ? $range_type.'/' : '') . 'files/flat'),
+ null,
+ [],
+ 'flat'
+ )->setActive(true);
+ Sidebar::get()->addWidget($views);
+} else {
+ ob_get_clean();
+}
diff --git a/app/views/files/index.php b/app/views/files/index.php
new file mode 100644
index 0000000..a0fc2bc
--- /dev/null
+++ b/app/views/files/index.php
@@ -0,0 +1,119 @@
+<? if ($topFolder): ?>
+ <?php
+ if (!$controllerpath) {
+ $controllerpath = 'files/index';
+ if ($topFolder->range_type !== 'user') {
+ $controllerpath = $topFolder->range_type . '/' . $controllerpath;
+ }
+ }
+
+ $show_downloads = Config::get()->DISPLAY_DOWNLOAD_COUNTER === 'always';
+ $vue_breadcrumbs = [];
+ $folder = $topFolder;
+ do {
+ $vue_breadcrumbs[] = [
+ 'folder_id' => $folder->getId(),
+ 'name' => $folder->name,
+ 'url' => $controller->url_for($controllerpath . '/' . $folder->getId())
+ ];
+ } while ($folder = $folder->getParent());
+
+ $vue_topFolder = [
+ 'description' => $topFolder->getDescriptionTemplate(),
+ 'additionalColumns' => $topFolder->getAdditionalColumns(),
+ 'buttons' => null
+ ];
+ if (is_a($vue_topFolder['description'], "Flexi_Template")) {
+ $vue_topFolder['description'] = $vue_topFolder['description']->render();
+ }
+ $vue_files = [];
+ foreach ($topFolder->getFiles() as $file) {
+ if ($file->isVisible($GLOBALS['user']->id)) {
+ $vue_files[] = FilesystemVueDataManager::getFileVueData($file, $topFolder, $last_visitdate);
+ }
+ }
+ $vue_folders = [];
+ foreach ($topFolder->getSubfolders() as $folder) {
+ if ($folder->isVisible($GLOBALS['user']->id)) {
+ $vue_folders[] = FilesystemVueDataManager::getFolderVueData($folder, $topFolder, $last_visitdate);
+ }
+ }
+
+ $vue_topFolder['buttons'] = '<span class="multibuttons">';
+ $vue_topFolder['buttons'] .= Studip\Button::create(_('Herunterladen'), 'download', [
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=d] :checkbox:checked'
+ ]);
+ if ($topFolder->isWritable($GLOBALS['user']->id)) {
+ $vue_topFolder['buttons'] .= Studip\Button::create(_('Verschieben'), 'move', [
+ 'formaction' => $controller->url_for('file/choose_destination/move/bulk'),
+ 'data-dialog' => 'size=auto',
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=w] :checkbox:checked'
+ ]);
+ }
+ if ($topFolder->isReadable($GLOBALS['user']->id)) {
+ $vue_topFolder['buttons'] .= Studip\Button::create(_('Kopieren'), 'copy', [
+ 'formaction' => $controller->url_for('file/choose_destination/copy/bulk'),
+ 'data-dialog' => 'size=auto',
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=r] :checkbox:checked'
+ ]);
+ }
+ if ($topFolder->isWritable($GLOBALS['user']->id)) {
+ $vue_topFolder['buttons'] .= Studip\Button::create(_('Löschen'), 'delete', [
+ 'data-confirm' => _('Soll die Auswahl wirklich gelöscht werden?'),
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=w] :checkbox:checked'
+ ]);
+ }
+ $vue_topFolder['buttons'] .= '</span>';
+ if ($topFolder->isSubfolderAllowed($GLOBALS['user']->id)) {
+ $vue_topFolder['buttons'] .= Studip\LinkButton::create(
+ _('Neuer Ordner'),
+ $controller->url_for('file/new_folder/' . $topFolder->getId()),
+ ['data-dialog' => '']
+ );
+ }
+ if ($topFolder->isWritable($GLOBALS['user']->id)) {
+ $vue_topFolder['buttons'] .= Studip\LinkButton::create(_('Dokument hinzufügen'), '#', [
+ 'onclick' => 'STUDIP.Files.openAddFilesWindow(); return false;'
+ ]);
+ }
+ foreach ($topFolder->getAdditionalActionButtons() as $button) {
+ $vue_topFolder['buttons'] .= $button;
+ }
+ ?>
+
+ <? if ($show_file_search) : ?>
+ <form class="default" method="get" action="<?= $controller->link_for('files_dashboard/search') ?>">
+ <?= $this->render_partial('files_dashboard/_input-group-search') ?>
+ </form>
+ <? endif ?>
+
+ <form method="post"
+ id="files_table_form"
+ action="<?= $controller->link_for('file/bulk/' . $topFolder->getId()) ?>"
+ data-files="<?= htmlReady(json_encode($vue_files)) ?>"
+ data-folders="<?= htmlReady(json_encode((array) $vue_folders)) ?>"
+ data-breadcrumbs="<?= htmlReady(json_encode((array) array_reverse($vue_breadcrumbs))) ?>"
+ data-topfolder="<?= htmlReady(json_encode((array) $vue_topFolder)) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="parent_folder_id" value="<?= $topFolder->getId() ?>">
+ <files-table :showdownloads="<?= $show_downloads ? "true" : "false" ?>"
+ :breadcrumbs="breadcrumbs"
+ :files="files"
+ :folders="folders"
+ :topfolder="topfolder"
+ ></files-table>
+ </form>
+ <? if ($GLOBALS['user']->id !== 'nobody') : ?>
+
+ <?= $this->render_partial('file/upload_window.php') ?>
+ <?= $this->render_partial('file/add_files_window.php', [
+ 'folder_id' => $topFolder->getId(),
+ 'hidden' => true,
+ 'range' => $topFolder instanceof StandardFolder ? $topFolder->getRangeObject() : null,
+ 'upload_type' => FileManager::getUploadTypeConfig($topFolder->range_id, $GLOBALS['user']->id),
+ 'show_library_functions' => Config::get()->LITERATURE_ENABLE,
+ 'library_search_description' => Config::get()->LIBRARY_ADD_ITEM_ACTION_DESCRIPTION
+ ]) ?>
+ <? endif ?>
+<? endif ?>
+<?= Feedback::getHTML($topFolder->getId(), 'Folder') ?>
diff --git a/app/views/files/my_public_files.php b/app/views/files/my_public_files.php
new file mode 100644
index 0000000..6743c61
--- /dev/null
+++ b/app/views/files/my_public_files.php
@@ -0,0 +1,34 @@
+<table class="default documents sortable-table" data-sortlist="[[1, 0]]" data-shiftcheck>
+ <caption><?= _('Meine öffentlichen Dateien') ?></caption>
+ <?= $this->render_partial(
+ 'files/_files_thead.php',
+ [
+ 'show_downloads' => $show_download_column,
+ 'show_bulk_checkboxes' => true
+ ]
+ ) ?>
+ <?= $this->render_partial(
+ 'files/_flat_tfoot',
+ [
+ 'show_downloads' => $show_downloads,
+ 'writable' => true
+ ]
+ ) ?>
+ <tbody class="files">
+ <? foreach ($file_refs as $file_ref) : ?>
+ <?
+ $folder = $file_ref->folder;
+ if ($folder instanceof Folder) {
+ $folder = $folder->getTypedFolder();
+ }
+ ?>
+ <?= $this->render_partial('files/_fileref_tr', [
+ 'file_ref' => $file_ref,
+ 'current_folder' => $folder,
+ 'controllerpath' => $controllerpath,
+ 'show_downloads' => $show_download_column,
+ 'show_bulk_checkboxes' => true
+ ]) ?>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/files/my_uploaded_files.php b/app/views/files/my_uploaded_files.php
new file mode 100644
index 0000000..edfd52d
--- /dev/null
+++ b/app/views/files/my_uploaded_files.php
@@ -0,0 +1,38 @@
+<table class="default documents sortable-table" data-sortlist="[[1, 0]]" data-shiftcheck>
+ <? if ($undefined_license_view) : ?>
+ <caption><?= _('Meine hochgeladenen Dateien mit ungeklärter Lizenz') ?></caption>
+ <? else : ?>
+ <caption><?= _('Meine hochgeladenen Dateien') ?></caption>
+ <? endif ?>
+ <?= $this->render_partial(
+ 'files/_files_thead.php',
+ [
+ 'show_downloads' => $show_download_column,
+ 'show_bulk_checkboxes' => true
+ ]
+ ) ?>
+ <?= $this->render_partial(
+ 'files/_flat_tfoot',
+ [
+ 'show_downloads' => $show_downloads,
+ 'writable' => true
+ ]
+ ) ?>
+ <tbody class="files">
+ <? foreach ($file_refs as $file_ref) : ?>
+ <?
+ $folder = $file_ref->folder;
+ if ($folder instanceof Folder) {
+ $folder = $folder->getTypedFolder();
+ }
+ ?>
+ <?= $this->render_partial('files/_fileref_tr', [
+ 'file_ref' => $file_ref,
+ 'current_folder' => $folder,
+ 'controllerpath' => $controllerpath,
+ 'show_downloads' => $show_download_column,
+ 'show_bulk_checkboxes' => true
+ ]) ?>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/files/overview.php b/app/views/files/overview.php
new file mode 100644
index 0000000..ba526e1
--- /dev/null
+++ b/app/views/files/overview.php
@@ -0,0 +1,5 @@
+<? if ($current_view == 'overview') : ?>
+ <?= $this->render_partial('files/_overview') ?>
+<? else : ?>
+ <?= $this->render_partial('files/flat') ?>
+<? endif ?>
diff --git a/app/views/files/upload-drag-and-drop.php b/app/views/files/upload-drag-and-drop.php
new file mode 100644
index 0000000..bf4b06c
--- /dev/null
+++ b/app/views/files/upload-drag-and-drop.php
@@ -0,0 +1,3 @@
+<form class="drag-and-drop files">
+ <?= _('Neue Dateien zum Hinzufügen per Drag & Drop in diesen Bereich ziehen.') ?>
+</form> \ No newline at end of file
diff --git a/app/views/files_dashboard/_input-group-search.php b/app/views/files_dashboard/_input-group-search.php
new file mode 100644
index 0000000..0606b68
--- /dev/null
+++ b/app/views/files_dashboard/_input-group-search.php
@@ -0,0 +1,20 @@
+<div class="input-group files-search">
+ <input
+ name="q"
+ value="<?= htmlReady($query) ?>"
+ placeholder="<?= _('Was suchen Sie?') ?>"
+ aria-label="<?= _('Was suchen Sie?') ?>"
+ minlength="4"
+ size="10"
+ type="text">
+
+ <span class="input-group-append">
+ <button type="submit" class="button">
+ <?= Icon::create('search')->asImg(['title' => _("Suche starten")]) ?>
+ </button>
+
+ <? if ($query != '') : ?>
+ <?= \Studip\LinkButton::createReset(_('Zurücksetzen'), $controller->url_for('files_dashboard/search')) ?>
+ <? endif ?>
+ </span>
+</div>
diff --git a/app/views/files_dashboard/_search_active_filters.php b/app/views/files_dashboard/_search_active_filters.php
new file mode 100644
index 0000000..19c3092
--- /dev/null
+++ b/app/views/files_dashboard/_search_active_filters.php
@@ -0,0 +1,43 @@
+<?
+$filter = $query->getFilter();
+$removeActiveFilterUrl = function ($key) use ($query, $filter) {
+ $array = $filter->toArray();
+ unset($array[$key]);
+
+ return URLHelper::getLink(
+ 'dispatch.php/files_dashboard/search',
+ [ 'q' => $query->getQuery(), 'filter' => $array ]
+ );
+};
+?>
+<? if ($filter->isFiltering()) : ?>
+ <div class="files-search-active-filters">
+ <ul>
+ <li><?= _('Aktive Filter') ?>:</li>
+ <? if ($filter->hasCategory()) : ?>
+ <?
+ $categories = \FilesSearch\Filter::getCategories();
+ $categoryLabel = $categories[$filter->getCategory()];
+ ?>
+ <li class="files-search-active-filter">
+ <a href="<?= $removeActiveFilterUrl('category') ?>">
+ <?= _('Kategorie') ?>:
+ <?= htmlReady($categoryLabel) ?>
+ <?= Icon::create('trash') ?>
+ </a>
+ </li>
+ <? endif ?>
+
+ <? if ($filter->hasSemester()) : ?>
+ <li class="files-search-active-filter">
+ <a href="<?= $removeActiveFilterUrl('semester') ?>">
+ <?= _('Semester') ?>:
+ <?= htmlReady($filter->getSemester()->name) ?>
+
+ <?= Icon::create('trash') ?>
+ </a>
+ </li>
+ <? endif ?>
+ </ul>
+ </div>
+<? endif ?>
diff --git a/app/views/files_dashboard/_search_time.php b/app/views/files_dashboard/_search_time.php
new file mode 100644
index 0000000..ccd80ec5
--- /dev/null
+++ b/app/views/files_dashboard/_search_time.php
@@ -0,0 +1,7 @@
+<?
+$absTime = strftime('%x %X', $searchResult['fileRef']->chdate);
+$relTime = reltime($searchResult['fileRef']->chdate);
+?>
+<span class="time" title="<?= htmlReady($absTime) ?>">
+ <?= $searchResult['fileRef']->chdate ? htmlReady($relTime) : '' ?>
+</span>
diff --git a/app/views/files_dashboard/_search_tr.php b/app/views/files_dashboard/_search_tr.php
new file mode 100644
index 0000000..e8e7010
--- /dev/null
+++ b/app/views/files_dashboard/_search_tr.php
@@ -0,0 +1,97 @@
+<tr id="fileref_<?= htmlReady($searchResult['fileRef']->id) ?>">
+
+ <td class="files-search-icon">
+ <? if ($searchResult['folder']->isFileDownloadable($searchResult['fileRef'], $user->id)) : ?>
+ <a href="<?= htmlReady($searchResult['fileRef']->getDownloadURL('force_download')) ?>" target="_blank" rel="noopener noreferrer">
+ <?= FileManager::getIconForFileRef($searchResult['fileRef'])->asImg(24) ?>
+ </a>
+ <? else : ?>
+ <?= FileManager::getIconForFileRef($searchResult['fileRef'], Icon::ROLE_INACTIVE)->asImg(24) ?>
+ <? endif ?>
+ </td>
+
+ <td>
+ <? if ($searchResult['folder']->isFileDownloadable($searchResult['fileRef'], $user->id)) : ?>
+ <a href="<?= htmlReady($controller->url_for('file/details/'.$searchResult['fileRef']->id)) ?>" data-dialog="">
+ <? if (mb_strlen(($searchResult['fileRef']->name))) : ?>
+ <?= $controller->markPhrase($searchResult['fileRef']->name, $query->getQuery()) ?>
+ <? else : ?>
+ <i><?= _('kein Titel') ?></i>
+ <? endif ?>
+
+ <? if ($searchResult['fileRef']->terms_of_use &&
+ $searchResult['fileRef']->terms_of_use->download_condition > 0) : ?>
+ <?= Icon::create('lock-locked', ICON::ROLE_INACTIVE)->asImg([
+ 'class' => 'text-top',
+ 'title' => _('Das Herunterladen dieser Datei ist nur eingeschränkt möglich.')]) ?>
+ <? endif; ?>
+ </a>
+ <? else : ?>
+ <? if (mb_strlen(($searchResult['fileRef']->name))) : ?>
+ <?= $controller->markPhrase($searchResult['fileRef']->name, $query->getQuery()) ?>
+ <? else : ?>
+ <i><?= _('kein Titel') ?></i>
+ <? endif ?>
+
+ <? if ($searchResult['fileRef']->terms_of_use &&
+ $searchResult['fileRef']->terms_of_use->download_condition > 0) : ?>
+ <?= Icon::create('lock-locked', Icon::ROLE_INFO)->asImg([
+ 'class' => 'text-top',
+ 'title' => _('Das Herunterladen dieser Datei ist nur eingeschränkt möglich.')]) ?>
+ <? endif; ?>
+ <? endif ?>
+ </td>
+
+ <td>
+ <? if (mb_strlen($searchResult['fileRef']->description)) : ?>
+ <? if ($searchResult['folder']->isFileDownloadable($searchResult['fileRef'], $user->id)) : ?>
+ <a href="<?= htmlReady($controller->url_for('file/details/'.$searchResult['fileRef']->id)) ?>" data-dialog="">
+ <?= $controller->markPhrase($searchResult['fileRef']->description, $query->getQuery(), 100) ?>
+ </a>
+ <? else : ?>
+ <?= $controller->markPhrase($searchResult['fileRef']->description, $query->getQuery(), 100) ?>
+ <? endif ?>
+ <? endif ?>
+ </td>
+
+ <td>
+ <a href="<?= htmlReady(\FilesController::getRangeLink($searchResult['folder'])) ?>">
+ <? if ($searchResult['folder']->range_type === 'course') : ?>
+ <?= htmlReady($searchResult['folder']->course->getSemType()['name']) ?>:
+ <?= $controller->markPhrase($searchResult['folder']->course->name, $query->getQuery()) ?>
+ <? elseif ($searchResult['folder']->range_type === 'institute') : ?>
+ <?= _('Einrichtung') ?>:
+ <?= $controller->markPhrase($searchResult['folder']->institute->name, $query->getQuery()) ?>
+ <? elseif ($searchResult['folder']->range_type === 'message') : ?>
+ <?= _('Nachrichtenanhang') ?>:
+ <?= $controller->markPhrase($searchResult['folder']->message->subject, $query->getQuery()) ?>
+ <? elseif ($searchResult['folder']->range_type === 'user') : ?>
+ <?= _('Öffentlicher Dateibereich') ?>:
+ <?= $controller->markPhrase($searchResult['folder']->user->getFullname('full_rev_username'), $query->getQuery()) ?>
+ <? endif ?>
+ </a>
+ </td>
+
+ <td>
+ <? if ($searchResult['fileRef']->owner): ?>
+ <span class="files-search-owner">
+ <? if ($searchResult['fileRef']->user_id !== $user->id
+ && $searchResult['fileRef']->owner) : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $searchResult['fileRef']->owner->username) ?>">
+ <?= $controller->markPhrase($searchResult['fileRef']->author_name, $query->getQuery()) ?>
+ </a>
+ <? else: ?>
+ <?= $controller->markPhrase($searchResult['fileRef']->author_name, $query->getQuery()) ?>
+ <? endif ?>
+ </span>
+ <? endif ?>
+ </td>
+
+ <td>
+ <?= $this->render_partial('files_dashboard/_search_time') ?>
+ </td>
+
+ <td class="files-search-actions">
+ <?= $controller->getActionMenu($searchResult['fileRef'], $searchResult['folder'], $user) ?>
+ </td>
+</tr>
diff --git a/app/views/files_dashboard/search.php b/app/views/files_dashboard/search.php
new file mode 100644
index 0000000..ec738d4
--- /dev/null
+++ b/app/views/files_dashboard/search.php
@@ -0,0 +1,91 @@
+<? $filter = $query->getFilter() ?>
+<form class="default files-search-search" novalidate="novalidate">
+ <label>
+ <input type="hidden"
+ name="filter[category]"
+ value="<?= $filter->getCategory() ?: '' ?>">
+
+ <input type="hidden"
+ name="filter[semester]"
+ value="<?= $filter->getSemester() ? $filter->getSemester()->id : '' ?>">
+
+ <?= $this->render_partial('files_dashboard/_input-group-search', ['query' => $query->getQuery()]) ?>
+ </label>
+</form>
+
+<? if ($query->hasError()) : ?>
+ <?= MessageBox::error($query->getError()) ?>
+<? endif ?>
+
+<? if (isset($result)) : ?>
+
+ <? $resultPage = $result->getResultPage() ?>
+
+ <? if (count($resultPage) || $query->getOffset()) : ?>
+ <? $counter = $query->getOffset() ?>
+ <div class="table-scrollbox-horizontal">
+ <table class="default flat files-search-results">
+ <caption>
+ <?= $this->render_partial('files_dashboard/_search_active_filters') ?>
+
+ <? if ($result->hasMore()) : ?>
+ <span><?= _('Suchergebnisse') ?></span>
+ <? else : ?>
+ <span><?= sprintf('Suchergebnis: %d Treffer', $result->getTotal()) ?></span>
+ <? endif ?>
+ </caption>
+
+ <thead>
+ <tr>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ <th><?= _('Ort') ?></th>
+ <th><?= _('Autor/-in') ?></th>
+ <th><?= _('Datum') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <? foreach ($resultPage as $searchResult) : ?>
+ <?= $this->render_partial(
+ 'files_dashboard/_search_tr.php',
+ ['counter' => $counter++, 'searchResult' => $searchResult,]
+ ) ?>
+ <? endforeach ?>
+ </tbody>
+
+ <tfoot>
+ <tr>
+ <td colspan="7">
+ <? if ($result->hasMore()) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Weitere Ergebnisse suchen'),
+ \URLHelper::getUrl(
+ 'dispatch.php/files_dashboard/search',
+ [
+ 'q' => $query->getQuery(),
+ 'filter' => $filter->toArray(),
+ 'page' => $query->getPage() + 1
+ ]
+ ),
+ ['class' => 'files-search-more']
+ ) ?>
+
+ <? else : ?>
+ <div><?= sprintf('%d Treffer', $result->getTotal()) ?></div>
+ <? endif ?>
+ </td>
+ </tr>
+ </tfoot>
+
+ </table>
+ </div>
+ <? else : ?>
+ <?= $this->render_partial('files_dashboard/_search_active_filters') ?>
+
+ <?= MessageBox::info(_('Leider keine Treffer.')) ?>
+ </div>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/global_search/settings.php b/app/views/global_search/settings.php
new file mode 100644
index 0000000..e4e1e0e
--- /dev/null
+++ b/app/views/global_search/settings.php
@@ -0,0 +1,92 @@
+<form class="default" action="<?= $controller->url_for('globalsearch/saveconfig') ?>" method="post">
+ <section>
+ <label>
+ <span class="required">
+ <?= _('Wieviele Ergebnisse pro Kategorie sollen in der Schnellsuche angezeigt werden?') ?>
+ </span>
+ <input type="number" name="entries_per_type" size="5"
+ value="<?= intval(Config::get()->GLOBALSEARCH_MAX_RESULT_OF_TYPE) ?>" required>
+ </label>
+ </section>
+ <br>
+ <section>
+ <label>
+ <?= _('Auf welche Art sollen die Suchergebnisse aus der Datenbank gelesen werden?') ?>
+ <select name="async_queries" size="1">
+ <?php if (in_array('mysqli', get_loaded_extensions())) : ?>
+ <option value="1"<?= Config::get()->GLOBALSEARCH_ASYNC_QUERIES ? ' selected' : '' ?>>
+ <?= _('Asynchron, via mysqli') ?>
+ </option>
+ <?php endif ?>
+ <option value="0"<?= Config::get()->GLOBALSEARCH_ASYNC_QUERIES ? '' : ' selected' ?>>
+ <?= _('Synchron, via PDO') ?>
+ </option>
+ </select>
+ </label>
+ </section>
+ <br>
+ <section>
+ <table class="default sortable-table" id="globalsearch-modules">
+ <caption>
+ <?= _('In welcher Reihenfolge sollen Suchergebnisse erscheinen?') ?>
+ </caption>
+ <colgroup>
+ <col width="10">
+ <col>
+ <col width="50">
+ <col width="50">
+ </colgroup>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('Kategorie') ?></th>
+ <th><?= _('Aktiv?') ?></th>
+ <th><?= _('Volltext?') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($modules as $module) : ?>
+ <tr>
+ <td class="dragHandle"></td>
+ <td>
+ <?php $resourcesInactive = (get_class($module) == 'GlobalSearchResources' ||
+ get_class($module) == 'GlobalSearchRoomBookings') && !Config::get()->RESOURCES_ENABLE ?>
+ <label for="active[<?= htmlReady(get_class($module)) ?>]"
+ <?php if ($resourcesInactive) : ?>
+ class="inactive-settings-category"
+ data-tooltip="<?= htmlReady(sprintf(_('%s sind inaktiv, da die Ressourcenverwaltung derzeit deaktiviert ist.'), $module->getName())) ?>"
+ <?php endif ?>
+ >
+ <?= htmlReady($module->getName()) ?>
+ </label>
+ <input type="hidden" name="modules[<?= htmlReady(get_class($module)) ?>][class]"
+ value="<?= htmlReady(get_class($module)) ?>">
+ </td>
+ <td>
+ <input type="checkbox" id="active[<?= htmlReady(get_class($module)) ?>]"
+ name="modules[<?= htmlReady(get_class($module)) ?>][active]" value="1"
+ <?= $config[get_class($module)]['active'] && !$resourcesInactive ? ' checked' : '' ?>
+ <?= $resourcesInactive ? ' disabled' : '' ?>>
+ </td>
+ <td>
+ <?php if (is_a($module, 'GlobalSearchFulltext')) : ?>
+ <input type="checkbox" name="modules[<?= htmlReady(get_class($module)) ?>][fulltext]"
+ value="1"<?= $config[get_class($module)]['fulltext'] ? ' checked' : ''?>>
+ <?php endif ?>
+ </td>
+ </tr>
+ <?php endforeach ?>
+ </tbody>
+ </table>
+ </section>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= \Studip\Button::createAccept(_('Speichern'), 'submit')?>
+ </footer>
+</form>
+
+<script language="JavaScript" type="text/javascript">
+ //<!--
+ jQuery('#globalsearch-modules tbody').sortable();
+ //-->
+</script>
diff --git a/app/views/help_content/admin_conflicts.php b/app/views/help_content/admin_conflicts.php
new file mode 100644
index 0000000..cff1fc4
--- /dev/null
+++ b/app/views/help_content/admin_conflicts.php
@@ -0,0 +1,44 @@
+<? use Studip\LinkButton; ?>
+<form action="<?= $controller->url_for('help_content/admin_conflicts') ?>" method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <? if (count($conflicts)) : ?>
+ <? foreach ($conflicts as $conflict) : ?>
+ <table class="default">
+ <colgroup>
+ <col width="50%">
+ <col width="50%">
+ </colgroup>
+ <thead>
+ <? $keys = array_keys($conflict); ?>
+ <tr>
+ <th colspan="2"><?= _('Seite:') ?> <?= $conflict[$keys[0]]->route ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th><?= sprintf(_("Lokale Version (%s)"), $conflict[$keys[0]]->studip_version) ?></th>
+ <th><?= sprintf(_("Offizielle Version (%s)"), $conflict[$keys[1]]->studip_version) ?></th>
+ </tr>
+ <tr>
+ <td>
+ <?= $conflict[$keys[0]]->content ?>
+ </td>
+ <td>
+ <?= $conflict[$keys[1]]->content ?>
+ </td>
+ </tr>
+ <tr>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td><?= LinkButton::create(_('Übernehmen'), $controller->url_for('help_content/resolve_conflict/' . $conflict[$keys[0]]->getId() . '/accept')) ?></td>
+ <td><?= LinkButton::create(_('Übernehmen'), $controller->url_for('help_content/resolve_conflict/' . $conflict[$keys[0]]->getId() . '/delete')) ?></td>
+ </tr>
+ </tfoot>
+ </table>
+ <? endforeach ?>
+ <? else : ?>
+ <?= MessageBox::info(_('Keine Konflikte vorhanden.')) ?>
+ <? endif ?>
+</form> \ No newline at end of file
diff --git a/app/views/help_content/admin_overview.php b/app/views/help_content/admin_overview.php
new file mode 100644
index 0000000..ac697e0
--- /dev/null
+++ b/app/views/help_content/admin_overview.php
@@ -0,0 +1,62 @@
+<? use Studip\Button; ?>
+<? if ($count = count($help_contents)) : ?>
+ <form action="<?= $controller->url_for('help_content/store_settings') ?>" method="post">
+ <input type="hidden" name="help_content_searchterm" value="<?= $help_content_searchterm ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <?= sprintf(ngettext('%u Hilfe-Text', '%u Hilfe-Texte', $count), $count) ?>
+ </caption>
+ <colgroup>
+ <col width="20">
+ <col width="20%">
+ <col width="10%">
+ <col>
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _("Aktiv") ?></th>
+ <th><?= _("Seite") ?></th>
+ <th><?= _("Sprache") ?></th>
+ <th><?= _("Inhalt") ?></th>
+ <th><?= _("Aktion") ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($help_contents as $help_content_id => $help_content) : ?>
+ <tr>
+ <td><input type="checkbox" name="help_content_status_<?= $help_content_id ?>"
+ id="help_content_status_<?= $help_content_id ?>" value="1"
+ class="studip-checkbox help_on"
+ <?= tooltip(_("Status der Hilfe (aktiv oder inaktiv)"), false) ?><?= ($help_content->visible) ? ' checked' : '' ?>>
+ <label for="help_content_status_<?= $help_content_id ?>">
+ <? _('Status der Hilfe (aktiv oder inaktiv)') ?>
+ </label>
+ </td>
+ <td><?= htmlReady($help_content->route) ?></td>
+ <td><?= htmlReady($help_content->language) ?></td>
+ <td><?= formatReady($help_content->content) ?></td>
+ <td>
+ <a href="<?= URLHelper::getURL('dispatch.php/help_content/edit/' . $help_content_id) ?>" <?= tooltip(_('Hilfe-Text bearbeiten')) ?>
+ data-dialog="size=auto;reload-on-close">
+ <?= Icon::create('edit', 'clickable')->asImg() ?></a>
+ <a href="<?= URLHelper::getURL('dispatch.php/help_content/delete/' . $help_content_id) ?>" <?= tooltip(_('Hilfe-Text löschen')) ?>
+ data-dialog="size=auto;reload-on-close">
+ <?= Icon::create('trash', 'clickable')->asImg() ?></a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <?= Button::createAccept(_('Speichern'), 'save_help_content_settings') ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </form>
+<? else : ?>
+ <?= _('Keine Hilfe-Texte vorhanden.') ?>
+<? endif ?>
diff --git a/app/views/help_content/delete.php b/app/views/help_content/delete.php
new file mode 100644
index 0000000..c86e7a0
--- /dev/null
+++ b/app/views/help_content/delete.php
@@ -0,0 +1,21 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<form id="delete_help_content_form" class="default"
+ action="<?= $controller->url_for('help_content/delete/' . $help_content_id) ?>"
+ method="POST">
+ <?=CSRFProtection::tokenTag(); ?>
+ <fieldset>
+ <input type="hidden" name="help_content_route" value="<?=$help_content->route?>">
+ <legend><?= sprintf(_('Seite %s'), $help_content->route) ?></legend>
+ <?= _('Hilfe-Text:') ?>
+ <?= $help_content->content ? htmlReady($help_content->content) : '' ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($via_ajax): ?>
+ <?= Button::create(_('Löschen'), 'delete_help_content', ['data-dialog' => '']) ?>
+ <? else: ?>
+ <?= Button::create(_('Löschen'), 'delete_help_content') ?>
+ <? endif; ?>
+ </footer>
+</form>
diff --git a/app/views/help_content/edit.php b/app/views/help_content/edit.php
new file mode 100644
index 0000000..dd8263e
--- /dev/null
+++ b/app/views/help_content/edit.php
@@ -0,0 +1,43 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<form id="edit_help_content_form" class="default"
+ action="<?= $controller->url_for('help_content/store' . ($help_content_id ? '/' . $help_content_id : ''), $parameters) ?>"
+ method="POST">
+ <?= CSRFProtection::tokenTag(); ?>
+ <fieldset>
+ <? if ($help_content_route) : ?>
+ <legend><?= sprintf(_('Seite %s'), $help_content_route) ?></legend>
+ <input type="hidden" name="help_content_route" value="<?= $help_content_route ?>">
+ <? else : ?>
+ <legend><?= _('Neuer Hilfe-Text') ?></legend>
+ <label for="help_content_route">
+ <?= _('Seite:') ?>
+ <input type="text" size="60" maxlength="255" name="help_content_route"
+ value=""
+ placeholder="<?= _('Bitte geben Sie eine Route für den Hilfe-Text an') ?>">
+ </label>
+ <? endif ?>
+ <? if ($help_admin) : ?>
+ <label for="help_content_language">
+ <span class="required"><?= _('Sprache des Textes:') ?></span>
+ <select name="help_content_language">
+ <? foreach ($GLOBALS['INSTALLED_LANGUAGES'] as $key => $language) : ?>
+ <option value="<?= mb_substr($key, 0, 2) ?>"<?= ($help_content->language == mb_substr($key, 0, 2)) ? ' selected' : '' ?>>
+ <?= $language['name'] ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif ?>
+ <label for="help_content_content">
+ <?= _('Hilfe-Text:') ?>
+ <textarea cols="60" rows="5" name="help_content_content"
+ placeholder="<?= _('Bitte geben Sie den Text ein') ?>"><?= $help_content->content ? htmlReady($help_content->content) : '' ?></textarea>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button="1">
+ <?= Button::createAccept(_('Speichern'), 'save_help_content', ['data-dialog' => '']) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('help_content/admin_overview'), []) ?>
+ </footer>
+</form>
diff --git a/app/views/institute/basicdata/index.php b/app/views/institute/basicdata/index.php
new file mode 100644
index 0000000..c794997
--- /dev/null
+++ b/app/views/institute/basicdata/index.php
@@ -0,0 +1,152 @@
+<?= $question ?>
+<form method="post" name="edit" action="<?= $controller->url_for('institute/basicdata/store/' . $i_view) ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Verwaltung der Einrichtungsgrunddaten') ?></legend>
+
+ <label class="col-6">
+ <span class="required"><?= _('Name') ?></span>
+ <?= I18N::input('Name', $institute->Name, LockRules::Check($institute->id, 'name') ? ['readonly' => true, 'disabled' => true] : ['required' => true]); ?>
+ </label>
+
+ <label class="col-3">
+ <?= _('Fakultät') ?>
+
+ <? if (count($institute->sub_institutes) > 0): ?>
+ <br>
+ <small style="font-weight: normal;">
+ <?= _('Diese Einrichtung hat den Status einer Fakultät.') ?><br>
+ <?= sprintf(_('Es wurden bereits %u andere Einrichtungen zugeordnet.'), count($institute->sub_institutes)) ?>
+ </small>
+ <input type="hidden" name="Fakultaet" id="Fakultaet" value="<?= $institute->id ?>">
+ <? else: ?>
+ <select <?= !$may_edit_faculty ? 'readonly disabled' : '' ?> name="Fakultaet" id="Fakultaet">
+ <? if ($GLOBALS['perm']->have_perm('root')): ?>
+ <option value="<?= $institute->id ?>" <?= ($institute->fakultaets_id == Request::option('Fakultaet', $institute->id)) ? 'selected' : '' ?>>
+ <?= _('Diese Einrichtung hat den Status einer Fakultät.') ?>
+ </option>
+ <? endif; ?>
+ <? if ($may_edit_faculty): ?>
+ <? foreach ($faculties as $faculty): ?>
+ <option value="<?= $faculty->id ?>"
+ <? if ($faculty->id === $institute->id): echo 'disabled'; ?>
+ <? elseif ($faculty->id == Request::option('Fakultaet', $institute->fakultaets_id)): echo 'selected'; ?>
+ <? endif; ?>>
+ <?= htmlReady($faculty->name) ?>
+ </option>
+ <? endforeach; ?>
+ <? else: ?>
+ <option value="<?= $institute->fakultaets_id ?>">
+ <?= htmlReady($institute->faculty->name) ?>
+ </option>
+ <? endif; ?>
+ </select>
+ <? endif; ?>
+ </label>
+
+ <label class="col-3">
+ <?= _('Bezeichnung') ?>
+
+ <select name="type" id="type" <?= LockRules::Check($institute->id, 'type') ? 'readonly disabled' : '' ?> >
+ <? foreach ($GLOBALS['INST_TYPE'] as $i => $inst_type): ?>
+ <option value="<?= $i ?>" <?= (Request::int('type', $institute->type) == $i) ? 'selected' : '' ?>>
+ <?= htmlReady($inst_type['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <?= _('Straße') ?>
+ <input type="text" <?= LockRules::Check($institute->id, 'strasse') ? 'readonly disabled' : '' ?> id="strasse" name="strasse"
+ value="<?= htmlReady(Request::get('strasse', $institute->strasse)) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Ort') ?>
+ <input type="text" <?= LockRules::Check($institute->id, 'plz') ? 'readonly disabled' : '' ?> id="plz" name="plz"
+ value="<?= htmlReady(Request::get('plz', $institute->plz)) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Telefonnummer') ?>
+ <input type="text" <?= LockRules::Check($institute->id, 'telefon') ? 'readonly disabled' : '' ?> id="telefon" name="telefon"
+ value="<?= htmlReady(Request::get('telefon', $institute->telefon)) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Faxnummer') ?>
+ <input type="text" <?= LockRules::Check($institute->id, 'fax') ? 'readonly disabled' : '' ?> id="fax" name="fax"
+ value="<?= htmlReady(Request::get('fax', $institute->fax)) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('E-Mail-Adresse') ?>
+ <input type="text" <?= LockRules::Check($institute->id, 'email') ? 'readonly disabled' : '' ?> id="email" name="email"
+ value="<?= htmlReady(Request::get('email', $institute->email)) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Homepage') ?>
+ <input type="text" <?= LockRules::Check($institute->id, 'url') ? 'readonly disabled' : '' ?> id="home" name="home"
+ value="<?= htmlReady(Request::get('home', $institute->url)) ?>">
+ </label>
+
+ <? if ($GLOBALS['perm']->have_perm('root')): // Select lockrule to apply ?>
+ <label class="col-3">
+ <?= _('Sperrebene') ?>
+ <select id="lock_rule" name="lock_rule">
+ <option value="">&nbsp;</option>
+ <? foreach (LockRule::findAllByType('inst') as $rule): ?>
+ <option value="<?= $rule->getId() ?>" <?= ($rule->getId() == Request::option('lock_rule', $institute->lock_rule)) ? 'selected' : '' ?>>
+ <?= htmlReady($rule->name) ?>
+ </option>
+ <? endforeach;?>
+ </select>
+ </label>
+ <? endif; ?>
+
+ <? foreach ($datafields as $key => $datafield): ?>
+ <div class="col-3" style="vertical-align: top">
+ <?= $datafield['value'] ?>
+ </div>
+ <? endforeach; ?>
+ </fieldset>
+
+ <footer>
+ <? if ($i_view != 'new' && !$institute->isNew()): ?>
+ <input type="hidden" name="i_id" value="<?= $institute->id ?>">
+ <?= Studip\Button::createAccept(_('Übernehmen'), 'i_edit') ?>
+ <?= Studip\LinkButton::create(_('Löschen'),
+ $controller->url_for('institute/basicdata/index/' . $i_view, ['i_trykill' => 1]),
+ !$may_delete ? ['disabled' => ''] : []) ?>
+ <? if (!$may_delete && mb_strlen($reason_txt) > 0): ?>
+ <?= tooltipIcon($reason_txt, true) ?>
+ <? endif; ?>
+ <? else: ?>
+ <?= Studip\Button::create(_('Anlegen'), 'create') ?>
+ <? endif; ?>
+ <input type="hidden" name="i_view" value="<?= $i_view ?>">
+ </footer>
+</form>
+
+<?php
+$sidebar = Sidebar::get();
+
+if (!$institute->isNew()) {
+ $widget = new ActionsWidget();
+ $widget->addLink(
+ _('Infobild ändern'),
+ URLHelper::getURL('dispatch.php/avatar/update/institute/' . $institute->id),
+ Icon::create('edit')
+ )->asDialog();
+ if (InstituteAvatar::getAvatar($institute->id)->is_customized()) {
+ $widget->addLink(
+ _('Infobild löschen'),
+ URLHelper::getURL('dispatch.php/avatar/delete/institute/' . $institute->id),
+ Icon::create('trash')
+ );
+ }
+ $sidebar->addWidget($widget);
+}
diff --git a/app/views/institute/members/_table_body.php b/app/views/institute/members/_table_body.php
new file mode 100644
index 0000000..284a46c
--- /dev/null
+++ b/app/views/institute/members/_table_body.php
@@ -0,0 +1,173 @@
+<tbody style="vertical-align: top;">
+<? if ($th_title): ?>
+ <tr>
+ <th colspan="<?= 1 + count($structure) - ($structure['actions'] ? 1 : 0) ?>">
+ <?= htmlReady($th_title) ?>
+ </th>
+ <? if ($structure['actions']): ?>
+ <th class="actions">
+ <?= ActionMenu::get()
+ ->condition($mail_status)
+ ->addLink(
+ $controller->url_for('messages/write?filter=inst_status', [
+ 'who' => $key,
+ 'default_subject' => Context::get()->Name,
+ 'course_id' => Context::getId(),
+ ]),
+ sprintf(_('Nachricht an alle Mitglieder mit dem Status %s verschicken'), $th_title),
+ Icon::create('mail', 'clickable'),
+ ['data-dialog' => '']
+ )
+ ->condition($mail_gruppe)
+ ->addLink(
+ $controller->url_for('messages/write', [
+ 'group_id' => $group->id,
+ 'default_subject' => Context::get()->Name,
+ ]),
+ sprintf(_('Nachricht an alle Mitglieder der Gruppe %s verschicken'), $th_title),
+ Icon::create('mail', 'clickable'),
+ ['data-dialog' => '']
+ ) ?>
+ </th>
+ <? endif; ?>
+ </tr>
+<? endif; ?>
+<? foreach ($members as $member):
+ $default_entries = DataFieldEntry::getDataFieldEntries([$member->user_id, $institute->id]);
+
+ if ($group) {
+ $role_entries = DataFieldEntry::getDataFieldEntries([$member->user_id, $group->id]);
+ }
+?>
+ <tr>
+ <td>
+ <a href="<?= $controller->link_for('profile', ['username' => $member->username]) ?>">
+ <?= Avatar::getAvatar($member->user_id, $member->username)->getImageTag(Avatar::SMALL) ?>
+ </a>
+ </td>
+ <td>
+ <? if ($admin_view): ?>
+ <a href="<?= $controller->link_for("settings/statusgruppen#{$institute->id}", ['username' => $member->username, 'contentbox_open' => $institute->id]) ?>">
+ <?= htmlReady($member->getUserFullname('full_rev')) ?>
+ </a>
+ <? else: ?>
+ <a href="<?= $controller->link_for('profile', ['username' => $member->username]) ?>">
+ <?= htmlReady($member->getUserFullname('full_rev')) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <? if ($structure['status']): ?>
+ <td><?= htmlReady($member->inst_perms) ?></td>
+ <? endif; ?>
+ <? if ($structure['statusgruppe']): ?>
+ <td></td>
+ <? endif; ?>
+ <? if ($structure['raum']): ?>
+ <td><?= htmlReady($member->raum) ?></td>
+ <? endif; ?>
+ <? if ($structure['sprechzeiten']): ?>
+ <td><?= htmlReady($member->sprechzeiten) ?></td>
+ <? endif; ?>
+ <? if ($structure['telefon']): ?>
+ <td><?= htmlReady($member->Telefon) ?></td>
+ <? endif; ?>
+ <? if ($structure['email']): ?>
+ <td><?= htmlReady(get_visible_email($member->user_id)) ?></td>
+ <? endif; ?>
+ <? if ($structure['homepage']): ?>
+ <td><?= htmlReady($member->user_info->Home) ?></td>
+ <? endif; ?>
+ <? foreach (array_filter($datafields_list, function ($e) use ($structure) { return isset($structure[$e->getId()]); }) as $entry): ?>
+ <td>
+ <? if ($role_entries[$entry->getId()] && $role_entries[$entry->getId()]->getValue() !== 'default_value'): ?>
+ <?= $role_entries[$entry->getId()]->getDisplayValue() ?>
+ <? elseif ($default_entries[$entry->getId()]): ?>
+ <?= $default_entries[$entry->getId()]->getDisplayValue() ?>
+ <? endif; ?>
+ </td>
+ <? endforeach; ?>
+ <? if ($structure['actions']): ?>
+ <td class="actions">
+ <?= ActionMenu::get()
+ ->addLink(
+ $controller->url_for("messages/write?rec_uname={$member->username}"),
+ _('Nachricht an Benutzer verschicken'),
+ Icon::create('mail', 'clickable'),
+ ['data-dialog' => '']
+ )
+ ->conditionAll(
+ $admin_view && !LockRules::Check($institute->id, 'participants') // General permission check
+ && ($member->inst_perms !== 'admin' // Don't delete admins
+ || ($GLOBALS['perm']->get_profile_perm($member->user_id) === 'admin' // unless you are a global admin yourself
+ && $member->user_id !== $GLOBALS['user']->id)) // but don't delete yourself
+ )
+ ->condition(isset($group))
+ ->addLink(
+ $controller->url_for('institute/members/remove_from_group', $group->id, $type, ['username' => $member->username]),
+ _('Person aus Gruppe austragen'),
+ Icon::create('door-leave', 'clickable'),
+ ['data-confirm' => _('Wollen Sie die Person wirklich aus der Gruppe austragen?')]
+ )
+ ->condition(!isset($group))
+ ->addLink(
+ $controller->url_for('institute/members/remove_from_institute', $type, ['username' => $member->username]),
+ _('Person aus Einrichtung austragen'),
+ Icon::create('door-leave', 'clickable'),
+ ['data-confirm' => _('Wollen Sie die Person wirklich aus der Einrichtung austragen?')]
+ ) ?>
+ </td>
+ <? endif; ?>
+ </tr>
+<? if ($structure['statusgruppe']): ?>
+ <?
+ $my_groups = $groups->filter(function ($group) use ($member) {
+ return $group->isMember($member->user_id);
+ });
+ foreach ($my_groups as $group):
+ $group_member = $group->members->findOneBy('user_id', $member->user_id);
+ ?>
+ <tr>
+ <td colspan="<?= 2 + (int)!empty($structure['status']) ?>"></td>
+ <td colspan="<?= 1 + count(array_filter(['raum', 'sprechzeiten', 'telefon', 'email', 'homepage'], function ($item) use ($structure) { return !empty($structure[$item]); })) ?>">
+ <? if ($admin_view): ?>
+ <a href="<?= $controller->link_for('admin/statusgroups/editGroup/' . $group->id) ?>">
+ <? endif; ?>
+ <?= htmlReady($group->getFullGenderedName($member->user_id)) ?>
+ <? if ($admin_view): ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <? foreach ($group_member->datafields->filter(function ($e) use ($dview) { return in_array($e->getId(), $dview); }) as $entry): ?>
+ <td>
+ <? if ($entry->getValue() === 'default_value'): ?>
+ <?= $default_entries[$e_id]->getDisplayValue() ?>
+ <? else: ?>
+ <?= $entry->getDisplayValue() ?>
+ <? endif; ?>
+ </td>
+ <? endforeach; ?>
+ <? if ($structure['actions']): ?>
+ <td class="actions">
+ <?= ActionMenu::get()
+ ->conditionAll($admin_view && !LockRules::Check($institute->id, 'participants'))
+ ->addLink(
+ $controller->url_for("settings/statusgruppen#{$group->id}", [
+ 'username' => $member->username,
+ 'contentbox_open' => $group->id,
+ ]),
+ _('Gruppendaten bearbeiten'),
+ Icon::create('edit', 'clickable')
+ )
+ ->addLink(
+ $controller->url_for('institute/members/remove_from_group', $group->id, $type, ['username' => $member->username]),
+ _('Person aus Gruppe austragen'),
+ Icon::create('door-leave', 'clickable'),
+ ['data-confirm' => _('Wollen Sie die Person wirklich aus der Gruppe austragen?')]
+ ) ?>
+ </td>
+ <? endif; ?>
+ </tr>
+ <? endforeach; ?>
+<? endif; ?>
+<? endforeach; ?>
+</tbody>
diff --git a/app/views/institute/members/index.php b/app/views/institute/members/index.php
new file mode 100644
index 0000000..a0b2854
--- /dev/null
+++ b/app/views/institute/members/index.php
@@ -0,0 +1,35 @@
+<?php
+SkipLinks::addIndex(_('Mitarbeiterliste'), 'list_institute_members');
+?>
+
+<? if ($institute): ?>
+ <table class="default" id="list_institute_members">
+ <caption><?= _('Mitarbeiterinnen und Mitarbeiter') ?></caption>
+ <colgroup>
+ <col width="32">
+ <? foreach ($structure as $key => $field): ?>
+ <? if ($key !== 'statusgruppe'): ?>
+ <col <? if ($field['width']): ?> width="<?= $field['width'] ?>"<? endif; ?>>
+ <? endif; ?>
+ <? endforeach; ?>
+ </colgroup>
+ <thead>
+ <tr>
+ <? foreach ($structure as $key => $field): ?>
+ <th <? if ($key === 'actions') echo 'class="actions"'; ?> <? if ($field['colspan']): ?>colspan="<?= $field['colspan'] ?>"<? endif; ?>>
+ <? if ($field['link']): ?>
+ <a href="<?= URLHelper::getLink($field['link']) ?>">
+ <?= htmlReady($field['name']) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($field['name']) ?>
+ <? endif; ?>
+ </th>
+ <? endforeach; ?>
+ </tr>
+ </thead>
+ <? foreach ($display_tables as $variables): ?>
+ <?= $this->render_partial('institute/members/_table_body', $variables) ?>
+ <? endforeach; ?>
+ </table>
+<? endif; ?>
diff --git a/app/views/institute/overview/index.php b/app/views/institute/overview/index.php
new file mode 100644
index 0000000..3543d66
--- /dev/null
+++ b/app/views/institute/overview/index.php
@@ -0,0 +1,69 @@
+<article class="studip">
+ <header>
+ <h1><?= _('Grunddaten') ?></h1>
+ </header>
+ <section>
+ <dl style="margin: 0">
+ <? if ($institute->strasse) : ?>
+ <dt><?= _('Straße') ?></dt>
+ <dd><?= htmlReady($institute->strasse) ?></dd>
+ <? endif ?>
+
+ <? if ($institute->Plz) : ?>
+ <dt><?= _('Ort') ?></dt>
+ <dd><?= htmlReady($institute->Plz) ?></dd>
+ <? endif ?>
+
+ <? if ($institute->telefon) : ?>
+ <dt><?=_('Telefon')?></dt>
+ <dd><?= htmlReady($institute->telefon) ?></dd>
+ <? endif ?>
+
+ <? if ($institute->fax) : ?>
+ <dt><?= _('Fax') ?></dt>
+ <dd><?= htmlReady($institute->fax) ?></dd>
+ <? endif ?>
+
+ <? if ($institute->url) : ?>
+ <dt><?= _('Homepage') ?></dt>
+ <dd><?= htmlReady($institute->url) ?></dd>
+ <? endif ?>
+
+ <? if ($institute->email) : ?>
+ <dt><?= _('E-Mail') ?></dt>
+ <dd><?= htmlReady($institute->email) ?></dd>
+ <? endif ?>
+
+ <? if ($institute->fakultaets_id) : ?>
+ <dt><?= _('Fakultät') ?></dt>
+ <dd><?= htmlReady($institute->faculty->name) ?></dd>
+ <? endif ?>
+
+ <? foreach ($institute->datafields->getTypedDatafield() as $entry): ?>
+ <? if ($entry->isVisible() && $entry->getValue()): ?>
+ <dt><?= htmlReady($entry->getName()) ?></dt>
+ <dd><?= $entry->getDisplayValue() ?></dd>
+ <? endif?>
+ <? endforeach ?>
+ </dl>
+ </section>
+</article>
+
+<?= $news ?>
+<?= $dates ?>
+<?= $evaluations ?>
+<?= $questionnaires ?>
+
+<?
+// display plugins
+$plugins = PluginEngine::getPlugins('StandardPlugin', $institute_id);
+$layout = $GLOBALS['template_factory']->open('shared/index_box');
+
+foreach ($plugins as $plugin) {
+ $template = $plugin->getInfoTemplate($institute_id);
+
+ if ($template) {
+ echo $template->render(NULL, $layout);
+ $layout->clear_attributes();
+ }
+}
diff --git a/app/views/library_file/_add_edit_form.php b/app/views/library_file/_add_edit_form.php
new file mode 100644
index 0000000..595b96d
--- /dev/null
+++ b/app/views/library_file/_add_edit_form.php
@@ -0,0 +1,52 @@
+<? if ($defined_variables) : ?>
+ <form class="default" method="post" data-dialog="size=auto;reload-on-close"
+ action="<?= $form_action ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="document_type"
+ value="<?= htmlReady($document_type['name']) ?>">
+ <? foreach ($enriched_properties as $property) : ?>
+ <label>
+ <span <?= in_array($property['name'], $required_properties)
+ ? 'class="required"'
+ : '' ?>>
+ <?= htmlReady($property['display_name'][$user_language] ?: $property['name']) ?>
+ </span>
+ <? if ($property['type'] == 'number') : ?>
+ <input type="number"
+ value="<?= htmlReady($document_properties[$property['name']]) ?>"
+ name="document_properties[<?= htmlReady($property['name']) ?>]">
+ <? else : ?>
+ <? if ($property['type'] == 'name') : ?>
+ <input type="text" placeholder="<?= _('Nachname') ?>"
+ value="<?= htmlReady($document_properties[$property['name']][0]['family']) ?>"
+ name="document_properties[<?= htmlReady($property['name']) ?>][0][family]">
+ <input type="text" placeholder="<?= _('Vorname') ?>"
+ value="<?= htmlReady($document_properties[$property['name']][0]['given']) ?>"
+ name="document_properties[<?= htmlReady($property['name']) ?>][0][given]">
+ <input type="text" placeholder="<?= _('Namenszusatz') ?>"
+ value="<?= htmlReady($document_properties[$property['name']][0]['suffix']) ?>"
+ name="document_properties[<?= htmlReady($property['name']) ?>][0][suffix]">
+ <? elseif ($property['type'] == 'date') : ?>
+ <input type="text" placeholder="<?= _('Jahr') ?>"
+ value="<?= htmlReady($document_properties[$property['name']]['date-parts'][0][0]) ?>"
+ name="document_properties[<?= htmlReady($property['name']) ?>][date-parts][0][0]">
+ <input type="text" placeholder="<?= _('Monat') ?>"
+ value="<?= htmlReady($document_properties[$property['name']]['date-parts'][0][1]) ?>"
+ name="document_properties[<?= htmlReady($property['name']) ?>][date-parts][0][1]">
+ <input type="text" placeholder="<?= _('Tag') ?>"
+ value="<?= htmlReady($document_properties[$property['name']]['date-parts'][0][2]) ?>"
+ name="document_properties[<?= htmlReady($property['name']) ?>][date-parts][0][2]">
+
+ <? else : ?>
+ <input type="text"
+ value="<?= htmlReady($document_properties[$property['name']]) ?>"
+ name="document_properties[<?= htmlReady($property['name']) ?>]">
+ <? endif ?>
+ <? endif ?>
+ </label>
+ <? endforeach ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/library_file/create.php b/app/views/library_file/create.php
new file mode 100644
index 0000000..fb142ef
--- /dev/null
+++ b/app/views/library_file/create.php
@@ -0,0 +1,14 @@
+<? if ($defined_variables) : ?>
+ <p>
+ <?= sprintf(
+ _('Erstellung eines Bibliothekseintrages vom Typ „%s“'),
+ htmlReady($document_type['display_name'][$user_language] ?: $document_type['name'])
+ ) ?>
+ </p>
+ <?= $this->render_partial(
+ 'library_file/_add_edit_form',
+ [
+ 'form_action' => $controller->link_for('library_file/create/' . $folder_id)
+ ]
+ ) ?>
+<? endif ?>
diff --git a/app/views/library_file/edit.php b/app/views/library_file/edit.php
new file mode 100644
index 0000000..8785e0e
--- /dev/null
+++ b/app/views/library_file/edit.php
@@ -0,0 +1,8 @@
+<? if ($defined_variables) : ?>
+ <?= $this->render_partial(
+ 'library_file/_add_edit_form',
+ [
+ 'form_action' => $controller->link_for('library_file/edit/' . $file_ref->id)
+ ]
+ ) ?>
+<? endif ?>
diff --git a/app/views/library_file/select_type.php b/app/views/library_file/select_type.php
new file mode 100644
index 0000000..5709000
--- /dev/null
+++ b/app/views/library_file/select_type.php
@@ -0,0 +1,21 @@
+<? if ($document_types) : ?>
+ <form class="default" method="post" data-dialog="size=auto"
+ action="<?= $controller->link_for('library_file/create/' . htmlReady($folder_id)) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <label>
+ <span class="required"><?= _('Von welchem Dokumenttyp ist der Bibliothekseintrag?') ?></span>
+ <select name="document_type" required>
+ <option value=""><?= _('Bitte wählen') ?></option>
+ <? foreach ($document_types as $type) : ?>
+ <?
+ $display_name = $type['display_name'][$user_language] ?: $type['name'];
+ ?>
+ <option value="<?= htmlReady($type['name']) ?>"><?= htmlReady($display_name) ?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Auswählen')) ?>
+ </div>
+ </form>
+<?endif ?>
diff --git a/app/views/localizations/show.php b/app/views/localizations/show.php
new file mode 100644
index 0000000..bc3adb0
--- /dev/null
+++ b/app/views/localizations/show.php
@@ -0,0 +1,44 @@
+<?php
+
+$translations = array(
+ // app/controllers/messages.php
+ 'Wirklich %s Nachrichten löschen?' => _('Wirklich %s Nachrichten löschen?'),
+ ', [\'id\' => $this->user]))
+ . \' Nachrichten endgültig gelöscht.' => _(', [\'id\' => $this->user]))
+ . \' Nachrichten endgültig gelöscht.'),
+ ', [\'id\' => $this->user]))
+ . \' Nachrichten endgütlig gelöscht.' => _(', [\'id\' => $this->user]))
+ . \' Nachrichten endgütlig gelöscht.'),
+
+ // app/views/admin/autoinsert/manual.php
+ 'Fehler' => _('Fehler'),
+ 'Fehler bei der Übertragung' => _('Fehler bei der Übertragung'),
+ 'Gefundene Nutzer' => _('Gefundene Nutzer'),
+ 'Wollen Sie diesen Filter wirklich entfernen?' => _('Wollen Sie diesen Filter wirklich entfernen?'),
+
+ // public/assets/javascripts/ckeditor/plugins/studip-quote/plugin.js
+ 'Zitat einfügen' => _('Zitat einfügen'),
+ 'Zitat teilen' => _('Zitat teilen'),
+ 'Zitat löschen' => _('Zitat löschen'),
+ '%s hat geschrieben:' => _('%s hat geschrieben:'),
+
+ // public/plugins_packages/core/Forum/javascript/forum.js
+ 'Wenn Sie die Seite verlassen, gehen ihre Änderungen verloren!' => _('Wenn Sie die Seite verlassen, gehen ihre Änderungen verloren!'),
+ 'Sind sie sicher, dass Sie diese Kategorie entfernen möchten? ' => _('Sind sie sicher, dass Sie diese Kategorie entfernen möchten? '),
+ 'Alle Bereiche werden dann nach "Allgemein" verschoben!' => _('Alle Bereiche werden dann nach "Allgemein" verschoben!'),
+ 'Sind sie sicher, dass Sie diesen Bereich löschen möchten? ' => _('Sind sie sicher, dass Sie diesen Bereich löschen möchten? '),
+ 'Es werden auch alle Beiträge in diesem Bereich gelöscht!' => _('Es werden auch alle Beiträge in diesem Bereich gelöscht!'),
+ 'Sind sie sicher, dass Sie ihren bisherigen Beitrag verwerfen wollen?' => _('Sind sie sicher, dass Sie ihren bisherigen Beitrag verwerfen wollen?'),
+ 'Anonym' => _('Anonym'),
+ 'Die Senderin/der Sender dieser Nachricht möchte Sie auf den folgenden Beitrag aufmerksam machen. ' => _('Die Senderin/der Sender dieser Nachricht möchte Sie auf den folgenden Beitrag aufmerksam machen. '),
+ 'Link zum Beitrag: ' => _('Link zum Beitrag: '),
+ 'Beitrag verschieben' => _('Beitrag verschieben'),
+ 'Thema schließen' => _('Thema schließen'),
+ 'Thema öffnen' => _('Thema öffnen'),
+ 'Hervorhebung aufheben' => _('Hervorhebung aufheben'),
+ 'Thema hervorheben' => _('Thema hervorheben'),
+
+);
+
+?>
+<?= json_encode($translations) ?> \ No newline at end of file
diff --git a/app/views/lvgruppen/lvgruppen/details.php b/app/views/lvgruppen/lvgruppen/details.php
new file mode 100644
index 0000000..aec4a3a
--- /dev/null
+++ b/app/views/lvgruppen/lvgruppen/details.php
@@ -0,0 +1,151 @@
+<td colspan="6">
+ <table class="default nohover">
+ <colgroup>
+ <col style="width: 20%">
+ <col>
+ </colgroup>
+ <tbody>
+ <tr>
+ <td style="vertical-align: top;"><strong><?= _('Alternativtext:') ?></strong></td>
+ <td>
+ <? if ($lvgruppe->isI18nField('alttext')) : ?>
+ <? if (!mb_strlen($lvgruppe->alttext->original())
+ && count(array_diff([null], $lvgruppe->alttext->toArray())) === 0) : ?>
+ <span class="mvv-no-entry">
+ <?= _('Kein Alternativtext vorhanden.') ?>
+ </span>
+ <? else : ?>
+ <? $languages = Config::get()->CONTENT_LANGUAGES; ?>
+ <? $def_lang = reset(array_keys($languages)); ?>
+ <? if (mb_strlen($lvgruppe->alttext->original())) : ?>
+ <div>
+ <img style="display: block;" src="<?= Assets::image_path('languages/' . $languages[$def_lang]['picture']) ?>" alt="<?= $languages[$def_lang]['name'] ?>" title="<?= $languages[$def_lang]['name'] ?>">
+ <?= formatReady($lvgruppe->alttext->original()) ?>
+ </div>
+ <? endif; ?>
+ <? foreach ($lvgruppe->alttext->toArray() as $lang => $alttext) : ?>
+ <? if (mb_strlen($alttext)) : ?>
+ <div style="margin-top:10px;">
+ <img style="display: block;" src="<?= Assets::image_path('languages/' . $languages[$lang]['picture']) ?>" alt="<?= $languages[$lang]['name'] ?>" title="<?= $languages[$lang]['name'] ?>">
+ <?= formatReady($alttext) ?>
+ </div>
+ <? endif; ?>
+ <? endforeach; ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if (!mb_strlen($lvgruppe->alttext)) : ?>
+ <span class="mvv-no-entry">
+ <?= _('Kein Alternativtext vorhanden.') ?>
+ </span>
+ <? else : ?>
+ <div>
+ <?= formatReady($lvgruppe->alttext) ?>
+ </div>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2"><strong><?= _('Verwendet in Modulteilen:') ?></strong>
+ <?= $this->render_partial('lvgruppen/lvgruppen/trails_table_lvgruppe') ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <strong><?= _('Zugeordnete Lehrveranstaltungen:') ?></strong>
+ <? if (count($courses) == 0) : ?>
+ <div class="mvv-no-entry">
+ <?= _('Dieser Lehrveranstaltungsgruppe wurde für das ausgewählte Semester keine Lehrveranstaltung zugeordnet.') ?>
+ </div>
+ <? elseif ($sem_filter == 'all') : ?>
+ <span style="margin-left: 20%" onClick="jQuery('#mvv-lvgruppen-semester').find('.mvv-sem-hidden').slideToggle(); jQuery(this).find('span').toggle(); return false;">
+ <a href="<?= $controller->url_for('/details/' . $lvgruppe->id, ['all_sem' => 1]) ?>">
+ <span>
+ <?= Icon::create('arr_1up', Icon::ROLE_CLICKABLE, ['style' => 'vertical-align:text-bottom;'])->asImg(); ?>
+ <?= _('Alle Semester anzeigen') ?>
+ </span>
+ <span style="display: none;">
+ <?= Icon::create('arr_1down', Icon::ROLE_CLICKABLE, ['style' => 'vertical-align:text-bottom;'])->asImg(); ?>
+ <?= _('Nur aktuelle Semester anzeigen') ?>
+ </span>
+ </a>
+ </span>
+ <ul style="list-style-type:none;" id="mvv-lvgruppen-semester">
+ <? foreach ($display_semesters as $semester) : ?>
+ <? if ($courses[$semester->id]) : ?>
+ <? $show_sem = ($semester->id === $current_sem->id || $semester->id === $next_sem->id || Request::get('all_sem', 0)) ?>
+ <li<?= (!$show_sem ? ' style="display:none;" class="mvv-sem-hidden"' : '') ?>>
+ <strong><?= htmlReady($semester->name) ?></strong>
+ <ul style="list-style-type:none;">
+ <? foreach ($courses[$semester->id] as $course) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $course['seminar_id']]) ?>">
+ <?= htmlReady(($course['VeranstaltungsNummer'] ? $course['VeranstaltungsNummer'] . ' - ' : '') . $course['Name']) ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ </ul>
+ <? else : ?>
+ <ul style="list-style-type:none;" id="mvv-lvgruppen-semester">
+ <? foreach ($display_semesters as $semester) : ?>
+ <? if ($courses[$semester->id]) : ?>
+ <li>
+ <strong><?= htmlReady($semester->name) ?></strong>
+ <ul style="list-style-type:none;">
+ <? foreach ($courses[$semester->id] as $course) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $course['seminar_id']]) ?>">
+ <?= htmlReady(($course['VeranstaltungsNummer'] ? $course['VeranstaltungsNummer'] . ' - ' : '') . $course['Name']) ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? $archived_courses = $lvgruppe->getArchivedCourses(); ?>
+ <? if (count($archived_courses)) : ?>
+ <tr>
+ <td><strong><?= _('Zugeordnete archivierte Veranstaltungen:') ?></strong></td>
+ <td>
+ <ul>
+ <? foreach ($archived_courses as $archived_course) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink("dispatch.php/archive/overview/{$archived_course['seminar_id']}") ?>" target="_blank">
+ <?= htmlReady($archived_course['name'] . '(' . $archived_course['semester'] . ')') ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </td>
+ </tr>
+ <? endif; ?>
+ <tr>
+ <td><strong><?= _('Erstellt am:') ?></strong></td>
+ <td>
+ <?= strftime('%x, %X', $lvgruppe->mkdate) . ', ' ?>
+ <?= htmlReady(get_fullname($lvgruppe->author_id)) ?>
+ <?= ' (' . htmlReady(get_username($lvgruppe->author_id)) . ')' ?>
+ </td>
+ </tr>
+ <? if ($lvgruppe->mkdate !== $lvgruppe->chdate) : ?>
+ <tr>
+ <td><strong><?= _('Letzte Änderung am:') ?></strong></td>
+ <td>
+ <?= strftime('%x, %X', $lvgruppe->chdate) . ', ' ?>
+ <?= htmlReady(get_fullname($lvgruppe->editor_id)) ?>
+ <?= ' (' . htmlReady(get_username($lvgruppe->editor_id)) . ')' ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ </table>
+</td>
diff --git a/app/views/lvgruppen/lvgruppen/export_xls.php b/app/views/lvgruppen/lvgruppen/export_xls.php
new file mode 100644
index 0000000..50a9090
--- /dev/null
+++ b/app/views/lvgruppen/lvgruppen/export_xls.php
@@ -0,0 +1,39 @@
+<table>
+ <tr>
+ <th><?= _('LV-Gruppe') ?></th>
+ <th><?= _('Verantw. Einrichtung Modul') ?></th>
+ <th><?= _('Abschluss') ?></th>
+ <th><?= _('Studiengang') ?></th>
+ <th><?= _('Version des Studiengangteils') ?></th>
+ <th><?= _('Modul') ?></th>
+ <th><?= _('Modulteil') ?></th>
+ </tr>
+ <? $trail_classes = words('Modulteil Modul StgteilAbschnitt StgteilVersion '
+ . 'Studiengang Fachbereich'); ?>
+ <? foreach ($lvgruppen as $lvgruppe) : ?>
+ <? $trails = $lvgruppe->getTrails($trail_classes, MvvTreeItem::TRAIL_SHOW_INCOMPLETE); ?>
+ <? if (count($trails)) : ?>
+ <? foreach ($trails as $trail) : ?>
+ <tr>
+ <td><?= htmlReady($lvgruppe->getDisplayName()) ?></td>
+ <? foreach (array_reverse($trail_classes) as $trail_class) : ?>
+ <? if ($trail[$trail_class]) : ?>
+ <td><?= htmlReady($trail[$trail_class]->getDisplayName()) ?></td>
+ <? else : ?>
+ <td></td>
+ <? endif; ?>
+ <? endforeach; ?>
+ </tr>
+ <? endforeach; ?>
+ <? else : ?>
+ <tr>
+ <td><?= htmlReady($lvgruppe->getDisplayName()) ?></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <? endif; ?>
+ <? endforeach; ?>
+</table>
diff --git a/app/views/lvgruppen/lvgruppen/index.php b/app/views/lvgruppen/lvgruppen/index.php
new file mode 100644
index 0000000..aae9d80
--- /dev/null
+++ b/app/views/lvgruppen/lvgruppen/index.php
@@ -0,0 +1,101 @@
+<form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <table class="default collapsable">
+ <caption>
+ <?= _('Lehrveranstaltungsgruppen'); ?>
+ <span class="actions"><? printf(ngettext('%s LV-Gruppe', '%s LV-Gruppen', $count), $count) ?></span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('/index', _('Name'), 'name') ?>
+ <?= $controller->renderSortLink('/index', _('Veranstaltungen'), 'count_seminare', ['style' => 'text-align: center; width: 5%;']) ?>
+ <?= $controller->renderSortLink('/index', _('Archiv'), 'count_archiv', ['style' => 'text-align: center; width: 5%;']) ?>
+ <?= $controller->renderSortLink('/index', _('Modulteile'), 'count_modulteile', ['style' => 'text-align: center; width: 5%;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? if (count($lvgruppen)) : ?>
+ <? foreach ($lvgruppen as $lvgruppe): ?>
+ <tbody class="<?= $lvgruppe->count_seminare || true ? '' : 'empty' ?> <?= ($lvgruppe_id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <a class="mvv-load-in-new-row" href="<?= $controller->url_for('/details/' . $lvgruppe->id) ?>">
+ <?= htmlReady($lvgruppe->getDisplayName()) ?>
+ </a>
+ </td>
+ <td style="text-align: center;" class="dont-hide"><?= $lvgruppe->count_seminare ?> </td>
+ <td style="text-align: center;" class="dont-hide"><?= $lvgruppe->count_archiv ?> </td>
+ <td style="text-align: center;" class="dont-hide"><?= $lvgruppe->count_modulteile ?> </td>
+ <td class="dont-hide actions" style="white-space: nowrap;">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (MvvPerm::get($lvgruppe)->havePermWrite()) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/lvgruppe/' . $lvgruppe->id),
+ _('Lehrveranstaltungsgruppe bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE, tooltip2(_('Lehrveranstaltungsgruppe bearbeiten'))),
+ ['data-dialog' => 'size=']
+ ) ?>
+
+ <? $actionMenu->addLink(
+ $controller->url_for('shared/log_event/show/Lvgruppe/' . $lvgruppe->id),
+ _('Log-Einträge dieser Lehrveranstaltungsgruppe'),
+ Icon::create('log', Icon::ROLE_CLICKABLE, tooltip2(_('Log-Einträge dieser Lehrveranstaltungsgruppe'))),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? endif; ?>
+ <? if (MvvPerm::get($lvgruppe)->havePermCreate()) : ?>
+ <? if ($lvgruppe->count_semester == 0 && $lvgruppe->count_modulteile == 0): ?>
+ <? $actionMenu->addButton(
+ 'delete',
+ _('Lehrveranstaltungsgruppe löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, tooltip2(_('Modulteil löschen'))),
+ [
+ 'formaction' => $controller->url_for('/delete', $lvgruppe->id),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie wirklich die Lehrveranstaltungsgruppe "%s" löschen?'),
+ htmlReady($lvgruppe->getDisplayName())
+ )
+ ]
+ ) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? if ($lvgruppe_id === $lvgruppe->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('lvgruppen/lvgruppen/details', compact('lvgruppe')) ?>
+ </tr>
+ <? endif; ?>
+ <? endforeach ?>
+ </tbody>
+ <? else : ?>
+ <tbody>
+ <tr>
+ <td colspan="6" style="text-align: center">
+ <?= _('Es wurden keine Lehrveranstaltungsgruppen gefunden.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif ?>
+
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="6" style="text-align: right;">
+ <?php
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_lvgruppen=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render("shared/pagechooser");
+ ?>
+ </td>
+ </tr>
+ <tfoot>
+ <? endif; ?>
+ </table>
+</form> \ No newline at end of file
diff --git a/app/views/lvgruppen/lvgruppen/lvgruppe.php b/app/views/lvgruppen/lvgruppen/lvgruppe.php
new file mode 100644
index 0000000..3726987
--- /dev/null
+++ b/app/views/lvgruppen/lvgruppen/lvgruppe.php
@@ -0,0 +1,27 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+<? $perm = MvvPerm::get($lvgruppe) ?>
+<form data-dialog="size=auto" class="default" action="<?= $submit_url ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Lehrveranstaltungsgruppe') ?></legend>
+ <label>
+ <?= _('Name') ?>
+ <input <?= $perm->disable('name') ?> id="name" type="text" name="name" value="<?= htmlReady($lvgruppe->name) ?>" size="50" maxlength="250">
+ </label>
+ <label>
+ <?= _('Alternativtext') ?>
+ <?= MvvI18N::textarea('alttext', $lvgruppe->alttext, ['class' => 'add_toolbar ui-resizable wysiwyg'])->checkPermission($lvgruppe) ?>
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <? if ($lvgruppe->isNew()) : ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Lehrveranstaltungsgruppe anlegen')]) ?>
+ <? endif; ?>
+ <? elseif ($perm->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/lvgruppen/lvgruppen/trails_table_lvgruppe.php b/app/views/lvgruppen/lvgruppen/trails_table_lvgruppe.php
new file mode 100644
index 0000000..cd150be
--- /dev/null
+++ b/app/views/lvgruppen/lvgruppen/trails_table_lvgruppe.php
@@ -0,0 +1,26 @@
+<? if (count($trails)) : ?>
+<table class="default" style="font-size: 0.8em">
+ <tr>
+ <? foreach (array_reverse($trail_classes) as $trail_class) : ?>
+ <th><?= $trail_class::getClassDisplayName() ?></th>
+ <? endforeach; ?>
+ </tr>
+<? foreach ($trails as $key => $trail) : ?>
+ <tr>
+ <? foreach (array_reverse($trail_classes) as $trail_class) : ?>
+ <? if (isset($trail[$trail_class])) : ?>
+ <td style="vertical-align: top;">
+ <?= htmlReady($trail[$trail_class]->getDisplayName()) ?>
+ </td>
+ <? else : ?>
+ <td style="text-align: center; vertical-align: top;">-</td>
+ <? endif; ?>
+ <? endforeach; ?>
+ </tr>
+<? endforeach; ?>
+</table>
+<? else : ?>
+<span class="mvv-no-entry">
+<?= _('Diese Lehrveranstaltungsgruppe wurde für das ausgewählte Semester keinen Modulteilen zugeordnet.') ?>
+</span>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/materialien/files/add_dokument.php b/app/views/materialien/files/add_dokument.php
new file mode 100644
index 0000000..2b7c5ac
--- /dev/null
+++ b/app/views/materialien/files/add_dokument.php
@@ -0,0 +1,130 @@
+<form class="default" action="<?= $controller->url_for('/add_dokument', $origin, $range_type, $range_id, $mvvfile_id) ?>" method="post" data-dialog="size=auto">
+ <input type="hidden" name="mvvfile_id" id="mvvfile_id" value="<?= htmlReady($mvvfile_id) ?>">
+ <input type="hidden" name="range_id" id="range_id" value="<?= htmlReady($range_id) ?>">
+ <input type="hidden" name="range_type" id="range_type" value="<?= htmlReady($range_type) ?>">
+
+
+
+ <label>
+ <?= _('Jahr') ?>
+ <input name="doc_year" type="text" value="<?= htmlReady($doc_year) ?>"<?= $perm->disable('year') ?>>
+ </label>
+
+ <input type="hidden" name="doc_type" value="<?= $doc_type ?>">
+ <label>
+ <?= _('Art der Datei') ?>
+ <select name="doc_type"<?= $perm->haveFieldPerm('type') ? '' : ' disable' ?>>
+ <? foreach ($GLOBALS['MVV_DOCUMENTS']['TYPE']['values'] as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key == $doc_type ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <table class="default">
+ <? foreach($GLOBALS['MVV_LANGUAGES']['values'] as $key => $entry) : ?>
+ <tr>
+ <td rowspan="2">
+ <?= Assets::img('languages/lang_' . mb_strtolower($key) . '.gif') ?>
+ </td>
+ <td>
+ <label>
+ <?= _('Angezeigter Name des Dokuments') ?>
+ <input name="doc_displayname_<?= $key; ?>" type="text" value="<?= (!$documents || !key_exists($key, $documents)) ? '' : htmlReady($documents[$key]->name) ?>"<?= $perm->disable('name') ?>>
+ </label>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div class="attachments" style="<?= (!$documents || !key_exists($key, $documents)) ? '' : 'display: none;'?>">
+ <span style="cursor:pointer;" onClick="$('#fileselector_<?= $key; ?>').toggle();$(this).toggle();">
+ <?= Icon::create('file+add', Icon::ROLE_CLICKABLE, ['title' => _("Datei hinzufügen"), 'class' => 'text-bottom']); ?>
+ <?= _("Datei hinzufügen") ?>
+ </span>
+ <div id="fileselector_<?= $key; ?>" style="display:none;">
+ <ul class="stgfiles list-unstyled">
+ <li style="display: none;" class="stgfile">
+ <input type="hidden" name="document_id" id="document_id" value="<?= htmlReady($document_id) ?>">
+ <span class="icon"></span>
+ <span class="name"></span>
+ <span class="size"></span>
+ <a class="remove_attachment"><?= Icon::create('trash', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ </li>
+ </ul>
+ <div id="statusbar_container">
+ <div class="statusbar" style="display: none;">
+ <div class="progress"></div>
+ <div class="progresstext">0%</div>
+ </div>
+ </div>
+ <label id="upload_chooser" style="cursor: pointer;">
+ <input type="file" id="fileupload" multiple onChange="STUDIP.MVV.Document.upload_from_input(this, '<?= $key; ?>');" style="display: none;">
+ <?= Icon::create('upload', 'clickable', ['title' => _("Datei hochladen"), 'class' => "text-bottom"])->asImg(20) ?>
+ <?= _("Datei hochladen") ?>
+ </label>
+ <br>
+ <b><?= _('oder'); ?></b>
+ <label>
+ <?= _('Link hinzufügen') ?>
+ <input name="doc_url_<?= $key; ?>" type="text" value="" placeholder="https://...">
+ </label>
+ <div id="upload_finished" style="display: none"><?= _("wird verarbeitet") ?></div>
+ <div id="upload_received_data" style="display: none"><?= _("gespeichert") ?></div>
+ </div>
+ </div>
+ <div id="fileviewer_<?= $key; ?>">
+ <ul class="stgfiles list-unstyled">
+ <? if ($documents && key_exists($key, $documents)): ?>
+ <li class="stgfile">
+ <input type="hidden" name="document_id" id="document_id" value="<?= htmlReady($documents[$key]->fileref_id) ?>">
+ <span class="icon"><?= Icon::create('file', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?></span>
+ <span class="name"><?= htmlReady($documents[$key]->filename) ?></span>
+ <span class="size"></span>
+ <a class="remove_attachment"><?= Icon::create('trash', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ </li>
+ <? endif; ?>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </table>
+
+ <label>
+ <?= _('Kategoriezuordnung') ?>
+ <select name="doc_cat">
+ <? foreach ($GLOBALS['MVV_DOCUMENTS']['CATEGORY']['values'] as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key == $doc_cat ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label for="mvv-files-tags">
+ <?= _('Schlagwörter') ?>
+ <select id="mvv-files-tags" multiple name="doc_tags[]">
+ <option value=""></option>
+ <? foreach ($GLOBALS['MVV_DOCUMENTS']['TAG']['values'] as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key == in_array($key, explode(';', $doc_tags))? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <input name="doc_extvisible" type="checkbox" value="1" <?= $doc_extvisible?'checked':''; ?>>
+ <?= _('Sichtbarkeit nach außen') ?>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store_document') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+</form>
+
+<script>
+ $(document).ready(function() {
+ $('#mvv-files-tags').select2({
+ placeholder: '<?= _('Schlagwörter wählen') ?>'
+ });
+ });
+</script>
diff --git a/app/views/materialien/files/add_files_to_range.php b/app/views/materialien/files/add_files_to_range.php
new file mode 100644
index 0000000..ca8da1d
--- /dev/null
+++ b/app/views/materialien/files/add_files_to_range.php
@@ -0,0 +1,17 @@
+<form class="default" action="<?= $controller->url_for('/add_files_to_range',$range_type, $range_id) ?>" method="post" data-dialog="">
+ <label>
+ <select id="search-file-select" class="nested-select" multiple name="files[]">
+ <? if ($files) : ?>
+ <? foreach ($files as $file) : ?>
+ <option value="<?= $file->id ?>" selected><?= htmlReady($file->getDisplayName()) ?></option>
+ <? endforeach; ?>
+ <? endif; ?>
+ </select>
+ </label>
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+</form>
+
diff --git a/app/views/materialien/files/add_ranges_to_file.php b/app/views/materialien/files/add_ranges_to_file.php
new file mode 100644
index 0000000..5458dad
--- /dev/null
+++ b/app/views/materialien/files/add_ranges_to_file.php
@@ -0,0 +1,37 @@
+<form class="default" action="<?= $controller->url_for('/add_ranges_to_file', $mvvfile_id, $range_type) ?>" method="post" data-dialog="size=auto">
+
+ <label>
+ <? if ($range_type == 'Studiengang'): ?>
+ <select id="search-file-studiengang-select" class="nested-select" multiple name="ranges[]">
+ <? if ($mvv_objects) : ?>
+ <? foreach ($mvv_objects as $mvv_object) : ?>
+ <option value="<?= $mvv_object->id ?>" selected><?= htmlReady($mvv_object->getDisplayName()) ?></option>
+ <? endforeach; ?>
+ <? endif; ?>
+ </select>
+ <? elseif ($range_type == 'Modul'): ?>
+ <select id="search-file-modul-select" class="nested-select" multiple name="ranges[]">
+ <? if ($mvv_objects) : ?>
+ <? foreach ($mvv_objects as $mvv_object) : ?>
+ <option value="<?= $mvv_object->id ?>" selected><?= htmlReady($mvv_object->getDisplayName()) ?></option>
+ <? endforeach; ?>
+ <? endif; ?>
+ </select>
+ <? elseif ($range_type == 'AbschlussKategorie'): ?>
+ <select id="search-file-abschlusskategorie-select" class="nested-select" multiple name="ranges[]">
+ <? if ($mvv_objects) : ?>
+ <? foreach ($mvv_objects as $mvv_object) : ?>
+ <option value="<?= $mvv_object->id ?>" selected><?= htmlReady($mvv_object->getDisplayName()) ?></option>
+ <? endforeach; ?>
+ <? endif; ?>
+ </select>
+ <? endif; ?>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+</form>
diff --git a/app/views/materialien/files/details.php b/app/views/materialien/files/details.php
new file mode 100644
index 0000000..af72b0a
--- /dev/null
+++ b/app/views/materialien/files/details.php
@@ -0,0 +1,82 @@
+<td colspan="10">
+ <table class="default nohover">
+ <tr>
+ <td><?= _('Jahr'); ?></td>
+ <td><?= htmlReady($doc_year); ?></td>
+ </tr>
+
+ <tr>
+ <td><?= _('Art der Datei '); ?></td>
+ <td><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['TYPE']['values'][$doc_type]['name']); ?></td>
+ </tr>
+
+ <tr>
+ <td><?= _('Dokumente'); ?></td>
+ <td>
+ <ul class="list-unstyled">
+ <? foreach($documents as $key => $document): ?>
+ <li>
+ <?= Assets::img('languages/lang_' . mb_strtolower($key) . '.gif') ?>
+ <b><?= htmlReady($document->getDisplayName()); ?></b>
+ <? if($document->file_ref->isLink()): ?>
+ <a href="<?= htmlReady($document->getFilename()); ?>" target="_blank"><?= htmlReady($document->getFilename()); ?></a>
+ <? else: ?>
+ <?= htmlReady($document->getFilename()); ?>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </td>
+ </tr>
+
+ <tr>
+ <td><?= _('Kategoriezuordnung'); ?></td>
+ <td><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['CATEGORY']['values'][$doc_cat]['name']); ?></td>
+ </tr>
+
+ <tr>
+ <td><?= _('Schlagwörter'); ?></td>
+ <td>
+ <? if ($doc_tags): ?>
+ <ul>
+ <? foreach(explode(';', $doc_tags) as $tag): ?>
+ <li><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['TAG']['values'][$tag]['name']); ?></li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ </td>
+ </tr>
+
+ <tr>
+ <td><?= _('Sichtbarkeit nach außen'); ?></td>
+ <td><?= $doc_extvisible?_('sichtbar'):_('unsichtbar'); ?></td>
+ </tr>
+
+ <tr>
+ <td><?= _('Zuordnungen'); ?></td>
+ <td>
+
+
+ <? if (!sizeof($relations)) : ?>
+ <?= _('Das Dokument wurde noch nicht referenziert.') ?>
+ <? else : ?>
+ <? foreach ($relations as $object_type => $relation) : ?>
+ <strong><?= htmlReady($object_type::getClassDisplayName()) ?></strong>
+ <ul class="default">
+ <? foreach ($relation as $rel) : ?>
+ <? $related_object = $object_type::find($rel['range_id']) ?>
+ <li>
+ <a href="<?= $this->controller->url_for('materialien/files/dispatch', mb_strtolower($object_type), $rel['range_id']) ?>">
+ <?= $related_object->getDisplayName() ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endforeach; ?>
+ <? endif; ?>
+
+ </td>
+ </tr>
+
+ </table>
+</td>
diff --git a/app/views/materialien/files/index.php b/app/views/materialien/files/index.php
new file mode 100644
index 0000000..af3d8cd
--- /dev/null
+++ b/app/views/materialien/files/index.php
@@ -0,0 +1,129 @@
+<table id="mvv_files" class="default collapsable">
+ <caption>
+ <?= _('Verlinkte Dokumente') ?>
+ <span class="actions"><? printf(ngettext('%s Dokument', '%s Dokumente', $count), $count) ?></span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('materialien/files/', _('Name'), 'mvv_files_filerefs.name') ?>
+ <?= $controller->renderSortLink('materialien/files/', _('Dateiname'), 'file_refs.name') ?>
+ <?= $controller->renderSortLInk('materialien/files/', _('Sichtbarkeit'), 'extern_visible') ?>
+ <?= $controller->renderSortLInk('materialien/files/', _('Sprache'), 'file_language') ?>
+ <?= $controller->renderSortLink('materialien/files/', _('Art der Datei'), 'type') ?>
+ <?= $controller->renderSortLink('materialien/files/', _('Datum'), 'mkdate') ?>
+ <th><?= _('Dateityp') ?></th>
+ <?= $controller->renderSortLInk('materialien/files/', _('Kategorie'), 'category') ?>
+ <?= $controller->renderSortLink('materialien/files/', _('Zuordnungen'), 'count_relations') ?>
+ <th class="actions" style="width: 5%"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+<? foreach ($dokumente as $mvv_file) : ?>
+ <tbody class="<?= (in_array($range_id, $mvv_file->getRangesArray()) && ($fileref_id && in_array($fileref_id, $mvv_file->getFileRefsArray())) ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->link_for('materialien/files/details', $mvv_file->mvvfile_id) ?>">
+ <?= htmlReady($mvv_file->getDisplayName()) ?>
+ </a>
+ </td>
+ <td class="dont-hide">
+ <? if ($mvv_file->getFiletypes()[0] === 'Link'): ?>
+ <a href="<?= htmlReady($mvv_file->file_refs[0]->file_ref->file->metadata['url']); ?>" target="_blank">
+ <?= Icon::create('link-extern')->asImg(['class' => 'text-bottom']) ?>
+ <?= htmlReady($mvv_file->getFilenames()[0]); ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($mvv_file->getFilenames()[0]); ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide" style="text-align: center;">
+ <?= Icon::create(
+ $mvv_file->extern_visible?'visibility-visible':'visibility-invisible',
+ Icon::ROLE_INFO
+ )->asImg([
+ 'class' => 'text-bottom',
+ 'title' => $mvv_file->extern_visible?_('sichtbar'):_('unsichtbar')
+ ]) ?>
+ </td>
+ <td class="dont-hide">
+ <? foreach ($mvv_file->file_refs as $fileref) : ?>
+ <?= Assets::img('languages/lang_' . mb_strtolower($fileref->file_language) . '.gif') ?>
+ <? endforeach; ?>
+ </td>
+ <td class="dont-hide"><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['TYPE']['values'][$mvv_file->type]['name']) ?></td>
+ <td class="dont-hide"><?= strftime('%x', $mvv_file->mkdate) ?></td>
+ <td class="dont-hide"><?= htmlReady($mvv_file->getFiletypes()[0]) ?></td>
+ <td class="dont-hide"><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['CATEGORY']['values'][$mvv_file->category]['name']) ?></td>
+ <td class="dont-hide" style="text-align: center;"><?= htmlReady($mvv_file->count_relations) ?></td>
+ <td class="dont-hide actions">
+ <?
+ $actions = ActionMenu::get();
+ $actions->addLink(
+ $controller->url_for('materialien/files/add_dokument', 'index', $mvv_file->getRangeType()?:0, 0, $mvv_file->mvvfile_id),
+ _('Dokument bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ );
+ $actions->addLink(
+ $controller->url_for('materialien/files/add_ranges_to_file',$mvv_file->mvvfile_id),
+ _('Dokument zuordnen'),
+ Icon::create('file+add'),
+ ['data-dialog' => 'size=auto']
+ );
+ foreach ($mvv_file->file_refs as $fileref) {
+ $actions->addLink(
+ $fileref->file_ref->getDownloadURL('force_download'),
+ _('Datei herunterladen') . ' (' . $fileref->file_language . ')',
+ Icon::create('download'),
+ ['target' => '_blank']
+ );
+ }
+ $actions->addLink(
+ $controller->url_for("materialien/files/delete_all_dokument/{$mvv_file->mvvfile_id}"),
+ _('Dokument löschen'),
+ Icon::create('trash'),
+ [
+ 'data-confirm' => _('Wollen Sie das Dokument wirklich entfernen?'),
+ 'data-dialog' => 'size=auto'
+ ]
+ );
+ echo $actions->render();
+ ?>
+ </td>
+ </tr>
+ <? if (in_array($range_id, $mvv_file->getRangesArray()) && ($fileref_id && in_array($fileref_id, $mvv_file->getFileRefsArray()))) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('materialien/files/details', compact('mvv_file')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+<? endforeach; ?>
+<? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="10" style="text-align: right">
+ <?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ // ARGH!
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_files=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render("shared/pagechooser");
+ ?>
+ </td>
+ </tr>
+ </tfoot>
+<? endif; ?>
+</table>
+<script type="text/javascript">
+jQuery(function ($) {
+ $(document).on('dialog-close', function(event) {
+ if ($('div.ui-dialog.studip-confirmation').length) {
+ STUDIP.MVV.Document.reload_documenttable();
+ }
+ });
+});
+</script>
diff --git a/app/views/materialien/files/new_dokument.php b/app/views/materialien/files/new_dokument.php
new file mode 100644
index 0000000..2401fd5
--- /dev/null
+++ b/app/views/materialien/files/new_dokument.php
@@ -0,0 +1,17 @@
+<form class="default" action="<?= $controller->url_for('/new_dokument') ?>" method="post" data-dialog="size=auto">
+
+ <label>
+ <select id="mvv-contacts-range_types" name="range_type">
+ <? foreach ($allowed_object_types as $object_type) : ?>
+ <option value="<?= $object_type ?>"><?= htmlReady($object_type::getClassDisplayName()) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Weiter'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+</form> \ No newline at end of file
diff --git a/app/views/materialien/files/range.php b/app/views/materialien/files/range.php
new file mode 100644
index 0000000..b00ac14
--- /dev/null
+++ b/app/views/materialien/files/range.php
@@ -0,0 +1,113 @@
+<div id="messagebox-container">
+<? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $messagebox) : ?>
+ <?= $messagebox ?>
+ <? endforeach ?>
+<? endif; ?>
+</div>
+<table id="mvv_files" class="default sortable-table" data-sortlist="[[0, 0]]">
+ <caption>
+ <span class="actions">
+ <a href="<?= $controller->url_for('materialien/files/add_dokument', 'range', $range_type, $range_id);?>" data-dialog="">
+ <?= Icon::create('upload+add', Icon::ROLE_CLICKABLE, ['title' => _('neues Dokument hinzufügen')]); ?>
+ </a>
+ <a href="<?= $controller->url_for('materialien/files/add_files_to_range',$range_type, $range_id);?>" data-dialog="">
+ <?= Icon::create('file+add', Icon::ROLE_CLICKABLE, ['title' => _('vorhandenes Dokument hinzufügen')]); ?>
+ </a>
+ <a href="<?= $controller->url_for('materialien/files/sort', $range_type, $range_id);?>" data-dialog="size=auto">
+ <?= Icon::create('arr_2up', Icon::ROLE_CLICKABLE, ['title' => _('Reihenfolge der Dokumente ändern')]); ?>
+ </a>
+ </span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <th data-sorter="digit"><?= _('Pos.') ?></th>
+ <th data-sorter="text"><?= _('Name') ?></th>
+ <th data-sorter="text"><?= _('Dateiname') ?></th>
+ <th data-sorter="digit"><?= _('Sichtbarkeit') ?></th>
+ <th><?= _('Sprache') ?></th>
+ <th data-sorter="text"><?= _('Art der Datei') ?></th>
+ <th data-sorter="digit"><?= _('Datum') ?></th>
+ <th data-sorter="text"><?= _('Dateityp') ?></th>
+ <th data-sorter="text"><?= _('Kategorie') ?></th>
+ <th data-sorter="digit"><?= _('Zuordnungen') ?></th>
+ <th data-sorter="false" style="text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+<? if($dokumente): ?>
+ <tbody>
+ <? foreach($dokumente as $mvv_file): ?>
+ <tr>
+ <td><?= htmlReady($mvv_file->getPositionInRange($range_id)); ?></td>
+ <td><?= htmlReady($mvv_file->getDisplayName()) ?></td>
+ <td data-sort-value="<?= htmlReady($mvv_file->getFilenames()[0]); ?>">
+ <? if($mvv_file->getFiletypes()[0] == 'Link'): ?>
+ <a href="<?= htmlReady($mvv_file->getFilenames()[0]); ?>" target="_blank">
+ <?= Icon::create('link-extern', Icon::ROLE_CLICKABLE, ['class' => 'text-bottom']); ?>
+ <?= htmlReady($mvv_file->getFilenames()[0]); ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($mvv_file->getFilenames()[0]); ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center;" data-sort-value="<?= $mvv_file->extern_visible?'1':'0' ?>">
+ <?= Icon::create(
+ $mvv_file->extern_visible?'visibility-visible':'visibility-invisible',
+ Icon::ROLE_INFO,
+ [
+ 'class' => 'text-bottom',
+ 'title' => $mvv_file->extern_visible?_('sichtbar'):_('unsichtbar')
+ ]
+ );
+ ?>
+ </td>
+ <td>
+ <? foreach ($mvv_file->file_refs as $fileref) : ?>
+ <?= Assets::img('languages/lang_' . mb_strtolower($fileref->file_language) . '.gif') ?>
+ <? endforeach; ?>
+ </td>
+ <td><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['TYPE']['values'][$mvv_file->type]['name']); ?></td>
+ <td data-sort-value="<?= htmlReady($mvv_file->mkdate); ?>"><?= htmlReady(date('d.m.Y', $mvv_file->mkdate)); ?></td>
+ <td style="text-align: center;"><?= htmlReady($mvv_file->getFiletypes()[0]); ?></td>
+ <td><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['CATEGORY']['values'][$mvv_file->category]['name']); ?></td>
+ <td style="text-align: center;"><?= htmlReady($mvv_file->count_relations); ?></td>
+ <td class="actions">
+ <?
+ $actions = ActionMenu::get();
+ $actions->addLink(
+ $controller->url_for('materialien/files/details',$mvv_file->mvvfile_id),
+ _('Details'),
+ Icon::create('info-circle'),
+ ['data-dialog' => 'size=auto']
+ );
+ $actions->addLink(
+ $controller->url_for('materialien/files/add_dokument','range', $range_type, $range_id, $mvv_file->mvvfile_id),
+ _('Dokument bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => '']
+ );
+ foreach ($mvv_file->file_refs as $fileref) {
+ $actions->addLink(
+ $fileref->file_ref->getDownloadURL('force_download'),
+ _('Datei herunterladen') . ' (' . $fileref->file_language . ')',
+ Icon::create('download', 'clickable', ['size' => 20]),
+ ['target' => '_blank']
+ );
+ }
+ $actions->addLink(
+ $controller->url_for('materialien/files/delete_range', $mvv_file->mvvfile_id, $range_id),
+ _('Dokument-Zuordnung löschen'),
+ Icon::create('trash'),
+ [
+ 'data-confirm' => _('Wollen Sie die Zuordnung des Dokuments wirklich entfernen?'),
+ 'data-dialog' => 'size=auto'
+ ]
+ );
+ echo $actions;
+ ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+<? endif; ?>
+</table>
diff --git a/app/views/materialien/files/select_range.php b/app/views/materialien/files/select_range.php
new file mode 100644
index 0000000..1148668
--- /dev/null
+++ b/app/views/materialien/files/select_range.php
@@ -0,0 +1,25 @@
+<form class="default" action="<?= $controller->url_for('/select_range', $range_type) ?>" method="post" data-dialog="">
+ <label>
+ <select class="nested-select" multiple name="range_id[]">
+ <? if ($range_type == 'Studiengang'): ?>
+ <? foreach(Studiengang::getAllEnriched() as $studiengang) : ?>
+ <option value="<?= $studiengang->id; ?>"><?= htmlReady($studiengang->getDisplayName()); ?></option>
+ <? endforeach; ?>
+ <? elseif ($range_type == 'AbschlussKategorie'): ?>
+ <? foreach(AbschlussKategorie::getAllEnriched() as $abs_kat) : ?>
+ <option value="<?= $abs_kat->id; ?>"><?= htmlReady($abs_kat->getDisplayName()); ?></option>
+ <? endforeach; ?>
+ <? endif; ?>
+ </select>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Weiter'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+ <div id="search-contact-params"
+ data-contact=""
+ ></div>
+</form> \ No newline at end of file
diff --git a/app/views/materialien/files/select_range_type.php b/app/views/materialien/files/select_range_type.php
new file mode 100644
index 0000000..e443d5a
--- /dev/null
+++ b/app/views/materialien/files/select_range_type.php
@@ -0,0 +1,17 @@
+<form class="default" action="<?= $controller->url_for('/select_range_type', $mvvfile_id) ?>" method="post" data-dialog="size=auto">
+
+ <label>
+ <select id="mvv-files-range_types" name="range_type">
+ <? foreach ($allowed_object_types as $object_type) : ?>
+ <option value="<?= $object_type ?>"><?= htmlReady($object_type::getClassDisplayName()) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Weiter'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+</form> \ No newline at end of file
diff --git a/app/views/materialien/files/sort.php b/app/views/materialien/files/sort.php
new file mode 100644
index 0000000..30946f2
--- /dev/null
+++ b/app/views/materialien/files/sort.php
@@ -0,0 +1,28 @@
+<script type="text/javascript">
+jQuery(function ($) {
+ $('div.ui-dialog').on('dialogclose', function(event) {
+ STUDIP.MVV.Document.reload_documenttable('<?= htmlReady($range_id) ?>', '<?= htmlReady($range_type) ?>');
+ });
+});
+</script>
+
+<div class="ordering" title="<?= _('Reihenfolge ändern') ?>">
+ <div class="nestable" data-max-depth="1">
+ <? if ($mvv_files): ?>
+ <ol class="dd-list">
+ <? foreach ($mvv_files as $mvv_file): ?>
+ <li class="dd-item" data-id="<?= $mvv_file->mvvfile_id; ?>">
+ <div class="dd-handle"><?= formatReady($mvv_file->getDisplayName()) ?></div>
+ </li>
+ <? endforeach; ?>
+ </ol>
+ <? endif; ?>
+ </div>
+</div>
+
+<form class="default" id="order_form" action="<?= $controller->url_for('/sort', $range_type, $range_id) ?>" method="POST" data-dialog="size=auto">
+ <input type="hidden" name="ordering" id="ordering">
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'order') ?>
+ </footer>
+</form>
diff --git a/app/views/messages/_message_row.php b/app/views/messages/_message_row.php
new file mode 100644
index 0000000..c73fb4e
--- /dev/null
+++ b/app/views/messages/_message_row.php
@@ -0,0 +1,52 @@
+<tr id="message_<?= $message->getId() ?>" class="<?= $message->isRead() || $message['autor_id'] === $GLOBALS['user']->id ? "" : "unread" ?>">
+ <td class="hidden-small-down"><input type="checkbox" name="bulk[]" value="<?= htmlReady($message->getId()) ?>"></td>
+ <td class="title">
+ <a href="<?= URLHelper::getLink("dispatch.php/messages/read/".$message->getId()) ?>" data-dialog>
+ <?= trim($message['subject']) ? htmlReady($message['subject']) : htmlReady(mila(kill_format($message['message']), 40)) ?>
+ <div class="message-indicators">
+ <span><?= $message->getNumAttachments() ? Icon::create('staple', 'info', ["title" => _("Mit Anhang")])->asImg(20) : "" ?></span>
+ <span><?= $message->isAnswered($GLOBALS['user']->id) ? Icon::create('outbox', 'info', ["title" => _("Beantwortet")])->asImg(20) : "" ?></span>
+ </div>
+ </a>
+ <p class="hidden-medium-up responsive_author">
+ <? if ($message['autor_id'] == "____%system%____") : ?>
+ <?= _("Systemnachricht") ?>
+ <? elseif (!$received): ?>
+ <? $num_recipients = $message->getNumRecipients() ?>
+ <? if ($num_recipients > 1) : ?>
+ <?= sprintf(_("%s Personen"), $num_recipients) ?>
+ <? else : ?>
+ <?= htmlReady(get_fullname($message->receivers[0]['user_id'])) ?>
+ <? endif ?>
+ <? else: ?>
+ <?= htmlReady(get_fullname($message['autor_id'])) ?>
+ <? endif; ?>
+ </p>
+ </td>
+ <td class="hidden-small-down">
+ <? if ($message['autor_id'] == "____%system%____") : ?>
+ <?= _("Systemnachricht") ?>
+ <? elseif (isset($received) && !$received): ?>
+ <? $num_recipients = $message->getNumRecipients() ?>
+ <? if ($num_recipients > 1) : ?>
+ <?= sprintf(_("%s Personen"), $num_recipients) ?>
+ <? else : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => get_username($message->receivers[0]['user_id'])]) ?>">
+ <?= htmlReady(get_fullname($message->receivers[0]['user_id'])) ?>
+ </a>
+ <? endif ?>
+ <? else: ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => get_username($message['autor_id'])]) ?>">
+ <?= htmlReady(get_fullname($message['autor_id'])) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <td><?= strftime('%x %R', $message['mkdate']) ?></td>
+ <td class="tag-container hidden-small-down">
+ <? foreach ($message->getTags() as $tag) : ?>
+ <a href="<?= URLHelper::getLink("?", ['tag' => $tag]) ?>" class="message-tag" title="<?= _("Alle Nachrichten zu diesem Schlagwort") ?>">
+ <?= htmlReady(ucfirst($tag)) ?>
+ </a>
+ <? endforeach ?>
+ </td>
+</tr>
diff --git a/app/views/messages/overview.php b/app/views/messages/overview.php
new file mode 100644
index 0000000..9eae50b
--- /dev/null
+++ b/app/views/messages/overview.php
@@ -0,0 +1,102 @@
+<input type="hidden" name="received" id="received" value="<?= (int) $received ?>">
+<input type="hidden" name="since" id="since" value="<?= time() ?>">
+<input type="hidden" name="folder_id" id="tag" value="<?= htmlReady(ucfirst(Request::get("tag"))) ?>">
+<input type="hidden" name="search" id="search" value="<?= htmlReady(Request::get("search")) ?>">
+<input type="hidden" name="search_autor" id="search_autor" value="<?= htmlReady(Request::get("search_autor")) ?>">
+<input type="hidden" name="search_subject" id="search_subject" value="<?= htmlReady(Request::get("search_subject")) ?>">
+<input type="hidden" name="search_content" id="search_content" value="<?= htmlReady(Request::get("search_content")) ?>">
+
+<form action="?" method="post" id="bulk">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default" id="messages">
+ <caption>
+ <?= $received ? _("Eingang") : _("Gesendet") ?>
+ <? if (Request::get("tag")) : ?>
+ <?= ', ' . _('Schlagwort') . ': ' . htmlReady(ucfirst(Request::get('tag'))) ?>
+ <button onClick="STUDIP.Dialog.confirmAsPost('<?=_('Schlagwort wirklich löschen?')?>', '<?=$controller->link_for('messages/delete_tag', ['tag' => Request::get('tag')])?>');return false;" style="background: none; border: none; cursor: pointer;" title="<?= _("Schlagwort von allen Nachrichten entfernen.") ?>">
+ <?= Icon::create('trash', 'clickable')->asImg(20) ?>
+ </button>
+ <? endif ?>
+ </caption>
+ <colgroup>
+ <col class="hidden-small-down">
+ <col>
+ <col class="hidden-small-down">
+ <col style="width: 20ex">
+ <col class="hidden-small-down">
+ </colgroup>
+ <thead>
+ <tr>
+ <th class="hidden-small-down">
+ <input type="checkbox" data-proxyfor="#bulk tbody :checkbox">
+ </th>
+ <th><?= _("Betreff") ?></th>
+ <th class="hidden-small-down"><?= $received ? _('Absender') : _('Empfänger') ?></th>
+ <th><?= _("Zeit") ?></th>
+ <th class="hidden-small-down"><?= _("Schlagworte") ?></th>
+ </tr>
+ </thead>
+
+ <tbody aria-relevant="additions" aria-live="polite" data-shiftcheck>
+ <? if (count($messages) > 0) : ?>
+ <? if ($more || (Request::int("offset") > 0)) : ?>
+ <noscript>
+ <tr>
+ <td colspan="8">
+ <? if (Request::int("offset") > 0) : ?>
+ <a title="<?= _("zurück") ?>" href="<?= URLHelper::getLink("?", ['offset' => Request::int("offset") - $messageBufferCount > 0 ? Request::int("offset") - $messageBufferCount : null]) ?>"><?= Icon::create('arr_1left', 'clickable')->asImg(["class" => "text-bottom"]) ?></a>
+ <? endif ?>
+ <? if ($more) : ?>
+ <div style="float:right">
+ <a title="<?= _("weiter") ?>" href="<?= URLHelper::getLink("?", ['offset' => Request::int("offset") + $messageBufferCount]) ?>"><?= Icon::create('arr_1right', 'clickable')->asImg(["class" => "text-bottom"]) ?></a>
+ </div>
+ <? endif ?>
+ </td>
+ </tr>
+ </noscript>
+ <? endif ?>
+ <? foreach ($messages as $message) : ?>
+ <?= $this->render_partial("messages/_message_row.php", compact("message", "received". "settings")) ?>
+ <? endforeach ?>
+ <? if ($more || (Request::int("offset") > 0)) : ?>
+ <noscript>
+ <tr>
+ <td colspan="7">
+ <? if (Request::int("offset") > 0) : ?>
+ <a title="<?= _("zurück") ?>" href="<?= URLHelper::getLink("?", ['offset' => Request::int("offset") - $messageBufferCount > 0 ? Request::int("offset") - $messageBufferCount : null]) ?>"><?= Icon::create('arr_1left', 'clickable')->asImg(["class" => "text-bottom"]) ?></a>
+ <? endif ?>
+ <? if ($more) : ?>
+ <div style="float:right">
+ <a title="<?= _("weiter") ?>" href="<?= URLHelper::getLink("?", ['offset' => Request::int("offset") + $messageBufferCount]) ?>"><?= Icon::create('arr_1right', 'clickable')->asImg(["class" => "text-bottom"]) ?></a>
+ </div>
+ <? endif ?>
+ </td>
+ </tr>
+ </noscript>
+ <? endif ?>
+ <? else : ?>
+ <tr>
+ <td colspan="7" style="text-align: center"><?= _("Keine Nachrichten") ?></td>
+ </tr>
+ <? endif ?>
+ <tr id="reloader" class="more">
+ <td colspan="7"><?= Assets::img("ajax_indicator_small.gif") ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+</form>
+
+
+<div style="display: none; background-color: rgba(255,255,255, 0.3); padding: 3px; border-radius: 5px; border: thin solid black;" id="move_handle">
+ <?= Icon::create('mail', 'clickable')->asImg(20, ['class' => "text-bottom"]) ?>
+ <span class="title"></span>
+</div>
+
+<? if ($message_id): ?>
+<script>
+jQuery(function ($) {
+ STUDIP.Dialog.fromURL('<?= $controller->url_for('messages/read/' . $message_id) ?>');
+});
+</script>
+<? endif; ?>
diff --git a/app/views/messages/print.php b/app/views/messages/print.php
new file mode 100644
index 0000000..db7b6b4
--- /dev/null
+++ b/app/views/messages/print.php
@@ -0,0 +1,30 @@
+<div>
+<span style="font-weight:bold"><?php echo _("Betreff")?>:</span>
+<span style="padding-left:5px"><?php echo htmlReady($msg['subject'])?></span>
+</div>
+<div>
+<span style="font-weight:bold"><?php echo _("Datum")?>:</span>
+<span style="padding-left:5px"><?php echo strftime('%x %X', $msg['mkdate'])?></span>
+</div>
+<div>
+<span style="font-weight:bold"><?php echo _("Von")?>:</span>
+<span style="padding-left:5px"><?php echo htmlReady($msg['from'])?></span>
+</div>
+<div>
+<span style="font-weight:bold"><?php echo _("An")?>:</span>
+<span style="padding-left:5px"><?php echo htmlReady($msg['to'])?></span>
+</div>
+<div style="margin-top:10px;margin-bottom:10px;">
+<?php echo formatReady($msg['message'])?>
+</div>
+<?php if (!empty($msg['attachments'])) : ?>
+ <hr>
+ <div style="font-weight:bold">
+ <?php echo _("Dateianhänge:")?>
+ </div>
+ <?php foreach($msg['attachments'] as $one) : ?>
+ <div>
+ <?php echo htmlReady($one['name']) . ' (' . relsize($one['size'], false) . ')' ?>
+ </div>
+ <?php endforeach;?>
+<?php endif;?>
diff --git a/app/views/messages/read.php b/app/views/messages/read.php
new file mode 100644
index 0000000..24b4c8a
--- /dev/null
+++ b/app/views/messages/read.php
@@ -0,0 +1,102 @@
+<? if (!Request::isXhr()) : ?>
+ <h1 class="responsive-hidden"><?= _("Betreff").": ".htmlReady($message["subject"]) ?></h1>
+<? endif ?>
+
+<? if ($message["autor_id"] !== "____%system%____") : ?>
+<div style="float:left; margin-right: 10px;"><?= Avatar::getAvatar($message["autor_id"])->getImageTag(Avatar::MEDIUM) ?></div>
+<? endif ?>
+<table id="message_metadata" data-message_id="<?= $message->getId() ?>">
+ <tbody>
+ <tr>
+ <td><strong><?= _("Von") ?></strong></td>
+ <td>
+ <? if ($message['autor_id'] === '____%system%____'): ?>
+ <?= _('Stud.IP') ?>
+ <? else: ?>
+ <a href="<?= URLHelper::getLink("dispatch.php/profile", ['username' => get_username($message["autor_id"])]) ?>"><?= htmlReady(get_fullname($message["autor_id"])) ?></a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _("An") ?></strong></td>
+ <td>
+ <? $num_recipients = $message->getNumRecipients() ?>
+ <? if ($message["autor_id"] !== $GLOBALS["user"]->id && (!$message['show_adressees'] || $num_recipients > Config::get()->SHOW_ADRESSEES_LIMIT)) : ?>
+ <?= $num_recipients > 1 ? sprintf(_("%s Personen"), $num_recipients) : _("Eine Person") ?>
+ <? else : ?>
+ <ul class="list-csv" id="adressees">
+ <? foreach ($message->getRecipients() as $message_user) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink("dispatch.php/profile", ['username' => $message_user["username"]]) ?>">
+ <?= htmlReady($message_user['fullname']) ?><!-- avoid extra space before ::after
+ --></a><!--
+ --></li>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _("Datum") ?></strong></td>
+ <td><?= date("d.m.Y H:i", $message['mkdate']) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _("Schlagworte") ?></strong></td>
+ <td>
+ <form id="message-tags" action="<?= $controller->url_for('messages/tag/' . $message->id) ?>" method="post" data-dialog>
+ <? foreach ($message->getTags() as $tag) : ?>
+ <span>
+ <a href="<?= URLHelper::getLink("?", ['tag' => $tag]) ?>" class="message-tag" title="<?= _("Alle Nachrichten zu diesem Schlagwort") ?>">
+ <?= htmlReady($tag) ?>
+ </a>
+ <?= Icon::create('trash', 'clickable', ['title' => _("Schlagwort entfernen")])->asInput(["class" => 'text-bottom', "name" => 'remove_tag', "value" => $tag]) ?>
+ </span>
+ <? endforeach ?>
+ <span>
+ <input type="text" name="add_tag" style="width: 50px; opacity: 0.8;">
+ <?= Icon::create('add', 'clickable', ['title' => _("Schlagwort hinzufügen")])->asInput(["class" => 'text-bottom']) ?>
+ </span>
+ </form>
+ </td>
+ </tr>
+ </tbody>
+</table>
+<div class="clear"></div>
+
+<div class="message_body">
+ <?= formatReady($message["message"]) ?>
+</div>
+<? if($attachment_folder): ?>
+<h3><?= Icon::create('staple', 'inactive')->asImg(20, ["class" => "text-bottom"]) ?><?= _('Anhänge') ?></h3>
+ <table class="default sortable-table" data-sortlist="[[2, 0]]">
+ <?= $this->render_partial('files/_files_thead') ?>
+ <? foreach($attachment_folder->getFiles() as $file): ?>
+ <? if ($file->isVisible($GLOBALS['user']->id)) : ?>
+ <?= $this->render_partial(
+ 'files/_fileref_tr',
+ [
+ 'file' => $file,
+ 'current_folder' => $attachment_folder,
+ 'last_visitdate' => time()
+ ]
+ ) ?>
+ <? endif ?>
+ <? endforeach ?>
+ </table>
+<? endif ?>
+
+<div align="center" data-dialog-button>
+ <div class="button-group">
+ <? if ($message['autor_id'] !== '____%system%____'): ?>
+ <a href="<?= URLHelper::getLink("dispatch.php/messages/write", ['answer_to' => $message->getId(), 'quote' => $message->getId()]) ?>" data-dialog="width=700;height=700"><?= \Studip\Button::create(_("Antworten"))?></a>
+ <? endif; ?>
+ <a href="<?= URLHelper::getLink("dispatch.php/messages/write", ['answer_to' => $message->getId(), 'forward' => "rec"]) ?>" data-dialog="width=700;height=700"><?= \Studip\Button::create(_("Weiterleiten"))?></a>
+ </div>
+ <a href="<?= URLHelper::getLink("dispatch.php/messages/print/".$message->getId()) ?>" class="print_action"><?= \Studip\Button::create(_("Drucken"))?></a>
+ <form action="<?= $controller->url_for('messages/delete/' . $message->id) ?>" method="post" style="display: inline;">
+ <input type="hidden" name="studip-ticket" value="<?= get_ticket() ?>">
+ <?= \Studip\Button::create(_("Löschen"), 'delete', [
+ 'onClick' => 'return window.confirm("' . _('Nachricht wirklich löschen?') . '");',
+ ])?>
+ </form>
+</div>
diff --git a/app/views/messages/send.php b/app/views/messages/send.php
new file mode 100644
index 0000000..99e6963
--- /dev/null
+++ b/app/views/messages/send.php
@@ -0,0 +1,5 @@
+<? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $messagebox) : ?>
+ <?= $messagebox ?>
+ <? endforeach ?>
+<? endif ?> \ No newline at end of file
diff --git a/app/views/messages/write.php b/app/views/messages/write.php
new file mode 100644
index 0000000..af3fe25
--- /dev/null
+++ b/app/views/messages/write.php
@@ -0,0 +1,179 @@
+<form class="default" name="write_message" action="<?= URLHelper::getLink("dispatch.php/messages/send") ?>" method="post" style="margin-left: auto; margin-right: auto;" data-dialog data-secure="#adressees > li:eq(1), .files > li:eq(1)">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <input type="hidden" name="message_id" id="message_id" value="<?= htmlReady($default_message->id) ?>">
+ <input type="hidden" name="answer_to" value="<?= htmlReady($answer_to) ?>">
+
+ <fieldset>
+ <legend><?= _('Neue Nachricht') ?></legend>
+ <div>
+ <label for="user_id_1"><?= _("An") ?></label>
+ <ul class="list-csv" id="adressees">
+ <li id="template_adressee" style="display: none;" class="adressee">
+ <input type="hidden" name="message_to[]" value="">
+ <span class="visual"></span>
+ <a class="remove_adressee"><?= Icon::create('trash', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ </li>
+ <? foreach ($default_message->getRecipients() as $user) : ?>
+ <li class="adressee">
+ <input type="hidden" name="message_to[]" value="<?= htmlReady($user['user_id']) ?>">
+ <span class="visual">
+ <?= htmlReady($user['fullname']) ?>
+ </span>
+ <a class="remove_adressee"><?= Icon::create('trash', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <div class="message-search-wrapper">
+ <?= QuickSearch::get('user_id', new StandardSearch('user_id'))
+ ->fireJSFunctionOnSelect('STUDIP.Messages.add_adressee')
+ ->withButton()
+ ->render();
+
+ $mps = MultiPersonSearch::get('add_adressees')
+ ->setLinkText(_('Mehrere Adressaten hinzufügen'))
+ //->setDefaultSelectedUser($defaultSelectedUser)
+ ->setTitle(_('Mehrere Adressaten hinzufügen'))
+ ->setExecuteURL($controller->url_for('messages/write'))
+ ->setJSFunctionOnSubmit('STUDIP.Messages.add_adressees')
+ ->setSearchObject($this->mp_search_object);
+ foreach (Statusgruppen::findContactGroups() as $group) {
+ $mps->addQuickfilter(
+ $group['name'],
+ $group->members->pluck('user_id')
+ );
+ }
+ echo $mps->render();
+ ?>
+ </div>
+ <script>
+ STUDIP.MultiPersonSearch.init();
+ </script>
+ </div>
+ <div>
+ <label>
+ <?= _("Betreff") ?>
+ <input type="text" name="message_subject" style="width: 100%" required value="<?= htmlReady($default_message['subject']) ?>">
+ </label>
+ </div>
+ <div>
+ <label>
+ <?= _("Nachricht") ?>
+ <textarea style="width: 100%; height: 200px;" name="message_body" class="add_toolbar wysiwyg"><?= wysiwygReady($default_message['message'],false) ?></textarea>
+ </label>
+ </div>
+ <div>
+ <ul class="message-options">
+ <? if ($GLOBALS['ENABLE_EMAIL_ATTACHMENTS']): ?>
+ <li>
+ <a href="" onClick="STUDIP.Messages.toggleSetting('attachments'); return false;">
+ <?= Icon::create('staple', 'clickable')->asImg(40) ?>
+ <br>
+ <strong><?= _("Anhänge") ?></strong>
+ </a>
+ </li>
+ <? endif; ?>
+ <li>
+ <a href="" onClick="STUDIP.Messages.toggleSetting('tags'); return false;">
+ <?= Icon::create('star', 'clickable')->asImg(40) ?>
+ <br>
+ <strong><?= _("Schlagworte") ?></strong>
+ </a>
+ </li>
+ <li>
+ <a href="" onClick="STUDIP.Messages.toggleSetting('settings'); return false;">
+ <?= Icon::create('admin', 'clickable')->asImg(40) ?>
+ <br>
+ <strong><?= _("Optionen") ?></strong>
+ </a>
+ </li>
+ <? if (!\Studip\Markup::editorEnabled()) : ?>
+ <li>
+ <a href="" onClick="STUDIP.Messages.toggleSetting('preview'); STUDIP.Messages.previewComposedMessage(); return false;">
+ <?= Icon::create('visibility-visible', 'clickable')->asImg(40) ?>
+ <br>
+ <strong><?= _("Vorschau") ?></strong>
+ </a>
+ </li>
+ <? endif ?>
+ </ul>
+ </div>
+
+<? if ($GLOBALS['ENABLE_EMAIL_ATTACHMENTS']): ?>
+ <div id="attachments" style="<?= $default_attachments ? '' : 'display: none;'?>">
+ <?= _("Anhänge") ?>
+ <div>
+ <ul class="files">
+ <li style="display: none;" class="file">
+ <span class="icon"></span>
+ <span class="name"></span>
+ <span class="size"></span>
+ <a class="remove_attachment"><?= Icon::create('trash', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ </li>
+ <? if ($default_attachments) : ?>
+ <? foreach ($default_attachments as $a) : ?>
+ <li class="file" data-document_id="<?=$a['document_id']?>">
+ <span class="icon"><?=$a['icon']?></span>
+ <span class="name"><?=$a['name']?></span>
+ <span class="size"><?=$a['size']?></span>
+ <a class="remove_attachment"><?= Icon::create('trash', 'clickable')->asImg(['class' => "text-bottom"]) ?></a>
+ </li>
+ <? endforeach ?>
+ <? endif ?>
+ </ul>
+ <div id="statusbar_container">
+ <div class="statusbar" style="display: none;">
+ <div class="progress"></div>
+ <div class="progresstext">0%</div>
+ </div>
+ </div>
+ <label style="cursor: pointer;">
+ <input type="file" id="fileupload" multiple onChange="STUDIP.Messages.upload_from_input(this);" style="display: none;">
+ <?= Icon::create('upload', 'clickable', ['title' => _("Datei hochladen"), 'class' => "text-bottom"])->asImg(20) ?>
+ <?= _("Datei hochladen") ?>
+ </label>
+
+ <div id="upload_finished" style="display: none"><?= _("wird verarbeitet") ?></div>
+ <div id="upload_received_data" style="display: none"><?= _("gespeichert") ?></div>
+ </div>
+ </div>
+<? endif; ?>
+ <div id="tags" style="<?= Request::get("default_tags") ? "" : 'display: none; ' ?>">
+ <label>
+ <?= _("Schlagworte") ?>
+ <input type="text"
+ name="message_tags"
+ style="width: 100%"
+ placeholder="<?= _("z.B. klausur termin statistik etc.") ?>"
+ value="<?= htmlReady($default_tags) ?>">
+ </label>
+ </div>
+ <div id="settings" style="display: none;">
+ <?= _("Optionen") ?>
+ <label for="message_mail">
+ <input type="checkbox" name="message_mail" id="message_mail" value="1"<?= $mailforwarding ? " checked" : "" ?>>
+ <?= _("Immer per E-Mail weiterleiten") ?>
+ </label>
+
+ <? if (isset($show_adressees)) : ?>
+ <label for="show_adressees">
+ <input type="checkbox" name="show_adressees" id="show_adressees" value="1"<?= $show_adressees ? " checked" : "" ?>>
+ <?= _("Sollen die Adressaten für die Empfänger sichtbar sein?") ?>
+ </label>
+ <? endif ?>
+ </div>
+ </fieldset>
+
+ <? if (!\Studip\Markup::editorEnabled()) : ?>
+ <div id="preview" style="display: none;">
+ <?= _("Vorschau") ?>
+ <p class="message_body"></p>
+ </div>
+ <? endif ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Abschicken'), null, ['onclick' => "STUDIP.Messages.checkAdressee();"]) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('messages')) ?>
+ </footer>
+
+</form>
diff --git a/app/views/module/download/doc.php b/app/views/module/download/doc.php
new file mode 100644
index 0000000..2519a5f
--- /dev/null
+++ b/app/views/module/download/doc.php
@@ -0,0 +1,60 @@
+<html lang="de" xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'>
+ <head>
+ <meta charset="UTF-8">
+ <title><?= htmlReady($modul->getDisplayName()) ?></title>
+
+ <!--[if gte mso 9]>
+ <xml>
+ <w:WordDocument>
+ <w:View>Print</w:View>
+ <w:Zoom>90</w:Zoom>
+ <w:DoNotOptimizeForBrowser/>
+ </w:WordDocument>
+ </xml>
+ <![endif]-->
+
+ <style>
+
+ div.Section1 {
+ page: Section1;
+ font: italic 10pt arial, sans-serif;
+ }
+ table.mvv-modul-details {
+ border: 1px solid black;
+ border-collapse: collapse;
+ font: 8pt arial, sans-serif;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ margin-bottom: 10px;
+ }
+ table.mvv-modul-details td, table.mvv-modul-details th {
+ border: 1px solid black;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ }
+ table.mvv-modul-details th {
+ text-align: left;
+ vertical-align: top;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ }
+
+ </style>
+ </head>
+ <body>
+ <div class="Section1" style="font: 10pt arial, sans-serif;">
+ <?= $this->render_partial('shared/modul/_modul') ?>
+ <? if ($type === 1) : ?>
+ <?= $this->render_partial('shared/modul/_modullvs') ?>
+ <?= $this->render_partial('shared/modul/_pruefungen') ?>
+ <?= $this->render_partial('shared/modul/_regularien') ?>
+ <? endif;?>
+ <? if ($type === 2): ?>
+ <?= $this->render_partial('shared/modul/_modullv') ?>
+ <? endif; ?>
+ <? if ($type === 3) : ?>
+ <?= $this->render_partial('shared/modul/_modul_ohne_lv') ?>
+ <? endif; ?>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/app/views/module/download/pdf.php b/app/views/module/download/pdf.php
new file mode 100644
index 0000000..b00831f
--- /dev/null
+++ b/app/views/module/download/pdf.php
@@ -0,0 +1,33 @@
+<style>
+ table.mvv-modul-details {
+ border: 1px solid black;
+ border-collapse: collapse;
+ hyphens: auto;
+ font: 8pt normal;
+ width: 100%;
+ }
+ table.mvv-modul-details td, table.mvv-modul-details th {
+ border: 1px solid black;
+ hyphens: auto;
+ }
+ table.mvv-modul-details th {
+ text-align: left;
+ vertical-align: top;
+ hyphens: auto;
+ }
+</style>
+<?= $this->render_partial('shared/modul/_modul') ?>
+<br><br>
+<? if ($type === 1) : ?>
+<?= $this->render_partial('shared/modul/_modullvs') ?>
+<br><br>
+<?= $this->render_partial('shared/modul/_pruefungen') ?>
+<br><br>
+<?= $this->render_partial('shared/modul/_regularien') ?>
+<? endif;?>
+<? if ($type === 2): ?>
+<?= $this->render_partial('shared/modul/_modullv') ?>
+<? endif; ?>
+<? if ($type === 3) : ?>
+<?= $this->render_partial('shared/modul/_modul_ohne_lv') ?>
+<? endif; ?>
diff --git a/app/views/module/institute/details.php b/app/views/module/institute/details.php
new file mode 100644
index 0000000..c62b4bb
--- /dev/null
+++ b/app/views/module/institute/details.php
@@ -0,0 +1,17 @@
+<td colspan="2">
+ <table class="default collapsable">
+ <thead>
+ <tr>
+ <th style="width: 7%;"><?= _('Modulcode') ?></th>
+ <th><?= _('Modul') ?></th>
+ <th style="width: 5%;"><?= _('Fassung') ?></th>
+ <th style="width: 5%;"><?= _('Modulteile') ?></th>
+ <th style="text-align: center; width: 150px;">
+ <?= _('Ausgabesprachen') ?>
+ </th>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <?= $this->render_partial('module/module/module') ?>
+ </table>
+</td> \ No newline at end of file
diff --git a/app/views/module/institute/index.php b/app/views/module/institute/index.php
new file mode 100644
index 0000000..e2125ed
--- /dev/null
+++ b/app/views/module/institute/index.php
@@ -0,0 +1,35 @@
+<?= $controller->jsUrl() ?>
+<table class="default collapsable">
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('module/institute/index', _('Einrichtung'), 'name', ['style' => 'width: 75%;']) ?>
+ <?= $controller->renderSortLink('module/institute/index', _('Module'), 'count_objects', ['style' => 'text-align: center;']) ?>
+ </tr>
+ </thead>
+ <? foreach ($institute as $institut) : ?>
+ <? if (!$institut->id) continue; ?>
+ <tbody class="<?= ($institut->count_objects ? '' : 'empty') ?> <?= ($inst_id == $institut->id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row" id="institut_<?= $institut->id ?>">
+ <td class="toggle-indicator">
+ <? if ($institut->count_objects) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details', ['institut_id' => $institut->id]) ?>">
+ <?= htmlReady($institut->getDisplayName()) ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($institut->getDisplayName()) ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center;" class="dont-hide"><?= $institut->count_objects ?></td>
+ </tr>
+ <? if ($institut->id && $inst_id == $institut->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('module/institute/details',
+ ['institut_id' => $institut->id]
+ ) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+</table>
+
diff --git a/app/views/module/modul_teile/index.php b/app/views/module/modul_teile/index.php
new file mode 100644
index 0000000..7ff04e7
--- /dev/null
+++ b/app/views/module/modul_teile/index.php
@@ -0,0 +1,3 @@
+<div id="main">
+ <h3>Module Modulteile</h3>
+</div> \ No newline at end of file
diff --git a/app/views/module/module/approve.php b/app/views/module/module/approve.php
new file mode 100644
index 0000000..c2348dc
--- /dev/null
+++ b/app/views/module/module/approve.php
@@ -0,0 +1,12 @@
+<form name="approve"
+ action="<?= $controller->url_for('/approve/' . $modul_id) ?>"
+ method="post" class="default">
+
+ <? $response = $controller->relay('shared/modul/description/' . $modul_id); ?>
+ <?= $response->body ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Genehmigen'), 'approval') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), ['data-dialog' => 'close']) ?>
+ </footer>
+</form>
diff --git a/app/views/module/module/assignments.php b/app/views/module/module/assignments.php
new file mode 100644
index 0000000..5d6537a
--- /dev/null
+++ b/app/views/module/module/assignments.php
@@ -0,0 +1,13 @@
+<section>
+ <h3><?= _('Verwendet in Studiengängen') ?></h3>
+ <? $trails = $modul->getTrails(['Studiengang', 'StgteilVersion', 'StgteilAbschnitt']); ?>
+ <? if (count($trails)) : ?>
+ <ul>
+ <? foreach ($modul->getPathes($trails, ' > ') as $path) : ?>
+ <li><?= htmlReady($path) ?></li>
+ <? endforeach; ?>
+ </ul>
+ <? else : ?>
+ <strong><?= _('Keine Zuordnungen vorhanden') ?></strong>
+ <? endif; ?>
+</section>
diff --git a/app/views/module/module/copy_form.php b/app/views/module/module/copy_form.php
new file mode 100644
index 0000000..da95611
--- /dev/null
+++ b/app/views/module/module/copy_form.php
@@ -0,0 +1,95 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? if ($modul) : ?>
+ <? $end_sem = Semester::find($modul->end); ?>
+ <? if (!$end_sem) : ?>
+ <?= MessageBox::warning(
+ _('Das Modul kann nicht kopiert werden, da die aktuellste Version unbegrenzt gültig ist. Setzen Sie erst ein Endsemester für die aktuellste Version.')
+ ) ?>
+ <? if ($perm->havePermRead()) : ?>
+ <section>
+ <p>
+ <a href="<?= $controller->url_for('/modul/' . $modul->id) ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE ,['title' => _('Modul bearbeiten')]) ?>
+ <strong><?= _('Aktuellste Version bearbeiten') ?></strong>
+ </a>
+ </p>
+ </section>
+ <? endif; ?>
+ <? endif; ?>
+
+ <form class="default" action="<?= $submit_url ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($end_sem) : ?>
+ <section>
+ <h3>
+ <?= htmlReady(sprintf(
+ _('Wollen Sie wirklich das Modul "%s" und alle zugehörigen Modulteile kopieren?'),
+ $modul->getDisplayName()
+ )) ?>
+ </h3>
+ </section>
+ <? endif; ?>
+ <section>
+ <dl>
+ <dt>
+ <?= _('Das Modul ist in seiner aktuellsten Version gültig von:') ?>
+ </dt>
+ <dd>
+ <?= htmlReady(Semester::find($modul->start)->name) ?>
+ </dd>
+ <dt>
+ <?= _('Bis:') ?>
+ </dt>
+ <dd>
+ <?= htmlReady($end_sem->name ?: _('unbegrenzt')) ?>
+ </dd>
+ </dl>
+ </section>
+ <? if ($end_sem) : ?>
+ <section>
+ <dl>
+ <dt>
+ <?= _('Neues Startsemester:') ?>
+ </dt>
+ <dd>
+ <?= htmlReady(Semester::findNext($end_sem->ende)->name) ?>
+ </dd>
+ <dt>
+ <label for="end_sem"><?= _('Gültig bis:') ?></label>
+ </dt>
+ <dd>
+ <select name="end_sem" id="end_sem">
+ <option value=""><?= _('unbegrenzt') ?></option>
+ <? foreach (Semester::getAll() as $end_sem_new) : ?>
+ <? if ($end_sem_new->beginn > $end_sem->ende) : ?>
+ <option value="<?= htmlReady($end_sem_new->id) ?>">
+ <?= htmlReady($end_sem_new->name) ?>
+ </option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </dd>
+ </dl>
+ </section>
+ <section>
+ <p>
+ <label class="undecorated">
+ <input type="checkbox" name="copy_assignments" value="1" checked>
+ <?= _('Zuordnungen zu Studiengängen mit übernehmen') ?>
+ </label>
+ <a title="<?= _('Verwendet in Studiengängen') ?>"
+ href="<?= $controller->url_for('/assignments/' . $modul->id) ?>"
+ onclick="STUDIP.Dialog.fromURL(this.href, {title: this.title, resizable: true, id: 'stgteil_assignments'}); return false;">
+ <?= Icon::create('info-circle', Icon::ROLE_CLICKABLE , ['title' => _('Zuordnungen anzeigen')]) ?>
+ </a>
+ </p>
+ </section>
+ <? endif; ?>
+ <footer data-dialog-button>
+ <? if ($perm->havePermWrite() && $end_sem) : ?>
+ <?= Button::createAccept(_('Kopieren'), 'copy', ['title' => _('Modul kopieren')]) ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('Zurück zur Übersicht')]) ?>
+ </footer>
+ </form>
+<? endif; ?>
diff --git a/app/views/module/module/details.php b/app/views/module/module/details.php
new file mode 100644
index 0000000..b8f813e
--- /dev/null
+++ b/app/views/module/module/details.php
@@ -0,0 +1,87 @@
+<td colspan="6">
+ <table class="default collapsable sortable" id="<?= $modul->id ?>">
+ <colgroup>
+ <col>
+ <col span="2" style="width: 150px;">
+ </colgroup>
+ <? foreach ($modul->modulteile as $modulteil) : ?>
+ <? $perm = MvvPerm::get($modulteil) ?>
+ <tbody class="<?= ($modulteil_id === $modulteil->getId() ? 'not-collapsed' : 'collapsed') ?><?= $perm->haveFieldPerm('position') ? ' sort_items' : '' ?>"
+ id="<?= $modulteil->getId() ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <? if (count($modulteil->lvgruppen) || $perm->haveFieldPermLvgruppen(MvvPerm::PERM_CREATE)) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/modulteil_lvg/' . $modulteil->id) ?>">
+ <?= htmlReady($modulteil->getDisplayName()) ?></a>
+ <? else : ?>
+ <?= htmlReady($modulteil->getDisplayName()) ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide actions" style="white-space: nowrap; text-align: center;">
+ <? if ($perm->havePermWrite()) : ?>
+ <? foreach ($modulteil->deskriptoren->getAvailableTranslations() as $language) : ?>
+ <? $lang = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$language]; ?>
+ <a href="<?= $controller->url_for('/modulteil/' . join('/', [$modulteil->id, $institut_id]), ['display_language' => $language]) ?>">
+ <img src="<?= Assets::image_path('languages/lang_' . mb_strtolower($language) . '.gif') ?>"
+ alt="<?= $lang['name'] ?>" title="<?= $lang['name'] ?>">
+ </a>
+ <? endforeach; ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide actions" style="white-space: nowrap;">
+ <form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (MvvPerm::havePermCreate('Lvgruppe') && $perm->haveFieldPermLvgruppen(MvvPerm::PERM_CREATE)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/lvgruppe/' . $modulteil->id),
+ _('Neue LV-Gruppe anlegen'),
+ Icon::create('file+add', Icon::ROLE_CLICKABLE, ['title' => _('Neue LV-Gruppe anlegen')]),
+ [
+ 'data-dialog' => 'size=normal',
+ 'title' => _('Neue LV-Gruppe anlegen')
+ ]
+ ) ?>
+ <? endif; ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/modulteil/' . $modulteil->id),
+ _('Modulteil bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE, ['title' => _('Modulteil bearbeiten')])
+ ) ?>
+ <? endif; ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/copy_modulteil/' . $modulteil->id),
+ _('Modulteil kopieren'),
+ Icon::create('files', Icon::ROLE_CLICKABLE,['title' => _('Modulteil kopieren')])
+ ) ?>
+ <? endif; ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <? $actionMenu->addButton(
+ 'delete',
+ _('Modulteil löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, ['title' => _('Modulteil löschen')]),
+ [
+ 'formaction' => $controller->url_for('/delete_modulteil/' . $modulteil->id),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie wirklich den Modulteil "%s" löschen?'),
+ htmlReady($modulteil->getDisplayName())
+ )
+ ]
+ ) ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </form>
+ </td>
+ </tr>
+ <? if ($modulteil_id === $modulteil->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('module/module/modulteil_lvg', compact('modulteil')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+ </table>
+</td>
diff --git a/app/views/module/module/diff.php b/app/views/module/module/diff.php
new file mode 100644
index 0000000..0aaae62
--- /dev/null
+++ b/app/views/module/module/diff.php
@@ -0,0 +1,172 @@
+<style>
+ del.diffmod {
+ color: red;
+ }
+
+ del.diffdel {
+ color: red;
+ }
+
+ ins.diffmod {
+ color: green;
+ }
+
+ ins.diffins {
+ color: green;
+ }
+
+ .mvv-diff {
+ margin: 0;
+ padding: 0;
+ width: 95%;
+ }
+
+ .mvv-modul-details {
+ margin: 10px;
+ border-collapse: collapse;
+ font-size: 5pt;
+ width: 100%;
+ }
+
+ .mvv-modul-details td {
+ padding: 3px;
+ vertical-align: top;
+ border: 1px solid black;
+ }
+
+ .mvv-modul-details th {
+ border: 1px solid black;
+ }
+
+ .mvv-diff-deleted .mvv-modul-details {
+ color: red;
+ }
+
+ .mvv-diff-deleted .mvv-modul-details td,
+ .mvv-diff-deleted .mvv-modul-details th {
+ border: solid 1px red;
+ }
+
+ .mvv-diff-added .mvv-modul-details {
+ color: green;
+ }
+
+ .mvv-diff-added .mvv-modul-details td,
+ .mvv-diff-added .mvv-modul-details th {
+ border: solid 1px green;
+ }
+
+</style>
+<h2>
+ <?= sprintf(_('Vergleich von %s mit %s'), '<span style="font-style: italic">'
+ . htmlReady($old_module->getDisplayName()) . '</span>',
+ '<span style="font-style: italic;">' . htmlReady($new_module->getDisplayName()) . '</span>'); ?>
+</h2>
+<div class="mvv-diff">
+ <?php
+ $old = $this->render_partial('shared/modul/_modul', ['modul' => $old_module]);
+ $new = $this->render_partial('shared/modul/_modul', ['modul' => $new_module]);
+ $diff = new Caxy\HtmlDiff\HtmlDiff($old, $new);
+ $diff->build();
+ echo $diff->getDifference();
+ ?>
+</div>
+<? if ($type_old == 1) : ?>
+ <? if ($type_new == 1) : ?>
+ <div class="mvv-diff">
+ <?php
+ $old = $this->render_partial('shared/modul/_modullvs', ['modul' => $old_module]);
+ $new = $this->render_partial('shared/modul/_modullvs', ['modul' => $new_module]);
+ $diff = new Caxy\HtmlDiff\HtmlDiff($old, $new);
+ $diff->build();
+ echo $diff->getDifference();
+
+ $old = $this->render_partial('shared/modul/_pruefungen', ['modul' => $old_module]);
+ $new = $this->render_partial('shared/modul/_pruefungen', ['modul' => $new_module]);
+ $diff = new Caxy\HtmlDiff\HtmlDiff($old, $new);
+ $diff->build();
+ echo $diff->getDifference();
+
+ $old = $this->render_partial('shared/modul/_regularien', ['modul' => $old_module]);
+ $new = $this->render_partial('shared/modul/_regularien', ['modul' => $new_module]);
+ $diff = new Caxy\HtmlDiff\HtmlDiff($old, $new);
+ $diff->build();
+ echo $diff->getDifference();
+ ?>
+ </div>
+ <? else : ?>
+ <div class="mvv-diff mvv-diff-deleted">
+ <?= $this->render_partial('shared/modul/_modullvs', ['modul' => $old_module]) ?>
+ <?= $this->render_partial('shared/modul/_pruefungen', ['modul' => $old_module]) ?>
+ <?= $this->render_partial('shared/modul/_regularien', ['modul' => $old_module]) ?>
+ </div>
+ <? endif; ?>
+
+ <div class="mvv-diff mvv-diff-added">
+ <? if ($type_new === 2) : ?>
+ <?= $this->render_partial('shared/modul/_modullv', ['modul' => $new_module]) ?>
+ <? endif; ?>
+ <? if ($type_new === 3) : ?>
+ <?= $this->render_partial('shared/modul/_modul_ohne_lv', ['modul' => $new_module]) ?>
+ <? endif; ?>
+ </div>
+
+<? endif; ?>
+
+<? if ($type_old === 2) : ?>
+ <? if ($type_new === 2) : ?>
+ <div class="mvv-diff">
+ <?
+ $old = $this->render_partial('shared/modul/_modullv', ['modul' => $old_module]);
+ $new = $this->render_partial('shared/modul/_modullv', ['modul' => $new_module]);
+ $diff = new Caxy\HtmlDiff\HtmlDiff($old, $new);
+ $diff->build();
+ echo $diff->getDifference();
+ ?>
+ </div>
+ <? else : ?>
+ <div class="mvv-diff mvv-diff-deleted">
+ <?= $this->render_partial('shared/modul/_modullv', ['modul' => $old_module]) ?>
+ </div>
+ <? endif; ?>
+
+ <div class="mvv-diff mvv-diff-added">
+ <? if ($type_new === 1) : ?>
+ <?= $this->render_partial('shared/modul/_modullvs', ['modul' => $old_module]) ?>
+ <?= $this->render_partial('shared/modul/_pruefungen', ['modul' => $old_module]) ?>
+ <?= $this->render_partial('shared/modul/_regularien', ['modul' => $old_module]) ?>
+ <? endif; ?>
+ <? if ($type_new === 3) : ?>
+ <?= $this->render_partial('shared/modul/_modul_ohne_lv', ['modul' => $new_module]) ?>
+ <? endif; ?>
+ </div>
+<? endif; ?>
+
+<? if ($type_old === 3) : ?>
+ <? if ($type_new === 3) : ?>
+ <div class="mvv-diff">
+ <?php
+ $old = $this->render_partial('shared/modul/_modul_ohne_lv', ['modul' => $old_module]);
+ $new = $this->render_partial('shared/modul/_modul_ohne_lv', ['modul' => $new_module]);
+ $diff = new Caxy\HtmlDiff\HtmlDiff($old, $new);
+ $diff->build();
+ echo $diff->getDifference();
+ ?>
+ </div>
+ <? else : ?>
+ <div class="mvv-diff mvv-diff-deleted">
+ <?= $this->render_partial('shared/modul/_modul_ohne_lv', ['modul' => $old_module]) ?>
+ </div>
+ <? endif; ?>
+
+ <div class="mvv-diff mvv-diff-added">
+ <? if ($type_new === 1) : ?>
+ <?= $this->render_partial('shared/modul/_modullvs', ['modul' => $old_module]) ?>
+ <?= $this->render_partial('shared/modul/_pruefungen', ['modul' => $old_module]) ?>
+ <?= $this->render_partial('shared/modul/_regularien', ['modul' => $old_module]) ?>
+ <? endif; ?>
+ <? if ($type_new === 2) : ?>
+ <?= $this->render_partial('shared/modul/_modullv', ['modul' => $new_module]) ?>
+ <? endif; ?>
+ </div>
+<? endif; ?>
diff --git a/app/views/module/module/diff_select.php b/app/views/module/module/diff_select.php
new file mode 100644
index 0000000..cfb09b1
--- /dev/null
+++ b/app/views/module/module/diff_select.php
@@ -0,0 +1,44 @@
+<h1><?= htmlReady($modul->getDisplayName()) ?></h1>
+<div>
+ <h4><?= _('Vergleich mit folgendem Modul:') ?></h4>
+ <form data-dialog="size=auto" class="mvv-new-tab" action="<?= $controller->link_for('/diff') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <div>
+ <?= $search_modul->render(); ?>
+ <? if (Request::submitted('search_modul')) : ?>
+ <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['name' => 'reset_modul', 'data-qs_id' => $qs_id_module])->asInput(); ?>
+ <? else : ?>
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE, ['name' => 'search_modul', 'data-qs_id' => $qs_id_module, 'data-qs_name' => $search_modul->getId(), 'class' => 'mvv-qs-button', 'data-qs_submit' => ''])->asInput(); ?>
+ <? endif; ?>
+ <input type="hidden" name="new_id" value="<?= $modul->id ?>">
+ <input name="modul_diff" class="mvv-submit" type="image" title="<?= _('Modul suchen') ?>" src="<?= Icon::create('accept')->asImagePath(); ?>">
+ </div>
+ </form>
+</div>
+<? if ($quelle) : ?>
+<div>
+ <h4><?= _('Dieses Modul ist eine Novellierung des Moduls:') ?></h4>
+ <a class="mvv-new-tab" href="<?= $controller->link_for('/diff', $modul->id, $quelle->id) ?>"><?= htmlReady($quelle->getDisplayName()) ?></a>
+</div>
+<? endif; ?>
+<? if ($variante) : ?>
+<div>
+ <h4><?= _('Dieses Modul ist eine Variante von:') ?></h4>
+ <a class="mvv-new-tab" href="<?= $controller->link_for('/diff', $modul->id, $variante->id) ?>"><?= htmlReady($variante->getDisplayName()) ?></a>
+<? endif; ?>
+</div>
+<? $variants = $modul->getVariants(); ?>
+<? if (count($variants)) : ?>
+<div>
+ <h4><?= _('Folgende Module sind Varianten dieses Moduls:') ?></h4>
+ <ul>
+ <? foreach ($variants as $variant) : ?>
+ <li>
+ <a href="<?= $controller->link_for('/diff', $modul->id, $variant->id) ?>">
+ <?= htmlReady($variant->getDisplayName()) ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+</div>
+<? endif; ?>
diff --git a/app/views/module/module/index.php b/app/views/module/module/index.php
new file mode 100644
index 0000000..e15d3f0
--- /dev/null
+++ b/app/views/module/module/index.php
@@ -0,0 +1,38 @@
+<?= $controller->jsUrl() ?>
+<table class="default collapsable">
+ <caption>
+ <?= _('Module')?>
+ <span class="actions"><?= sprintf(ngettext('%s Modul', '%s Module', $count), $count) ?></span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('module/module/', _('Modulcode'), 'code', ['style' => 'width: 7%; white-space: nowrap;']) ?>
+ <?= $controller->renderSortLink('module/module/', _('Modul'), 'bezeichnung') ?>
+ <?= $controller->renderSortLink('module/module/', _('Fassung'), 'fassung_nr', ['style' => 'width: 5%;']) ?>
+ <?= $controller->renderSortLink('module/module/', _('Modulteile'), 'count_modulteile', ['style' => 'width: 5%;']) ?>
+ <th style="text-align: right; width: 150px;">
+ <?= _('Ausgabesprachen') ?>
+ </th>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <?= $this->render_partial('module/module/module') ?>
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="6" style="text-align: right;">
+ <?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_module=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render('shared/pagechooser');
+ ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+</table>
diff --git a/app/views/module/module/lvgruppe.php b/app/views/module/module/lvgruppe.php
new file mode 100644
index 0000000..5dd1d17
--- /dev/null
+++ b/app/views/module/module/lvgruppe.php
@@ -0,0 +1,28 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+<? $perm = MvvPerm::get($lvgruppe) ?>
+<h1>
+ <?= $headline ?>
+</h1>
+<form data-dialog class="default" action="<?= $submit_url ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label><?= _('Name') ?>
+ <input <?= $perm->disable('name') ?>
+ id="name" type="text" name="name" value="<?= htmlReady($lvgruppe->name) ?>" size="50">
+ </label>
+ <label><?= _('Alternativtext') ?>
+ <?= MvvI18N::textarea('alttext', $lvgruppe->alttext, ['class' => 'add_toolbar resizable'])->checkPermission($lvgruppe) ?>
+ </fieldset>
+ <footer data-dialog-button>
+ <? if ($lvgruppe->isNew()) : ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Lehrveranstaltungsgruppe anlegen')]) ?>
+ <? endif; ?>
+ <? elseif ($perm->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/module/module/modul.php b/app/views/module/module/modul.php
new file mode 100644
index 0000000..6e69837
--- /dev/null
+++ b/app/views/module/module/modul.php
@@ -0,0 +1,699 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+<?
+$perm = MvvPerm::get($modul);
+$perm_d = MvvPerm::get($deskriptor);
+if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) {
+ $perm_d->setVariant($display_language);
+}
+?>
+<? if (!$def_lang) : ?>
+ <script>
+ STUDIP.MVV.PARENT_ID = '<?= $modul->getId() ?>';
+ </script>
+<? endif; ?>
+
+<form id="modul_form" class="default" action="<?= $controller->url_for('/modul', $modul->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset class="collapsable">
+ <legend>
+ <?= _('Bezeichnung') ?>
+ </legend>
+ <label id="mvv-field-modul-bezeichnung"><?= _('Modulbezeichnung') ?>
+ <input <?= $perm_d->disable('bezeichnung') ?> type="text" name="bezeichnung" id="bezeichnung"
+ value="<?= htmlReady($deskriptor->bezeichnung) ?>" required>
+ </label>
+ <label id="mvv-field-modul-code"><?= _('Modulcode') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('code') ?> type="text" name="code" id="code"
+ value="<?= htmlReady($modul->code) ?>" maxlength="250">
+ <? else : ?>
+ <?= $modul->code ? htmlReady($modul->code) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-quelle"><?= _('Quelle') ?>
+ <? if (!$modul->modul_quelle) : ?>
+ <?= _('Dieses Modul hat keine Vorlage.') ?>
+ <? else : ?>
+ <?= sprintf(_('Dieses Modul ist eine Novellierung des Moduls <strong><em>%s</em></strong>.'), htmlReady($modul->modul_quelle->getDisplayName())) ?>
+ <input type="hidden" name="quelle" id="quelle" value="<?= $modul->modul_quelle->id ?>">
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-flexnow_modul"><?= _('Modul-ID Fremdsystem') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('flexnow_modul') ?> type="text" name="flexnow_modul" id="flexnow_modul"
+ value="<?= htmlReady($modul->flexnow_modul) ?>"
+ maxlength="250">
+ <? else : ?>
+ <?= htmlReady($modul->flexnow_modul) ?>
+ <? endif; ?>
+ </label>
+
+ <label>
+ <?= _('Ist Variante von') ?>
+ <? if ($def_lang) : ?>
+ <? if ($perm->haveFieldPerm('modul_variante', MvvPerm::PERM_WRITE)) : ?>
+ <div>
+ <?= $search_modul->render(); ?>
+ <? if (Request::submitted('search_modul')) : ?>
+ <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['name' => 'reset_modul', 'data-qs_id' => $qs_id_module])->asInput(); ?>
+ <? else : ?>
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE, ['name' => 'search_modul', 'data-qs_id' => $qs_id_module, 'data-qs_name' => $search_modul->getId(), 'class' => 'mvv-qs-button'])->asInput(); ?>
+ <? endif; ?>
+ </div>
+ <? endif; ?>
+ <ul id="modul_target" class="mvv-assigned-items mvv-assign-single mvv-modul">
+ <li class="mvv-item-list-placeholder"<?= ($modul->modul_variante ? ' style="display: none;"' : '') ?>><?= _('Dieses Modul ist nicht die Variante eines anderen Moduls.') ?></li>
+ <? if ($modul->modul_variante->id) : ?>
+ <li id="modul_<?= $modul->modul_variante->id ?>">
+ <div class="mvv-item-list-text">
+ <?= htmlReady($modul->modul_variante->getDisplayName()) ?>
+ </div>
+ <? if ($perm->haveFieldPerm('modul_variante', MvvPerm::PERM_WRITE)) : ?>
+ <div class="mvv-item-list-buttons">
+ <a href="#"
+ class="mvv-item-remove"><?= Icon::create('trash', Icon::ROLE_CLICKABLE, ['title' => _(' entfernen')])->asImg(); ?></a>
+ </div>
+ <? endif; ?>
+ <input type="hidden" name="modul_item" value="<?= $modul->modul_variante->id ?>">
+ </li>
+ <? endif; ?>
+ </ul>
+ <? else : ?>
+ <ul id="modul_target" class="mvv-assigned-items mvv-assign-single mvv-modul">
+ <? if ($modul->modul_variante) : ?>
+ <li id="modul_<?= $modul->modul_variante->id ?>">
+ <div class="mvv-item-list-text">
+ <?= htmlReady($modul->modul_variante->getDisplayName()) ?>
+ </div>
+ </li>
+ <? else : ?>
+ <li class="mvv-item-list-placeholder"><?= _('Dieses Modul ist nicht die Variante eines anderen Moduls.') ?></li>
+ <? endif; ?>
+ </ul>
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed" id="mvv-field-modul-gueltigkeit">
+ <legend>
+ <?= _('Gültigkeit') ?>
+ </legend>
+ <? if ($def_lang) : ?>
+ <label id="mvv-field-modul-modul_start">
+ <?= _('von Semester:') ?>
+ <? if ($perm->haveFieldPerm('start')) : ?>
+ <select name="start" size="1">
+ <option value=""><?= _('-- Semester wählen --') ?></option>
+ <? foreach ($semester as $sem) : ?>
+ <option value="<?= $sem->semester_id ?>"<?= ($sem->semester_id == $modul->start ? ' selected' : '') ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <? $sem = Semester::find($modul->start) ?>
+ <?= htmlReady($sem->name) ?>
+ <input type="hidden" name="start" value="<?= htmlReady($modul->start) ?>">
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-modul_end">
+ <?= _('bis Semester:') ?>
+ <? if ($perm->haveFieldPerm('end')) : ?>
+ <select name="end" size="1">
+ <option value=""><?= _('unbegrenzt gültig') ?></option>
+ <? foreach ($semester as $sem) : ?>
+ <option value="<?= $sem->semester_id ?>"<?= ($sem->semester_id == $modul->end ? ' selected' : '') ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <? if ($modul->end != '') : ?>
+ <? $sem = Semester::find($modul->end) ?>
+ <?= htmlReady($sem->name) ?>
+ <? else : ?>
+ <?= _('unbegrenzt gültig') ?>
+ <? endif; ?>
+ <input type="hidden" name="end" value="<?= htmlReady($modul->end) ?>">
+ <? endif; ?>
+ </label>
+ <div><?= _('Das Endsemester wird nur angegeben, wenn das Modul abgeschlossen ist.') ?></div>
+ <label id="mvv-field-modul-beschlussdatum">
+ <?= _('Beschlussdatum:') ?>
+ <? if ($perm->haveFieldPerm('beschlussdatum')) : ?>
+ <input type="text" name="beschlussdatum"
+ value="<?= ($modul->beschlussdatum ? strftime('%d.%m.%Y', $modul->beschlussdatum) : '') ?>"
+ placeholder="<?= _('TT.MM.JJJJ') ?>" class="with-datepicker">
+ <? else : ?>
+ <?= ($modul->beschlussdatum ? strftime('%d.%m.%Y', $modul->beschlussdatum) : '') ?>
+ <input type="hidden" name="beschlussdatum"
+ value="<?= ($modul->beschlussdatum ? strftime('%d.%m.%Y', $modul->beschlussdatum) : '') ?>">
+ <? endif; ?>
+ </label>
+ <label for="mvv-field-modul-fassung_nr"><?= _('Fassung:') ?>
+ <section class="hgroup size-m">
+ <select<?= $perm->haveFieldPerm('fassung_nr') ? '' : ' disabled' ?> name="fassung_nr"
+ id="mvv-field-modul-fassung_nr">
+ <option value="">--</option>
+ <? foreach (range(1, 30) as $nr) : ?>
+ <option<?= $nr === (int)$modul->fassung_nr ? ' selected' : '' ?> value="<?= $nr ?>"><?= $nr ?>.
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? if (!$perm->haveFieldPerm('fassung_nr')) : ?>
+ <input type="hidden" name="fassung_nr" value="<?= htmlReady($modul->fassung_nr) ?>">
+ <? endif; ?>
+ <select<?= $perm->haveFieldPerm('fassung_typ') ? '' : ' disabled' ?> id="mvv-field-modul-fassung_typ"
+ style="display: inline-block; max-width: 40em;"
+ name="fassung_typ">
+ <option value="0">--</option>
+ <? foreach ($GLOBALS['MVV_MODUL']['FASSUNG_TYP'] as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key === $modul->fassung_typ ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ <? if (!$perm->haveFieldPerm('fassung_typ')) : ?>
+ <input type="hidden" name="fassung_typ" value="<?= htmlReady($modul->fassung_typ) ?>">
+ <? endif; ?>
+ </section>
+ </label>
+ <label id="mvv-field-modul-version">
+ <?= _('Version:') ?>
+ <input <?= $perm->disable("version") ?>
+ type="text" name="version" id="version" value="<?= htmlReady($modul->version) ?>"
+ maxlength="120">
+ </label>
+ <? else: ?>
+ <div id="mvv-field-modul-modul_start">
+ <?
+ $start_sem = Semester::find($modul->start);
+ $end_sem = Semester::find($modul->end);
+ printf(_('von Semester: %s bis Semester: %s'),
+ $start_sem ? htmlReady($start_sem->name) : _('unbekanntes Semester'),
+ $end_sem ? htmlReady($end_sem->name) : _('unbegrenzt gültig'));
+ ?>
+ </div>
+ <div id="mvv-field-modul-beschlussdatum">
+ <? printf(_('Beschlussdatum: %s'),
+ $modul->beschlussdatum ? strftime('%d.%m.%Y', $modul->beschlussdatum) : _('nicht angegeben')) ?>
+ </div>
+ <div id="mvv-field-modul-fassung_nr">
+ <?
+ if ($modul->fassung_nr) {
+ printf(
+ _('Fassung: %s. %s'),
+ htmlReady($modul->fassung_nr),
+ $GLOBALS['MVV_MODUL']['FASSUNG_TYP'][$modul->fassung_typ]['name']
+ );
+ }
+ ?>
+ </div>
+ <? endif; ?>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Einstellungen') ?>
+ </legend>
+
+ <label id="mvv-field-modul-status"><?= _('Bearbeitungsstatus') ?></label>
+ <? $modul_stat = $modul->isNew() ? $GLOBALS['MVV_MODUL']['STATUS']['default'] : $modul->stat; ?>
+ <? if ($def_lang) : ?>
+ <input type="hidden" name="status" value="<?= $modul_stat ?>">
+ <? foreach ($GLOBALS['MVV_MODUL']['STATUS']['values'] as $key => $status_modul) : ?>
+ <? // The MVVAdmin have always PERM_CREATE for all fields ?>
+ <? if ($perm->haveFieldPerm('stat', MvvPerm::PERM_CREATE) && $modul_stat != 'planung') : ?>
+ <label>
+ <input type="radio" name="status" value="<?= $key ?>"<?= ($modul_stat == $key ? ' checked' : '') ?>>
+ <?= $status_modul['name'] ?>
+ </label>
+ <? elseif ($perm->haveFieldPerm('stat', MvvPerm::PERM_WRITE) && $modul_stat != 'planung') : ?>
+ <label>
+ <input <?= ($modul_stat == 'ausgelaufen' && $key == 'genehmigt') ? 'disabled' :'' ?> type="radio" name="status" value="<?= $key ?>"<?= ($modul_stat == $key ? ' checked' : '') ?>>
+ <?= $status_modul['name'] ?>
+ </label>
+ <? elseif($modul_stat == $key) : ?>
+ <div>
+ <?= $status_modul['name'] ?>
+ </div>
+ <? endif; ?>
+ <? endforeach; ?>
+ <label id="mvv-field-modul-kommentar_status"><?= _('Kommentar') ?>
+ <? if ($perm->haveFieldPerm('kommentar_status', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="kommentar_status" id="kommentar_status" class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($modul->kommentar_status) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_status" id="kommentar_status" class="ui-resizable"><?= htmlReady($modul->kommentar_status) ?></textarea>
+ <? endif; ?>
+ </label>
+ <? else : ?>
+ <input type="text" disabled value="<?= $GLOBALS['MVV_MODUL']['STATUS']['values'][$modul->stat]['name'] ?>">
+ <? if ($modul->kommentar_status): ?>
+ <div id="mvv-field-modul-kommentar_status" style="padding-top:10px;">
+ <div><?= _('Kommentar') ?></div>
+ <?= htmlReady($modul->kommentar_status) ?>
+ </div>
+ <? endif; ?>
+ <? endif; ?>
+
+ <label><?= _('Verantwortliche Einrichtung') ?></label>
+ <? if ($def_lang && $perm->haveFieldPerm('responsible_institute', MvvPerm::PERM_WRITE)) : ?>
+ <?= $search_responsible->render(); ?>
+ <? if (Request::submitted('search_responsible')) : ?>
+ <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['name' => 'reset_responsible', 'data-qs_id' => $qs_id_responsible])->asInput(); ?>
+ <? else : ?>
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE, ['name' => 'search_responsible', 'data-qs_id' => $qs_id_responsible, 'data-qs_name' => $search_responsible->getId(), 'class' => 'mvv-qs-button'])->asInput(); ?>
+ <? endif; ?>
+ <ul id="responsible_target" class="mvv-assigned-items mvv-assign-single mvv-institute">
+ <? $display_institute = $modul->responsible_institute && $modul->responsible_institute->institut_id ?>
+ <li class="mvv-item-list-placeholder"<?= ($display_institute ? ' style="display: none;"' : '') ?>><?= _('Bitte geben Sie eine verantwortliche Einrichtung an.') ?></li>
+ <? if ($display_institute) : ?>
+ <li id="modul_<?= $modul->responsible_institute->institut_id; ?>">
+ <div class="mvv-item-list-text">
+ <? if ($modul->responsible_institute->institute) : ?>
+ <?= htmlReady($modul->responsible_institute->institute->getDisplayName()) ?>
+ <? else: ?>
+ <?= _('Unbekannte Einrichtung') ?>
+ <? endif; ?>
+ </div>
+ <div class="mvv-item-list-buttons">
+ <a href="#"
+ class="mvv-item-remove"><?= Icon::create('trash', Icon::ROLE_CLICKABLE, ['title' => _(' entfernen')])->asImg(); ?></a>
+ </div>
+ <input type="hidden" name="responsible_item"
+ value="<?= $modul->responsible_institute->institut_id ?>">
+ </li>
+ <? endif; ?>
+ </ul>
+ <? else : ?>
+ <ul id="maininst_target" class="mvv-assigned-items mvv-assign-single mvv-institute">
+ <? if ($modul->responsible_institute->institute) : ?>
+ <li id="modul_<?= $modul->responsible_institute->institut_id ?>">
+ <div class="mvv-item-list-text">
+ <? if ($modul->responsible_institute->institute) : ?>
+ <?= htmlReady($modul->responsible_institute->institute->getDisplayName()) ?>
+ <? else : ?>
+ <?= _('Unbekannte Einrichtung') ?>
+ <? endif; ?>
+ </div>
+ <input type="hidden" name="responsible_item"
+ value="<?= $modul->responsible_institute->institute->getId() ?>">
+ </li>
+ <? else : ?>
+ <li class="mvv-item-list-placeholder"><?= _('Es wurde noch keine verantwortliche Einrichtung angegeben.') ?></li>
+ <? endif; ?>
+ </ul>
+ <? endif; ?>
+
+ <label>
+ <?= _('Beteiligte Einrichtungen') ?>
+ </label>
+ <? if ($def_lang && $perm->haveFieldPerm('assigned_institutes', MvvPerm::PERM_WRITE)) : ?>
+ <?= $search_institutes->render(); ?>
+ <? if (Request::submitted('search_institutes')) : ?>
+ <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['name' => 'reset_institutes', 'data-qs_id' => $qs_id_institutes])->asInput(); ?>
+ <? else : ?>
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE, ['name' => 'search_institutes', 'data-qs_id' => $qs_id_institutes, 'data-qs_name' => $search_institutes->getId(), 'class' => 'mvv-qs-button'])->asInput(); ?>
+ <? endif; ?>
+ <ul id="institutes_target" class="mvv-assigned-items sortable mvv-institute">
+ <li class="mvv-item-list-placeholder"<?= (count($modul->assigned_institutes) ? ' style="display:none;"' : '') ?>>
+ <?= _('Geben Sie gegebenenfalls beteiligte Einrichtungen an.') ?>
+ </li>
+ <? foreach ($modul->assigned_institutes as $assigned_institute) : ?>
+ <li id="institut_<?= $assigned_institute->institut_id ?>" class="sort_items">
+ <div class="mvv-item-list-text">
+ <? if ($assigned_institute->institute) : ?>
+ <?= htmlReady($assigned_institute->institute->Name) ?>
+ <? else : ?>
+ <?= _('Unbekannte Einrichtung') ?>
+ <? endif; ?>
+ </div>
+ <div class="mvv-item-list-buttons">
+ <a href="#" class="mvv-item-remove">
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE, ['title' => _('Einrichtung entfernen')])->asImg(); ?>
+ </a>
+ </div>
+ <input type="hidden" name="institutes_items[]" value="<?= $assigned_institute->institut_id ?>">
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <label><?= _('Die Reihenfolge der beteiligten Einrichtungen kann durch Anklicken und Ziehen geändert werden.') ?></label>
+ <? else : ?>
+ <ul id="institute_target" class="mvv-assigned-items mvv-institute">
+ <? if (count($modul->assigned_institutes)) : ?>
+ <? foreach ($modul->assigned_institutes as $assigned_institute) : ?>
+ <li id="institut_<?= $assigned_institute->institut_id ?>">
+ <div class="mvv-item-list-text">
+ <? if ($assigned_institute->institute) : ?>
+ <?= htmlReady($assigned_institute->institute->Name) ?>
+ <? else : ?>
+ <?= _('Unbekannte Einrichtung') ?>
+ <? endif; ?>
+ </div>
+ <input type="hidden" name="institute_items[]"
+ value="<?= $assigned_institute->institut_id ?>">
+ </li>
+ <? endforeach; ?>
+ <? else : ?>
+ <li class="mvv-item-list-placeholder">
+ <?= _('Es wurden noch keine weiteren beteiligten Einrichtungen angegeben.') ?>
+ </li>
+ <? endif; ?>
+ </ul>
+ <? endif; ?>
+
+ <label for="mvv-language-chooser-select"><?= _('Lehrsprachen') ?>
+ <? if ($def_lang && $perm->haveFieldPerm('languages', MvvPerm::PERM_WRITE)) : ?>
+ <ul id="language_target" class="mvv-assigned-items sortable mvv-languages">
+ <? if (!count($modul->languages)) : ?>
+ <li class="mvv-item-list-placeholder"<?= (count($modul->languages) ? ' style="display:none;"' : '') ?>>
+ <?= _('Geben Sie die Lehrsprachen an.') ?>
+ </li>
+ <? endif; ?>
+ <? foreach ($modul->languages as $assigned_language) : ?>
+ <li id="language_<?= $assigned_language->lang ?>" class="sort_items">
+ <div class="mvv-item-list-text"><?= htmlReady($assigned_language->getDisplayName()) ?></div>
+ <div class="mvv-item-list-buttons">
+ <a href="#" class="mvv-item-remove"><?= Icon::create('trash', 'clickable', array('title' => _('Sprache entfernen')))->asImg(); ?></a>
+ </div>
+ <input type="hidden" name="language_items[]" value="<?= htmlReady($assigned_language->lang) ?>">
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <?= $this->render_partial('shared/language_chooser', ['chooser_id' => 'language', 'chooser_languages' => $GLOBALS['MVV_MODUL']['SPRACHE']['values'], 'addition' => _('Die Reihenfolge der Sprachen kann durch Anklicken und Ziehen geändert werden.')]); ?>
+ <? else : ?>
+ <ul id="languages_target" class="mvv-assigned-items mvv-languages">
+ <? if (count($modul->languages)) : ?>
+ <? foreach ($modul->languages as $assigned_language) : ?>
+ <li id="institut_<?= $assigned_language->lang ?>">
+ <div class="mvv-item-list-text"><?= htmlReady($assigned_language->getDisplayName()) ?></div>
+ <input type="hidden" name="language_items[]" value="<?= htmlReady($assigned_language->lang) ?>">
+ </li>
+ <? endforeach; ?>
+ <? else : ?>
+ <li class="mvv-item-list-placeholder">
+ <?= _('Es wurden noch keine Sprachen angegeben.') ?>
+ </li>
+ <? endif; ?>
+ </ul>
+ <? endif; ?>
+ </label>
+
+ <label id="mvv-field-modul-dauer"><?= _('Dauer (Semester)') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('dauer') ?> type="text" name="dauer" id="dauer" value="<?= htmlReady($modul->dauer) ?>" maxlength="50">
+ <? else : ?>
+ <?= $modul->dauer ? htmlReady($modul->dauer) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-turnus"><?= _('Turnus/Angebotsrhythmus') ?>
+ <input <?= $perm_d->disable('turnus') ?> type="text" name="turnus" id="turnus" value="<?= htmlReady($deskriptor->turnus) ?>" maxlength="250">
+ </label>
+
+ <label>
+ <?= _('Kapazität/Teilnahmezahl') ?>
+ </label>
+ <section id="mvv-field-modul-kapazitaet" class="hgroup size-m">
+ <? if ($perm->haveFieldPerm('kapazitaet') && $def_lang): ?>
+ <label><?= _('Teilnahmezahl') ?>
+ <input type="text" name="kapazitaet" id="kapazitaet" value="<?= htmlReady($modul->kapazitaet) ?>" <?= $modul->kapazitaet == '' ? ' disabled' : ''; ?>>
+ </label>
+ <label>
+ <input type="checkbox" name="kap_unbegrenzt" id="kap_unbegrenzt" value="1"<?= $modul->kapazitaet == '' ? ' checked' : ''; ?> onchange="jQuery('#kapazitaet').attr('disabled', function(foo, attr){ jQuery(this).val(attr ? '0' : ''); return !attr; }); return false;">
+ <?= _('unbegrenzt') ?>
+ </label>
+ <? else : ?>
+ <?= _('Teilnahmezahl') ?>: <?= $modul->kapazitaet == '' ? _('unbegrenzt') : htmlReady($modul->kapazitaet) ?>
+ <input type="hidden" name="kapazitaet" value="<?= htmlReady($modul->kapazitaet) ?>">
+ <input type="hidden" name="kap_unbegrenzt" value="<?= $modul->kapazitaet == '' ? '1' : ''; ?>">
+ <? endif; ?>
+ </section>
+ <label id="mvv-field-modul-kommentar_kapazitaet"><?= _('Kommentar') ?>
+ <? if($perm_d->haveFieldPerm('kommentar_kapazitaet', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="kommentar_kapazitaet" id="kommentar_kapazitaet" class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_kapazitaet) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_kapazitaet" id="kommentar_kapazitaet" class="ui-resizable"><?= htmlReady($deskriptor->kommentar_kapazitaet) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ <label id="mvv-field-modul-kp"><?= _('Kreditpunkte') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('kp') ?> type="text" name="kp" id="kp" value="<?= htmlReady($modul->kp) ?>" maxlength="10">
+ <? else : ?>
+ <?= $modul->kp ? htmlReady($modul->kp) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+
+ </fieldset>
+
+ <fieldset class="collapsable collapsed" id="mvv-field-modul-assigned_users">
+ <legend>
+ <?= _('Personen') ?>
+ </legend>
+ <label>
+ <?= _('Ansprechpartner'); ?>
+ <?= $this->render_partial('shared/contacts/range', ['perm_contacts' => $perm->haveFieldPerm('contact_assignments', MvvPerm::PERM_CREATE), 'range_type' => 'Modul', 'range_id' => $modul->id]) ?>
+ </label>
+
+ <label><?= _('Weitere verantwortliche Personen') ?>
+ <? if ($perm_d->haveFieldPerm('verantwortlich', MvvPerm::PERM_WRITE)): ?>
+ <textarea name="verantwortlich" id="verantwortlich" cols="25"
+ rows="6"><?= htmlReady($deskriptor->verantwortlich) ?></textarea>
+ <? else: ?>
+ <textarea readonly name="verantwortlich" id="verantwortlich" cols="25"
+ rows="6"><?= htmlReady($deskriptor->verantwortlich) ?></textarea>
+ <? endif; ?>
+ <div>
+ <?= _('Gegebenenfalls weitere Namen von verantwortlichen Personen, die keinen Account in Stud.IP haben. Oder allgemeine Angaben zur Verantwortlichkeit.') ?>
+ </div>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Inhalte und Informationen') ?>
+ </legend>
+ <label id="mvv-field-modul-voraussetzung"><?= _('Teilnahmevoraussetzung') ?>
+ <? if ($perm_d->haveFieldPerm('voraussetzung', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="voraussetzung" id="voraussetzung"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->voraussetzung) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="voraussetzung" id="voraussetzung"
+ class="ui-resizable"><?= htmlReady($deskriptor->voraussetzung) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-kompetenzziele"><?= _('Kompetenzziele') ?>
+ <? if ($perm_d->haveFieldPerm('kompetenzziele', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="kompetenzziele" id="kompetenzziele"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kompetenzziele) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="kompetenzziele" id="kompetenzziele"
+ class="ui-resizable"><?= htmlReady($deskriptor->kompetenzziele) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-inhalte"><?= _('Inhalte') ?>
+ <? if ($perm_d->haveFieldPerm('inhalte', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="inhalte" id="inhalte"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->inhalte) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="inhalte" id="inhalte"
+ class="ui-resizable"><?= htmlReady($deskriptor->inhalte) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-literatur"><?= _('Literatur') ?>
+ <? if ($perm_d->haveFieldPerm('literatur', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="literatur" id="literatur"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->literatur) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="literatur" id="literatur"
+ class="ui-resizable"><?= htmlReady($deskriptor->literatur) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-links"><?= _('Links') ?>
+ <? if ($perm_d->haveFieldPerm('links', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="links" id="links"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->links) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="links" id="links"
+ class="ui-resizable"><?= htmlReady($deskriptor->links) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-kommentar"><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="kommentar" id="kommentar"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="kommentar" id="kommentar"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ </fieldset>
+
+ <fieldset class="collapsable collapsed" id="mvv-field-modul-wl_selbst">
+ <legend>
+ <?= _('Workload') ?>
+ </legend>
+ <label><?= _('Stunden (selbstgestaltete Arbeitszeit)') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('wl_selbst') ?> type="text" name="wl_selbst" id="wl_selbst"
+ value="<?= htmlReady($modul->wl_selbst) ?>" maxlength="4">
+ <? else : ?>
+ <?= $modul->wl_selbst ? htmlReady($modul->wl_selbst) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-kommentar_wl_selbst"><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar_wl_selbst', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="kommentar_wl_selbst" id="kommentar_wl_selbst"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_wl_selbst) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_wl_selbst" id="kommentar_wl_selbst"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar_wl_selbst) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ <label><?= _('Stunden (Prüfung)') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('wl_pruef') ?> type="text" name="wl_pruef" id="wl_pruef"
+ value="<?= htmlReady($modul->wl_pruef) ?>" maxlength="4">
+ <? else : ?>
+ <?= $modul->wl_pruef ? htmlReady($modul->wl_pruef) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-kommentar_wl_pruef"><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar_wl_pruef', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="kommentar_wl_pruef" id="kommentar_wl_pruef"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_wl_pruef) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_wl_pruef" id="kommentar_wl_pruef"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar_wl_pruef) ?></textarea>
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Prüfung') ?>
+ </legend>
+
+ <label>
+ <?= _('Prüfungsebene') ?>
+ </label>
+ <? if ($def_lang && $perm->haveFieldPerm('pruef_ebene', MvvPerm::PERM_WRITE)) : ?>
+ <? foreach ($GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'] as $key => $ebene) : ?>
+ <label>
+ <input type="radio" name="pruef_ebene"
+ value="<?= $key ?>"<?= $modul->pruef_ebene == $key ? ' checked' : '' ?>>
+ <?= $ebene['name'] ?>
+ </label>
+ <? endforeach; ?>
+ <? else : ?>
+ <input type="text" disabled value="<?= htmlReady($GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$modul->pruef_ebene]['name']) ?>">
+ <input type="hidden" name="pruef_ebene" value="<?= htmlReady($modul->pruef_ebene) ?>">
+ <? endif; ?>
+
+ <label id="mvv-field-modul-pruef_vorleistung"><?= _('Prüfungsvorleistung') ?>
+ <? if ($perm_d->haveFieldPerm('pruef_vorleistung', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="pruef_vorleistung" id="pruef_vorleistung"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->pruef_vorleistung) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="pruef_vorleistung" id="pruef_vorleistung"
+ class="ui-resizable"><?= htmlReady($deskriptor->pruef_vorleistung) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-pruef_leistung"><?= _('Leistung/Prüfungsform') ?>
+ <? if ($perm_d->haveFieldPerm('pruef_leistung', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="pruef_leistung" id="pruef_leistung"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->pruef_leistung) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="pruef_leistung" id="pruef_leistung"
+ class="ui-resizable"><?= htmlReady($deskriptor->pruef_leistung) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-pruef_wiederholung"><?= _('Wiederholungsprüfung') ?>
+ <? if ($perm_d->haveFieldPerm('pruef_wiederholung', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="pruef_wiederholung" id="pruef_wiederholung"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->pruef_wiederholung) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="pruef_wiederholung" id="pruef_wiederholung"
+ class="ui-resizable"><?= htmlReady($deskriptor->pruef_wiederholung) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ <label><?= _('Kommentar Note') ?>
+ <? if($perm_d->haveFieldPerm('kommentar_note', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="kommentar_note" id="kommentar_note" class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_note) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_note" id="kommentar_note" class="ui-resizable"><?= htmlReady($deskriptor->kommentar_note) ?></textarea>
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Weitere Angaben') ?>
+ </legend>
+ <label id="mvv-field-modul-faktor_note"><?= _('Faktor der Modulnote für die Endnote des Studiengangs') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('faktor_note') ?> type="text" name="faktor_note" id="faktor_note"
+ value="<?= htmlReady($modul->faktor_note) ?>" maxlength="4">
+ <? else : ?>
+ <?= $modul->faktor_note ? htmlReady($modul->faktor_note) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modul-ersatztext"><?= _('Ersatztext') ?>
+ <? if ($perm_d->haveFieldPerm('ersatztext', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="ersatztext" id="ersatztext"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->ersatztext) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="ersatztext" id="ersatztext"
+ class="ui-resizable"><?= htmlReady($deskriptor->ersatztext) ?></textarea>
+ <? endif; ?>
+ </label>
+ <? foreach ($deskriptor->datafields as $entry) : ?>
+ <? if ($entry->lang == '') : ?>
+ <? if (!$def_lang) : ?>
+ <? $df = new DatafieldEntryModel(
+ [
+ $entry->datafield_id,
+ $entry->range_id,
+ $entry->sec_range_id,
+ $language == 'de_DE' ? '' : $language
+ ]); ?>
+ <? else : ?>
+ <? $df = $entry; ?>
+ <? endif; ?>
+ <? $tdf = $df->getTypedDatafield(); ?>
+ <? if ($perm_d->haveDfEntryPerm($df->datafield_id, MvvPerm::PERM_WRITE)) : ?>
+ <?= $tdf->getHTML('datafields') ?>
+ <? else : ?>
+ <em><?= htmlReady($tdf->getName()) ?>:</em><br>
+ <?= $tdf->getDisplayValue() ?>
+ <? endif; ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </fieldset>
+
+
+ <input type="hidden" name="display_language" value="<?= $display_language ?>">
+ <footer>
+ <? if ($deskriptor->isNew()) : ?>
+ <? if ($perm_d->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Modul anlegen')]) ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($perm_d->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <? if (!$def_lang && !$deskriptor->isNew() && in_array($display_language, $translations)) : ?>
+ <?= Button::create(_('Löschen'), 'delete', ['title' => _('Deskriptor löschen'), 'data-confirm' => sprintf(_('Soll der Deskriptor in der Ausgabesprache %s gelöscht werden?'), htmlReady($GLOBALS['MVV_LANGUAGES']['values'][$display_language]['name'])),
+ 'formaction' => $controller->url_for('/delete_modul_deskriptor', $deskriptor->id, $display_language)]); ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
+<? if (!$def_lang) : ?>
+ <script>
+ jQuery('#modul_form').find('textarea, input[type=text]').after('<div style="padding-top:10px;"><a href="#" title="<?= _('Originalfassung anzeigen') ?>" class="mvv-show-original" data-type="modul"><img src="<?= Assets::image_path('languages/lang_' . mb_strtolower($modul->getDefaultLanguage()) . '.gif') ?>" alt="<?= _('Originalfassung') ?>"></a></div>');
+ </script>
+<? endif; ?>
diff --git a/app/views/module/module/module.php b/app/views/module/module/module.php
new file mode 100644
index 0000000..75d3071
--- /dev/null
+++ b/app/views/module/module/module.php
@@ -0,0 +1,125 @@
+<? foreach ($module as $modul) : ?>
+ <? $perm = MvvPerm::get($modul) ?>
+ <tbody class="<?= ($modul->count_modulteile ? '' : 'empty ') ?><?= ($modul_id === $modul->getId() ? 'not-collapsed' : 'collapsed') ?>">
+ <? $ampel_icon = $GLOBALS['MVV_STUDIENGANG']['STATUS']['values'][$modul->stat]['icon'] ?>
+ <? $ampelstatus = $GLOBALS['MVV_STUDIENGANG']['STATUS']['values'][$modul->stat]['name'] ?>
+ <tr class="header-row" id="modul_<?= $modul->getId() ?>">
+ <? if ($modul->count_modulteile) : ?>
+ <td style="white-space:nowrap;" class="toggle-indicator">
+ <? $details_url = $details_url ?: '/details'; ?>
+ <a class="mvv-load-in-new-row" href="<?= $controller->url_for($details_url, $modul->getId()) ?>">
+ <? if ($ampel_icon) : ?>
+ <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?>
+ <? endif; ?>
+ <?= htmlReady($modul->code) ?>
+ </a>
+ </td>
+ <td class="dont-hide toggle-indicator">
+ <a class="mvv-load-in-new-row" href="<?= $controller->url_for($details_url, $modul->getId()) ?>"
+ style="background-image: none; padding: 0; display: inline;">
+ <?= htmlReady($modul->getDisplayName(0)) ?>
+ </a>
+ <? $trails = $modul->getTrails(array('Studiengang', 'StgteilAbschnitt')); ?>
+ <? if (count($trails)) : ?>
+ <? $li = []; ?>
+ <? foreach ($modul->getPathes($trails, ' > ') as $i => $path) : ?>
+ <? $li[] = htmlReady(sprintf('%s) %s', $i+1, $path)); ?>
+ <? endforeach; ?>
+ <?= tooltipIcon(implode('<br>', $li), false, true); ?>
+ <? endif;?>
+ </td>
+ <? else : ?>
+ <td style="white-space:nowrap;">
+ <? if ($ampel_icon) : ?>
+ <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?>
+ <? endif; ?>
+ <?= htmlReady($modul->code) ?>
+ </td>
+ <td class="dont-hide" style="font-weight: bold;">
+ <?= htmlReady($modul->getDisplayName()) ?>
+ </td>
+ <? endif; ?>
+ <td style="text-align:center;" class="dont-hide"><?= htmlReady($modul->fassung_nr) ?></td>
+ <td style="text-align: center;" class="dont-hide"><?= $modul->count_modulteile ?></td>
+ <td class="dont-hide actions" style="text-align: center;">
+ <? if ($perm->havePermRead()) : ?>
+ <? $languages = $modul->deskriptoren->getAvailableTranslations(); ?>
+ <? foreach ($languages as $language) : ?>
+ <? $lang = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$language]; ?>
+ <a href="<?= $controller->url_for('/modul/' . $modul->id . '/', ['display_language' => $language]) ?>">
+ <img src="<?= Assets::image_path('languages/lang_' . mb_strtolower($language) . '.gif') ?>"
+ alt="<?= $lang['name'] ?>" title="<?= $lang['name'] ?>">
+ </a>
+ <? endforeach; ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide actions" style="white-space: nowrap;">
+ <form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($modul->stat === 'planung' && $perm->haveFieldPerm('stat')) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/approve/' . $modul->id),
+ _('Modul genehmigen'),
+ Icon::create('accept', Icon::ROLE_CLICKABLE, ['title' => _('Modul genehmigen')]),
+ ['data-dialog' => 'size=auto;']
+ ) ?>
+ <? endif; ?>
+ <? if ($perm->havePermRead()) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/description', $modul->id),
+ _('Modulbeschreibung ansehen'),
+ Icon::create('log', Icon::ROLE_CLICKABLE,['title' => _('Modulbeschreibung ansehen')]),
+ [
+ 'data-dialog' => 'size=auto',
+ 'title' => htmlReady($modul->getDisplayName())
+ ]
+ ) ?>
+ <? endif; ?>
+ <? if ($perm->haveFieldPerm('modulteile', MvvPerm::PERM_CREATE)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/modulteil', ['modul_id' => $modul->id]),
+ _('Modulteil anlegen'),
+ Icon::create('file+add', Icon::ROLE_CLICKABLE,['title' => _('Modulteil anlegen')])
+ ) ?>
+ <? endif; ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/modul/' . $modul->id),
+ _('Modul bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE,['title' => _('Modul bearbeiten')])
+ ) ?>
+ <? endif; ?>
+ <? if ($perm->haveFieldPerm('copy_module', MvvPerm::PERM_CREATE)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/copy_form', $modul->id),
+ _('Modul kopieren'),
+ Icon::create('files', Icon::ROLE_CLICKABLE,['title' => _('Modul kopieren')]),
+ ['data-dialog' => '']
+ ) ?>
+ <? endif; ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <? $actionMenu->addButton(
+ 'delete',
+ _('Modul löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE,['title' => _('Modul löschen')]),
+ [
+ 'formaction' => $controller->url_for('/delete/' . $modul->id),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie wirklich das Modul "%s" löschen?'),
+ htmlReady($modul->getDisplayName())
+ )
+ ]
+ ) ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </form>
+ </td>
+ </tr>
+ <? if ($modul->count_modulteile && $modul_id === $modul->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('module/module/details', compact('modul')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+<? endforeach; ?>
diff --git a/app/views/module/module/modulteil.php b/app/views/module/module/modulteil.php
new file mode 100644
index 0000000..c2c4f20
--- /dev/null
+++ b/app/views/module/module/modulteil.php
@@ -0,0 +1,483 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+<?php
+$perm = MvvPerm::get($modulteil);
+$perm_d = MvvPerm::get($deskriptor);
+if ($GLOBALS['MVV_MODULTEIL']['SPRACHE']['default'] != $display_language) {
+ $perm_d->setVariant($display_language);
+}
+?>
+<script>
+ STUDIP.MVV.PARENT_ID = '<?= $modulteil->getId() ?>';
+</script>
+
+<form id="modulteil_form" class="default" action="<?= $controller->url_for('/modulteil/', $modulteil->id) ?>"
+ method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset class="collapsable" id="mvv-field-modulteil-numbering">
+ <legend>
+ <?= _('Nummerierung und Bezeichnung') ?>
+ </legend>
+ <? if ($perm->haveFieldPerm('num_bezeichnung')): ?>
+ <? if ($def_lang) : ?>
+ <section class="hgroup">
+ <label id="mvv-field-modulteil-num_bezeichnung">
+ <?= _('Bezeichnung') ?>
+ <select name="num_bezeichnung">
+ <? $num_bezeichnung = $modulteil->isNew()
+ ? $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['default']
+ : $modulteil->num_bezeichnung; ?>
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'] as $key => $value) : ?>
+ <? if ($value['visible']) : ?>
+ <option value="<?= $key ?>"<?= $key === $num_bezeichnung ? ' selected' : '' ?>><?= htmlReady($value['name']) ?></option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <label id="mvv-field-modulteil-nummer">
+ <?= _('Nummer') ?>
+ <input <?= $perm->disable('nummer') ?> type="text" name="nummer" id="nummer"
+ value="<?= htmlReady($modulteil->nummer) ?>" size="29">
+ </label>
+ </section>
+ <? else : ?>
+ <? if ($modulteil->nummer || $modulteil->num_bezeichnung) : ?>
+ <?= $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulteil->num_bezeichnung]['name'] ?> <?= htmlReady($modulteil->nummer) ?>
+ <? else : ?>
+ <?= _('Keine Angabe') ?>
+ <? endif; ?>
+ <? endif; ?>
+ <? else: ?>
+ <? if ($modulteil->nummer || $modulteil->num_bezeichnung) : ?>
+ <?= $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulteil->num_bezeichnung]['name'] ?> <?= htmlReady($modulteil->nummer) ?>
+ <? else : ?>
+ <?= _('Keine Angabe') ?>
+ <? endif; ?>
+ <input type="hidden" name="num_bezeichnung" value="<?= $modulteil->num_bezeichnung ?>">
+ <? endif; ?>
+ <label id="mvv-field-modulteil-lernlehrform" for="lernlehrform"><?= _('Lern-/Lehrform') ?>
+ <? if ($perm->haveFieldPerm('lernlehrform')): ?>
+ <? if ($def_lang) : ?>
+ <select id="lernlehrform" name="lernlehrform">
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($formen as $form_group) : ?>
+ <optgroup label="<?= htmlReady($form_group['group']['name']) ?>">
+ <? foreach ($form_group['options'] as $form) : ?>
+ <option value="<?= $form['key'] ?>"<?= $form['key'] === $modulteil->lernlehrform ? ' selected' : '' ?>><?= $form['name'] ?></option>
+ <? endforeach; ?>
+ </optgroup>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <? if ($modulteil->lernlehrform) : ?>
+ <?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulteil->lernlehrform]['name'] ?>
+ <? else : ?>
+ <?= _('Keine Angabe') ?>
+ <? endif; ?>
+ <? endif; ?>
+ <? else: ?>
+ <? if ($modulteil->lernlehrform) : ?>
+ <?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulteil->lernlehrform]['name'] ?>
+ <? else : ?>
+ <?= _('Keine Angabe') ?>
+ <? endif; ?>
+ <input type="hidden" name="lernlehrform" value="<?= $modulteil->lernlehrform ?>">
+ <? endif; ?>
+ </label>
+ <label id="mvv-field-modulteil-bezeichnung"><?= _('Zusätzliche Bezeichnung') ?>
+ <input <?= $perm_d->disable('bezeichnung') ?>
+ type="text" name="bezeichnung" id="bezeichnung" value="<?= htmlReady($deskriptor->bezeichnung) ?>">
+ </label>
+
+ <label><?= _('Modulteil-ID aus Fremdsystem') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('flexnow_modul') ?>
+ type="text" name="flexnow_modul" id="flexnow_modul"
+ value="<?= htmlReady($modulteil->flexnow_modul) ?>"
+ maxlength="250">
+ <? else : ?>
+ <?= $modulteil->flexnow_modul ? htmlReady($modulteil->flexnow_modul) : _('Keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed" id="mvv-field-modulteil-semester">
+ <legend>
+ <?= _('Einstellungen') ?>
+ </legend>
+ <label><?= _('Häufigkeit') ?>
+ <? $semester = $modulteil->semester ? $modulteil->semester
+ : $GLOBALS['MVV_NAME_SEMESTER']['default']; ?>
+ <? if ($perm->haveFieldPerm('semester')): ?>
+ <? if ($def_lang) : ?>
+ <select id="mvv-semester" name="semester" size="1">
+ <? foreach ($GLOBALS['MVV_NAME_SEMESTER']['values'] as $key => $value) : ?>
+ <? if ($value['visible']) : ?>
+ <option value="<?= $key ?>"<?= $semester === $key ? ' selected' : '' ?>>
+ <?= htmlReady($value['name']) ?>
+ </option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <?= htmlReady($GLOBALS['MVV_NAME_SEMESTER']['values'][$semester]['name']) ?>
+ <? endif; ?>
+ <? else: ?>
+ <?= htmlReady($GLOBALS['MVV_NAME_SEMESTER']['values'][$semester]['name']) ?>
+ <input type="hidden" name="semester" value="<?= $semester ?>">
+ <? endif; ?>
+ </label>
+
+ <label for="mvv-language-chooser-select"><?= _('Lehrsprachen') ?>
+ <? if ($def_lang && $perm->haveFieldPerm('languages', MvvPerm::PERM_WRITE)) : ?>
+ <ul id="language_target" class="mvv-assigned-items sortable mvv-languages">
+ <? if (!count($modulteil->languages)) : ?>
+ <li class="mvv-item-list-placeholder"<?= (count($modulteil->languages) ? ' style="display:none;"' : '') ?>>
+ <?= _('Geben Sie die Lehrsprachen an.') ?>
+ </li>
+ <? endif; ?>
+ <? foreach ($modulteil->languages as $assigned_language) : ?>
+ <li id="language_<?= $assigned_language->lang ?>" class="sort_items">
+ <div class="mvv-item-list-text"><?= htmlReady($assigned_language->getDisplayName()) ?></div>
+ <div class="mvv-item-list-buttons">
+ <a href="#" class="mvv-item-remove">
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE ,['title' => _('Sprache entfernen')])->asImg(); ?>
+ </a>
+ </div>
+ <input type="hidden" name="language_items[]" value="<?= $assigned_language->lang ?>">
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <?= $this->render_partial('shared/language_chooser', ['chooser_id' => 'language', 'chooser_languages' => $GLOBALS['MVV_MODULTEIL']['SPRACHE']['values'], 'addition' => _('Die Reihenfolge der Sprachen kann durch Anklicken und Ziehen geändert werden.')]); ?>
+ <? else : ?>
+ <ul id="languages_target" class="mvv-assigned-items mvv-languages">
+ <? if (count($modulteil->languages)) : ?>
+ <? foreach ($modulteil->languages as $assigned_language) : ?>
+ <li id="language_<?= $assigned_language->lang ?>">
+ <div class="mvv-item-list-text"><?= htmlReady($assigned_language->getDisplayName()) ?></div>
+ <input type="hidden" name="language_items[]" value="<?= $assigned_language->lang ?>">
+ </li>
+ <? endforeach; ?>
+ <? else : ?>
+ <li class="mvv-item-list-placeholder">
+ <?= _('Es wurden noch keine Sprachen angegeben.') ?>
+ </li>
+ <? endif; ?>
+ </ul>
+ <? endif; ?>
+ </label>
+
+ <label>
+ <?= _('Kapazität/Teilnahmezahl Modulteil') ?>
+ </label>
+ <section id="mvv-field-modulteil-kapazitaet" class="hgroup size-m">
+ <? if ($perm->haveFieldPerm('kapazitaet') && $def_lang): ?>
+ <label><?= _('Teilnahmezahl') ?>
+ <input type="text" name="kapazitaet" id="kapazitaet"
+ value="<?= htmlReady($modulteil->kapazitaet) ?>" <?= $modulteil->kapazitaet === '' ? ' disabled' : ''; ?>>
+ </label>
+ <label>
+ <input type="checkbox" name="kap_unbegrenzt" id="kap_unbegrenzt"
+ value="1"<?= $modulteil->kapazitaet === '' ? ' checked' : ''; ?>
+ onchange="jQuery('#kapazitaet').attr('disabled', function(foo, attr){ jQuery(this).val(attr ? '0' : ''); return !attr; }); return false;">
+ <?= _('unbegrenzt') ?>
+ </label>
+ <? else: ?>
+ <?= _('Teilnahmezahl') ?>: <?= $modulteil->kapazitaet === '' ? _('unbegrenzt') : htmlReady($modulteil->kapazitaet) ?>
+ <input type="hidden" name="kapazitaet" value="<?= htmlReady($modulteil->kapazitaet) ?>">
+ <input type="hidden" name="kap_unbegrenzt" value="<?= $modulteil->kapazitaet === '' ? '1' : ''; ?>">
+ <? endif; ?>
+ </section>
+ <label id="mvv-field-modulteil-kommentar_kapazitaet"><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar_kapazitaet', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="kommentar_kapazitaet" id="kommentar_kapazitaet"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_kapazitaet) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_kapazitaet" id="kommentar_kapazitaet"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar_kapazitaet) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ <label><?= _('SWS') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('sws') ?>
+ type="text" name="sws" id="sws" value="<?= htmlReady($modulteil->sws) ?>">
+ <? else : ?>
+ <?= $modulteil->sws ? htmlReady($modulteil->sws) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+
+ <label>
+ <?= _('Kreditpunkte') ?>
+ </label>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('kp') ?>
+ type="text" name="kp" id="kp" value="<?= htmlReady($modulteil->kp) ?>" maxlength="10">
+ <? else : ?>
+ <?= $modulteil->kp ? htmlReady($modulteil->kp) : _('keine Angabe') ?>
+ <? endif; ?>
+
+
+
+ </fieldset>
+
+
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Teilnahmevoraussetzung Modulteil') ?>
+ </legend>
+ <label><?= _('Teilnahmevoraussetzung') ?>
+ <? if ($perm_d->haveFieldPerm('voraussetzung', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="voraussetzung" id="voraussetzung" class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->voraussetzung) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="voraussetzung" id="voraussetzung" class="ui-resizable"><?= htmlReady($deskriptor->voraussetzung) ?></textarea>
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Kommentar Modulteil') ?>
+ </legend>
+ <label><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="kommentar" id="kommentar" class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="kommentar" id="kommentar" class="ui-resizable"><?= htmlReady($deskriptor->kommentar) ?></textarea>
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+
+
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Workload') ?>
+ </legend>
+ <label><?= _('Workload (Präsenzzeit)') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('wl_praesenz') ?>
+ type="text" name="wl_praesenz" id="wl_praesenz"
+ value="<?= htmlReady($modulteil->wl_praesenz) ?>" size="4"
+ maxlength="4">
+ <? else : ?>
+ <?= $modulteil->wl_praesenz ? htmlReady($modulteil->wl_praesenz) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label for="kommentar_wl_praesenz" style="vertical-align: top;"><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar_wl_praesenz', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="kommentar_wl_praesenz" id="kommentar_wl_praesenz"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_wl_praesenz) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_wl_praesenz" id="kommentar_wl_praesenz"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar_wl_praesenz) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ <label><?= _('Workload ( Vor-/Nachbereitung)') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('wl_bereitung') ?>
+ type="text" name="wl_bereitung" id="wl_bereitung"
+ value="<?= htmlReady($modulteil->wl_bereitung) ?>" size="4"
+ maxlength="4">
+ <? else : ?>
+ <?= $modulteil->wl_bereitung ? htmlReady($modulteil->wl_bereitung) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar_wl_bereitung', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="kommentar_wl_bereitung" id="kommentar_wl_bereitung"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_wl_bereitung) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_wl_bereitung" id="kommentar_wl_bereitung"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar_wl_bereitung) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ <label><?= _('Workload (Modulteil selbstgestaltete Arbeitszeit)') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable("wl_selbst") ?>
+ type="text" name="wl_selbst" id="wl_selbst"
+ value="<?= htmlReady($modulteil->wl_selbst) ?>" size="4"
+ maxlength="4">
+ <? else : ?>
+ <?= $modulteil->wl_selbst ? htmlReady($modulteil->wl_selbst) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar_wl_selbst', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="kommentar_wl_selbst" id="kommentar_wl_selbst"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_wl_selbst) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_wl_selbst" id="kommentar_wl_selbst"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar_wl_selbst) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ <label><?= _('Workload (Modulteil Prüfung)') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('wl_pruef') ?> type="text" name="wl_pruef" id="wl_pruef"
+ value="<?= htmlReady($modulteil->wl_pruef) ?>" maxlength="4">
+ <? else : ?>
+ <?= $modulteil->wl_pruef ? htmlReady($modulteil->wl_pruef) : _('keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar_wl_pruef', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="kommentar_wl_pruef" id="kommentar_wl_pruef"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_wl_pruef) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_wl_pruef" id="kommentar_wl_pruef"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar_wl_pruef) ?></textarea>
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Prüfung/Note') ?>
+ </legend>
+ <label><?= _('Prüfungsvorleistung') ?>
+ <? if ($perm_d->haveFieldPerm('pruef_vorleistung', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="pruef_vorleistung" id="pruef_vorleistung"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->pruef_vorleistung) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="pruef_vorleistung" id="pruef_vorleistung"
+ class="ui-resizable"><?= htmlReady($deskriptor->pruef_vorleistung) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label><?= _('Prüfungsleistung Modulteil') ?>
+ <? if ($perm_d->haveFieldPerm('pruef_leistung', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="pruef_leistung" id="pruef_leistung"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->pruef_leistung) ?></textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="pruef_leistung" id="pruef_leistung"
+ class="ui-resizable"><?= htmlReady($deskriptor->pruef_leistung) ?></textarea>
+ <? endif; ?>
+ </label>
+ <label><?= _('Anteil an Modulnote') ?>
+ <? if ($def_lang) : ?>
+ <input <?= $perm->disable('anteil_note') ?> type="text" name="anteil_note" id="anteil_note"
+ value="<?= htmlReady($modulteil->anteil_note) ?>" size="29">
+ <? else : ?>
+ <?= $modulteil->anteil_note ? htmlReady($modulteil->anteil_note) : _('Keine Angabe') ?>
+ <? endif; ?>
+ </label>
+ <label><?= _('Ausgleichbar bei Minderleistung') ?>
+ <? if ($def_lang && $perm->haveFieldPerm('ausgleichbar', MvvPerm::PERM_WRITE)) : ?>
+ <section class="hgroup">
+ <label>
+ <input type="radio" id="ausgleichbar" name="ausgleichbar" value="0"
+ <? if (!$modulteil->ausgleichbar) echo 'checked'; ?>>
+ <?= _('Nein') ?>
+ </label>
+ <label>
+ <input type="radio" name="ausgleichbar" value="1"
+ <? if ($modulteil->ausgleichbar) echo 'checked'; ?>>
+ <?= _('Ja') ?>
+ </label>
+ </section>
+ <? else : ?>
+ <? if ($modulteil->ausgleichbar) : ?>
+ <?= _('Dieser Modulteil <strong>ist ausgleichbar</strong> bei Minderleistung.') ?>
+ <? else : ?>
+ <?= _('Dieser Modulteil ist <strong>nicht ausgleichbar</strong> bei Minderleistung.') ?>
+ <? endif; ?>
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Anwesenheitspflicht') ?>
+ </legend>
+ <? if ($def_lang && $perm->haveFieldPerm('pflicht', MvvPerm::PERM_WRITE)) : ?>
+ <section class="hgroup">
+ <label>
+ <input type="radio" id="pflicht" name="pflicht" value="0"
+ <? if (!$modulteil->pflicht) echo 'checked'; ?>>
+ <?= _('Nein') ?>
+ </label>
+ <label>
+ <input type="radio" name="pflicht" value="1"
+ <? if ($modulteil->pflicht) echo 'checked'; ?>>
+ <?= _('Ja') ?>
+ </label>
+ </section>
+ <? else : ?>
+ <? if ($modulteil->pflicht) : ?>
+ <?= _('Es besteht <strong>Anwesenheitspflicht</strong>.') ?>
+ <? else : ?>
+ <?= _('Es besteht <strong>keine Anwesenheitspflicht</strong>.') ?>
+ <? endif; ?>
+ <? endif; ?>
+ <label><?= _('Kommentar') ?>
+ <? if ($perm_d->haveFieldPerm('kommentar_pflicht', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="kommentar_pflicht" id="kommentar_pflicht"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($deskriptor->kommentar_pflicht) ?>
+ </textarea>
+ <? else : ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_pflicht" id="kommentar_pflicht"
+ class="ui-resizable"><?= htmlReady($deskriptor->kommentar_pflicht) ?>
+ </textarea>
+ <? endif; ?>
+ </label>
+ </fieldset>
+ <? if (count($deskriptor->datafields)) : ?>
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Weitere Angaben') ?>
+ </legend>
+ <? foreach ($deskriptor->datafields as $entry) : ?>
+ <? if ($entry->lang === '') : ?>
+ <? if (!$def_lang) : ?>
+ <? $df = new DatafieldEntryModel(
+ [
+ $entry->datafield_id,
+ $entry->range_id,
+ $entry->sec_range_id,
+ $language === 'de_DE' ? '' : $language
+ ]); ?>
+ <? else : ?>
+ <? $df = $entry; ?>
+ <? endif; ?>
+ <? $tdf = $df->getTypedDatafield(); ?>
+ <? if ($perm_d->haveDfEntryPerm($df->datafield_id, MvvPerm::PERM_WRITE)) : ?>
+ <?= $tdf->getHTML('datafields'); ?>
+ <? else : ?>
+ <em><?= htmlReady($tdf->getName()) ?>:</em><br>
+ <?= $tdf->getDisplayValue() ?>
+ <? endif; ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </fieldset>
+ <? endif; ?>
+ <input type="hidden" name="modul_id" value="<?= htmlReady($modulteil->modul_id) ?>">
+ <input type="hidden" name="display_language" value="<?= $display_language ?>">
+ <footer>
+ <? if ($deskriptor->isNew()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Modulteil anlegen')]) ?>
+ <? else : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? if (!$def_lang && !$deskriptor->isNew() && in_array($display_language, $translations)) : ?>
+ <?= Button::create(
+ _('Löschen'),
+ 'delete',
+ ['title' => _('Deskriptor löschen'), 'data-confirm' => sprintf(_('Soll der Deskriptor in der Ausgabesprache %s gelöscht werden?'), htmlReady($GLOBALS['MVV_LANGUAGES']['values'][$display_language]['name'])),
+ 'formaction' => $controller->url_for('/delete_modulteil_deskriptor', $deskriptor->id, $display_language)
+ ]
+ ); ?>s
+ <? endif; ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
+<? if (!$def_lang) : ?>
+ <script>
+ jQuery('#modulteil_form').find('textarea, input[type=text]').after('<div style="padding-top:10px;"><a href="#" title="<?= _('Originalfassung anzeigen') ?>" class="mvv-show-original" data-type="modulteil"><img src="<?= Assets::image_path('languages/lang_' . mb_strtolower($modul->getDefaultLanguage()) . '.gif') ?>" alt="<?= _('Originalfassung') ?>"></a></div>');
+ </script>
+<? endif; ?>
diff --git a/app/views/module/module/modulteil_lvg.php b/app/views/module/module/modulteil_lvg.php
new file mode 100644
index 0000000..c2e5c39
--- /dev/null
+++ b/app/views/module/module/modulteil_lvg.php
@@ -0,0 +1,66 @@
+<td colspan="3">
+ <table id="modulteil_<?= $modulteil_id ?>" class=" default collapsable sortable">
+ <colgroup>
+ <col>
+ <col style="width: 150px;">
+ </colgroup>
+ <? foreach ($modulteil->lvgruppen as $lvgruppe) : ?>
+ <? $lvgruppe_modulteil = LvgruppeModulteil::get([$lvgruppe->getId(), $modulteil->getId()]) ?>
+ <tbody id="<?= $modulteil_id . '_' . $lvgruppe->getId() ?>"<?= MvvPerm::haveFieldPermPosition($lvgruppe_modulteil) ? 'class="sort_items"' : '' ?>>
+ <tr class="header-row">
+ <td><?= htmlReady($lvgruppe->getDisplayName()) ?></td>
+ <td class="actions">
+ <form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (MvvPerm::haveFieldPermLvgruppen($modulteil, MvvPerm::PERM_WRITE)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/lvgruppe/' . $modulteil->id . '/' . $lvgruppe->id),
+ _('LV-Gruppe bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE ,['title' => _('LV-Gruppe bearbeiten')]),
+ [
+ 'data-dialog' => 'size=auto',
+ 'title' => _('LV-Gruppe bearbeiten')
+ ]
+ ) ?>
+ <? endif; ?>
+ <? if (MvvPerm::haveFieldPermLvgruppen($modulteil, MvvPerm::PERM_CREATE)) : ?>
+ <? $actionMenu->addButton(
+ 'delete',
+ _('Zuordnung der LV-Gruppe löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE , ['title' => _('Zuordnung der LV-Gruppe löschen')]),
+ [
+ 'formaction' => $controller->url_for('/delete_lvgruppe/' . $modulteil->id . '/' . $lvgruppe->id),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie wirklich die Lehrveranstaltungsgruppe "%s" vom Modulteil "%s" entfernen?'),
+ htmlReady($lvgruppe->getDisplayName()),
+ htmlReady($modulteil->getDisplayName())
+ )
+ ]
+ ) ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </form>
+ </td>
+ </tr>
+ </tbody>
+ <? endforeach; ?>
+ <? if (MvvPerm::haveFieldPermLvgruppen($modulteil, MvvPerm::PERM_CREATE)) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <form action="<?= $controller->url_for('/add_lvgruppe/' . $modulteil->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <input type="hidden" name="security_token" value="<?= $security_token ?>">
+ <div style="float: left; padding-right: 10px;"><?= _('LV-Gruppe hinzufügen:') ?></div>
+ <?= $search->render(); ?>
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE , ['title' => _('LV-Gruppe suchen'), 'name' => 'search_stgteil', 'data-qs_name' => $search->getId(), 'data-qs_id' => $qs_search_id, 'data-qs_submit' => 'no', 'class' => 'mvv-qs-button'])->asInput(); ?>
+ <?= Icon::create('accept', Icon::ROLE_CLICKABLE , ['title' => _('LV-Gruppe zuordnen')])->asInput(['class' => 'mvv-submit', 'name' => 'add_lvgruppe']); ?>
+ <input type="hidden" name="modulteil_id" value="<?= $modulteil_id ?>">
+ </form>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</td>
diff --git a/app/views/multipersonsearch/js_form.php b/app/views/multipersonsearch/js_form.php
new file mode 100644
index 0000000..6c3ddfa
--- /dev/null
+++ b/app/views/multipersonsearch/js_form.php
@@ -0,0 +1,56 @@
+<div class="mpscontainer" data-dialogname="<?= $name ?>">
+<form method="post" class="default" action="<?= URLHelper::getLink('dispatch.php/multipersonsearch/js_form_exec/?name=' . $name); ?>" id="<?= $name ?>" <?= $data_dialog_status ? 'data-dialog' : ''?>
+ data-secure="li.ms-selected:gt(0)">
+ <fieldset>
+ <legend>
+ <?= htmlReady($title) ?: _('Nach Personen suchen') ?>
+ </legend>
+
+ <label class="with-action">
+ <span><?= htmlReady($description); ?></span>
+ <input id="<?= $name . '_searchinput'; ?>" type="text" placeholder="<?= _("Suchen"); ?>" value="" name="<?= $name . '_searchinput'; ?>" style="width: 260px;" aria-label="<?= _("Suchen"); ?>">
+
+ <?= Icon::create('search', 'clickable', ['title' => _('Suche starten')])->asImg(16, ['onclick' => 'STUDIP.MultiPersonSearch.search()']) ?>
+ <?= Icon::create('decline', 'clickable', ['title' => _('Suche zurücksetzen')])->asImg(16, ['onclick' => 'STUDIP.MultiPersonSearch.resetSearch()']) ?>
+ </label>
+ <p><? foreach($quickfilter as $title => $users) : ?>
+ <a href="#" class="quickfilter" data-quickfilter="<?= md5($title); ?>"><?= htmlReady($title); ?> (<?= count($users); ?>)</a>
+ <select multiple="multiple" id="<?= $name . '_quickfilter_' . md5($title); ?>" style="display: none;">
+ <? foreach($users as $user) : ?>
+ <option value="<?= $user->id ?>"><?= Avatar::getAvatar($user->id)->getURL(Avatar::MEDIUM); ?> -- <?= htmlReady($user->getFullName('full_rev')) ?> -- <?= htmlReady($user->perms) ?> (<?= htmlReady($user->username)?>)</option>
+ <? endforeach; ?>
+ </select>
+ <? endforeach; ?></p>
+ <select multiple="multiple" id="<?= $name . '_selectbox'; ?>" name="<?= $name . '_selectbox'; ?>[]" data-init-js="true">
+ <? foreach ($defaultSelectableUsers as $person): ?>
+ <option value="<?= $person->id ?>"><?= Avatar::getAvatar($person->id)->getURL(Avatar::MEDIUM); ?> -- <?= htmlReady($person->getFullName('full_rev')) ?> -- <?= htmlReady($person->perms) ?> (<?= htmlReady($person->username)?>)</option>
+ <? endforeach; ?>
+ </select>
+ <select multiple="multiple" id="<?= $name . '_selectbox_default'; ?>" style="display: none;">
+ <? foreach ($defaultSelectedUsers as $person): ?>
+ <option value="<?= $person->id ?>"><?= Avatar::getAvatar($person->id)->getURL(Avatar::MEDIUM); ?> -- <?= htmlReady($person->getFullName('full_rev')) ?> -- <?= htmlReady($person->perms) ?> (<?= htmlReady($person->username)?>)</option>
+ <? endforeach; ?>
+ </select>
+
+ <?= $additionHTML; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if ($ajax): ?>
+ <?= \Studip\Button::create(_('Speichern'), 'confirm', ['data-dialog-button' => true]) ?>
+ <? else: ?>
+ <?= \Studip\Button::create(_('Speichern'), 'confirm') ?>
+ <?= \Studip\Button::create(_('Abbrechen'), $name . '_button_abort') ?>
+ <? endif; ?>
+ <?= CSRFProtection::tokenTag() ?>
+ </footer>
+</form>
+</div>
+
+<? if ($jsFunction): ?>
+<script>
+jQuery(document).off('submit.mps-<?= md5($name) ?>').on('submit.mps-<?= md5($name) ?>', '#<?= $name ?>', function () {
+ return <?= $jsFunction ?><?= preg_match('/;$/', $jsFunction) ? '' : '(this);'; ?>
+});
+</script>
+<? endif; ?>
diff --git a/app/views/multipersonsearch/no_js_form.php b/app/views/multipersonsearch/no_js_form.php
new file mode 100644
index 0000000..bbca28e
--- /dev/null
+++ b/app/views/multipersonsearch/no_js_form.php
@@ -0,0 +1,88 @@
+<? if (isset($title)): ?>
+ <h1><?= htmlReady($title) ?></h1>
+<? endif; ?>
+<form method="POST" action="<?= $controller->url_for("multipersonsearch/no_js_form/?name=" . $name) ?>">
+ <input type="hidden" name="search_persons_selectable_hidden" value="<?=htmlReady(json_encode($selectableUsersHidden))?>">
+ <input type="hidden" name="search_persons_selected_hidden" value="<?=htmlspecialchars(json_encode($selectedUsersHidden))?>">
+ <input type="hidden" name="last_search_hidden" value="<?= $search?>">
+ <input type="hidden" name="last_search_preset" value="<?= $searchPreset?>">
+ <input type="hidden" name="not_first_call" value="true">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <!-- neue Suche -->
+ <div id="search_persons" style="width: 800px;">
+ <label>
+ <input name="freesearch" type="text" placeholder="<?=_('Suchen')?>"
+ aria-label="<?= _('Suchbegriff') ?>" style="width: 45%" value="<?= $search ?>">
+ <?= Icon::create('search', 'clickable', ['title' => _('Suche starten')])->asInput(['name'=>'submit_search','class'=>'stay_on_dialog',]) ?>
+ </label>
+ <br><br>
+ <select name="search_preset" aria-label="<?= _('Vorauswahl bestimmter Bereiche, alternativ zur Suche') ?>" style="width: 45%">
+ <option><?=_('--- Suchvorlagen ---')?></option>
+ <? foreach ($quickfilter as $title) : ?>
+ <option value="<?= htmlReady($title) ?>" <?= $searchPreset == $title ? "selected" : ""; ?>>
+ <?= $title; ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <?= Icon::create('accept', 'clickable', ['title' => _('Vorauswahl anwenden')])->asInput(['name'=>'submit_search_preset','class'=>'stay_on_dialog']) ?>
+
+ <div id="search_persons_content">
+ <div style="display: inline-block; float: left; width: 44%; height: 100%">
+ <label><?=_('Suchergebnis')?><br>
+ <select id="search_persons_selectable" name="search_persons_selectable[]" style="minWidth: 200px; width: 100%; height: 116px" style="height: 16px" multiple
+ aria-label="<?= _('Gefundene Personen, die der Gruppe hinzugefügt werden können') ?>">
+ <? if (count($selectableUsers) == 0) : ?>
+ <option disabled><?= _("Keine neuen Suchergebnisse gefunden"); ?></option>
+ <? else : ?>
+ <? foreach ($selectableUsers as $person): ?>
+ <option value="<?= $person->id ?>"><?= htmlReady($person->nachname . ', ' . $person->vorname) ?> - <?= htmlReady($person->perms) ?> (<?= htmlReady($person->username)?>)</option>
+ <? endforeach; ?>
+ <? endif; ?>
+ </select>
+ </label>
+ </div>
+ <div style="display: inline-block; width: 10%; text-align: center">
+ <br>
+ <br>
+ <br>
+ <?= Icon::create('arr_2right', 'clickable', ['title' => _('In den Suchergebnissen markierte Bereiche der Gruppe hinzufügen')])
+ ->asInput([
+ 'id' => 'search_persons_add',
+ 'name' => 'search_persons_add',
+ 'class' => 'stay_on_dialog']) ?>
+ <br><br>
+ <?= Icon::create('arr_2left', 'clickable', ['title' => _('Bei den bereits ausgewählten Personen die markierten Personen entfernen')])
+ ->asInput([
+ 'id' => 'search_persons_remove',
+ 'name' => 'search_persons_remove',
+ 'class' => 'stay_on_dialog']) ?>
+ </div>
+ <div style="display: inline-block; float: right; width: 44%">
+ <label>
+ <div>
+ <? $selectedCount = count($selectedUsers);
+ if ($selectedCount == 0) : ?>
+ <?=_('Niemand wurde ausgewählt.')?>
+ <? elseif ($selectedCount == 1) : ?>
+ <?=_('Eine Person wurde ausgewählt')?>
+ <? else : ?>
+ <?=sprintf(_('%s Personen wurden ausgewählt.'), $selectedCount)?>
+ <? endif ?>
+ </div>
+ <select id="search_persons_selected" name="search_persons_selected[]" style="minWidth: 200px; width: 100%; height: 116px" size="7" multiple
+ aria-label="<?= _('Personen, die in die Gruppe eingetragen werden') ?>"
+ >
+ <? foreach ($selectedUsers as $user): ?>
+ <option value="<?= $user->id ?>"><?= htmlReady($user->nachname . ', ' . $user->vorname) ?> - <?= htmlReady($user->perms) ?> (<?= htmlReady($user->username)?>)</option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </div><br>
+ </div>
+ </div>
+ <br>
+ <?= $additionHTML; ?>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ <?= \Studip\Button::create(_('Abbrechen'), 'abort') ?>
+</form>
diff --git a/app/views/my_courses/_course.php b/app/views/my_courses/_course.php
new file mode 100644
index 0000000..cea4199
--- /dev/null
+++ b/app/views/my_courses/_course.php
@@ -0,0 +1,142 @@
+<? foreach ($course_collection as $course) : ?>
+ <? $sem_class = $course['sem_class']; ?>
+ <tr <? if ($course['children']) echo 'class="has-subcourses"'; elseif ($children) echo 'class="subcourses"'; ?>>
+ <td <? if (!$children) echo 'class="gruppe' . $course['gruppe'] . '"'; ?>></td>
+ <td>
+ <? if ($sem_class['studygroup_mode']) : ?>
+ <?= StudygroupAvatar::getAvatar($course['seminar_id'])->getImageTag(Avatar::SMALL, ['title' => $course['name']])
+ ?>
+ <? else : ?>
+ <?= CourseAvatar::getAvatar($course['seminar_id'])->getImageTag(Avatar::SMALL, ['title' => $course['name']])
+ ?>
+ <? endif ?>
+ </td>
+ <? if ($config_sem_number) :?>
+ <td><?= htmlReady($course['veranstaltungsnummer']) ?></td>
+ <? endif?>
+ <td style="text-align: left">
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $course['seminar_id']]) ?>"
+ <? if ($course['visitdate'] <= $course['chdate']) echo 'style="color: red;"'; ?>>
+ <?= htmlReady($course['name']) ?>
+ <? if ($course['is_deputy']): ?>
+ <?= _('[Vertretung]') ?>
+ <? endif; ?>
+ </a>
+ <? if (!$course['visible']) : ?>
+ <? $infotext = _('Versteckte Veranstaltungen können über die Suchfunktionen nicht gefunden werden.'); ?>
+ <? $infotext .= ' '; ?>
+ <? if (Config::get()->ALLOW_DOZENT_VISIBILITY && in_array($course['user_status'], ['dozent', 'admin'])) : ?>
+ <? $infotext .= _('Um die Veranstaltung sichtbar zu machen, wählen Sie den Punkt "Sichtbarkeit" im Administrationsbereich der Veranstaltung.'); ?>
+ <? else : ?>
+ <? $infotext .= _('Um die Veranstaltung sichtbar zu machen, wenden Sie sich an Admins.'); ?>
+ <? endif ?>
+
+ <?= _('[versteckt]') ?>
+ <?= tooltipicon($infotext) ?>
+ <? endif ?>
+ <div class="mycourse_elements hidden-medium-up">
+ <? if (!empty($course['navigation'])) : ?>
+ <? foreach (MyRealmModel::array_rtrim($course['navigation']) as $key => $nav) : ?>
+ <? if (isset($nav) && $nav->isVisible(true)) : ?>
+ <a href="<?= URLHelper::getLink('seminar_main.php', [
+ 'auswahl' => $course['seminar_id'],
+ 'redirect_to' => strtr($nav->getURL(), '?', '&')
+ ]) ?>" <? if ($nav->hasBadgeNumber()) printf('class="badge" data-badge-number="%u"', $nav->getBadgeNumber()); ?>>
+ <?= $nav->getImage()->asImg(20, $nav->getLinkAttributes()) ?>
+ </a>
+ <? elseif (is_string($key)) : ?>
+ <?= Assets::img('blank.gif', ['width' => 20, 'height' => 20]) ?>
+ <? endif ?>
+ <? endforeach ?>
+ <? endif ?>
+ <div class="special_nav">
+ <? if (in_array($course['user_status'], ['dozent', 'tutor'])) : ?>
+ <? $adminmodule = $sem_class->getAdminModuleObject(); ?>
+ <? if ($adminmodule) : ?>
+ <? $adminnavigation = $adminmodule->getIconNavigation($course['seminar_id'], 0, $GLOBALS['user']->id); ?>
+ <? endif ?>
+
+ <? if ($adminnavigation) : ?>
+ <a href="<?= URLHelper::getLink($adminnavigation->getURL(), ['cid' => $course['seminar_id']]) ?>">
+ <?= $adminnavigation->getImage()->asImg(20, $adminnavigation->getLinkAttributes()) ?>
+ </a>
+ <? endif ?>
+
+ <? elseif ($values["binding"]) : ?>
+ <a href="<?= $controller->url_for('my_courses/decline_binding') ?>">
+ <?= Icon::create('door-leave+decline', 'inactive', ['title' => _("Die Teilnahme ist bindend. Bitte wenden Sie sich an die Lehrenden.")])->asImg(20) ?>
+ </a>
+ <?
+ else : ?>
+ <a href="<?= $controller->link_for('my_courses/decline', $course['seminar_id'], ['cmd' => 'suppose_to_kill']) ?>">
+ <?= Icon::create('door-leave', 'inactive', ['title' => _("aus der Veranstaltung abmelden")])->asImg(20) ?>
+ </a>
+ <? endif ?>
+ </div>
+ </div>
+ </td>
+ <td class="hidden-small-down">
+ <? if (!$sem_class['studygroup_mode']) : ?>
+ <a data-dialog href="<?= $controller->link_for('course/details/index', $course['seminar_id'],
+ ['from' => $controller->url_for('my_courses/index')]) ?>">
+ <? $params = tooltip2(_("Veranstaltungsdetails")); ?>
+ <? $params['style'] = 'cursor: pointer'; ?>
+ <?= Icon::create('info-circle', 'inactive')->asImg(20, $params) ?>
+ </a>
+ <? else : ?>
+ <?= Assets::img('blank.gif', ['width' => 20, 'height' => 20]); ?>
+ <? endif ?>
+ </td>
+ <td style="text-align: left; white-space: nowrap;" class="hidden-small-down">
+ <? if (!empty($course['navigation'])) : ?>
+ <? foreach (MyRealmModel::array_rtrim($course['navigation']) as $key => $nav) : ?>
+ <? if (isset($nav) && $nav->isVisible(true)) : ?>
+ <a href="<?=
+ UrlHelper::getLink('seminar_main.php',
+ ['auswahl' => $course['seminar_id'],
+ 'redirect_to' => strtr($nav->getURL(), '?', '&')]) ?>" <?= $nav->hasBadgeNumber() ? 'class="badge" data-badge-number="' . intval($nav->getBadgeNumber()) . '"' : '' ?>>
+ <?= $nav->getImage()->asImg(20, $nav->getLinkAttributes()) ?>
+ </a>
+ <? elseif (is_string($key)) : ?>
+ <?=
+ Assets::img('blank.gif', ['width' => 20,
+ 'height' => 20]); ?>
+ <? endif ?>
+ <? echo ' ' ?>
+ <? endforeach ?>
+ <? endif ?>
+
+ </td>
+ <td style="text-align: right" class="hidden-small-down">
+ <? if (!$course['is_group']) : ?>
+ <? if (in_array($course['user_status'], ['dozent', 'tutor'])) : ?>
+ <? $adminmodule = $sem_class->getAdminModuleObject(); ?>
+ <? if ($adminmodule) : ?>
+ <? $adminnavigation = $adminmodule->getIconNavigation($course['seminar_id'], 0, $GLOBALS['user']->id); ?>
+ <? endif ?>
+
+ <? if ($adminnavigation) : ?>
+ <a href="<?= URLHelper::getLink($adminnavigation->getURL(), ['cid' => $course['seminar_id']]) ?>">
+ <?= $adminnavigation->getImage()->asImg(20, $adminnavigation->getLinkAttributes()) ?>
+ </a>
+ <? endif ?>
+ <? elseif ($course['admission_binding']) : ?>
+ <a href="<?= $controller->url_for('my_courses/decline_binding') ?>">
+ <?= Icon::create('door-leave+decline', 'inactive', ['title' => _("Die Teilnahme ist bindend. Bitte wenden Sie sich an die Lehrenden.")])->asImg(20) ?>
+ </a>
+ <? else: ?>
+ <a href="<?= $controller->url_for('my_courses/decline/' . $course['seminar_id'], ['cmd' => 'suppose_to_kill']) ?>">
+ <?= Icon::create('door-leave', 'inactive', ['title' => _('aus der Veranstaltung abmelden')])->asImg(20) ?>
+ </a>
+ <? endif ?>
+ <? endif ?>
+ </td>
+ </tr>
+<? if ($course['children']) : ?>
+ <?= $this->render_partial('my_courses/_course', [
+ 'course_collection' => $course['children'],
+ 'children' => true,
+ 'gruppe' => $course['gruppe'],
+ ]) ?>
+<? endif ?>
+<? endforeach ?>
diff --git a/app/views/my_courses/_deputy_bosses.php b/app/views/my_courses/_deputy_bosses.php
new file mode 100644
index 0000000..f85ae1c
--- /dev/null
+++ b/app/views/my_courses/_deputy_bosses.php
@@ -0,0 +1,48 @@
+<? SkipLinks::addIndex(_('Personen, deren Standardvertretung ich bin'), 'my_deputy_bosses') ?>
+<table class="default" id="my_deputy_bosses">
+ <caption>
+ <?= _('Personen, deren Standardvertretung ich bin') ?>
+ </caption>
+ <colgroup>
+ <col style="width: 30px">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($my_bosses as $boss) : ?>
+ <? $boss_fullname = $boss->getBossFullname(); ?>
+ <tr>
+ <td>
+ <?= Avatar::getAvatar($boss->user_id)->getImageTag(Avatar::SMALL, ['title' => $boss_fullname]) ?>
+ </td>
+ <td>
+ <?= htmlReady($boss_fullname)?>
+ </td>
+ <td class="actions">
+ <? if ($boss->edit_about && $deputies_edit_about_enabled) : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $boss->boss_username]) ?>">
+ <?= Icon::create('person')->asImg(['title' => _('Personenangaben bearbeiten')]) ?>
+ </a>
+ <? endif ?>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/messages/write',
+ ['filter' => 'send_sms_to_all', 'rec_uname' => $boss->boss_username])?>" data-dialog>
+ <?= Icon::create('mail')->asImg(['title' => sprintf(_('Nachricht an %s senden'), htmlReady($boss_fullname))]) ?>
+ </a>
+ <a href="<?= $controller->link_for('my_courses/delete_boss/' . $boss->range_id) ?>"
+ data-confirm="<?= sprintf(_('Wollen Sie sich wirklich als Standardvertretung von %s austragen?'), htmlReady($boss_fullname)) ?>">
+ <?= Icon::create('trash')->asImg([
+ 'title' => sprintf(_('Mich als Standardvertretung von %s austragen'), htmlReady($boss_fullname))
+ ]) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/my_courses/_dozent.php b/app/views/my_courses/_dozent.php
new file mode 100644
index 0000000..cb7bf90
--- /dev/null
+++ b/app/views/my_courses/_dozent.php
@@ -0,0 +1,4 @@
+<?
+# Lifter010: TODO
+?>
+<?= $colon ? ', ' : '' ?><a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $_dozent['username']]) ?>"><?= htmlReady($_dozent["fullname"]) ?></a><? $this->colon = true; ?>
diff --git a/app/views/my_courses/_exportcourse.php b/app/views/my_courses/_exportcourse.php
new file mode 100644
index 0000000..84ccdc8
--- /dev/null
+++ b/app/views/my_courses/_exportcourse.php
@@ -0,0 +1,80 @@
+<? foreach ($course_collection as $course):
+ $teachers = CourseMember::findByCourseAndStatus($course['seminar_id'], 'dozent');
+ $collection = SimpleCollection::createFromArray($teachers);
+ $dozenten = $collection->map(function (CourseMember $teacher) {
+ return [
+ 'user_id' => $teacher->user_id,
+ 'username' => $teacher->username,
+ 'Nachname' => $teacher->nachname,
+ 'fullname' => $teacher->getUserFullname('no_title_rev'),
+ ];
+ });
+
+ if ($with_modules) {
+ $trail_classes = ['Modulteil', 'StgteilabschnittModul', 'StgteilAbschnitt', 'StgteilVersion'];
+ $mvv_object_pathes = MvvCourse::get($course['seminar_id'])->getTrails($trail_classes);
+
+ if ($mvv_object_pathes) {
+ foreach ($mvv_object_pathes as $mvv_object_path) {
+ // show only complete pathes
+ if (count($mvv_object_path) === 4) {
+ $mvv_object_names = [];
+ $modul_id = '';
+ foreach ($mvv_object_path as $mvv_object) {
+ if ($mvv_object instanceof StgteilabschnittModul) {
+ $modul_id = $mvv_object->modul_id;
+ }
+ $mvv_object_names[] = $mvv_object->getDisplayName();
+ }
+ $mvv_pathes[] = [$modul_id => $mvv_object_names];
+ }
+ }
+ }
+ }
+ $sem_class = $course['sem_class'];
+?>
+
+<table>
+<tr>
+<th width="2cm"><?= _('Nr.') ?></th>
+<td width="16cm"><?= htmlReady($course['veranstaltungsnummer'])?></td>
+</tr>
+<tr>
+<th><?= _('Name') ?></th>
+<td><?= htmlReady($course['name']) ?></td>
+</tr>
+<? if ($course['untertitel']): ?>
+<tr>
+<th><?= _('Untertitel') ?></th>
+<td><?= htmlReady($course['untertitel']) ?></td>
+</tr>
+<? endif; ?>
+<? if ($dozenten): ?>
+<tr>
+<th><?= _('Lehrende') ?></th>
+<td><? foreach ($dozenten as $dozent): ?>
+<?= $colon ? ', ' : '' ?><?= htmlReady($dozent['fullname']) ?><? $this->colon = true; ?>
+<? endforeach; ?></td>
+</tr>
+<? endif; ?>
+<? if ($mvv_pathes): ?>
+<tr nobr="true">
+<th><?= _('Module') ?></th>
+<td>
+<? foreach ($mvv_pathes as $i => $mvv_path) : ?>
+<span <? if ($i%2==1) echo 'style="background-color:#eaeaea;"'; ?>><?= htmlReady(implode(' > ', reset(array_values($mvv_path)))) ?></span><br>
+<? endforeach; ?>
+</td>
+</tr>
+<? endif; ?>
+</table>
+<br><br>
+
+<? if ($course['children']) : ?>
+ <?= $this->render_partial('my_courses/_exportcourse', [
+ 'course_collection' => $course['children'],
+ 'children' => true,
+ 'gruppe' => $course['gruppe'],
+ ]) ?>
+<? endif ?>
+<? endforeach ?>
diff --git a/app/views/my_courses/archive.php b/app/views/my_courses/archive.php
new file mode 100644
index 0000000..81ece3d
--- /dev/null
+++ b/app/views/my_courses/archive.php
@@ -0,0 +1,76 @@
+<? if (empty($seminars)): ?>
+ <?= MessageBox::info(_('Es befinden sich zur Zeit keine Veranstaltungen im Archiv, an denen Sie teilgenommen haben.')) ?>
+<? else: ?>
+ <? foreach ($seminars as $semester => $rows): ?>
+ <table class="default">
+ <? if ($semester): ?>
+ <caption><?= htmlReady($semester) ?></caption>
+
+ <? endif; ?>
+ <colgroup>
+ <col width="80%">
+ <col width="10%">
+ <col width="10%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <a href="<?= $controller->url_for('my_courses/archive?sortby=name') ?>">
+ <?= _('Name') ?>
+ </a>
+ </th>
+ <th style="text-align: center"><?= _('Inhalt') ?></th>
+ <th style="text-align: center">
+ <a href="<?= $controller->url_for('my_courses/archive?sortby=status') ?>">
+ <?= _('Status') ?>
+ </a>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($rows as $row): ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/archive/overview/' . $row['seminar_id']) ?>" data-dialog>
+ <?= htmlReady($row['name']) ?>
+ </a>
+ </td>
+ <td align="center">
+ <? if ($row['forumdump'] and archiv_check_perm($row['seminar_id'])) : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/archive/forum/' . $row['seminar_id']) ?>" data-dialog>
+ <?= Icon::create('forum', 'clickable', ['title' => _('Beiträge des Forums der Veranstaltung')])->asImg(20) ?>
+ </a>
+ <? else: ?>
+ <?= Icon::create('forum', 'inactive')->asImg(20, ["style" => 'visibility: hidden;']) ?>
+ <? endif; ?>
+
+
+ <? $course = ArchivedCourse::find($row['seminar_id']); ?>
+
+ <? if(($row['archiv_file_id']) and archiv_check_perm($row['seminar_id'])): ?>
+ <a href="<?= FileManager::getDownloadLinkForArchivedCourse($course, false) ?>">
+ <?= Icon::create('file-archive', 'clickable', ['title' => _('Dateisammlung der Veranstaltung herunterladen')])->asImg(20) ?>
+ </a>
+ <? elseif(($row['archiv_protected_file_id']) and archiv_check_perm($row['seminar_id'] == 'admin')): ?>
+ <a href="<?= FileManager::getDownloadLinkForArchivedCourse($course, true) ?>">
+ <?= Icon::create('file-archive', 'clickable', ['title' => _('Dateisammlung der Veranstaltung herunterladen')])->asImg(20) ?>
+ </a>
+ <? else: ?>
+ <?= Icon::create('file-archive', 'inactive')->asImg(20, ["style" => 'visibility: hidden;']) ?>
+ <? endif; ?>
+
+ <? if ($row['wikidump'] and archiv_check_perm($row['seminar_id'])) : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/archive/wiki/' . $row['seminar_id']) ?>" data-dialog>
+ <?= Icon::create('wiki', 'clickable', ['title' => _('Beiträge des Wikis der Veranstaltung')])->asImg(20) ?>
+ </a>
+ <? else: ?>
+ <?= Icon::create('wiki', 'inactive')->asImg(20, ["style" => 'visibility: hidden;']) ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center"><?= $row['status'] ?></td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ <? endforeach; ?>
+<? endif; ?>
diff --git a/app/views/my_courses/courseexport.php b/app/views/my_courses/courseexport.php
new file mode 100644
index 0000000..d953187
--- /dev/null
+++ b/app/views/my_courses/courseexport.php
@@ -0,0 +1,32 @@
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title><?= _('Export Veranstaltungsübersicht') ?></title>
+ <style>
+ table {
+ border: 1px solid #000;
+ }
+ th {
+ font-weight: bold;
+ background-color: #c7c7c7;
+ border: 1px solid #a8a8a8;
+ }
+ td {
+ border: 1px solid #c7c7c7;
+ }
+ </style>
+ </head>
+ <body>
+ <? if ($sem_courses && is_array($sem_courses)) : ?>
+ <h1><?= _('Meine Veranstaltungen'); ?></h1>
+ <div id="my_seminars">
+ <? foreach ($sem_courses as $sem_key => $course_group) : ?>
+ <h2><?= htmlReady($sem_data[$sem_key]['name']) ?></h2>
+ <?= $this->render_partial('my_courses/_exportcourse', [
+ 'course_collection' => $course_group,
+ ]) ?>
+ <? endforeach ?>
+ </div>
+ <? endif ?>
+ </body>
+</html>
diff --git a/app/views/my_courses/groups.php b/app/views/my_courses/groups.php
new file mode 100644
index 0000000..654f54c
--- /dev/null
+++ b/app/views/my_courses/groups.php
@@ -0,0 +1,59 @@
+<form method="post" action="<?= $controller->url_for('my_courses/store_groups/'.$studygroups) ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <input type="hidden" name="cid" value="<?= $cid ?>">
+ <table class="default collapsable">
+ <caption><?= _('Gruppenzuordnung') ?></caption>
+ <thead>
+ <tr>
+ <th><?= _('Veranstaltung') ?></th>
+ <th colspan="100%"><?= _('Gruppen/Farbe') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($groups as $group_id => $group_members): ?>
+ <tbody class="<?= $current_semester != $semesters[$group_id]['semester_id'] ? 'collapsed' : ''?>">
+ <? if ($group_field !== 'not_grouped'): ?>
+
+ <tr class="table_header header-row">
+ <th colspan='100%' class="toggle-indicator">
+ <a class="toggler">
+ <? if (is_array($group_names[$group_id])): ?>
+ <?= htmlReady(my_substr($group_names[$group_id][1] . ' > ' . $group_names[$group_id][0], 0, 70)) ?>
+ <? else: ?>
+ <?= htmlReady(my_substr($group_names[$group_id], 0, 70)) ?>
+ <? endif; ?>
+ </a>
+ </th>
+ </tr>
+ <? endif; ?>
+ <? foreach ($group_members as $member): ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php?auswahl=' . $member['seminar_id']) ?>">
+ <?= htmlReady(Config::get()->IMPORTANT_SEMNUMBER ? $my_sem[$member['seminar_id']]['sem_nr'] : '') ?>
+ <?= htmlReady(my_substr($my_sem[$member['seminar_id']]['name'], 0, 70)) ?>
+ </a>
+ <? if (!$my_sem[$member['seminar_id']]['visible']): ?>
+ <?= _('(versteckt)') ?>
+ <? endif; ?>
+ </td>
+ <? for ($i = 0; $i < 9; $i++): ?>
+ <td class="gruppe<?= $i ?>" width="28">
+ <input type="radio" name="gruppe[<?= $member['seminar_id'] ?>]" value="<?= $i ?>"
+ aria-label="<?= _('Zugeordnet zu Gruppe ') . $i ?>"
+ <? if ($my_sem[$member['seminar_id']]['gruppe'] == $i) echo 'checked'; ?>>
+ </td>
+ <? endfor; ?>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <? endforeach; ?>
+ </table>
+
+ <div align="center" data-dialog-button>
+ <div class="button-group">
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('my_courses/groups')) ?>
+ </div>
+ </div>
+</form>
diff --git a/app/views/my_courses/index.php b/app/views/my_courses/index.php
new file mode 100644
index 0000000..1bbfd73
--- /dev/null
+++ b/app/views/my_courses/index.php
@@ -0,0 +1,11 @@
+<? if ($waiting_list) : ?>
+ <?= $this->render_partial('my_courses/waiting_list.php', compact('waiting_list')) ?>
+<? endif ?>
+
+<div class="my-courses-vue-app">
+ <my-courses />
+</div>
+
+<? if (count($my_bosses) > 0) : ?>
+ <?= $this->render_partial('my_courses/_deputy_bosses'); ?>
+<? endif ?>
diff --git a/app/views/my_courses/waiting_list.php b/app/views/my_courses/waiting_list.php
new file mode 100644
index 0000000..7ed9124
--- /dev/null
+++ b/app/views/my_courses/waiting_list.php
@@ -0,0 +1,102 @@
+<? SkipLinks::addIndex(_("Wartelisten"), 'my_waitlists') ?>
+<table class="default collapsable" id="my_waitlists">
+ <caption>
+ <?= _("Anmelde- und Wartelisteneinträge") ?>
+ </caption>
+ <colgroup class="hidden-small-down">
+ <col width="1px">
+ <col width="65%">
+ <col width="7%">
+ <col width="10%">
+ <col width="10%">
+ <col width="15%">
+ <col width="3%">
+ </colgroup>
+ <colgroup class="hidden-medium-up">
+ <col width="1px">
+ </colgroup>
+
+ <thead>
+ <tr>
+ <th></th>
+ <th style="text-align: left"><?= _("Name") ?></th>
+ <th class="hidden-small-down"><?= _('Inhalt') ?></th>
+ <th style="text-align: center"><?= _("Datum") ?></th>
+ <th class="hidden-small-down" style="text-wrap: none; white-space: nowrap"><b><?= _("Position/Chance") ?></th>
+ <th class="hidden-small-down"><?= _("Art") ?></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($waiting_list as $wait) {
+
+ // wir sind in einer Anmeldeliste und brauchen Prozentangaben
+ if ($wait["status"] == "claiming") {
+ // Grün der Farbe nimmt mit Wahrscheinlichkeit ab
+ $chance_color = dechex(55 + $wait['admission_chance'] * 2);
+ } // wir sind in einer Warteliste
+ else {
+ $chance_color = $wait["position"] < 30
+ ? dechex(255 - $wait["position"] * 6)
+ : 44;
+ }
+
+ $seminar_name = $wait["Name"];
+ if (SeminarCategories::GetByTypeId($wait['sem_status'])->studygroup_mode) {
+ $seminar_name .= ' (' . _("Studiengruppe") . ', ' . _("geschlossen") . ')';
+ }
+ ?>
+ <tr>
+ <td title="<?=_("Position oder Wahrscheinlichkeit")?>" style="background:#44<?= $chance_color ?>44">
+ </td>
+
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details/', ['sem_id' => $wait['seminar_id'], 'send_from_search_page' => 'dispatch.php/my_courses/index', 'send_from_search' => 'TRUE']) ?>">
+ <?= htmlReady($seminar_name) ?>
+ </a>
+ <?php if ($wait['status'] === 'claiming') : ?>
+ <br>
+ <?= sprintf(_('Priorität %1$u im Anmeldeset "%2$s"'), $wait['priority'], $wait['cname']) ?>
+ <?php endif ?>
+ </td>
+ <td class="hidden-small-down">
+ <a data-dialog="size=auto" href="<?= $controller->link_for('course/details/index', $wait['seminar_id']) ?>">
+ <? $params = tooltip2(_("Veranstaltungsdetails anzeigen")); ?>
+ <?= Icon::create('info-circle', Icon::ROLE_INACTIVE)->asImg(20, ['style' => 'cursor: pointer']) ?>
+ </a>
+ </td>
+ <td style="text-align: center">
+ <?= $wait['status'] === 'claiming' ? date('d.m.', $wait['admission_endtime']) : "-" ?>
+ </td>
+
+ <td class="hidden-small-down" style="text-align: center">
+ <?= $wait['status'] === 'claiming' ? ($wait['admission_chance'] . "%") : $wait['position'] ?>
+ </td>
+
+ <td class="hidden-small-down" style="text-align: center">
+ <? if ($wait['status'] === 'claiming') : ?>
+ <?= _("Autom.") ?>
+ <? elseif ($wait['status'] === 'accepted') : ?>
+ <?= _('Vorl.') ?>
+ <? else: ?>
+ <?= _('Wartel.') ?>
+ <? endif ?>
+ </td>
+
+ <td style="text-align: right">
+ <? if ($wait["status"] == "accepted" && $wait['admission_binding']) : ?>
+ <a href="<?= $controller->url_for('my_courses/decline_binding') ?>">
+ <?= Icon::create('door-leave+decline', 'inactive', ['title' => _("Die Teilnahme ist bindend. Bitte wenden Sie sich an die Lehrenden.")])->asImg(20) ?>
+ </a>
+ <? else : ?>
+ <a href="<?= $controller->link_for('my_courses/decline', $wait['seminar_id'], ['cmd' => 'suppose_to_kill_admission']) ?>">
+ <?= Icon::create('door-leave', Icon::ROLE_INACTIVE)->asImg(20, ['title' => _("aus der Veranstaltung abmelden")]) ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+ <? } ?>
+ </tbody>
+</table>
+<br>
+<br>
diff --git a/app/views/my_ilias_accounts/_ilias_module.php b/app/views/my_ilias_accounts/_ilias_module.php
new file mode 100755
index 0000000..6d52039
--- /dev/null
+++ b/app/views/my_ilias_accounts/_ilias_module.php
@@ -0,0 +1,67 @@
+<div id="ilias_module_details_window">
+<aside id="ilias_module_aside">
+ <div class="ilias-module-icon">
+ <?= $module->getIcon()?>
+ </div>
+
+ <table class="default nohover">
+ <tbody>
+ <tr>
+ <td><?= _('Erstellt') ?></td>
+ <td>
+ <?= htmlReady($module->getMakeDate(), true, true)?>
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Geändert') ?></td>
+ <td>
+ <?= htmlReady($module->getChangeDate(), true, true)?>
+ </td>
+ </tr>
+ <tr>
+ <td><?= _('Besitzer/-in') ?></td>
+ <td>
+ <? if ($module->getAuthorStudip()): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $module->getAuthorStudip()->username]) ?>">
+ <?= htmlReady($module->getAuthorStudip()->getFullName()) ?>
+ </a>
+ <? else: ?>
+ <?= _('ILIAS-Nutzer/-in') ?>:
+ <?= htmlReady($ilias->getUserFullname($module->getAuthorIlias())); ?>
+ <? endif ?>
+ </td>
+ </tr>
+
+ </tbody>
+ </table>
+</aside>
+
+ <div id="ilias_module_preview">
+ <h2><?= htmlReady($module->getTitle()) ?></h2>
+ <h3><?= _('Typ') ?></h3>
+ <article>
+ <?= htmlReady($module->getModuleTypeName()) ?>
+ </article>
+
+ <h3><?= _('Beschreibung') ?></h3>
+ <article>
+ <?= htmlReady($module->getDescription()?: _('Keine Beschreibung vorhanden.'), true, true) ?>
+ </article>
+
+ <? if (!$module->isConnected()) : ?>
+ <h3><?=_('Pfad')?></h3>
+ <article>
+ <?= htmlReady($ilias->getPath($module->getId())); ?>
+ </article>
+ <? endif ?>
+
+ <? if ((($module->getModuleType() == 'htlm') || ($module->getModuleType() == 'sahs') || ($module->getModuleType() == 'lm')) && ($ilias->getStructure($module->getId()))) : ?>
+ <h3><?=_('Struktur')?></h3>
+ <article>
+ <? foreach ($ilias->getStructure($module->getId()) as $chapter) : ?>
+ <div><?=htmlReady($chapter)?></div>
+ <? endforeach ?>
+ </article>
+ <? endif ?>
+ </div>
+</div> \ No newline at end of file
diff --git a/app/views/my_ilias_accounts/add_object.php b/app/views/my_ilias_accounts/add_object.php
new file mode 100755
index 0000000..993ceb6
--- /dev/null
+++ b/app/views/my_ilias_accounts/add_object.php
@@ -0,0 +1,27 @@
+<form class="default" action="<?= $controller->url_for('my_ilias_accounts/redirect/'.$ilias_index.'/new/'.$ilias_ref_id) ?>" method="post" target="_blank">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="ilias_target" value="new">
+ <input type="hidden" name="ilias_ref_id" value="<?=$ilias_ref_id?>">
+ <label>
+ <span class="required"><?= _('Art des Lernobjekts') ?></span>
+ <select name="ilias_module_type" required>
+ <option></option>
+ <? foreach ($ilias->getAllowedModuleTypes() as $module_index => $module_name) : ?>
+ <option value="<?=$module_index?>"><?=$module_name?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <footer data-dialog-button>
+ <? if ($ilias->isActive()) : ?>
+ <?= Studip\Button::createAccept(_('Erstellen'), 'submit') ?>
+ <? endif ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form>
+<script>
+jQuery(function ($) {
+ $('button[name=submit]').click(function () {
+ window.location.reload();
+ });
+});
+</script>
diff --git a/app/views/my_ilias_accounts/index.php b/app/views/my_ilias_accounts/index.php
new file mode 100755
index 0000000..1dd77d6
--- /dev/null
+++ b/app/views/my_ilias_accounts/index.php
@@ -0,0 +1,149 @@
+<form method="post">
+<? foreach($ilias_list as $ilias_index => $ilias) : ?>
+ <? if (!$GLOBALS['perm']->have_perm($ilias->ilias_config['author_perm'])) continue; ?>
+ <table class="default">
+ <caption>
+ <?= sprintf(_('Meine Lernobjekte in %s'), $ilias->getName()) ?>
+ <span class="actions">
+ <a href="<?= $controller->url_for('my_ilias_accounts/add_object/'.$ilias_index) ?>" data-dialog="size=auto;reload-on-close">
+ <?= Icon::create('add', Icon::ROLE_CLICKABLE, tooltip2(_('Neues Lernobjekt anlegen'))) ?>
+ </a>
+ </span>
+ </caption>
+ <colgroup>
+ <col style="width: 5%">
+ <col style="width: 55%">
+ <col style="width: 20%">
+ <col style="width: 20%">
+ </colgroup>
+ <thead>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </thead>
+ <? if (count($ilias->getUserModules())) : ?>
+ <? foreach ($ilias->getUserModules() as $module_id => $module) : ?>
+ <tr>
+ <td><?=Icon::create('learnmodule', Icon::ROLE_INFO, [
+ 'title' => $module->getModuleTypeName()
+ ])
+ ?></td>
+ <td><a href="<?= $controller->url_for($module->getRoute('view_tools'))?>" data-dialog=""><?=$module->getTitle()?></a></td>
+ <td><?=$module->getModuleTypeName()?></td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addButton(
+ 'view',
+ _('Info'),
+ Icon::create('info-circle', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Info'),
+ 'formaction' => $controller->url_for($module->getRoute('view_tools')),
+ 'data-dialog' => ''
+ ])
+ ) ?>
+ <? if ($module->isAllowed('start')) $actionMenu->addButton(
+ 'start',
+ _('In ILIAS anzeigen'),
+ Icon::create('play', Icon::ROLE_CLICKABLE, [
+ 'title' => _('In ILIAS anzeigen'),
+ 'formaction' => $controller->url_for($module->getRoute('start')),
+ 'formtarget' => '_blank',
+ 'formrel' => 'noopener noreferrer'
+ ])
+ ) ?>
+ <? if ($module->isAllowed('edit')) $actionMenu->addButton(
+ 'edit',
+ _('In ILIAS bearbeiten'),
+ Icon::create('learnmodule+edit', Icon::ROLE_CLICKABLE, [
+ 'title' => _('In ILIAS bearbeiten'),
+ 'formaction' => $controller->url_for($module->getRoute('edit')),
+ 'formtarget' => '_blank',
+ 'formrel' => 'noopener noreferrer'
+ ])
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? else : ?>
+ <tr>
+ <td colspan="4">
+ <?= sprintf(
+ _("Sie haben im System %s noch keine eigenen Lernmodule."),
+ htmlReady($ilias->getName())
+ )?>
+ </td>
+ </tr>
+ <? endif ?>
+ </table>
+ <br>
+ <br>
+<? endforeach ?>
+ <table class="default">
+ <caption>
+ <?= count($ilias_list) == 1 ? _('Mein Account') : _('Meine Accounts') ?>
+ </caption>
+ <colgroup>
+ <col style="width: 5%">
+ <col style="width: 55%">
+ <col style="width: 20%">
+ <col style="width: 20%">
+ </colgroup>
+ <thead>
+ <th></th>
+ <th><?= _('Login') ?></th>
+ <th><?= _('System') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </thead>
+ <tbody>
+ <? foreach($ilias_list as $ilias_index => $ilias) : ?>
+ <tr id="ilias-account-<?= htmlReady($ilias_index)?>">
+ <td><?=Icon::create('person', Icon::ROLE_INFO, [
+ 'title' => $ilias->user->getUserName()
+ ])
+ ?></td>
+ <td><?=$ilias->user->getUserName()?></td>
+ <td><?=$ilias->getName()?></td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($ilias->ilias_config['allow_change_account'] && ($ilias->user->getUserType() === IliasUser::USER_TYPE_CREATED)) $actionMenu->addButton(
+ 'new_account',
+ _('Account neu zuordnen'),
+ Icon::create('person+new', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Account neu zuordnen'),
+ 'formaction' => $controller->url_for('my_ilias_accounts/new_account/'.$ilias_index),
+ 'data-confirm' =>
+ sprintf(_('Möchten Sie wirklich die bestehende Zuordnung aufheben? Sie verlieren dadurch alle mit dem bestehenden Account verbundenen Inhalte und Lernfortschritte im System "%s".'),
+ htmlReady($ilias->getName())
+ ),
+ 'data-dialog' => 'size=auto;reload-on-close'
+ ])
+ ) ?>
+ <? if ($ilias->ilias_config['allow_change_account'] && ($ilias->user->getUserType() === IliasUser::USER_TYPE_ORIGINAL)) $actionMenu->addButton(
+ 'change_account',
+ _('Account-Zuordnung aufheben'),
+ Icon::create('person+remove', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Account-Zuordnung aufheben'),
+ 'formaction' => $controller->url_for('my_ilias_accounts/change_account/'.$ilias_index.'/remove'),
+ 'data-confirm' =>
+ sprintf(_('Möchten Sie wirklich die bestehende Zuordnung aufheben? Sie verlieren dadurch alle mit dem bestehenden Account verbundenen Inhalte und Lernfortschritte im System "%s".'),
+ htmlReady($ilias->getName())
+ )
+ ])
+ ) ?>
+ <? if ($ilias->user->getUserType() === IliasUser::USER_TYPE_CREATED) $actionMenu->addButton(
+ 'update_account',
+ _('Account aktualisieren'),
+ Icon::create('person+refresh', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Account aktualisieren'),
+ 'formaction' => $controller->url_for('my_ilias_accounts/change_account/'.$ilias_index.'/update')
+ ])
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+</form>
diff --git a/app/views/my_ilias_accounts/new_account.php b/app/views/my_ilias_accounts/new_account.php
new file mode 100755
index 0000000..635c59d
--- /dev/null
+++ b/app/views/my_ilias_accounts/new_account.php
@@ -0,0 +1,15 @@
+<form class="default" action="<?= $controller->url_for('my_ilias_accounts/change_account/'.$ilias_index.'/add') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <label>
+ <span class="required"><?= _('Login') ?></span>
+ <input type="text" name="ilias_login" size="50" maxlength="50" required>
+ </label>
+ <label>
+ <span class="required"><?= _('Passwort') ?></span>
+ <input type="password" name="ilias_password" size="50" maxlength="50" required>
+ </label>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Zuordnen'), 'set_new_account') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/my_ilias_accounts/redirect.php b/app/views/my_ilias_accounts/redirect.php
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/app/views/my_ilias_accounts/redirect.php
diff --git a/app/views/my_ilias_accounts/view_object.php b/app/views/my_ilias_accounts/view_object.php
new file mode 100755
index 0000000..5d90331
--- /dev/null
+++ b/app/views/my_ilias_accounts/view_object.php
@@ -0,0 +1,11 @@
+<form class="default" action="<?= $controller->url_for($module->getRoute('view_tools')) ?>" method="post" target="_blank">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('my_ilias_accounts/_ilias_module.php') ?>
+ <footer data-dialog-button>
+ <? if ($ilias->isActive()) : ?>
+ <?= $module->isAllowed('start') ? Studip\LinkButton::create(_('Starten'), $controller->url_for($module->getRoute('start')), ['target' => '_blank', 'rel' => 'noopener noreferrer']) :'' ?>
+ <?= $module->isAllowed('edit') ? Studip\LinkButton::create(_('Bearbeiten'), $controller->url_for($module->getRoute('edit')), ['target' => '_blank', 'rel' => 'noopener noreferrer']) :'' ?>
+ <? endif ?>
+ <?= Studip\Button::createCancel(_('Schließen'), 'cancel', ['data-dialog' => 'close']) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/my_institutes/index.php b/app/views/my_institutes/index.php
new file mode 100644
index 0000000..53c8b1d
--- /dev/null
+++ b/app/views/my_institutes/index.php
@@ -0,0 +1,110 @@
+<? if (isset($flash['decline_inst'])) : ?>
+ <?= QuestionBox::create(
+ sprintf(
+ _('Wollen Sie sich aus dem/der %s wirklich austragen?'),
+ htmlReady($flash['name'])
+ ),
+ $controller->declineURL($flash['inst_id'], ['cmd' => 'kill', 'studipticket' => $flash['studipticket']]),
+ $controller->declineURL($flash['inst_id'], ['cmd'=> 'back', 'studipticket' => $flash['studipticket']])
+ ) ?>
+<? endif ?>
+
+<? if (empty($institutes)) : ?>
+ <? if (!Config::get()->ALLOW_SELFASSIGN_INSTITUTE || $GLOBALS['perm']->have_perm("dozent")) : ?>
+ <?=
+ MessageBox::info(sprintf(_('Sie wurden noch keinen Einrichtungen zugeordnet. Bitte wenden Sie sich an einen der zuständigen %sAdministratoren%s.'),
+ '<a href="' . URLHelper::getLink('dispatch.php/siteinfo/show') . '">', '</a>'))?>
+ <? else : ?>
+ <?=
+ MessageBox::info(sprintf(_('Sie haben sich noch keinen Einrichtungen zugeordnet.
+ Um sich Einrichtungen zuzuordnen, nutzen Sie bitte die entsprechende %sOption%s unter "Persönliche Angaben - Studiendaten"
+ auf Ihrer persönlichen Einstellungsseite.'), '<a href="' . URLHelper::getLink('dispatch.php/settings/studies#einrichtungen') . '">', '</a>'))?>
+ <? endif ?>
+<? else : ?>
+ <? SkipLinks::addIndex(_('Meine Einrichtungen'), 'my_institutes') ?>
+ <table class="default" id="my_institutes">
+ <caption><?= _('Meine Einrichtungen') ?></caption>
+ <colgroup>
+ <col width="10px">
+ <col width="25px">
+ <col>
+ <col width="<?= $nav_elements * 27 ?>px">
+ <col width="45px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th></th>
+ <th></th>
+ <th><?= _("Name") ?></th>
+ <th style="text-align: center"><?= _("Inhalt") ?></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($institutes as $values) : ?>
+ <? $lastVisit = $values['visitdate']; ?>
+ <? $instid = $values['institut_id'] ?>
+ <tr>
+ <td style="width:1px"></td>
+ <td>
+ <?= InstituteAvatar::getAvatar($instid)->getImageTag(Avatar::SMALL, ['title' => $values['name']]) ?>
+ </td>
+
+ <td style="text-align: left">
+ <a href="<?= URLHelper::getLink('dispatch.php/institute/overview', ['auswahl' => $instid]) ?>">
+ <?= htmlReady($GLOBALS['INST_TYPE'][$values["type"]]["name"] . ": " . $values["name"]) ?>
+ </a>
+ </td>
+
+ <td style="text-align: left; white-space: nowrap">
+ <? if (!empty($values['navigation'])) : ?>
+ <? foreach (MyRealmModel::array_rtrim($values['navigation']) as $key => $nav) : ?>
+ <? if (isset($nav) && $nav->isVisible(true)) : ?>
+ <a href="<?=
+ UrlHelper::getLink('dispatch.php/institute/overview',
+ ['auswahl' => $instid,
+ 'redirect_to' => strtr($nav->getURL(), '?', '&')]) ?>" <?= $nav->hasBadgeNumber() ? 'class="badge" data-badge-number="' . intval($nav->getBadgeNumber()) . '"' : '' ?>>
+ <?= $nav->getImage()->asImg(20, $nav->getLinkAttributes()) ?>
+ </a>
+ <? elseif (is_string($key)) : ?>
+ <?= Assets::img('blank.gif', ['widtd' => 20, 'height' => 20]); ?>
+ <? endif ?>
+ <? endforeach ?>
+ <? endif ?>
+ </td>
+
+ <td style="text-align: left; white-space: nowrap">
+ <? if (Config::get()->ALLOW_SELFASSIGN_INSTITUTE && $values['perms'] == 'user') : ?>
+ <a href="<?=$controller->url_for('my_institutes/decline_inst/'.$instid)?>">
+ <?= Icon::create('door-leave', 'inactive', ['title' => _("aus der Einrichtung austragen")])->asImg(20) ?>
+ </a>
+ <? else : ?>
+ <?= Assets::img('blank.gif', ['size' => '20']) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? endif ?>
+
+
+<?php
+$sidebar = Sidebar::Get();
+
+$links = new ActionsWidget();
+if ($reset) {
+ $links->addLink(_('Alles als gelesen markieren'),
+ $controller->url_for('my_institutes/tabularasa/' . time()), Icon::create('accept', 'clickable'));
+}
+if ($GLOBALS['perm']->have_perm('dozent') && !empty($institutes)) {
+ $links->addLink(_('Einrichtungsdaten bearbeiten'),
+ URLHelper::getURL('dispatch.php/settings/statusgruppen'), Icon::create('institute+edit', 'clickable') );
+}
+if ($GLOBALS['perm']->have_perm('autor')) {
+ $links->addLink(_('Einrichtungen suchen'),
+ URLHelper::getURL('dispatch.php/search/globalsearch#GlobalSearchInstitutes'), Icon::create('institute+add', 'clickable') );
+ $links->addLink(_('Studiendaten bearbeiten'),
+ URLHelper::getURL('dispatch.php/settings/studies'), Icon::create('person', 'clickable'));
+}
+$sidebar->addWidget($links);
diff --git a/app/views/my_studygroups/_course.php b/app/views/my_studygroups/_course.php
new file mode 100644
index 0000000..1244247
--- /dev/null
+++ b/app/views/my_studygroups/_course.php
@@ -0,0 +1,66 @@
+<? foreach ($studygroups as $group) : ?>
+ <tr>
+ <td class="gruppe<?= $group['gruppe'] ?>"></td>
+ <td>
+ <?= CourseAvatar::getAvatar($group['seminar_id'])->getImageTag(Avatar::SMALL, ['title' => $group['name']])
+ ?>
+ </td>
+ <td style="text-align: left">
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $group['seminar_id']]) ?>"
+ <?= $group['lastvisitdate'] >= $group['chdate'] ? 'style="color: red;"' : '' ?>>
+ <?= htmlReady($group['name']) ?>
+ </a>
+ <? if ($group['visible'] == 0) : ?>
+ <? $infotext = _("Versteckte Studiengruppen können über die Suchfunktionen nicht gefunden werden."); ?>
+ <? $infotext .= " "; ?>
+ <? if (Config::get()->ALLOW_DOZENT_VISIBILITY) : ?>
+ <? $infotext .= _("Um die Studiengruppe sichtbar zu machen, wählen Sie den Punkt \"Sichtbarkeit\" im Administrationsbereich der Veranstaltung."); ?>
+ <? else : ?>
+ <? $infotext .= _("Um die Studiengruppe sichtbar zu machen, wenden Sie sich an die Admins."); ?>
+ <? endif ?>
+ <?= _("[versteckt]") ?>
+ <?= tooltipicon($infotext) ?>
+ <? endif ?>
+ </td>
+ <td style="text-align: left">
+ <? if (!empty($group['navigation'])) : ?>
+ <? foreach (MyRealmModel::array_rtrim($group['navigation']) as $key => $nav) : ?>
+ <? if (isset($nav) && $nav->isVisible(true)) : ?>
+ <a href="<?=
+ UrlHelper::getLink('seminar_main.php',
+ ['auswahl' => $group['seminar_id'],
+ 'redirect_to' => strtr($nav->getURL(), '?', '&')]) ?>" <?= $nav->hasBadgeNumber() ? 'class="badge" data-badge-number="' . intval($nav->getBadgeNumber()) . '"' : '' ?>>
+ <?= $nav->getImage()->asImg(20, $nav->getLinkAttributes()) ?>
+ </a>
+ <? elseif (is_string($key)) : ?>
+ <?= Assets::img('blank.gif', ['width' => 20, 'height' => 20]); ?>
+ <? endif ?>
+ <? echo ' ' ?>
+ <? endforeach ?>
+ <? endif ?>
+ </td>
+ <td style="text-align: right">
+ <? if (in_array($group["user_status"], ["dozent", "tutor"])) : ?>
+ <? $adminmodule = $group["sem_class"]->getAdminModuleObject(); ?>
+ <? if ($adminmodule) : ?>
+ <? $adminnavigation = $adminmodule->getIconNavigation($group['seminar_id'], 0, $GLOBALS['user']->id); ?>
+ <? endif ?>
+ <? if ($adminnavigation) : ?>
+ <a href="<?= URLHelper::getLink($adminnavigation->getURL(), ['cid' => $group['seminar_id']]) ?>">
+ <?= $adminnavigation->getImage()->asImg(20, $adminnavigation->getLinkAttributes())?>
+ </a>
+ <? endif ?>
+
+ <? elseif ($group["binding"]) : ?>
+ <a href="<?= URLHelper::getLink('', ['auswahl' => $group['seminar_id'], 'cmd' => 'no_kill']) ?>">
+ <?= Icon::create('door-leave+decline', 'inactive', ['title' => _("Die Teilnahme ist bindend. Bitte wenden Sie sich an die Lehrenden.")])->asImg(20) ?>
+ </a>
+ <?
+ else : ?>
+ <a href="<?= URLHelper::getLink("dispatch.php/my_courses/decline/{$group['seminar_id']}", ['cmd' => 'suppose_to_kill']) ?>">
+ <?= Icon::create('door-leave', 'inactive', ['title' => _("aus der Studiengruppe abmelden")])->asImg(20) ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+<? endforeach ?>
diff --git a/app/views/my_studygroups/index.php b/app/views/my_studygroups/index.php
new file mode 100644
index 0000000..403e444
--- /dev/null
+++ b/app/views/my_studygroups/index.php
@@ -0,0 +1,30 @@
+<? if (!empty($studygroups)) : ?>
+ <table class="default" id="my_seminars">
+ <caption>
+ <?= _('Meine Studiengruppen') ?>
+ </caption>
+ <colgroup>
+ <col width="10px">
+ <col width="25px">
+ <col>
+ <col width="<?= $nav_elements * 27 ?>px">
+ <col width="45px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th colspan="2" nowrap align="center">
+ <a href="<?= URLHelper::getLink('dispatch.php/my_courses/groups/all/true') ?>"
+ data-dialog="size=normal">
+ <?= Icon::create('group', 'clickable', ['title' => _('Gruppe ändern'), 'class' => 'middle'])->asImg(20) ?>
+ </a>
+ </th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Inhalt') ?></th>
+ <th></th>
+ </tr>
+ </thead>
+ <?= $this->render_partial('my_studygroups/_course', compact('courses')) ?>
+ </table>
+<? else : ?>
+ <?= MessageBox::info(_('Sie haben bisher noch keine Studiengruppe gegründet oder sich in eine eingetragen.')) ?>
+<? endif ?>
diff --git a/app/views/new_password/index.php b/app/views/new_password/index.php
new file mode 100644
index 0000000..9cddc31
--- /dev/null
+++ b/app/views/new_password/index.php
@@ -0,0 +1,18 @@
+<form class="default" action="<?= $controller->url_for('new_password/send_mail') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Mail zum Zurücksetzen des Passworts anfordern') ?>
+ </legend>
+
+ <label>
+ <?= _('Geben sie die Mail-Adresse des Zugangs an, für den sie das Passwort zurücksetzen möchten') ?>
+ <input type="text" name="mail" placeholder="<?= _('Ihre Mail-Adresse') ?>" required>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::createAccept(_('Mail zuschicken')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('start')) ?>
+ </footer>
+</form>
diff --git a/app/views/new_password/send_mail.php b/app/views/new_password/send_mail.php
new file mode 100644
index 0000000..2c3faba
--- /dev/null
+++ b/app/views/new_password/send_mail.php
@@ -0,0 +1,5 @@
+<form class="default">
+ <footer>
+ <?= Studip\LinkButton::create(_('Zurück zum Login'), $controller->url_for('start')) ?>
+ </footer>
+</form>
diff --git a/app/views/new_password/set.php b/app/views/new_password/set.php
new file mode 100644
index 0000000..7fa28ca
--- /dev/null
+++ b/app/views/new_password/set.php
@@ -0,0 +1,23 @@
+<form class="default" action="<?= $controller->url_for('new_password/set/' . $token_id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <?= _('Neues Passwort setzen') ?>
+ </legend>
+
+ <label>
+ <?= _('Neues Passwort') ?>
+ <input type="password" name="new_password" placeholder="<?= _('Neues Passwort') ?>">
+ </label>
+
+ <label>
+ <?= _('Neues Passwort wiederholen') ?>
+ <input type="password" name="new_password_confirm" placeholder="<?= _('Neues Passwort wiederholen') ?>">
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::createAccept(_('Passwort setzen')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('start')) ?>
+ </footer>
+</form>
diff --git a/app/views/news/_actions.php b/app/views/news/_actions.php
new file mode 100644
index 0000000..b3df43c
--- /dev/null
+++ b/app/views/news/_actions.php
@@ -0,0 +1,53 @@
+<? $user = new User($new['user_id']); ?>
+<? if (Config::get()->NEWS_DISPLAY >= 1 || $new->havePermission('edit')): ?>
+ <a class='news_user' href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $user->username) ?>">
+ <?= htmlReady($user->getFullName()) ?>
+ </a>
+<? endif; ?>
+
+<span class='news_date' title="<?= ($perm ? _("Ablaufdatum") . ': ' . date('d.m.Y', $new['date'] + $new['expire']) : '') ?>">
+ <?= date('d.m.Y', $new['date']) ?>
+</span>
+
+<? if (Config::get()->NEWS_DISPLAY >= 2 || $new->havePermission('edit')): ?>
+ <span title="<?= _('Aufrufe') ?>" class='news_visits' style="color: #050">
+ <?= object_return_views($new['news_id']) ?>
+ </span>
+<? endif; ?>
+
+<?
+if ($new['allow_comments']) :
+ $num = StudipComment::NumCommentsForObject($new['news_id']);
+ $visited = object_get_visit($new['news_id'], 'news', false, false);
+ $isnew = StudipComment::NumCommentsForObjectSinceLastVisit($new['news_id'], $visited, $GLOBALS['user']->id);
+ ?>
+ <? if ($num): ?>
+ <? if ($isnew): ?>
+ <span class="news_comments_indicator nowrap" title="<?= sprintf(_('%s neue(r) Kommentar(e)'), $isnew) ?>">
+ <?= Icon::create("chat", "new")->asImg() ?>
+ <? else: ?>
+ <span class="news_comments_indicator nowrap" title="<?= sprintf(_('%s Kommentare'), $num) ?>">
+ <?= Icon::create("chat", "info")->asImg() ?>
+ <? endif; ?>
+ <?= $num ?>
+ </span>
+ <? endif; ?>
+<? endif; ?>
+
+
+
+<? if ($new->havePermission('edit')): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/news/edit_news/' . $new->id) ?>" rel="get_dialog">
+ <?= Icon::create('edit', 'clickable')->asImg(); ?>
+ </a>
+ <? if ($new->havePermission('unassign', $range)): ?>
+ <a href=" <?= URLHelper::getLink('', ['remove_news' => $new->id, 'news_range' => $range]) ?>" >
+ <?= Icon::create('remove', 'clickable')->asImg(); ?>
+ </a>
+ <? endif; ?>
+ <? if ($new->havePermission('delete')): ?>
+ <a href=" <?= URLHelper::getLink('', ['delete_news' => $new->id]) ?>" >
+ <?= Icon::create('trash', 'clickable')->asImg(); ?>
+ </a>
+ <? endif; ?>
+<? endif; ?>
diff --git a/app/views/news/_commentbox.php b/app/views/news/_commentbox.php
new file mode 100644
index 0000000..87d4fad
--- /dev/null
+++ b/app/views/news/_commentbox.php
@@ -0,0 +1,9 @@
+<article class="comment open">
+ <time><?= reltime($comment[3]) ?></time>
+ <h1>#<?= $index + 1 ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . $comment[2]) ?>">
+ <?= htmlReady($comment[1]) ?>
+ </a>
+ </h1>
+ <?= formatReady($comment[0]) ?>
+</article> \ No newline at end of file
diff --git a/app/views/news/_comments.php b/app/views/news/_comments.php
new file mode 100644
index 0000000..a99238e
--- /dev/null
+++ b/app/views/news/_comments.php
@@ -0,0 +1,40 @@
+<? if ($new['allow_comments']): ?>
+ <footer>
+ <section class="comments">
+ <? if (Request::get('comments')): ?>
+ <h1>
+ <?= _('Kommentare') ?>
+ </h1>
+
+ <? foreach (StudipComment::GetCommentsForObject($new['news_id']) as $index => $comment): ?>
+ <?= $this->render_partial('news/_commentbox', compact('index', 'comment')) ?>
+ <? endforeach; ?>
+ <? if (!$nobody) : ?>
+ <form action="<?= ContentBoxHelper::href($new->id, ['comments' => 1]) ?>" method="POST" class="default" style="text-align: left;">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="comsubmit" value="<?= $new['news_id'] ?>">
+ <fieldset>
+ <legend>
+ <?= _('Kommentieren') ?>
+ </legend>
+ <label>
+ <textarea class="add_toolbar wysiwyg" name="comment_content" rows="8"
+ cols="38" wrap="virtual"
+ placeholder="<?= _('Geben Sie hier Ihren Kommentar ein!') ?>"></textarea>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::createAccept(_('Absenden')) ?>
+ </footer>
+ </form>
+ <? endif ?>
+ <? else: ?>
+ <a href="<?= ContentBoxHelper::href($new['news_id'], ["comments" => 1]) ?>">
+ <?= sprintf(_('Kommentare lesen (%s) / Kommentar schreiben'), StudipComment::NumCommentsForObject($new['news_id']))
+ ?>
+ </a>
+ <? endif; ?>
+ </section>
+ </footer>
+<? endif; ?>
diff --git a/app/views/news/admin_news.php b/app/views/news/admin_news.php
new file mode 100644
index 0000000..0909b1d
--- /dev/null
+++ b/app/views/news/admin_news.php
@@ -0,0 +1,168 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? if (!empty($flash['question_text'])) : ?>
+<?= QuestionBox::create(
+ htmlReady($flash['question_text']),
+ $controller->url_for('news/admin_news/' . $area_type, array_merge(
+ $flash['question_param'],
+ [
+ 'news_filter_term' => htmlReady($news_searchterm),
+ 'news_filter_start' => $news_startdate,
+ 'news_filter_end' => $news_enddate,
+ 'news_filter' => 'set'
+ ]
+ )),
+ $controller->url_for('news/admin_news/' . $area_type, [
+ 'news_filter_term' => htmlReady($news_searchterm),
+ 'news_filter_start' => $news_startdate,
+ 'news_filter_end' => $news_enddate,
+ 'news_filter' => 'set'
+ ])
+ );
+?>
+<? endif ?>
+
+<form action="<?= $controller->link_for('news/admin_news/' . $area_type) ?>" id="admin_news_form" class="default" method="post">
+ <input type="hidden" name="news_filter" value="set">
+ <input type="hidden" name="news_filter_term" value="<?= htmlReady($news_searchterm) ?>">
+ <input type="hidden" name="news_filter_start" value="<?= $news_startdate ?>">
+ <input type="hidden" name="news_filter_end" value="<?= $news_enddate ?>">
+ <?= CSRFProtection::tokenTag(); ?>
+
+ <fieldset>
+ <legend><?= _('Meine Ankündigungen') ?></legend>
+
+ <label>
+ <?= _('Suchbegriff') ?>
+ <input type="text" name="news_searchterm" aria-label="<?= _('Suchbegriff') ?>"
+ value="<?= htmlReady($news_searchterm) ?>">
+ </label>
+
+ <label class="col-1">
+ <?= _('Anzeige von') ?>
+ <input class="has-date-picker" type="text" name="news_startdate"
+ aria-label="<?= _('Ankündigungen anzeigen, die ab diesem Datum sichtbar sind') ?>"
+ value="<?= $news_startdate ? date('d.m.Y', $news_startdate) : '' ?>">
+ </label>
+
+ <label class="col-1">
+ <?= _('Anzeige bis') ?>
+ <input class="has-date-picker" type="text" name="news_enddate"
+ aria-label="<?= _('Ankündigungen anzeigen, die vor diesem Datum sichtbar sind') ?>"
+ value="<?= $news_enddate ? date('d.m.Y', $news_enddate) : '' ?>">
+ </label>
+ </fieldset>
+ <footer>
+ <?= Button::create(_('Filter anwenden'), 'apply_news_filter', ['aria-label' => _('Liste mit Suchbegriff und/oder Zeitraum filtern')]) ?>
+ <? if ($filter_text) : ?>
+ <?= Button::create(_('Filter zurücksetzen'), 'reset_filter') ?>
+ <? endif ?>
+ </footer>
+ <br>
+
+<? if ($filter_text) : ?>
+ <?= MessageBox::info(htmlReady($filter_text) )?>
+<? endif ?>
+
+<? if ($news_items && count($news_items)) : ?>
+ <? foreach ($area_structure as $type => $area_data) : ?>
+ <? $last_title = 'none' ?>
+ <? if (is_array($news_items[$type]) && count($news_items[$type])) : ?>
+ <table class="default">
+ <? if (!$area_type) : ?>
+ <caption>
+ <?= htmlReady($area_data['title']) ?>
+ </caption>
+ <? endif ?>
+ <colgroup>
+ <col width="20">
+ <col>
+ <col width="25%">
+ <col width="10%">
+ <col width="10%">
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('Überschrift') ?></th>
+ <th><?= _('Autor') ?></th>
+ <th><?= _('Einstelldatum') ?></th>
+ <th><?= _('Ablaufdatum') ?></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($news_items[$type] as $news) : ?>
+ <? $title = $news['title'] ?>
+ <? if ($title !== $last_title) : ?>
+ <? if ($title) : ?>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor=".news_<?= $news['range_id'] ?>"
+ aria-labelledby="<?= _('Alle auswählen') ?>">
+ </th>
+ <th colspan="5"><?= mila(htmlReady($news['title'])) . ' ' . htmlReady($news['semester']) ?></th>
+ </tr>
+ <? endif ?>
+ <? $last_title = $title ?>
+ <? endif ?>
+ <tr>
+ <td>
+ <input type="checkbox" class="news_<?= $news['range_id'] ?>" name="mark_news[]"
+ value="<?= $news['object']->news_id . '_' . $news['range_id'] ?>"
+ aria-label="<?= _('Diese Ankündigung zum Entfernen vormerken') ?>" <?= tooltip(_("Diese Ankündigung zum Entfernen vormerken"), false) ?>>
+ </td>
+ <td><?= htmlReady($news['object']->topic) ?></td>
+ <? list ($body, $admin_msg) = explode('<admin_msg>', $news['object']->body); ?>
+ <td><?= htmlReady($news['object']->author) ?></td>
+ <td><?= strftime("%d.%m.%y", $news['object']->date) ?></td>
+ <td><?= strftime("%d.%m.%y", $news['object']->date + $news['object']->expire) ?></td>
+ <td class="actions">
+ <?
+ $menu = ActionMenu::get();
+ $menu->addLink(
+ $controller->url_for('news/edit_news/' . $news['object']->news_id),
+ _('Ankündigung bearbeiten'),
+ Icon::create('edit', 'clickable'),
+ ['rel' => 'get_dialog', 'target' => '_blank']
+ );
+ $menu->addLink(
+ $controller->url_for('news/edit_news/new/template/' . $news['object']->news_id),
+ _('Kopieren, um neue Ankündigung zu erstellen'),
+ Icon::create('news+export', 'clickable'),
+ ['rel' => 'get_dialog', 'target' => '_blank']
+ );
+ if ($news['object']->havePermission('unassign', $news['range_id'])) {
+ $menu->addButton(
+ 'news_remove_' . $news['object']->news_id . '_' . $news['range_id'],
+ _('Ankündigung aus diesem Bereich entfernen'),
+ Icon::create('remove', 'clickable')
+ );
+ } else {
+ $menu->addButton(
+ 'news_remove_' . $news['object']->news_id . '_' . $news['range_id'],
+ _('Ankündigung löschen'),
+ Icon::create('trash', 'clickable')
+ );
+ }
+ echo $menu->render();
+ ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="6">
+ <?= Button::create(_('Alle markierten Ankündigungen entfernen'), 'remove_marked_news') ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ <? endif ?>
+ <? endforeach ?>
+<? else : ?>
+ <?= MessageBox::info(_('Keine Ankündigungen vorhanden.')) ?>
+<? endif ?>
+</form>
diff --git a/app/views/news/display.php b/app/views/news/display.php
new file mode 100644
index 0000000..7ffd856
--- /dev/null
+++ b/app/views/news/display.php
@@ -0,0 +1,72 @@
+<?= $question ?>
+<? if ($perm || $news): ?>
+<article class="studip">
+ <header>
+ <h1>
+ <?= Icon::create('news', 'info')->asImg() ?>
+
+ <?= _('Ankündigungen') ?>
+ </h1>
+ <nav>
+ <? if ($perm): ?>
+ <a href="<?= $controller->link_for('news/edit_news/new/' . $range); ?>" rel="get_dialog">
+ <?= Icon::create('add', 'clickable')->asImg(); ?>
+ </a>
+ <? endif; ?>
+ <? if ($perm && Config::get()->NEWS_RSS_EXPORT_ENABLE): ?>
+ <a data-dialog="size=auto;reload-on-close" title="<?=_('RSS-Feed konfigurieren') ?>" href="<?= $controller->link_for('news/rss_config/' . $range); ?>">
+ <?= Icon::create('rss+add')->asImg() ?>
+ </a>
+ <? endif; ?>
+ <? if ($rss_id): ?>
+ <a href="<?= URLHelper::getLink('rss.php', ['id' => $rss_id]) ?>">
+ <?= Icon::create('rss', 'clickable', ['title' => _('RSS-Feed')])->asImg() ?>
+ </a>
+ <? endif; ?>
+ </nav>
+ </header>
+ <? foreach ($news as $new): ?>
+ <? $is_new = ($new['chdate'] >= object_get_visit($new->id, 'news', false, false))
+ && ($new['user_id'] != $GLOBALS['user']->id); ?>
+ <article class="studip toggle <?= ContentBoxHelper::classes($new->id, $is_new) ?>" id="<?= $new->id ?>" data-visiturl="<?=URLHelper::getScriptLink('dispatch.php/news/visit')?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($new->id, ['contentbox_type' => 'news']) ?>">
+ <?= Icon::create('news', 'clickable')->asImg(); ?>
+ <?= htmlReady($new['topic']); ?>
+ </a>
+ </h1>
+ <nav>
+ <?= $this->render_partial('news/_actions.php', ['new' => $new, 'range' => $range]) ?>
+ </nav>
+ </header>
+ <section>
+ <article>
+ <?= formatReady($new['body']) ?>
+ </article>
+ </section>
+ <?= $this->render_partial('news/_comments.php', ['new' => $new, 'range' => $range]) ?>
+ </article>
+ <? endforeach; ?>
+ <? if (!$news): ?>
+ <section>
+ <?= _('Es sind keine aktuellen Ankündigungen vorhanden. Um neue Ankündigungen zu erstellen, klicken Sie rechts auf das Plus-Zeichen.') ?>
+ </section>
+ <? if ($perm && $count_all_news) : ?>
+ <footer>
+ <a href="<?=URLHelper::getLink('?nshow_all=1')?>"><?=sprintf(_("Abgelaufene und unveröffentlichte Ankündigungen anzeigen (%s)"), $count_all_news)?></a>
+ </footer>
+ <? endif; ?>
+ <? elseif ($perm) : ?>
+ <? if ($count_all_news > count($news)) : ?>
+ <footer>
+ <a href="<?=URLHelper::getLink('?nshow_all=1')?>"><?=sprintf(_("Abgelaufene und unveröffentlichte Ankündigungen anzeigen (%s)"), $count_all_news-count($news))?></a>
+ </footer>
+ <? elseif ($show_all_news) : ?>
+ <footer>
+ <a href="<?=URLHelper::getLink('?nshow_all=0')?>"><?=_("Abgelaufene und unveröffentlichte Ankündigungen ausblenden")?></a>
+ </footer>
+ <? endif ?>
+ <? endif; ?>
+</article>
+<?endif;
diff --git a/app/views/news/edit_news.php b/app/views/news/edit_news.php
new file mode 100644
index 0000000..3475270
--- /dev/null
+++ b/app/views/news/edit_news.php
@@ -0,0 +1,283 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? if(!empty($flash['question_text'])) : // TODO: This will certainly break with i18n fields ?>
+ <? $form_content = ['news_isvisible' => htmlReady(json_encode($news_isvisible)),
+ 'news_selectable_areas' => htmlReady(json_encode($area_options_selectable)),
+ 'news_selected_areas' => htmlReady(json_encode($area_options_selected)),
+ 'news_basic_js' => '',
+ 'news_comments_js' => '',
+ 'news_areas_js' => '',
+ 'news_allow_comments' => $news->allow_comments,
+ 'news_topic' => $news->topic,
+ 'news_body' => $news->body,
+ 'news_startdate' => $news->date ? date('d.m.Y H:i', $news->date) : '',
+ 'news_enddate' => $news->expire ? date('d.m.Y H:i', $news->date + $news->expire) : ''] ?>
+ <?= (string) QuestionBox::create(
+ htmlReady($flash['question_text']),
+ URLHelper::getURL('dispatch.php/'.$route.'#anker', array_merge($flash['question_param'], $form_content)),
+ URLHelper::getURL('dispatch.php/'.$route.'#anker', $form_content)
+ );?>
+<? endif ?>
+<form action="<?=URLHelper::getURL('dispatch.php/'.$route.'#anker')?>"
+ data-dialog="size=auto" method="POST" class="default collapsable">
+ <?=CSRFProtection::tokenTag(); ?>
+ <input type="hidden" name="news_basic_js" value="">
+ <input type="hidden" name="news_comments_js" value="">
+ <input type="hidden" name="news_areas_js" value="">
+ <input type="hidden" name="news_isvisible" value="<?=htmlReady(json_encode($news_isvisible))?>">
+ <input type="hidden" name="news_selectable_areas" value="<?=htmlReady(json_encode($area_options_selectable))?>">
+ <input type="hidden" name="news_selected_areas" value="<?=htmlReady(json_encode($area_options_selected))?>">
+
+ <? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $msg) : ?>
+ <?=$msg?>
+ <? $anker = ''; ?>
+ <? endforeach ?>
+ <? endif ?>
+
+ <fieldset <?= $news_isvisible['news_basic'] ? '' : 'class="collapsed"' ?>>
+ <legend class="news_category_header" id="news_basic">
+ <?=_("Grunddaten")?>
+ </legend>
+
+ <label>
+ <span class="required">
+ <?= _("Titel") ?>
+ </span>
+ <?= I18N::input('news_topic', $news->topic, [
+ 'required' => '',
+ 'class' => 'news_topic news_prevent_submit size-l',
+ 'aria-label' => _('Titel der Ankündigung'),
+ ]) ?>
+ </label>
+
+ <label>
+ <span class="required">
+ <?= _("Inhalt") ?>
+ </span>
+
+ <?= I18N::textarea('news_body', $news->body, [
+ 'required' => '',
+ 'class' => 'news_body add_toolbar wysiwyg size-l',
+ 'rows' => 6,
+ 'wrap' => 'virtual',
+ 'placeholder' => _('Geben Sie hier den Ankündigungstext ein'),
+ 'aria-label' => _('Inhalt der Ankündigung'),
+ ]) ?>
+ </label>
+
+ <label class="col-2">
+ <span class="required">
+ <?= _('Veröffentlichungsdatum') ?>
+ </span>
+
+ <input type="text" class="news_date news_prevent_submit"
+ name="news_startdate" id="news_startdate"
+ data-datetime-picker
+ value="<? if ($news->date) echo strftime('%x %H:%M', $news->date); ?>"
+ aria-label="<?= _('Einstelldatum') ?>" required>
+ </label>
+
+ <label class="col-2">
+ <span class="required">
+ <?= _('Ablaufdatum') ?>
+ </span>
+
+ <input type="text" class="news_date news_prevent_submit"
+ name="news_enddate" id="news_enddate"
+ data-datetime-picker='{">=":"#news_startdate","offset":"#news_duration"}'
+ value="<? if ($news->expire) echo strftime('%x %H:%M', $news->date + $news->expire) ?>"
+ aria-label="<?= _('Ablaufdatum') ?>" required>
+ </label>
+
+ <label class="col-2">
+ <?= _('Laufzeit in Tagen') ?>
+
+ <input type="number" class="news_date news_prevent_submit"
+ name="news_duration" id="news_duration"
+ value="<?= $news->expire ? round($news->expire / (24 * 60 * 60)) : 8 ?>"
+ aria-label="<?= _('Laufzeit') ?>"
+ min="1">
+ </label>
+
+ <? if ($anker == 'news_comments') : ?>
+ <a name='anker'></a>
+ <? endif ?>
+ <label>
+ <input type="checkbox"
+ id="news_allow_comments" name="news_allow_comments" value="1"
+ <? if ($news->allow_comments) echo 'checked'; ?>>
+ <?= _('Kommentare zulassen') ?>
+ </label>
+ </fieldset>
+
+ <? if (is_array($comments) && count($comments)) : ?>
+ <fieldset <?= $news_isvisible['news_comments'] ? '' : 'class="collapsed"' ?>>
+ <legend class="news_category_header" id="news_comments">
+ <?=_("Kommentare zu dieser Ankündigung")?>
+ </legend>
+ <table class="default nohover">
+ <tbody>
+ <? foreach ($comments as $index => $comment): ?>
+ <?= $this->render_partial('../../templates/news/comment-box', compact('index', 'comment')) ?>
+ <? endforeach; ?>
+
+ <? if ($comments_admin): ?>
+ <tfoot>
+ <tr>
+ <td colspan="3">
+ <?=Button::create(_('Markierte Kommentare löschen'), 'delete_marked_comments', ['title' => _('Markierte Kommentare löschen')]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </tbody>
+ </table>
+ </fieldset>
+ <? endif ?>
+
+ <fieldset <?= $news_isvisible['news_areas'] ? '' : 'class="collapsed"' ?>>
+ <legend class="news_category_header" id="news_areas">
+ <?=_('In weiteren Bereichen anzeigen')?>
+ </legend>
+
+ <? if ($anker == 'news_areas') : ?>
+ <a name='anker'></a>
+ <? endif ?>
+
+ <label class="with-action">
+ <span>
+ <?= _('Suchvorlage auswählen') ?>
+ </span>
+
+ <select name="search_preset" aria-label="<?= _('Vorauswahl bestimmter Bereiche, alternativ zur Suche') ?>"
+ onchange="jQuery('input[name=area_search_preset]').click()">
+ <option><?=_('--- Suchvorlagen ---')?></option>
+ <? foreach($search_presets as $value => $title) : ?>
+ <option value="<?=$value?>"<?=($this->current_search_preset == $value) ? ' selected' : '' ?>>
+ <?=htmlReady($title)?>
+ </option>
+ <? endforeach ?>
+ </select>
+
+ <?= Icon::create('accept')->asInput([
+ 'name' => 'area_search_preset',
+ 'title' => _('Vorauswahl anwenden'),
+ 'formnovalidate' => '',
+ ]) ?>
+ </label>
+
+ <label class="with-action">
+ <span>
+ <?= _('Freitextsuche') ?>
+ </span>
+
+ <input name="area_search_term" class="news_search_term" type="text" placeholder="<?=_('Suchen')?>"
+ aria-label="<?= _('Suchbegriff') ?>">
+ <?= Icon::create('search')->asInput([
+ 'name' => 'area_search',
+ 'title' => _('Suche starten'),
+ 'formnovalidate' => '',
+ ]) ?>
+ </label>
+
+
+ <div class="news_area_selectable">
+ <label>
+ <?=_('Suchergebnis')?>
+ <select name="area_options_selectable[]" class="news_area_options" size="7" multiple
+ aria-label="<?= _('Gefundene Bereiche, die der Ankündigung hinzugefügt werden können') ?>"
+ ondblclick="jQuery('input[name=news_add_areas]').click()">
+ <? foreach ($area_structure as $area_key => $area_data) : ?>
+ <? if (is_array($area_options_selectable[$area_key]) && count($area_options_selectable[$area_key])) : ?>
+ <optgroup class="news_area_title"
+ style="background-image: url('<?= Icon::create($area_data['icon'], 'info')->asImagePath() ?>');" label="<?=htmlReady($area_data['title'])?>">
+ <? foreach ($area_options_selectable[$area_key] as $area_option_key => $area_option_title) : ?>
+ <option <?= StudipNews::haveRangePermission('edit', $area_option_key) ? 'value="'.$area_option_key.'"' : 'disabled'?>
+ <?=tooltip($area_option_title);?>>
+ <?= htmlReady(mila($area_option_title))?>
+ </option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ <? endforeach ?>
+ </select>
+ </label>
+ </div>
+ <div class="news_area_actions">
+ <br>
+ <br>
+ <br>
+ <?= Icon::create('arr_2right')->asInput([
+ 'name' => 'news_add_areas',
+ 'title' => _('In den Suchergebnissen markierte Bereiche der Ankündigung hinzufügen'),
+ 'formnovalidate' => '',
+ ]) ?>
+ <br><br>
+ <?= Icon::create('arr_2left')->asInput([
+ 'name' => 'news_remove_areas',
+ 'title' => _('Bei den bereits ausgewählten Bereichen die markierten Bereiche entfernen'),
+ 'formnovalidate' => '',
+ ]) ?>
+ </div>
+ <div class="news_area_selected">
+ <? foreach ($area_structure as $area_key => $area_data) : ?>
+ <? if (isset($area_options_selected[$area_key])) : ?>
+ <? $area_count += count($area_options_selected[$area_key]) ?>
+ <? endif ?>
+ <? endforeach ?>
+ <label>
+ <div id="news_area_text">
+ <? if ($area_count == 0) : ?>
+ <?=_('Keine Bereiche ausgewählt')?>
+ <? elseif ($area_count == 1) : ?>
+ <?=_('1 Bereich ausgewählt')?>
+ <? else : ?>
+ <?=sprintf(_('%s Bereiche ausgewählt'), $area_count)?>
+ <? endif ?>
+ </div>
+ <select name="area_options_selected[]" class="news_area_options" size="7" multiple
+ aria-label="<?= _('Bereiche, in denen die Ankündigung angezeigt wird') ?>"
+ ondblclick="jQuery('input[name=news_remove_areas]').click()">
+ <? foreach ($area_structure as $area_key => $area_data) : ?>
+ <? if (isset($area_options_selected[$area_key]) && count($area_options_selected[$area_key])) : ?>
+ <optgroup class="news_area_title"
+ style="background-image: url('<?= Icon::create($area_data['icon'], 'info')->asImagePath() ?>');" label="<?=htmlReady($area_data['title'])?>">
+ <? foreach ($area_options_selected[$area_key] as $area_option_key => $area_option_title) : ?>
+ <option <?= (StudipNews::haveRangePermission('edit', $area_option_key) OR $may_delete) ? 'value="'.$area_option_key.'"' : 'disabled'?>
+ <?=tooltip($area_option_title);?>>
+ <?= htmlReady(mila($area_option_title))?>
+ </option>
+ <? endforeach ?>
+ </optgroup>
+ <? endif ?>
+ <? endforeach ?>
+ </select>
+ </label>
+ </div>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if ($news->isNew()) : ?>
+ <?= Button::createAccept(_('Ankündigung erstellen'), 'save_news') ?>
+ <? else : ?>
+ <?= Button::createAccept(_('Änderungen speichern'), 'save_news') ?>
+ <? endif ?>
+ <? if (Request::isXhr()) : ?>
+ <?= LinkButton::createCancel(_('Schließen'), URLHelper::getURL(''), ['rel' => 'close_dialog']) ?>
+ <? endif ?>
+ </footer>
+</form>
+
+<script>
+ jQuery('.news_prevent_submit').keydown(function(event) {
+ if (event.which === 13) {
+ event.preventDefault();
+ }
+ });
+ jQuery('input[name=area_search_term]').keydown(function(event) {
+ if (event.which === 13) {
+ jQuery('input[name=area_search]').click();
+ event.preventDefault();
+ }
+ });
+</script>
diff --git a/app/views/news/rss_config.php b/app/views/news/rss_config.php
new file mode 100644
index 0000000..19b7eff
--- /dev/null
+++ b/app/views/news/rss_config.php
@@ -0,0 +1,9 @@
+<form method="post" data-dialog="size=auto;reload-on-close" action="<?= $controller->link_for('news/rss_config/' . $range_id); ?>">
+ <div style="text-align:center">
+ <? if (!$rss_id) :?>
+ <?= \Studip\Button::createAccept(_("RSS Export aktivieren"), 'rss_on'); ?>
+ <? else : ?>
+ <?= \Studip\Button::createCancel(_("RSS Export deaktivieren"), 'rss_off'); ?>
+ <? endif ?>
+ </div>
+</form> \ No newline at end of file
diff --git a/app/views/oer/addfile/choose_file.php b/app/views/oer/addfile/choose_file.php
new file mode 100644
index 0000000..6c896cf
--- /dev/null
+++ b/app/views/oer/addfile/choose_file.php
@@ -0,0 +1,23 @@
+<?
+if ($best_nine_tags && count($best_nine_tags) > 0) {
+ $tags = [];
+ foreach ($best_nine_tags as $tag) {
+ $tags[] = [
+ 'tag_hash' => $tag['tag_hash'],
+ 'name' => $tag['name']
+ ];
+ }
+}
+?>
+<form class="oer_search"
+ action="<?= $controller->link_for("oer/market/search") ?>"
+ method="GET"
+ data-searchresults="<?= htmlReady(json_encode($material_data)) ?>"
+ data-filteredtag="<?= htmlReady(Request::get("tag")) ?>"
+ data-filteredcategory="<?= htmlReady(Request::get("category")) ?>"
+ data-tags="<?= htmlReady(json_encode($tags)) ?>"
+ data-material_select_url_template="<?= htmlReady($controller->url_for("oer/addfile/choose_file", ['material_id' => "__material_id__", 'to_plugin' => Request::get("to_plugin"), 'to_folder_id' => Request::get("to_folder_id")])) ?>">
+ <input type="hidden" name="to_plugin" value="<?= htmlReady(Request::get("to_plugin")) ?>">
+ <input type="hidden" name="to_folder_id" value="<?= htmlReady(Request::get("to_folder_id")) ?>">
+ <?= $this->render_partial("oer/market/_searchform") ?>
+</form>
diff --git a/app/views/oer/admin/add_new_host.php b/app/views/oer/admin/add_new_host.php
new file mode 100755
index 0000000..9d52b57
--- /dev/null
+++ b/app/views/oer/admin/add_new_host.php
@@ -0,0 +1,10 @@
+<form class="default" action="<?= $controller->link_for("oer/admin/add_new_host") ?>" method="post">
+ <label>
+ <?= _('Adresse des Servers plugin.php....') ?>
+ <input type="text" name="url" placeholder="https://www.myserver.de/studip/dispatch.php/oer/endpoints/">
+ </label>
+
+ <div style="text-align: center;" data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern')) ?>
+ </div>
+</form>
diff --git a/app/views/oer/admin/hosts.php b/app/views/oer/admin/hosts.php
new file mode 100755
index 0000000..c60c937
--- /dev/null
+++ b/app/views/oer/admin/hosts.php
@@ -0,0 +1,120 @@
+<table class="default serversettings">
+ <caption>
+ <?= _('Lernmarktplatz-Server') ?>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Adresse') ?></th>
+ <th title="<?= _('Ein Hash des Public-Keys des Servers.') ?>"><?= _('Key-Hash') ?></th>
+ <th><?= _('Index-Server') ?></th>
+ <th><?= _('Aktiv') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($hosts as $host) : ?>
+ <tr id="host_<?= $host->getId() ?>" data-host_id="<?= $host->getId() ?>">
+ <td>
+ <? if ($host->isMe()) : ?>
+ <?= Icon::create("home", Icon::ROLE_INFO)->asImg(20, ['class' => "text-bottom", 'title' => _('Das ist Ihr Stud.IP')]) ?>
+ <? endif ?>
+ <?= htmlReady($host['name']) ?></td>
+ <td>
+ <a href="<?= htmlReady($host['url']) ?>" target="_blank">
+ <?= Icon::create("link-extern", Icon::ROLE_CLICKABLE)->asImg(16, ['class' => "text-bottom"]) ?>
+ <?= htmlReady($host['url']) ?>
+ </a>
+ </td>
+ <td>
+ <?= $host['public_key'] ? md5($host['public_key']) : "" ?>
+ <? if (strpos($host['public_key'], "\r") !== false) : ?>
+ <?= Icon::create("exclaim", Icon::ROLE_STATUS_RED)->asImg(20, ['class' => "text-bottom", 'title' => _('Der Key hat ein Carriage-Return Zeichen, weshalb der Hash des Public-Keys vermutlich vom Original-Hash abweicht.')]) ?>
+ <? endif ?>
+ </td>
+ <td class="index_server">
+ <? if ($host->isMe()) : ?>
+ <a href="" title="<?= _('Als Index-Server aktivieren/deaktivieren') ?>" class="<?= $host['index_server'] ? "checked" : "unchecked" ?>">
+ <?= Icon::create("checkbox-".($host['index_server'] ? "" : "un")."checked", Icon::ROLE_CLICKABLE)->asImg(20) ?>
+ </a>
+ <? else : ?>
+ <? if ($host['index_server']) : ?>
+ <a href=""
+ class="<?= $host['allowed_as_index_server'] ? "checked" : "unchecked" ?>"
+ title="<?= _('Diesen Server als Indexserver aktivieren. Suchanfragen werden immer auch an ihn gerichtet. Sie sollten nur einen Indexserver verwenden.') ?>">
+ <?= Icon::create("checkbox-".($host['allowed_as_index_server'] ? "" : "un")."checked", Icon::ROLE_CLICKABLE)->asImg(20) ?>
+ </a>
+ <? else : ?>
+ <?= Icon::create("checkbox-unchecked", Icon::ROLE_INACTIVE)->asImg(20, ['title' => _('Dieser Server steht nicht als Indexserver zur Verfügung.')]) ?>
+ <? endif ?>
+ <? endif ?>
+ </td>
+ <td class="active">
+ <? if ($host->isMe()) : ?>
+ <?= Icon::create("checkbox-checked", Icon::ROLE_INFO)->asImg(20) ?>
+ <? else : ?>
+ <a href=""
+ title="<?= _('Soll dieser Server und seine OERs für uns relevant sein?') ?>"
+ class="<?= $host['active'] ? "checked" : "unchecked" ?>">
+ <?= Icon::create("checkbox-".($host['active'] ? "" : "un")."checked", Icon::ROLE_CLICKABLE)->asImg(20) ?>
+ </a>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <? if (!$host->isMe()) : ?>
+ <a href="<?= $controller->link_for("oer/admin/ask_for_hosts/".$host->getId()) ?>"
+ title="<?= _('Diesen Server nach weiteren bekannten Hosts fragen.') ?>">
+ <?= Icon::create("campusnavi", Icon::ROLE_CLICKABLE)->asImg(20, ['width' => "20px", 'class' => "text-bottom"]) ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+
+<? if (!$federation_problems && count($hosts) < 2 && !$_SESSION['Lernmarktplatz_no_thanx']) : ?>
+ <div id="init_first_hosts_dialog" style="display: none;">
+ <form action="<?= $controller->link_for("oer/admin/add_new_host") ?>" method="post">
+ <h2><?= _('Werden Sie Teil des weltweiten Stud.IP Lernmarktplatzes!') ?></h2>
+ <div>
+ <?= _('Der Lernmarktplatz ist ein Ort des Austauschs von kostenlosen und freien Lernmaterialien. Daher wäre es schade, wenn er nur auf Ihr einzelnes Stud.IP beschränkt wäre. Der Lernmarktplatz ist daher als dezentrales Netzwerk konzipiert, bei dem alle Nutzer aller Stud.IPs sich gegenseitig Lernmaterialien tauschen können und nach Lernmaterialien anderer Nutzer suchen können. <em>Dezentral</em> heißt dieses Netzwerk, weil es nicht einen einzigen zentralen Server gibt, der wie eine große Suchmaschine alle Informationen bereit hält. Stattdessen sind im besten Fall alle Stud.IPs mit allen anderen Stud.IPs direkt vernetzt. So ein dezentrales Netz ist sehr ausfallsicher und es passt zur Opensource-Idee von Stud.IP, weil man sich von keiner zentralen Institution abhängig macht. Aber Ihr Stud.IP muss irgendwo einen ersten Kontakt zum großen Netzwerk aller Lernmarktplätze finden, um loslegen zu können. Wählen Sie dazu irgendeinen der unten aufgeführten Server aus. Sie werden Index-Server genannt und bilden das Tor zum Rest des ganzen Netzwerks. Achten Sie darauf, dass Sie mit mindestens einem, aber auch nicht zu vielen Indexservern verbunden sind.') ?>
+ </div>
+
+ <ul class="clean" style="text-align: center;">
+ <li>
+ <?= \Studip\Button::create(_('Stud.IP Entwicklungsserver'), 'url', ['value' => 'https://develop.studip.de/studip/dispatch.php/oer/endpoints/']) ?>
+ </li>
+ <li>
+ <?= \Studip\Button::create(_('Nein, danke!'), 'nothanx') ?>
+ </li>
+ </ul>
+
+ </form>
+ </div>
+ <script>
+ jQuery(function () {
+ jQuery('#init_first_hosts_dialog').dialog({
+ 'modal': true,
+ 'title': '<?= _('Index-Server hinzufügen') ?>',
+ 'width': "80%"
+ });
+ });
+ </script>
+<? endif ?>
+
+<?
+$actions = new ActionsWidget();
+$actions->addLink(
+ _('Server hinzufügen'),
+ $controller->url_for("oer/admin/add_new_host"),
+ Icon::create("add", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "1"]
+);
+$actions->addLink(
+ _('Serverdaten aktualisieren'),
+ $controller->url_for("oer/admin/refresh_hosts"),
+ Icon::create("refresh", Icon::ROLE_CLICKABLE)
+);
+
+Sidebar::Get()->addWidget($actions);
diff --git a/app/views/oer/embed/_link.php b/app/views/oer/embed/_link.php
new file mode 100644
index 0000000..33ccc80
--- /dev/null
+++ b/app/views/oer/embed/_link.php
@@ -0,0 +1,7 @@
+<div style="text-align: right;">
+ <a href="<?= URLHelper::getLink("dispatch.php/oer/market/details/{$id}") ?>"
+ title="<?= htmlReady(sprintf(_('Zum %s wechseln'), Config::get()->OER_TITLE)) ?>">
+ <?= Icon::create('service')->asImg(['class' => 'text-bottom']) ?>
+ <?= htmlReady($material['name']) ?>
+ </a>
+</div>
diff --git a/app/views/oer/embed/audio.php b/app/views/oer/embed/audio.php
new file mode 100644
index 0000000..f77316e
--- /dev/null
+++ b/app/views/oer/embed/audio.php
@@ -0,0 +1,13 @@
+<div>
+ <a href="<?= htmlReady($url) ?>"
+ onClick="var player = jQuery('#audioplayer')[0]; if (player.paused == false) { player.pause(); } else { player.play(); }; return false;">
+ <img src="<?= htmlReady($material->getLogoURL()) ?>" class="lernmarktplatz_player">
+ </a>
+</div>
+<div class="center">
+ <audio controls
+ id="audioplayer"
+ crossorigin="anonymous"
+ src="<?= htmlReady($url) ?>"></audio>
+</div>
+<?= $this->render_partial("oer/embed/_link") ?>
diff --git a/app/views/oer/embed/standard.php b/app/views/oer/embed/standard.php
new file mode 100644
index 0000000..3060b71
--- /dev/null
+++ b/app/views/oer/embed/standard.php
@@ -0,0 +1,4 @@
+<a href="<?= htmlReady($url) ?>">
+ <?= Icon::create("service", Icon::ROLE_CLICKABLE)->asImg(16, ['class' => "text-bottom"]) ?>
+ <?= htmlReady($material['name']) ?>
+</a>
diff --git a/app/views/oer/embed/url.php b/app/views/oer/embed/url.php
new file mode 100644
index 0000000..2c9af80
--- /dev/null
+++ b/app/views/oer/embed/url.php
@@ -0,0 +1,11 @@
+<?php
+if ($material['player_url']) {
+ OERDownloadcounter::addCounter($material->id);
+ $url = $material['player_url'];
+}
+$htmlid = "oercampus_".$material->id."_".uniqid();
+?>
+<iframe id='<?= $htmlid ?>'
+ src="<?= htmlReady($url) ?>"
+ style="width: 100%; height: 70vh; border: none;"></iframe>
+<?= $this->render_partial("oer/embed/_link") ?>
diff --git a/app/views/oer/embed/video.php b/app/views/oer/embed/video.php
new file mode 100644
index 0000000..7039ee3
--- /dev/null
+++ b/app/views/oer/embed/video.php
@@ -0,0 +1,6 @@
+<video controls
+ <?= ($material['front_image_content_type'] ? 'poster="'.htmlReady($material->getLogoURL()).'"' : "") ?>
+ crossorigin="anonymous"
+ class='lernmarktplatz_player'
+ src="<?= htmlReady($url) ?>"></video>
+<?= $this->render_partial("oer/embed/_link") ?>
diff --git a/app/views/oer/endpoints/index.php b/app/views/oer/endpoints/index.php
new file mode 100755
index 0000000..dfedc01
--- /dev/null
+++ b/app/views/oer/endpoints/index.php
@@ -0,0 +1,66 @@
+<h1><?= htmlReady(Config::get()->OER_TITLE) ?></h1>
+
+<h2><?= _('Version') ?></h2>
+<?= _('Stud.IP') ?>: <?= htmlReady($GLOBALS['SOFTWARE_VERSION']) ?>
+
+<h2><?= _('Public-Key') ?></h2>
+<table class="default nohover">
+ <tbody>
+ <tr>
+ <td><?= _('MD5-Hash') ?></td>
+ <td><?= md5(OERHost::thisOne()->public_key) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Schlüssel') ?></td>
+ <td><?= nl2br(htmlReady(OERHost::thisOne()->public_key)) ?></td>
+ </tr>
+ </tbody>
+</table>
+
+
+<h2><?= _('Statistik') ?></h2>
+<table class="default nohover">
+ <tr>
+ <td><?= _('Anzahl verbundener Server') ?></td>
+ <td><?= OERHost::countBySQL("1=1") - 1 ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Anzahl eigener Materialien') ?></td>
+ <td><?= OERMaterial::countBySQL("host_id IS NULL") ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Anzahl Materialien von anderen Servern') ?></td>
+ <td><?= OERMaterial::countBySQL("host_id IS NOT NULL") ?></td>
+ </tr>
+</table>
+
+<h2><?= _('API-Endpoints') ?></h2>
+
+<ul class="clean">
+<? foreach ($controllerreflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) : ?>
+ <? if (stripos($method->name, "_action") === strlen($method->name) - 7) : ?>
+ <? $name = substr($method->name, 0, stripos($method->name, "_action")) ?>
+ <? if (!in_array($name, array("render", "map", "index"))) : ?>
+ <li style="margin-bottom: 20px;">
+ <? $name = substr($method->name, 0, stripos($method->name, "_action")) ?>
+ <h3><?= htmlReady($name) ?></h3>
+ <? $comment = $method->getDocComment() ?>
+ <div>
+ <? $html_comment = "" ?>
+ <? foreach (explode("\n", $comment) as $line) {
+ $line = ltrim($line, " \t/*");
+ if (!trim($line)) {
+ $html_comment .= $line."\n\n";
+ } elseif ($line[0] === "@" && $html_comment[strlen($html_comment) - 1] !== "\n") {
+ $html_comment .= "\n".$line;
+ } else {
+ $html_comment .= $line." ";
+ }
+ } ?>
+ <?= formatReady(trim($html_comment)) ?>
+ </div>
+ </li>
+ <? endif ?>
+ <? endif ?>
+<? endforeach ?>
+</ul>
diff --git a/app/views/oer/market/_details_file.php b/app/views/oer/market/_details_file.php
new file mode 100755
index 0000000..4a76437
--- /dev/null
+++ b/app/views/oer/market/_details_file.php
@@ -0,0 +1,21 @@
+<? if ($file['is_folder']) : ?>
+ <? if ($name !== "__MACOSX") : ?>
+ <li class="folder">
+ <?= Icon::create("folder-full", Icon::ROLE_INFO)->asImg("20px", ['class' => "text-bottom"]) ?>
+ <?= htmlReady($name) ?>
+ <ol>
+ <? foreach ($file['structure'] as $name => $subfile) : ?>
+ <?= $this->render_partial("oer/market/_details_file.php", ['name' => $name, 'file' => $subfile]) ?>
+ <? endforeach ?>
+ </ol>
+ </li>
+ <? endif ?>
+<? else : ?>
+ <li>
+ <div class="size" style="float: right">
+ <?= htmlReady(number_format($file['size'] / 1024, 2)) ?> KB
+ </div>
+ <?= FileManager::getFileIcon($name, "info")->asImg("20px", ['class' => "text-bottom"]) ?>
+ <?= htmlReady($name) ?>
+ </li>
+<? endif ?>
diff --git a/app/views/oer/market/_material_short.php b/app/views/oer/market/_material_short.php
new file mode 100755
index 0000000..83d1d13
--- /dev/null
+++ b/app/views/oer/market/_material_short.php
@@ -0,0 +1,31 @@
+<article class="contentbox">
+ <a href="<?= $controller->url_for('oer/market/details/' . $material->getId()) ?>">
+ <header>
+ <h1>
+ <?
+ if ($material['category'] === "video") {
+ $icon = "video";
+ }
+ if ($material['category'] === "audio") {
+ $icon = "file-audio";
+ }
+ if ($material['category'] === "presentation") {
+ $icon = "file-pdf";
+ }
+ if ($material['category'] === "elearning") {
+ $icon = "learnmodule";
+ }
+ if ($material['content_type'] === "application/zip") {
+ $icon = "archive3";
+ }
+ if (!$icon) {
+ $icon = "file";
+ }
+ ?>
+ <?= Icon::create($icon, Icon::ROLE_CLICKABLE)->asImg(20, ['class' => "text-bottom"]) ?>
+ <div class="title"><?= htmlReady($material['name']) ?></div>
+ </h1>
+ </header>
+ <div class="image" style="background-image: url(<?= $material->getLogoURL() ?>);<?= (!$material['front_image_content_type']) ? " background-size: 60% auto;" : "" ?>"></div>
+ </a>
+</article>
diff --git a/app/views/oer/market/_materials.php b/app/views/oer/market/_materials.php
new file mode 100755
index 0000000..8bb755e
--- /dev/null
+++ b/app/views/oer/market/_materials.php
@@ -0,0 +1,3 @@
+<? foreach ($materialien as $material) : ?>
+ <?= $this->render_partial("oer/market/_material_short.php", compact("material", "plugin")) ?>
+<? endforeach ?>
diff --git a/app/views/oer/market/_searchform.php b/app/views/oer/market/_searchform.php
new file mode 100644
index 0000000..fd21137
--- /dev/null
+++ b/app/views/oer/market/_searchform.php
@@ -0,0 +1,175 @@
+<div class="searchform">
+ <div class="oneliner">
+ <div class="frame">
+ <span v-if="category != null"
+ class="category activefilter" title="<?= _('Aktiver Filter der Kategorie') ?>">
+ <span>{{ category }}</span>
+ <a href="#"
+ @click.prevent="clearCategory"
+ class="erasefilter"
+ title="<?= _('Filter der Kategorie entfernen') ?>">
+ <studip-icon shape="decline" role="clickable" size="16" class="text-bottom"></studip-icon>
+ </a>
+ </span>
+
+ <span v-if="difficulty[0] != 1 || difficulty[1] != 12"
+ class="niveau activefilter"
+ title="<?= _('Aktiver Filter für das Niveau') ?>">
+ <?= _('Niveau') ?>: &nbsp;
+ <span>{{ difficulty[0] }}</span>
+ -
+ <span>{{ difficulty[1] }}</span>
+ <a href="#"
+ @click.prevent="clearDifficulty"
+ class="erasefilter"
+ title="<?= _('Filter des Niveaus entfernen') ?>">
+ <studip-icon shape="decline" role="clickable" size="16" class="text-bottom"></studip-icon>
+ </a>
+ </span>
+
+ <input type="text"
+ name="search"
+ @focus="showFilterPanel"
+ @keyup="sync_search_text"
+ @keydown.enter.prevent="search">
+
+ <button v-if="difficulty[0] != 1 || difficulty[1] != 12 || (category != null) || (searchtext.length > 0)"
+ class="erase"
+ type="button"
+ title="<?= _('Suchformular zurücksetzen') ?>"
+ @click="clearAllFilters">
+ <studip-icon shape="decline" role="clickable"></studip-icon>
+ </button>
+
+ <button @click="triggerFilterPanel"
+ type="button"
+ title="<?= _('Suchfilter einstellen') ?>"
+ :class="activeFilterPanel ? 'active' : ''">
+ <studip-icon shape="filter" :role="activeFilterPanel ? 'info_alt' : 'clickable'"></studip-icon>
+ </button>
+
+ <div v-if="activeFilterPanel" class="filterpanel_shadow"></div>
+
+ <div v-if="activeFilterPanel" class="filterpanel">
+ <div>
+ <h3><?= _('Kategorien') ?></h3>
+ <ul class="clean">
+ <li>
+ <a href="<?= $controller->link_for("oer/market", ['category' => "audio"]) ?>" @click.prevent="category = 'audio'">
+ <studip-icon v-if="category != 'audio'" shape="radiobutton-unchecked" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <studip-icon v-if="category == 'audio'" shape="radiobutton-checked" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <?= _('Audio') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= $controller->link_for("oer/market", ['category' => "video"]) ?>" @click.prevent="category = 'video'">
+ <studip-icon v-if="category != 'video'" shape="radiobutton-unchecked" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <studip-icon v-if="category == 'video'" shape="radiobutton-checked" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <?= _('Video') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= $controller->link_for("oer/market", ['category' => "presentation"]) ?>" @click.prevent="category = 'presentation'">
+ <studip-icon v-if="category != 'presentation'" shape="radiobutton-unchecked" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <studip-icon v-if="category == 'presentation'" shape="radiobutton-checked" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <?= _('Folien') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= $controller->link_for("oer/market", ['category' => "elearning"]) ?>" @click.prevent="category = 'elearning'">
+ <studip-icon v-if="category != 'elearning'" shape="radiobutton-unchecked" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <studip-icon v-if="category == 'elearning'" shape="radiobutton-checked" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <?= _('Lernmodule') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= $controller->link_for("oer/market", ['get' => "all"]) ?>">
+ <studip-icon shape="link-intern" role="clickable" size="16" class="text-bottom"></studip-icon>
+ <?= _('Alles') ?>
+ </a>
+ </li>
+ </ul>
+ </div>
+ <div class="level_filter">
+ <h3><?= _('Niveau') ?></h3>
+ <div class="level_labels">
+ <div><?= _('Leicht') ?></div>
+ <div><?= _('Schwer') ?></div>
+ </div>
+ <div class="level_numbers">
+ <? for ($i = 1; $i <= 12; $i++) : ?>
+ <div><?= ($i < 10 ? "&nbsp;" : "").$i ?></div>
+ <? endfor ?>
+ </div>
+ <div id="difficulty_slider"></div>
+
+ <input type="hidden" id="difficulty" name="difficulty" value="">
+ </div>
+ </div>
+
+
+ <button title="<?= _('Suche starten') ?>" @click.prevent="search" @focus="hideFilterPanel">
+ <studip-icon shape="search" role="clickable"></studip-icon>
+ </button>
+ </div>
+
+ </div>
+
+
+</div>
+
+<div class="browser">
+
+ <div v-if="browseMode === false" class="intro">
+ <img src="<?= Assets::image_path("oer-keyvisual-negative.svg") ?>" class="illustration responsive-hidden">
+ <div>
+ <h3><?= _('Wertvolle Lernmaterialien entdecken!') ?></h3>
+ <div class="responsive-hidden">
+ <?= _('Neue und spannende Lernmaterialien zu finden, ist ganz einfach. Mit dem Entdeckermodus können Sie nach Schlagwörtern stöbern und durch Themengebiete surfen.') ?>
+ </div>
+
+ <div>
+ <?= \Studip\LinkButton::create(_('Zum Entdeckermodus'), "#", ['@click.prevent' => "browseMode=true"]) ?>
+ </div>
+ </div>
+ </div>
+
+ <div v-if="browseMode === true" class="tagcloud">
+ <div>
+ <h3><?= _('Wertvolle Materialien entdecken!') ?></h3>
+ <?= _('Klicken Sie auf die Schlagwörter und entdecken Sie Lernmaterialien zum Thema.') ?>
+ </div>
+ <a v-if="tagHistory.length" href="" @click.prevent="backInCloud" class="back-button">
+ <studip-icon shape="arr_1left" role="clickable" size="50"></studip-icon>
+ </a>
+ <ul class="tags clean">
+ <li v-for="tag in tags">
+ <a href="#"
+ class="button"
+ :style="getTagStyle(tag.tag_hash)"
+ :title="tag.name"
+ @click.prevent="browseTag(tag.tag_hash, tag.name)">{{"#" + tag.name}}</a>
+ </li>
+ </ul>
+ </div>
+
+</div>
+
+<ul class="results oer_material_overview">
+ <li v-for="result in results" :key="result.material_id">
+ <article class="contentbox" :title="result.name">
+ <a :href="getMaterialURL(result.material_id)">
+ <header>
+ <h1>
+ <studip-icon :shape="getIconShape(result)"
+ role="clickable"
+ size="20"
+ class="text-bottom"></studip-icon>
+ {{ result.name }}
+ </h1>
+ </header>
+ <div class="image" :style="'background-image: url(' + result.logo_url + ');' + (!result.front_image_content_type ? ' background-size: 60% auto;': '')"></div>
+ </a>
+ </article>
+ </li>
+</ul>
diff --git a/app/views/oer/market/abo.php b/app/views/oer/market/abo.php
new file mode 100644
index 0000000..0538731
--- /dev/null
+++ b/app/views/oer/market/abo.php
@@ -0,0 +1,15 @@
+<form action="<?= $controller->link_for("oer/market/abo") ?>"
+ method="post">
+
+ <input type="hidden" name="abo" value="0">
+
+ <label>
+ <input type="checkbox" name="abo" value="1"<?= $abo ? " checked" : "" ?>>
+ <?= sprintf(_('Ich möchte Nachrichten bekommen über neue Inhalte im %s'), Config::get()->OER_TITLE) ?>
+ </label>
+
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern')) ?>
+ </div>
+
+</form>
diff --git a/app/views/oer/market/add_to_course.php b/app/views/oer/market/add_to_course.php
new file mode 100755
index 0000000..06df75b
--- /dev/null
+++ b/app/views/oer/market/add_to_course.php
@@ -0,0 +1,50 @@
+<? if ($GLOBALS['perm']->have_perm("admin")) : ?>
+ <form class="default oer_add_to_course"
+ action="<?= $controller->link_for("oer/market/add_to_course/".$material->getId()) ?>"
+ method="post"
+ data-dialog>
+ <?= QuickSearch::get("seminar_id", new StandardSearch("Seminar_id"))->render() ?>
+ <?= \Studip\Button::create(_('Auswählen')) ?>
+ </form>
+<? endif ?>
+
+<? if (count($courses)) : ?>
+ <table class="default">
+ <caption><?= _('Veranstaltungsliste') ?></caption>
+ <? foreach ($semesters as $semester) : ?>
+ <tbody>
+ <tr>
+ <td colspan="3">
+ <h2><?= htmlReady($semester['name']) ?></h2>
+ </td>
+ </tr>
+ </tbody>
+ <tbody>
+ <? foreach ($courses as $course) : ?>
+ <? if ($course->isInSemester($semester)) : ?>
+ <tr>
+ <td width="22px">
+ <?= CourseAvatar::getAvatar($course->getId())->getImageTag(Avatar::SMALL) ?>
+ </td>
+ <td><?= htmlReady($course['name']) ?></td>
+ <td class="actions">
+ <form action="<?= $controller->link_for("oer/market/add_to_course/".$material->getId()) ?>"
+ method="post"
+ data-dialog>
+ <input type="hidden" name="seminar_id" value="<?= htmlReady($course->getId()) ?>">
+ <button type="submit"
+ title="<?= _('Zur Veranstaltung hinzufügen') ?>"
+ style="border: none; background: none; cursor: pointer;">
+ <?= Icon::create("add", Icon::ROLE_CLICKABLE)->asImg("20px", ['class' => "text-bottom"]) ?>
+ </button>
+ </form>
+ </td>
+ </tr>
+ <? endif ?>
+ <? endforeach ?>
+ </tbody>
+ <? endforeach ?>
+ </table>
+<? elseif (!$GLOBALS['perm']->have_perm("admin")) : ?>
+ <?= MessageBox::info(_('Lernmaterialien können nur in eigene Veranstaltungen kopiert werden. Erstellen Sie eine Veranstaltung oder tragen Sie sich in eine ein.')) ?>
+<? endif ?>
diff --git a/app/views/oer/market/add_to_course_select_class.php b/app/views/oer/market/add_to_course_select_class.php
new file mode 100644
index 0000000..72c092a
--- /dev/null
+++ b/app/views/oer/market/add_to_course_select_class.php
@@ -0,0 +1,19 @@
+
+<h2><?= _('Bereich auswählen') ?></h2>
+
+<div class="file_select_possibilities">
+ <div>
+ <? foreach ($classes as $class) : ?>
+ <a href="<?= $controller->link_for("oer/market/add_to_course/".$material->getId(), ['seminar_id' => $course->getId(), 'class' => $class]) ?>">
+ <? $object = PluginManager::getInstance()->getPlugin($class) ?: new $class() ?>
+ <? $metadata = $object->getMetadata() ?>
+
+ <? $icon = $object->oerGetIcon() ?>
+ <? if ($icon) : ?>
+ <?= $icon->asImg(50) ?>
+ <? endif ?>
+ <?= htmlReady($metadata['displayname']) ?>
+ </a>
+ <? endforeach ?>
+ </div>
+</div>
diff --git a/app/views/oer/market/details.php b/app/views/oer/market/details.php
new file mode 100755
index 0000000..b47ed0d
--- /dev/null
+++ b/app/views/oer/market/details.php
@@ -0,0 +1,366 @@
+<?= $contentbar ?>
+
+<? $url = $material['host_id'] ? $material->host->url."download/".$material['foreign_material_id'] : $controller->link_for("oer/endpoints/download/".$material->getId()) ?>
+
+<? if ($material['player_url']) : ?>
+ <iframe src="<?= htmlReady($material['player_url']) ?>"
+ class="lernmarktplatz_player"></iframe>
+ <? OERDownloadcounter::addCounter($material->id) ?>
+<? elseif ($material->isVideo()) : ?>
+ <video controls
+ <?= $material['front_image_content_type'] ? 'poster="'.htmlReady($material->getLogoURL()).'"' : "" ?>
+ crossorigin="anonymous"
+ src="<?= htmlReady($url) ?>"
+ class="lernmarktplatz_player"></video>
+<? elseif ($material->isAudio()) : ?>
+ <div>
+ <a href="<?= htmlReady($url) ?>" onClick="var player = jQuery('#audioplayer')[0]; if (player.paused == false) { player.pause(); } else { player.play(); }; return false;">
+ <img src="<?= htmlReady($material->getLogoURL()) ?>" class="lernmarktplatz_player">
+ </a>
+ </div>
+ <div class="center">
+ <audio controls
+ id="audioplayer"
+ crossorigin="anonymous"
+ src="<?= htmlReady($url) ?>"></audio>
+ </div>
+<? elseif ($material->isPDF()) : ?>
+ <iframe src="<?= htmlReady($url) ?>"
+ class="lernmarktplatz_player"></iframe>
+<? elseif ($material['front_image_content_type']) : ?>
+ <div style="background-image: url('<?= htmlReady($material->getLogoURL()) ?>');" class="lernmarktplatz_player image"></div>
+<? endif ?>
+
+<? if ($material->isFolder() && !$material['player_url']) : ?>
+ <h2><?= _('Verzeichnisstruktur') ?></h2>
+ <ol class="lernmarktplatz structure">
+ <? foreach ($material['structure'] as $filename => $file) : ?>
+ <?= $this->render_partial("oer/market/_details_file.php", ['name' => $filename, 'file' => $file]) ?>
+ <? endforeach ?>
+ </ol>
+<? endif ?>
+
+<? if ($url && $material['filename']) : ?>
+ <div class="center bordered" style="margin-top: 20px; margin-bottom: 20px;">
+ <a class="button"
+ href="<?= htmlReady($url) ?>" title="<?= _('Herunterladen') ?>"
+ download="<?= htmlReady($material['filename']) ?>">
+ <div class="filename"><?= _('Herunterladen') ?></div>
+ </a>
+
+ <? if ($GLOBALS['perm']->have_perm("autor")) : ?>
+ <a class="button"
+ href="<?= $controller->link_for( "oer/market/add_to_course/" . $material->getId()) ?>"
+ data-dialog>
+ <?= _('Zu Veranstaltung hinzufügen') ?>
+ </a>
+ <? endif ?>
+
+ <? if (!$material['host_id'] && ($material->isMine() || $GLOBALS['perm']->have_perm("root"))) : ?>
+ <?= \Studip\LinkButton::create(_('Bearbeiten'), $controller->link_for("oer/mymaterial/edit/".$material->getId()), ['data-dialog' => "1"]) ?>
+ <form action="<?= $controller->link_for("oer/mymaterial/edit/".$material->getId()) ?>" method="post" style="display: inline;">
+ <?= \Studip\Button::create(_('Löschen'), "delete", ['value' => 1, 'data-confirm' => _('Wirklich löschen?')]) ?>
+ </form>
+ <? endif ?>
+ </div>
+<? endif ?>
+
+<div></div>
+
+<div class="oer_columns bordered">
+ <aside>
+ <? $tags = $material->getTopics() ?>
+ <? if (count($tags) > 0) : ?>
+ <div class="tags">
+ <h2><?= _('Themen') ?></h2>
+ <ul class="clean">
+ <? foreach ($tags as $tag) : ?>
+ <li>
+ <a href="<?= $controller->link_for("oer/market", ['tag' => $tag['name']]) ?>">
+ #
+ <?= htmlReady(ucfirst($tag['name'])) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </div>
+ <? endif ?>
+
+ <? if ($material['difficulty_start'] != 1 || $material['difficulty_end'] != 12) : ?>
+ <h2><?= _('Niveau') ?></h2>
+ <div>
+ <div style="display: flex; justify-content: space-between; font-size: 0.8em; color: grey;">
+ <div><?= _('Leicht') ?></div>
+ <div><?= _('Schwer') ?></div>
+ </div>
+ <div style="display: flex; justify-content: space-between;">
+ <? for ($i = 1; $i <= 12; $i++) : ?>
+ <div><?= ($i < 10 ? "&nbsp;" : "").$i ?></div>
+ <? endfor ?>
+ </div>
+ <div id="difficulty_slider" style="margin-left: 5px; margin-right: 9px;"></div>
+
+ <script>
+ jQuery(function () {
+ jQuery("#difficulty_slider").slider({
+ range: true,
+ min: 1,
+ max: 12,
+ disabled: true,
+ values: [<?= htmlReady($material['difficulty_start']) ?>, <?= htmlReady($material['difficulty_end']) ?>]
+ });
+ });
+ </script>
+ </div>
+ <? endif ?>
+
+ <? if (!Config::get()->OER_DISABLE_LICENSE) : ?>
+ <div class="license" style="margin-top: 20px;">
+ <h2><?= _('Lizenz') ?></h2>
+ <? if ($material->license['link']) : ?>
+ <a href="<?= htmlReady($material->license['link']) ?>" target="_blank">
+ <? endif ?>
+ <?= LicenseAvatar::getAvatar($material['license_identifier'])->getImageTag(Avatar::MEDIUM) ?>
+ <?= htmlReady($material['license_identifier']) ?>
+ <? if ($material->license['link']) : ?>
+ </a>
+ <? endif ?>
+ <div>
+ <a href="<?= $controller->link_for("oer/market/licenseinfo") ?>" data-dialog>
+ <?= _('Was heißt das?') ?>
+ </a>
+ </div>
+ </div>
+ <? endif ?>
+
+ </aside>
+ <div>
+ <div>
+ <h2><?= _('Beschreibung') ?></h2>
+ <?= formatReady($material['description']) ?>
+ </div>
+
+ <h2><?= _('Zum Autor') ?></h2>
+ <ul class="author_information clean">
+ <? foreach ($material->users as $materialuser) : ?>
+ <li>
+ <? if ($materialuser['external_contact']) : ?>
+ <? $user = $materialuser['oeruser'] ?>
+ <? $image = $user['avatar_url'] ?>
+ <? $host = OERHost::find($user['host_id']) ?>
+ <div class="avatar" style="background-image: url('<?= $image ?>');"></div>
+ <div>
+ <div class="author_name">
+ <a href="<?= $controller->link_for("oer/market/profile/".$user->getId()) ?>">
+ <?= htmlReady($user['name']) ?>
+ </a>
+ </div>
+ <div class="author_host">(<?= htmlReady($host->name) ?>)</div>
+ <div class="description"><?= formatReady($user['data']['description']) ?></div>
+ </div>
+ <? else : ?>
+ <? $user = User::find($materialuser['user_id']) ?>
+ <? $image = Avatar::getAvatar($materialuser['user_id'])->getURL(Avatar::MEDIUM) ?>
+ <div class="avatar" style="background-image: url('<?= $image ?>');"></div>
+ <div>
+ <div class="author_name">
+ <a href="<?= URLHelper::getLink("dispatch.php/profile", ['username' => $user['username']]) ?>">
+ <?= htmlReady($user ? $user->getFullName() : _('unbekannt')) ?>
+ </a>
+ </div>
+ <div class="author_host">(<?= htmlReady(Config::get()->UNI_NAME_CLEAN) ?>)</div>
+ <div class="description">
+ <? if ($user['oercampus_description']) : ?>
+ <?= htmlReady($user['oercampus_description']) ?>
+ <? elseif ($materialuser['user_id'] === $GLOBALS['user']->id) : ?>
+ <em>
+ <?= sprintf(_('Noch keine Beschreibung für den %s vorhanden.'), Config::get()->OER_TITLE) ?>
+ <a href="<?= URLHelper::getLink("dispatch.php/settings/details") ?>">
+ <?= _('Jetzt eine eingeben.') ?>
+ </a>
+ </em>
+ <? endif ?>
+ </div>
+ </div>
+ <? endif ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </div>
+</div>
+
+<? $allowed_to_review = !$material->isMine() && $GLOBALS['perm']->have_perm("autor") ?>
+<? if (!$material->isMine() || count($material->reviews)) : ?>
+ <article class="studip bordered">
+ <div class="center">
+ <? if ($material['rating'] === null) : ?>
+ <? if ($allowed_to_review) : ?>
+ <a style="opacity: 0.3;"
+ title="<?= $GLOBALS['perm']->have_perm("autor") ? _('Geben Sie die erste Bewertung ab.') : _('Noch keine Bewertung abgegeben.') ?>"
+ href="<?= $controller->link_for('oer/market/review/' . $material->getId()) ?>" data-dialog>
+ <? endif ?>
+ <?= Icon::create("star", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(50) ?>
+ <?= Icon::create("star", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(50) ?>
+ <?= Icon::create("star", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(50) ?>
+ <?= Icon::create("star", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(50) ?>
+ <?= Icon::create("star", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(50) ?>
+ <? if ($allowed_to_review) : ?>
+ </a>
+ <? endif ?>
+ <? else : ?>
+ <? if ($allowed_to_review) : ?>
+ <a href="<?= $controller->link_for('oer/market/review/' . $material->getId()) ?>" data-dialog title="<?= sprintf(_('%s von 5 Sternen'), round($material['rating'] / 2, 1)) ?>">
+ <? endif ?>
+ <? $material['rating'] = round($material['rating'], 1) / 2 ?>
+ <? $v = $material['rating'] >= 0.75 ? "" : ($material['rating'] >= 0.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INFO)->asImg(50) ?>
+ <? $v = $material['rating'] >= 1.75 ? "" : ($material['rating'] >= 1.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INFO)->asImg(50) ?>
+ <? $v = $material['rating'] >= 2.75 ? "" : ($material['rating'] >= 2.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INFO)->asImg(50) ?>
+ <? $v = $material['rating'] >= 3.75 ? "" : ($material['rating'] >= 3.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INFO)->asImg(50) ?>
+ <? $v = $material['rating'] >= 4.75 ? "" : ($material['rating'] >= 4.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", $allowed_to_review ? Icon::ROLE_CLICKABLE : Icon::ROLE_INFO)->asImg(50) ?>
+ <? if ($allowed_to_review) : ?>
+ </a>
+ <? endif ?>
+ <? endif ?>
+ </div>
+
+ <ul class="reviews">
+ <? foreach ($material->reviews as $review) : ?>
+ <li id="review_<?= $review->getId() ?>" class="review">
+ <div class="avatar">
+ <img width="50px" height="50px" src="<?= htmlReady($review['metadata']['host_id']
+ ? ExternalUser::find($review['user_id'])->avatar_url
+ : Avatar::getAvatar($review['user_id'])->getURL(Avatar::MEDIUM)) ?>">
+ </div>
+ <div class="content">
+ <div class="timestamp">
+ <?= date("j.n.Y G:i", $review['chdate']) ?>
+ </div>
+ <strong>
+ <? if ($review['metadata']['host_id']) : ?>
+ <? $user = ExternalUser::find($review['user_id']) ?>
+ <a href="<?= $controller->link_for("oer/market/profile/".$user->getId()) ?>">
+ <?= htmlReady($user->name) ?>
+ </a>
+ <? else : ?>
+ <? $user = new User($review['user_id']) ?>
+ <a href="<?= URLHelper::getLink("dispatch.php/profile", ['username' => $user['username']]) ?>">
+ <?= htmlReady($user->getFullName()) ?>
+ </a>
+ <? endif ?>
+ </strong>
+ <span class="origin">(<?= htmlReady($review['metadata']['host_id'] ? $review->host['name'] : Config::get()->UNI_NAME_CLEAN) ?>)</span>
+ <div class="review_text">
+ <?= formatReady($review['content']) ?>
+ </div>
+ <div class="stars">
+ <? $rating = round($review['metadata']['rating'], 1) ?>
+ <? $v = $rating >= 0.75 ? "" : ($rating >= 0.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", Icon::ROLE_INFO)->asImg(16) ?>
+ <? $v = $rating >= 1.75 ? "" : ($rating >= 1.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", Icon::ROLE_INFO)->asImg(16) ?>
+ <? $v = $rating >= 2.75 ? "" : ($rating >= 2.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", Icon::ROLE_INFO)->asImg(16) ?>
+ <? $v = $rating >= 3.75 ? "" : ($rating >= 3.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", Icon::ROLE_INFO)->asImg(16) ?>
+ <? $v = $rating >= 4.75 ? "" : ($rating >= 4.25 ? "-halffull" : "-empty") ?>
+ <?= Icon::create("star$v", Icon::ROLE_INFO)->asImg(16) ?>
+
+ <? if ($GLOBALS['perm']->have_perm("autor") && !count($review->comments)) : ?>
+ <a href="<?= $controller->link_for("oer/market/discussion/".$review->getId()) ?>" style="font-size: 0.8em;">
+ <?= _('Darauf antworten') ?>
+ </a>
+ <? endif ?>
+ </div>
+ <div class="comments center">
+ <? if (count($review->comments)) : ?>
+ <a href="<?= $controller->link_for("oer/market/discussion/".$review->getId()) ?>">
+ <?= Icon::create("comment", Icon::ROLE_CLICKABLE)->asImg(16, ['class' => "text-bottom"]) ?>
+ <?= sprintf(_('%s Kommentare dazu'), count($review->comments)) ?>
+ </a>
+ <? elseif ($material->isMine()) : ?>
+ <a href="<?= $controller->link_for("oer/market/discussion/".$review->getId()) ?>">
+ <?= Icon::create("comment", Icon::ROLE_CLICKABLE)->asImg(16, ['class' => "text-bottom"]) ?>
+ <?= _('Dazu einen Kommentar schreiben') ?>
+ </a>
+ <? endif ?>
+ </div>
+ </div>
+ </li>
+ <? endforeach ?>
+ </ul>
+
+ <div class="center">
+ <? if (!$material->isMine() && $GLOBALS['perm']->have_perm("autor")) : ?>
+ <?= \Studip\LinkButton::create(_('Review schreiben'), $controller->url_for('oer/market/review/' . $material->getId()), ['data-dialog' => 1]) ?>
+ <? endif ?>
+ </div>
+ </article>
+<? endif ?>
+
+
+
+<?
+$actions = new ActionsWidget();
+$GLOBALS['perm']->have_perm(Config::get()->OER_PUBLIC_STATUS);
+if ($GLOBALS['perm']->have_perm("autor")) {
+ $actions->addLink(
+ _('Eigenes Lernmaterial hochladen'),
+ $controller->url_for("oer/mymaterial/edit"),
+ Icon::create("add", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "1"]
+ );
+ if (!$material['host_id'] && $material->isMine()) {
+ $actions->addLink(
+ _('Bearbeiten'),
+ $controller->url_for("oer/mymaterial/edit/".$material->getId()),
+ Icon::create("edit", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "1"]
+ );
+ }
+}
+if ($url && $material['filename']) {
+ $actions->addLink(
+ _('Herunterladen'),
+ $url,
+ Icon::create("download", Icon::ROLE_CLICKABLE)
+ );
+}
+if ($GLOBALS['perm']->have_perm("autor")) {
+ $actions->addLink(
+ _('Zu Veranstaltung hinzufügen'),
+ $controller->url_for( "oer/market/add_to_course/" . $material->getId()),
+ Icon::create("seminar+move_right", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "1"]
+ );
+}
+
+if ($material['player_url'] || $material->isVideo() || $material->isPDF()) {
+ $actions->addLink(
+ _('Vollbild aktivieren'),
+ "#",
+ Icon::create("fullscreen-on", Icon::ROLE_CLICKABLE),
+ ['onclick' => "STUDIP.OER.requestFullscreen('.lernmarktplatz_player');"]
+ );
+}
+$actions->addLink(
+ _('Teilen und einbetten'),
+ $controller->url_for("oer/market/embed/".$material->getId()),
+ Icon::create("code", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "1"]
+);
+
+if (!$material['host_id'] && ($GLOBALS['perm']->have_perm("root") || $material->isMine())) {
+ $actions->addLink(
+ _('Zugriffszahlen'),
+ $controller->url_for("oer/mymaterial/statistics/".$material->getId()),
+ Icon::create("graph", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "1"]
+ );
+}
+
+Sidebar::Get()->addWidget($actions);
diff --git a/app/views/oer/market/discussion.php b/app/views/oer/market/discussion.php
new file mode 100755
index 0000000..139e2b9
--- /dev/null
+++ b/app/views/oer/market/discussion.php
@@ -0,0 +1,35 @@
+<a href="<?= $controller->link_for("oer/market/details/".$thread['context_id']) ?>">
+ <?= Icon::create("arr_1left", Icon::ROLE_CLICKABLE)->asImg("20px", ['class' => "text-bottom"]) ?>
+ <?= _('Zurück') ?>
+</a>
+
+<?
+$thread_data = $thread->getJSONData(
+ 50,
+ null,
+ Request::get("search")
+);
+?>
+
+<div class="blubber_panel vueinstance"
+ data-active_thread="<?= htmlReady($thread->getId()) ?>"
+ data-thread_data="<?= htmlReady(json_encode($thread_data ?: ['thread_posting' => []])) ?>"
+ data-threads_more_down="0"
+ :class="waiting ? 'waiting' : ''">
+
+ <div id="blubber_stream_container">
+ <blubber-thread :thread_data="thread_data"></blubber-thread>
+ </div>
+
+ <div class="blubber_sideinfo responsive-hidden" v-if="thread_data.context_info || thread_data.thread_posting.content">
+ <div class="posting" v-show="display_context_posting">
+ <div class="header">
+ <studip-date-time :timestamp="thread_data.thread_posting.mkdate" :relative="true"></studip-date-time>
+ <div>{{ thread_data.thread_posting.user_name }}</div>
+ </div>
+ <div class="content" v-html="thread_data.thread_posting.html"></div>
+ </div>
+ <div v-if="thread_data.context_info" class="context_info" v-html="thread_data.context_info"></div>
+ </div>
+
+</div>
diff --git a/app/views/oer/market/embed.php b/app/views/oer/market/embed.php
new file mode 100644
index 0000000..188246c
--- /dev/null
+++ b/app/views/oer/market/embed.php
@@ -0,0 +1,30 @@
+<form class="default">
+ <? $base = URLHelper::setBaseURL($GLOBALS['ABSOLUTE_URI_STUDIP']) ?>
+ <label>
+ <?= _('Platzhalter zum Teilen in Stud.IP (Forum, Blubber, Wiki, Ankündigung)') ?>
+ <input type="text" readonly value="[oermaterial]<?= htmlReady($material->getId()) ?>">
+ </label>
+
+ <? if (Config::get()->OER_PUBLIC_STATUS === "nobody") : ?>
+ <label>
+ <?= _('Teilen als Link') ?>
+ <input type="text" readonly value="<?= $controller->link_for("oer/market/details/".$material->getId()) ?>">
+ </label>
+ <? endif ?>
+
+ <? if ($material['player_url'] || $material->isPDF() || $material->isVideo() || $material->isAudio()) : ?>
+ <?
+ if ($material['player_url']) {
+ $url = $material['player_url'];
+ } else {
+ $url = $material['host_id'] ? $material->host->url."download/".$material['foreign_material_id'] : $controller->link_for("oer/market/download/".$material->getId());
+ }
+ ?>
+ <label>
+ <?= _('Teilen als HTML-Schnipsel') ?>
+ <textarea readonly><?= htmlReady('<iframe src="'.htmlReady($url).'"></iframe>') ?></textarea>
+ </label>
+
+ <? endif ?>
+ <? URLHelper::setBaseURL($base) ?>
+</form>
diff --git a/app/views/oer/market/index.php b/app/views/oer/market/index.php
new file mode 100755
index 0000000..aa1d985
--- /dev/null
+++ b/app/views/oer/market/index.php
@@ -0,0 +1,68 @@
+<?
+if ($best_nine_tags && count($best_nine_tags) > 0) {
+ $tags = [];
+ foreach ($best_nine_tags as $tag) {
+ $tags[] = [
+ 'tag_hash' => $tag['tag_hash'],
+ 'name' => $tag['name']
+ ];
+ }
+}
+if ($materialien !== null) {
+ $material_data = [];
+ foreach ($materialien as $material) {
+ $data = $material->toRawArray();
+
+ $data['tags'] = array_map(function($tag) {
+ return $tag['name'];
+ }, $material->getTopics());
+
+ $data['logo_url'] = $material->getLogoURL();
+ $data['download_url'] = $material->getDownloadUrl();
+ $material_data[] = $data;
+ }
+}
+?>
+<form class="oer_search"
+ action="<?= $controller->link_for("oer/market/search") ?>"
+ method="GET"
+ data-searchresults="<?= htmlReady(json_encode($material_data)) ?>"
+ data-filteredtag="<?= htmlReady(Request::get("tag")) ?>"
+ data-filteredcategory="<?= htmlReady(Request::get("category")) ?>"
+ data-tags="<?= htmlReady(json_encode($tags)) ?>"
+ data-material_select_url_template="<?= htmlReady($controller->url_for('oer/market/details/__material_id__')) ?>">
+ <?= $this->render_partial("oer/market/_searchform") ?>
+</form>
+
+
+<? if ($new_ones) : ?>
+ <div id="new_ones">
+ <h2><?= _('Neuste Materialien') ?></h2>
+ <ul class="oer_material_overview">
+ <?= $this->render_partial("oer/market/_materials.php", ['materialien' => $new_ones]) ?>
+ </ul>
+ </div>
+<? endif ?>
+
+
+
+
+
+
+<?
+if ($GLOBALS['perm']->have_perm("autor")) {
+ $actions = new ActionsWidget();
+ $actions->addLink(
+ _('Eigenes Lernmaterial hochladen'),
+ $controller->url_for("oer/mymaterial/edit"),
+ Icon::create("add", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "1"]
+ );
+ $actions->addLink(
+ $abo ? _('Neuigkeiten abbestellen') : _('Neuigkeiten abonnieren'),
+ $controller->url_for("oer/market/abo"),
+ $abo ? Icon::create("rss+decline", Icon::ROLE_CLICKABLE) : Icon::create("rss", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "size=small"]
+ );
+ Sidebar::Get()->addWidget($actions);
+}
diff --git a/app/views/oer/market/licenseinfo.php b/app/views/oer/market/licenseinfo.php
new file mode 100755
index 0000000..4618027
--- /dev/null
+++ b/app/views/oer/market/licenseinfo.php
@@ -0,0 +1,37 @@
+<h1><?= _('Wozu die Lizenzen im Lernmarktplatz?') ?></h1>
+
+<p>
+ <?= _('Urheberrecht und Lizenzrecht ist echt kompliziert. In jedem Land der Erde gibt es andere Auslegungen und als normaler Internetnutzer ist man schnell überfordert mit den Möglichkeiten, aber auch mit den Pflichten.') ?>
+</p>
+<p>
+ <?= _('Wer bei den üblichen und meist kommerziellen Plattformen etwas hochlädt, hat den AGB zugestimmt, dass alle eigenen Dateien unter einer Speziallizenz veröffentlicht werden. Wer die AGB nicht gelesen hat, weiß nichts davon, weshalb das immer so einfach erscheint. De facto gibt man beim Upload eines Fotos aber meist alle Rechte auf die Datei ab. So einen fiesen Umgang soll es bei Stud.IP absolut nicht geben! Wer Materialien hier hoch lädt, soll weiterhin volle Kontrolle über die Nutzung der eigenen Dateien haben.') ?>
+</p>
+<h2><?= _('Was ist uns wichtig?') ?></h2>
+<p>
+ <?= _('Um eine Lizenz kommen wir beim Lernmaterialienmarktplatz nicht herum. Und illegales Gemauschel wollen wir auch nicht. Wir gehen davon aus, dass alle, die auf dem Marktplatz eine Datei frei zur Verfügung stellen, auch möchte, dass die Datei am Ende auch verwendet wird und verwendet werden darf. Deshalb gilt:') ?>
+ <ul>
+ <li><?= _('Dateien sollen zum Selbstlernen verwendet werden.') ?></li>
+ <li><?= _('Die Dateien sollen im Rahmen von Veranstaltungen zum Einsatz kommen zum Beispiel als Vorlesungsfolien.') ?></li>
+ <li><?= _('Die Dateien sollen als Lernmaterial vom Lehrenden an die Studierenden weiter gegeben werden.') ?></li>
+ <li><?= _('Dabei soll Geld keine Rolle spielen.') ?></li>
+ </ul>
+</p>
+<h2><?= _('Lizenzen auf dem Marktplatz') ?></h2>
+<p>
+ <?= _('Zum Glück gibt es kluge Menschen, die sich zum Thema <em>Lizenzen</em> kluge Gedanken gemacht haben. Daher gibt es die sogenannten CreativeCommons-Lizenzen. Die sind international gültig und besagen genau das, was oben gefordert ist. Damit haben alle, die den Marktplatz nutzen, absolute Rechtssicherheit. Diese Lizenzen kommen auch außerhalb des Marktplatzes sehr oft zum Einsatz. Musikerinnen und Musiker lizensieren ihre Musikrohdateien damit, Schriftsteller und Schriftstellerinnen ihre Gedichte und Lehrende auch ganz natürlich ihre Vorlesungsfolien. Die einzige echte Auflage ist, dass bei Weitergabe oder bei der Bearbeitung der Materialien alle Autorinnen und Autoren in irgendeiner Form transparent genannt werden müssen!') ?>
+</p>
+<p>
+ <?= _('Dabei eine kleine Warnung: Wenn Sie vorhaben, mit ihren Vorlesungsfolien oder Übungsblättern und Musterlösungen noch Millionen Euro zu verdienen, dann stellen Sie diese Materialien nicht auf den Marktplatz, denn die Nutzung aller Materialien ist unentgeltlich (selbstverständlich verdienen auch wir nichts damit) und die Materialien können, wenn sie einmal heruntergeladen worden sind, auch noch beliebig weiter verteilt werden. Es gibt zwar eine CreativeCommons-Lizenz, die kommerzielle Nutzung ausschließt. Die ist aber explizit für den Marktplatz nicht praktikabel. Denn stellen Sie sich diese Frage: Wenn Lehrende Material vom Marktplatz innerhalb ihrer Veranstaltungen verwenden und zum Beispiel eine Infografik aus einer Präsentation an die Wand projizieren, ist das dann eine kommerzielle Nutzung? Ja, irgendwie schon, denn sie werden natürlich für ihre Lehrtätigkeit bezahlt. Wir legen besonderen Wert auf die Rechtssicherheit aller Nutzer und Nutzerinnen. Deswegen kommen auf unseren Marktplatz keine Materialien, die die kommerzielle Nutzung ausschließen. Nichtsdestotrotz haben Sie weiterhin alle Rechte, ihre Vorlesungsfolien auf anderem Wege über einen Verlag zu veröffentlichen und Tantiemen zu bekommen.') ?>
+</p>
+<h2><?= _('Was darf ich mit den Materialien machen?') ?></h2>
+<p>
+ <?= _('Grundsätzlich können Sie also mit Materialien im Marktplatz immer:') ?>
+ <ul>
+ <li><?= _('Die Dateien können Sie selbst nutzen.') ?></li>
+ <li><?= _('Die Dateien können Sie an andere Menschen weiter geben, sogar selbst auf anderen Seiten hochladen.') ?></li>
+ <li><?= _('Dabei müssen Sie immer den Originalautor der Datei nennen. Tun sie das in einem Beschreibungstext oder innerhalb der Datei.') ?></li>
+ <li><?= _('Sie können die Materialien auch verändern und verbessern.') ?></li>
+ <li><?= _('Auch dabei müssen Sie den Originalautor bzw. alle vorherigen Autoren des Materials nennen und das neue Werk gegebenenfalls unter dieselbe Lizenz stellen.') ?></li>
+ </ul>
+ <?= _('Wie gesagt: wir hoffen, dass dieser Weg für alle ein sehr intuitiver Weg ist, Materialien zu verbreiten und zu nutzen. Die meisten Menschen wollen sich keine Gedanken um Rechten und Pflichten in diesem Zusammenhang machen. Wir hoffen, dass wir diesen Menschen eine Freude mit dem Marktplatz machen können.') ?>
+</p>
diff --git a/app/views/oer/market/profile.php b/app/views/oer/market/profile.php
new file mode 100755
index 0000000..cce1342
--- /dev/null
+++ b/app/views/oer/market/profile.php
@@ -0,0 +1,26 @@
+<div style="display: flex; width: 100%; margin-bottom: 20px;">
+ <div>
+ <img class="avatar-normal" src="<?= htmlReady($user['avatar']) ?>">
+ </div>
+ <div style="width: 100%; padding-left: 10px;">
+ <h1><?= htmlReady($user['name']) ?></h1>
+ <div>
+ <?= formatReady($user['description']) ?>
+ </div>
+ </div>
+</div>
+
+<? if (count($materials)) : ?>
+ <section class="contentbox">
+ <header>
+ <h1>
+ <?= Icon::create("service", Icon::ROLE_CLICKABLE)->asImg("16px") ?>
+ <?= _('Lernmaterialien') ?>
+ </h1>
+ </header>
+ <section>
+ <?= $this->render_partial("mymaterial/_material_list.php", ['materialien' => $materials]) ?>
+ </section>
+ </section>
+<? endif ?>
+
diff --git a/app/views/oer/market/review.php b/app/views/oer/market/review.php
new file mode 100755
index 0000000..64b189a
--- /dev/null
+++ b/app/views/oer/market/review.php
@@ -0,0 +1,17 @@
+<form action="<?= $controller->link_for("oer/market/review/".$material->getId()) ?>"
+ method="post"
+ class="default">
+ <select name="rating">
+ <option value="0">0 <?= _('Sterne') ?></option>
+ <option value="1"<?= $review['metadata']['rating'] == 1 ? " selected" : "" ?>>1 <?= _('Stern') ?></option>
+ <option value="2"<?= $review['metadata']['rating'] == 2 ? " selected" : "" ?>>2 <?= _('Sterne') ?></option>
+ <option value="3"<?= $review['metadata']['rating'] == 3 ? " selected" : "" ?>>3 <?= _('Sterne') ?></option>
+ <option value="4"<?= $review['metadata']['rating'] == 4 ? " selected" : "" ?>>4 <?= _('Sterne') ?></option>
+ <option value="5"<?= $review['metadata']['rating'] == 5 ? " selected" : "" ?>>5 <?= _('Sterne') ?></option>
+ </select>
+
+ <textarea name="review"><?= htmlReady($review['content']) ?></textarea>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Absenden')) ?>
+ </div>
+</form>
diff --git a/app/views/oer/market/search.php b/app/views/oer/market/search.php
new file mode 100644
index 0000000..b75021f
--- /dev/null
+++ b/app/views/oer/market/search.php
@@ -0,0 +1,19 @@
+<? if ($materialien) : ?>
+ <ul class="oer_material_overview mainlist">
+ <?= $this->render_partial("oer/market/_materials.php", compact("material", "plugin")) ?>
+ </ul>
+<? else : ?>
+ <?= MessageBox::info(_('Keine Materialien gefunden')) ?>
+<? endif ?>
+
+<?
+if ($GLOBALS['perm']->have_perm("autor")) {
+ $actions = new ActionsWidget();
+ $actions->addLink(
+ _('Eigenes Lernmaterial hochladen'),
+ $controller->url_for("oer/mymaterial/edit"),
+ Icon::create("add", Icon::ROLE_CLICKABLE),
+ ['data-dialog' => "1"]
+ );
+ Sidebar::Get()->addWidget($actions);
+}
diff --git a/app/views/oer/market/type.php b/app/views/oer/market/type.php
new file mode 100644
index 0000000..b472191
--- /dev/null
+++ b/app/views/oer/market/type.php
@@ -0,0 +1,7 @@
+<? if ($materialien) : ?>
+ <ul class="oer_material_overview mainlist">
+ <?= $this->render_partial("oer/market/_materials.php", compact("material", "plugin")) ?>
+ </ul>
+<? else : ?>
+ <?= MessageBox::info(_('Keine Materialien gefunden')) ?>
+<? endif ?>
diff --git a/app/views/oer/mymaterial/_material_list.php b/app/views/oer/mymaterial/_material_list.php
new file mode 100755
index 0000000..371c392
--- /dev/null
+++ b/app/views/oer/mymaterial/_material_list.php
@@ -0,0 +1,68 @@
+<table class="default oer_mymaterial">
+ <thead>
+ <tr>
+ <th style="width:20px"></th>
+ <th><?= _('Material') ?></th>
+ <th><?= _('Bewertung') ?></th>
+ <th><?= _('Downloads') ?></th>
+ <th class="actions"><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $starwidth = '20px' ?>
+ <? foreach ($materialien as $material) : ?>
+ <tr>
+ <td>
+ <? if ($material->draft) : ?>
+ <?= Icon::create('lock-locked', Icon::ROLE_INFO)->asImg(20, ['class' => 'text-bottom']) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for('oer/market/details/' . $material->id) ?>">
+ <?= htmlReady($material['name']) ?>
+ </a>
+ </td>
+ <td>
+ <? if ($material->rating === null) : ?>
+ <?= Icon::create('star', Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <?= Icon::create('star', Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <?= Icon::create('star', Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <?= Icon::create('star', Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <?= Icon::create('star', Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <? else : ?>
+ <? $material->rating = round($material->rating, 1) / 2 ?>
+ <? $v = $material->rating >= 0.75 ? '' : ($material->rating >= 0.25 ? '-halffull' : '-empty') ?>
+ <?= Icon::create("star{$v}", Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <? $v = $material->rating >= 1.75 ? '' : ($material->rating >= 1.25 ? '-halffull' : '-empty') ?>
+ <?= Icon::create("star{$v}", Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <? $v = $material->rating >= 2.75 ? '' : ($material->rating >= 2.25 ? '-halffull' : '-empty') ?>
+ <?= Icon::create("star{$v}", Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <? $v = $material->rating >= 3.75 ? '' : ($material->rating >= 3.25 ? '-halffull' : '-empty') ?>
+ <?= Icon::create("star{$v}", Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <? $v = $material->rating >= 4.75 ? '' : ($material->rating >= 4.25 ? '-halffull' : '-empty') ?>
+ <?= Icon::create("star{$v}", Icon::ROLE_INFO)->asImg($starwidth) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <a href="<?= $controller->statistics($material) ?>" data-dialog="size=auto">
+ <?= OERDownloadcounter::countBySQL('material_id = ?', [$material->id]) ?>
+ </a>
+ </td>
+ <td class="actions">
+ <? if ($material->isMine()) : ?>
+ <a href="<?= $controller->edit($material) ?>" data-dialog
+ title="<?= _('Lernmaterial bearbeiten') ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE)->asImg(20) ?>
+ </a>
+ <form action="<?= $controller->delete($material) ?>"
+ class="inlineform"
+ method="post"
+ data-confirm="<?= _('Dieses Material wirklich löschen?') ?>">
+ <?= Icon::create("trash", Icon::ROLE_CLICKABLE)->asInput(20) ?>
+ </form>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/oer/mymaterial/edit.php b/app/views/oer/mymaterial/edit.php
new file mode 100755
index 0000000..5b20618
--- /dev/null
+++ b/app/views/oer/mymaterial/edit.php
@@ -0,0 +1,276 @@
+<form action="<?= $controller->edit($material->isNew() ? '' : $material) ?>"
+ method="post"
+ class="default"
+ onsubmit="$(window).off('beforeunload')"
+ data-secure
+ enctype="multipart/form-data">
+
+ <div class="oercampus_editmaterial">
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+
+ <label>
+ <?= _('Name') ?>
+ <input type="text"
+ name="data[name]"
+ class="oername"
+ value="<?= htmlReady($material['name'] ?: $template['name']) ?>"
+ @keyup="editName"
+ maxlength="64">
+ </label>
+
+
+ <div>
+ <?= _('Vorschau') ?>
+ </div>
+
+ <div class="hgroup" @drop.prevent="dropImage">
+ <label for="oer_logo_uploader">
+ <article class="contentbox" :title="name">
+ <header>
+ <h1>
+ <studip-icon shape="file"
+ role="clickable"
+ size="20"
+ class="text-bottom"></studip-icon>
+ {{ name }}
+ </h1>
+ </header>
+ <div class="image"
+ :style="'background-image: url(' + logo_url + ');' + (!customlogo ? ' background-size: 60% auto;': '')"></div>
+ </article>
+ </label>
+
+ <div>
+ <label class="file-upload logo_file"
+ data-oldurl="<?= htmlReady($_SESSION['NEW_OER']['image_tmp_name'] ? URLHelper::getURL("dispatch.php/oer/mymaterial/show_tmp_image") : $material->getLogoURL()) ?>"
+ data-customlogo="<?= $_SESSION['NEW_OER']['image_tmp_name'] || $material['front_image_content_type'] ? 1 : 0 ?>">
+ <?= _('Vorschau-Bilddatei (optional)') ?>
+ <input type="file"
+ name="image"
+ id="oer_logo_uploader"
+ accept="image/*"
+ @change="editImage">
+ </label>
+
+ <? if ($material['front_image_content_type']) : ?>
+ <label>
+ <input type="checkbox" name="delete_front_image" value="1">
+ <?= _('Logo löschen') ?>
+ </label>
+ <? endif ?>
+ </div>
+
+ </div>
+
+
+
+
+ <? if (!$_SESSION['NEW_OER']['tmp_name']) : ?>
+ <label class="file drag-and-drop"
+ data-filename="<?= htmlReady($material['filename']) ?>"
+ data-filesize="<?= htmlReady(!$material->isNew() ? filesize($material->getFilePath()) : "") ?>"
+ @drop.prevent="dropFile">
+ <?= _('Datei (gerne auch eine ZIP-Datei) auswählen') ?>
+ <input type="file" name="file" id="oer_file" @change="editFile">
+ <div v-if="filename">
+ <span>{{ filename }}</span>
+ <span>{{ filesize }}</span>
+ </div>
+ </label>
+ <? endif ?>
+
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea
+ name="data[description]"><?= htmlReady($material['description'] ?: $template['description']) ?></textarea>
+ </label>
+
+ <label>
+ <input type="hidden" name="data[draft]" value="0">
+ <input type="checkbox" name="data[draft]" value="1"<?= $material['draft'] ? " checked" : "" ?>>
+ <?= _('Entwurf (nicht veröffentlicht)') ?>
+ </label>
+
+ <label>
+ <?= _('Kategorie') ?>
+ <select name="data[category]">
+ <? if ($material->isNew()) : ?>
+ <option value="auto"><?= _('Automatisch erkennen') ?></option>
+ <? endif ?>
+ <option value="audio"<?= $material['category'] === "audio" ? " selected" : "" ?>>
+ <?= _('Audio') ?>
+ </option>
+ <option value="video"<?= $material['category'] === "video" ? " selected" : "" ?>>
+ <?= _('Video') ?>
+ </option>
+ <option value="presentation"<?= $material['category'] === "presentation" ? " selected" : "" ?>>
+ <?= _('Folien') ?>
+ </option>
+ <option value="elearning"<?= $material['category'] === "elearning" ? " selected" : "" ?>>
+ <?= _('Lernmodule') ?>
+ </option>
+ <option value=""<?= !$material['category'] && !$material->isNew() ? " selected" : "" ?>
+ title="<?= _('Fehlt eine Kategorie? Kein Problem, arbeiten Sie stattdessen mit Schlagwörtern. Die sind viel flexibler.') ?>">
+ <?= _('Ohne Kategorie') ?>
+ </option>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Vorschau-URL (optional)') ?>
+ <input type="text" name="data[player_url]"
+ value="<?= htmlReady($material['player_url'] ?: $template['player_url']) ?>">
+ </label>
+
+ <? if (!$material->isNew()) : ?>
+ <div>
+ <h4><?= _('Autoren') ?></h4>
+ <ul class="clean autoren<?= count($material->users) > 1 ? " multiple" : "" ?>">
+ <? foreach ($material->users as $materialuser) : ?>
+ <li>
+ <? if ($materialuser['external_contact']) : ?>
+ <? $user = $materialuser['oeruser'] ?>
+ <? $image = $user['avatar'] ?>
+ <label>
+ <? if (count($material->users) > 1) : ?>
+ <input type="checkbox" name="remove_users[]"
+ value="1_<?= htmlReady($user->getId()) ?>">
+ <? endif ?>
+ <div>
+ <span class="avatar" style="background-image: url('<?= $image ?>');"></span>
+ <span class="author_name">
+ <?= htmlReady($user['name']) ?>
+ </span>
+ <? if (count($material->users) > 1) : ?>
+ <?= Icon::create('trash')->asImg(16, ['class' => "text-bottom", 'title' => _('Person als Autor entfernen.')]) ?>
+ <? endif ?>
+ </div>
+ </label>
+ <? else : ?>
+ <? $user = User::find($materialuser['user_id']) ?>
+ <? $image = Avatar::getAvatar($materialuser['user_id'])->getURL(Avatar::SMALL) ?>
+ <label>
+ <? if (count($material->users) > 1) : ?>
+ <input type="checkbox" name="remove_users[]"
+ value="0_<?= htmlReady($user->getId()) ?>">
+ <? endif ?>
+ <div>
+ <span class="avatar" style="background-image: url('<?= $image ?>');"></span>
+ <span class="author_name">
+ <?= htmlReady($user ? $user->getFullName() : _('unbekannt')) ?>
+ </span>
+ <? if (count($material->users) > 1) : ?>
+ <?= Icon::create('trash')->asImg(['class' => "text-bottom", 'title' => _('Person als Autor/Autorin entfernen.')]) ?>
+ <? endif ?>
+ </div>
+ </label>
+ <? endif ?>
+ </li>
+ <? endforeach ?>
+ <li>
+ <quicksearch name="new_user"
+ searchtype="<?= htmlReady($usersearch) ?>"
+ placeholder="<?= _('Person hinzufügen') ?>"></quicksearch>
+ </li>
+ </ul>
+ </div>
+ <? endif ?>
+
+
+ <div class="oer_tags_container">
+ <?= _('Themen (am besten mindestens 5)') ?>
+ <?
+ $tags = [];
+ foreach ($material->getTopics() as $tag) {
+ $tags[] = $tag['name'];
+ }
+ foreach ((array) $template['tags'] as $tag) {
+ $tags[] = $tag;
+ }
+ ?>
+
+ <ul class="clean oer_tags" data-defaulttags="<?= htmlReady(json_encode($tags)) ?>">
+ <li v-for="(tag, index) in displayTags" :key="index">
+ #
+ <quicksearch name="tags[]"
+ searchtype="<?= htmlReady($tagsearch) ?>"
+ v-model="tags[index]"
+ :autocomplete="true"
+ ></quicksearch>
+ <a href="#"
+ @click.prevent="removeTag(index)"
+ title="<?= _('Thema aus der Liste streichen') ?>">
+ <studip-icon shape="trash" role="clickable" size="20" class="text-bottom"></studip-icon>
+ </a>
+
+ </li>
+ </ul>
+ <a href="#" @click.prevent="addTag">
+ <studip-icon shape="add" role="clickable" size="20" class="text-bottom"></studip-icon>
+ <?= _('Thema hinzufügen') ?>
+ </a>
+ </div>
+
+ <div style="margin-top: 13px; max-width: 682px;">
+ <?= _('Niveau') ?>
+
+ <input type="hidden" id="difficulty_start" name="data[difficulty_start]"
+ value="<?= htmlReady($material['difficulty_start']) ?>">
+ <input type="hidden" id="difficulty_end" name="data[difficulty_end]"
+ value="<?= htmlReady($material['difficulty_end']) ?>">
+
+ <div style="display: flex; justify-content: space-between; font-size: 0.8em; color: grey;">
+ <div><?= _('Leicht') ?></div>
+ <div><?= _('Schwer') ?></div>
+ </div>
+ <div style="display: flex; justify-content: space-between;">
+ <? for ($i = 1; $i <= 12; $i++) : ?>
+ <div><?= ($i < 10 ? "&nbsp;" : "") . $i ?></div>
+ <? endfor ?>
+ </div>
+ <div id="difficulty_slider_edit" style="margin-left: 5px; margin-right: 9px;"></div>
+ </div>
+
+ <? if ($template['module_id']) : ?>
+ <input type="hidden"
+ name="module_id"
+ value="<?= htmlReady($template['module_id']) ?>">
+ <? endif ?>
+
+ </fieldset>
+
+ <? if (!Config::get()->OER_DISABLE_LICENSE) : ?>
+ <? $license = $material->isNew()
+ ? License::findDefault()
+ : $material->license;
+ ?>
+ <fieldset class="oer_license_selector">
+ <legend><?= _('Lizenz') ?></legend>
+ <?=
+ _('Ich erkläre mich bereit, dass meine Lernmaterialien unter der angegebenen Lizenz an alle Nutzenden freigegeben werden. Ich bestätige zudem, dass ich das Recht habe, diese Dateien frei zu veröffentlichen, weil entweder ich selbst sie angefertigt habe, oder sie von anderen Quellen mit kompatibler Lizenz stammen.')
+ ?>
+
+ <div>
+ <select class="licenses_selector" name="data[license_identifier]">
+ <? foreach (License::findBySQL("1 ORDER BY name ASC") as $l) : ?>
+ <option value="<?= htmlReady($l->id) ?>" <?= $l->id === $license->id ? " selected" : "" ?>>
+ <?= htmlReady($l['name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </div>
+ </fieldset>
+
+ <? endif ?>
+ <? if ($template['redirect_url']) : ?>
+ <input type="hidden"
+ name="redirect_url"
+ value="<?= htmlReady($template['redirect_url']) ?>">
+ <? endif ?>
+ </div>
+
+ <div data-dialog-button>
+ <?= \Studip\Button::create($material->isNew() ? _('Hochladen') : _('Speichern'), "save") ?>
+ </div>
+</form>
diff --git a/app/views/oer/mymaterial/index.php b/app/views/oer/mymaterial/index.php
new file mode 100755
index 0000000..b512047
--- /dev/null
+++ b/app/views/oer/mymaterial/index.php
@@ -0,0 +1,5 @@
+<? if (empty($materialien)) : ?>
+ <?= MessageBox::info(_('Es wurden noch keine Materialien bereitgestellt.')) ?>
+<? else : ?>
+ <?= $this->render_partial("oer/mymaterial/_material_list.php") ?>
+<? endif ?>
diff --git a/app/views/oer/mymaterial/statistics.php b/app/views/oer/mymaterial/statistics.php
new file mode 100644
index 0000000..7b4d6fa
--- /dev/null
+++ b/app/views/oer/mymaterial/statistics.php
@@ -0,0 +1,20 @@
+<table class="default nohover">
+ <tbody>
+ <tr>
+ <td><?= _('Gesamtzugriffe') ?></td>
+ <td><?= htmlReady($counter) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Heute') ?></td>
+ <td><?= htmlReady($counter_today) ?></td>
+ </tr>
+ </tbody>
+</table>
+
+
+<div data-dialog-button>
+ <?= \Studip\LinkButton::create(
+ _('Exportieren'),
+ $controller->statisticsURL($material, ['export' => 1])
+ ) ?>
+</div>
diff --git a/app/views/oer/oai/badPrefix.php b/app/views/oer/oai/badPrefix.php
new file mode 100755
index 0000000..a86d4a1
--- /dev/null
+++ b/app/views/oer/oai/badPrefix.php
@@ -0,0 +1,9 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?= htmlReady($currentDate) ?></responseDate>
+ <request verb=<?='"'.htmlReady($verb).'"' ?>><?= htmlReady($request_url) ?></request>
+ <error code="badPrefix">Illegal metadata prefix</error>
+</OAI-PMH> \ No newline at end of file
diff --git a/app/views/oer/oai/badVerb.php b/app/views/oer/oai/badVerb.php
new file mode 100755
index 0000000..16f5f6c
--- /dev/null
+++ b/app/views/oer/oai/badVerb.php
@@ -0,0 +1,9 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?= htmlReady($currentDate) ?></responseDate>
+ <request verb=<?='"'.htmlReady($verb).'"' ?>><?= htmlReady($request_url) ?></request>
+ <error code="badVerb">Illegal OAI verb</error>
+</OAI-PMH>
diff --git a/app/views/oer/oai/getRecord.php b/app/views/oer/oai/getRecord.php
new file mode 100755
index 0000000..72f48d2
--- /dev/null
+++ b/app/views/oer/oai/getRecord.php
@@ -0,0 +1,97 @@
+<?= '<?xml version="1.0" encoding="UTF-8" ?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?=htmlReady($currentDate) ?></responseDate>
+ <request verb=<?='"'.htmlReady($verb).'"' ?> from=<?= '"'.htmlReady($currentDate).'"' ?> metadataPrefix=<?= '"'.htmlReady($metadataPrefix).'"'?>><?=htmlReady($request_url)?></request>
+ <GetRecord>
+ <record>
+ <header>
+ <identifier><?=htmlReady($targetMaterial->id)?></identifier>
+ <datestamp><?= htmlReady(gmdate(DATE_ATOM, $targetMaterial->mkdate))?></datestamp>
+ <? foreach ($tags as $tag) : ?>
+ <setSpec><?= htmlReady($tag['name']) ?></setSpec>
+ <? endforeach ?>
+ </header>
+ <metadata>
+ <lom xmlns="http://ltsc.ieee.org/xsd/LOM"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ltsc.ieee.org/xsd/LOM
+ http://ltsc.ieee.org/xsd/lomv1.0/lom.xsd">
+ <general>
+ <identifier>
+ <? foreach ($tags as $tag) : ?>
+ <catalog><?= htmlReady($tag['name']) ?></catalog>
+ <? endforeach ?>
+ <entry><?=htmlReady($targetMaterial->id)?></entry>
+ </identifier>
+ <title>
+ <string language="de"><?= htmlReady($targetMaterial->name) ?></string>
+ </title>
+ <language>de</language>
+ <description>
+ <string language="de"><?= htmlReady($targetMaterial->description) ?></string>
+ </description>
+ <keyword>
+ <? foreach ($tags as $tag) : ?>
+ <string language="de"><?= htmlReady($tag['name']) ?></string>
+ <? endforeach ?>
+ </keyword>
+
+ </general>
+
+ <lifeCycle>
+ <version>
+ <string language="de">1.0</string>
+ </version>
+ <contribute>
+ <role>
+ <source>LOMv1.0</source>
+ <value>Author</value>
+ </role>
+ <entity>
+ <?= htmlReady($vcard) ?>
+ </entity>
+ <date>
+ <dateTime><?= htmlReady(gmdate(DATE_ATOM, $targetMaterial->chdate)) ?></dateTime>
+ </date>
+ </contribute>
+ </lifeCycle>
+
+ <technical>
+ <format><?= htmlReady($targetMaterial->content_type) ?></format>
+ <location><?= $controller->url_for("market/download/".$targetMaterial->id) ?></location>
+
+ </technical>
+
+ <educational>
+ <learningResourceType>
+ <source>LREv3.0</source>
+ <value><?= htmlReady($targetMaterial->content_type) ?></value>
+ </learningResourceType>
+
+ <intendedEndUserRole>
+ <source>LREv3.0</source>
+ <value>students</value>
+ </intendedEndUserRole>
+ <context>
+ <source>LREv3.0</source>
+ <value>highschool education</value>
+ </context>
+ </educational>
+
+ <rights>
+ <copyrightAndOtherRestrictions>
+ <source>LOMv1.0</source>
+ <value>yes</value>
+ </copyrightAndOtherRestrictions>
+ <description>
+ <string language="xt-lic"><?= htmlReady($targetMaterial->license) ?></string>
+ </description>
+ </rights>
+ </lom>
+ </metadata>
+ </record>
+ </GetRecord>
+</OAI-PMH> \ No newline at end of file
diff --git a/app/views/oer/oai/idNotExists.php b/app/views/oer/oai/idNotExists.php
new file mode 100755
index 0000000..62b2002
--- /dev/null
+++ b/app/views/oer/oai/idNotExists.php
@@ -0,0 +1,9 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?= htmlReady($currentDate) ?></responseDate>
+ <request verb=<?='"'.htmlReady($verb).'"' ?>><?= htmlReady($request_url) ?></request>
+ <error code="idDoesNotExist">RecordId does not exists.</error>
+</OAI-PMH>
diff --git a/app/views/oer/oai/identify.php b/app/views/oer/oai/identify.php
new file mode 100755
index 0000000..f7cd037
--- /dev/null
+++ b/app/views/oer/oai/identify.php
@@ -0,0 +1,20 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?= $currentDate ?></responseDate>
+ <request verb=<?='"'.$verb.'"' ?>><?=htmlReady($request_url) ?></request>
+
+ <Identify>
+ <repositoryName><?= _('Lernmaterialien vom StudIP-Lernmarktplatz - Unter Angabe von folgenden Materialgruppen erhalten Sie frei zugängliche Materialien.') ?></repositoryName>
+ <baseURL><?= $controller->link_for("oer/oai/") ?></baseURL>
+
+ <protocolVersion>2.0</protocolVersion>
+ <adminEmail><?= htmlReady($GLOBALS['UNI_CONTACT']) ?></adminEmail>
+ <earliestDatestamp><?= htmlReady($earliest_stamp) ?></earliestDatestamp>
+ <deletedRecord>no</deletedRecord>
+ <granularity>YYYY-MM-DDThh:mm:ssZ</granularity>
+ <compression>deflate</compression>
+ </Identify>
+</OAI-PMH>
diff --git a/app/views/oer/oai/listIdentifiers.php b/app/views/oer/oai/listIdentifiers.php
new file mode 100755
index 0000000..4718c60
--- /dev/null
+++ b/app/views/oer/oai/listIdentifiers.php
@@ -0,0 +1,43 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?= htmlReady($currentDate) ?></responseDate>
+ <? if ($set): ?>
+ <request verb=<?='"'.$verb.'"' ?> from=<?= '"'.$currentDate.'"' ?>
+ metadataPrefix=<?= '"'.$metadataPrefix.'"' ?> set=<?= '"'.$set.'"' ?>>
+ <?=htmlReady($request_url)?>
+ </request>
+ <ListIdentifiers>
+ <? foreach ($records as $key=>$record) : ?>
+ <header>
+ <identifier><?= htmlReady($record->id)?></identifier>
+ <datestamp> <?= htmlReady($record->mkdate)?> </datestamp>
+ <? foreach ($tag_collection[$key] as $tag) : ?>
+ <setSpec> <?= htmlReady($tag) ?> </setSpec>
+ <? endforeach ?>
+ </header>
+ <? endforeach ?>
+
+ </ListIdentifiers>
+ <? else: ?>
+ <request verb=<?='"'.$verb.'"' ?> from=<?= '"'.$currentDate.'"' ?>
+ metadataPrefix=<?= '"'.$metadataPrefix.'"' ?>>
+ <?= htmlReady($request_url) ?>
+ </request>
+ <ListIdentifiers>
+
+ <? foreach ($records as $key=>$record) : ?>
+ <header>
+ <identifier><?= htmlReady($record->id)?></identifier>
+ <datestamp> <?= htmlReady($record->mkdate)?> </datestamp>
+ <? foreach ($tag_collection[$key] as $tag) : ?>
+ <setSpec> <?= htmlReady($tag) ?> </setSpec>
+ <? endforeach ?>
+ </header>
+ <? endforeach ?>
+ <? endif ?>
+ </ListIdentifiers>
+
+</OAI-PMH> \ No newline at end of file
diff --git a/app/views/oer/oai/listMetadataFormats.php b/app/views/oer/oai/listMetadataFormats.php
new file mode 100755
index 0000000..c4226e2
--- /dev/null
+++ b/app/views/oer/oai/listMetadataFormats.php
@@ -0,0 +1,28 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><? htmlReady($currentDate) ?></responseDate>
+ <? if ($identifier): ?>
+ <request verb=<?='"'.$verb.'"' ?>
+ identifier=<?= '"'.$identifier.'"'?>>
+ <?= htmlReady($request_url) ?>
+ </request>
+ <? else: ?>
+ <request verb=<?='"'.$verb.'"' ?>>
+ <?= htmlReady($request_url) ?>
+ </request>
+ <? endif ?>
+ <ListMetadataFormats>
+
+ <metadataFormat>
+ <metadataPrefix>oai_lom-de</metadataPrefix>
+ <schema>http://ltsc.ieee.org/xsd/LOM
+ </schema>
+ <metadataNamespace>http://www.w3.org/2001/XMLSchema-instance
+ </metadataNamespace>
+ </metadataFormat>
+
+ </ListMetadataFormats>
+</OAI-PMH>
diff --git a/app/views/oer/oai/listRecords.php b/app/views/oer/oai/listRecords.php
new file mode 100755
index 0000000..5abab37
--- /dev/null
+++ b/app/views/oer/oai/listRecords.php
@@ -0,0 +1,105 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?= htmlReady($currentDate) ?></responseDate>
+ <? if ($set): ?>
+ <request verb=<?='"'.$verb.'"' ?> from=<?= '"'.$currentDate.'"' ?>
+ metadataPrefix=<?= '"'.$metadataPrefix.'"' ?> set=<?= '"'.$set.'"' ?>>
+ <?= htmlReady($request_url) ?>
+ </request>
+ <? else: ?>
+ <request verb=<?='"'.$verb.'"' ?> from=<?= '"'.$currentDate.'"' ?>
+ identifier=<?= '"'.$metadataPrefix.'"' ?>>
+ <?= htmlReady($request_url) ?>
+ </request>
+ <? endif ?>
+ <ListRecords>
+ <? foreach ($records as $key => $targetMaterial) : ?>
+ <record>
+ <header>
+ <identifier><?=htmlReady($targetMaterial->id)?></identifier>
+ <datestamp><?= gmdate(DATE_ATOM, $targetMaterial->mkdate)?></datestamp>
+ <? foreach ($tag_collection[$key] as $tag) : ?>
+ <setSpec> <?= htmlReady($tag) ?> </setSpec>
+ <? endforeach ?>
+
+
+ </header>
+ <metadata>
+
+ <lom xmlns="http://ltsc.ieee.org/xsd/LOM"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ltsc.ieee.org/xsd/LOM
+ http://ltsc.ieee.org/xsd/lomv1.0/lom.xsd">
+ <general>
+ <identifier>
+ <? foreach ($tag_collection[$key] as $tag) : ?>
+ <catalog><?= htmlReady($tag) ?></catalog>
+ <? endforeach ?>
+
+ <entry><?=htmlReady($targetMaterial->id)?></entry>
+ </identifier>
+ <title>
+ <string language="de"><?= htmlReady($targetMaterial->name) ?></string>
+ </title>
+ <language>de</language>
+ <description>
+ <string language="de"><?= htmlReady($targetMaterial->description) ?></string>
+ </description>
+ <keyword>
+ <? foreach ($tag_collection[$key] as $tag) : ?>
+ <string language="de"><?= htmlReady($tag) ?></string>
+ <? endforeach ?>
+ </keyword>
+
+ </general>
+
+ <lifeCycle>
+ <version>
+ <string language="de">1.0</string>
+ </version>
+ <contribute>
+ <role>
+ <source>LOMv1.0</source>
+ <value>Author</value>
+ </role>
+ <entity>
+ <?= htmlReady($vcards[$key]) ?>
+ </entity>
+ <date>
+ <dateTime><?= gmdate(DATE_ATOM, $targetMaterial->chdate) ?></dateTime>
+ </date>
+ </contribute>
+ </lifeCycle>
+
+ <technical>
+ <format><?= htmlReady($targetMaterial->content_type) ?></format>
+ <location><?= $controller->url_for("market/download/".$targetMaterial->id) ?></location>
+ </technical>
+
+ <educational>
+ <learningResourceType>
+ <source>LREv3.0</source>
+ <value><?= htmlReady($targetMaterial->content_type) ?></value>
+ </learningResourceType>
+ </educational>
+
+ <rights>
+ <copyrightAndOtherRestrictions>
+ <source>LOMv1.0</source>
+ <value>yes</value>
+ </copyrightAndOtherRestrictions>
+ <description>
+ <string language="xt-lic"><?= htmlReady($targetMaterial->license) ?></string>
+ </description>
+ </rights>
+
+ </lom>
+ </metadata>
+ </record>
+ <? endforeach ?>
+
+ </ListRecords>
+</OAI-PMH> \ No newline at end of file
diff --git a/app/views/oer/oai/listSets.php b/app/views/oer/oai/listSets.php
new file mode 100755
index 0000000..b0a1cd3
--- /dev/null
+++ b/app/views/oer/oai/listSets.php
@@ -0,0 +1,17 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?=htmlReady($currentDate)?></responseDate>
+ <request verb=<?='"'.$verb.'"' ?>><?= htmlReady($request_url) ?></request>
+ <ListSets>
+ <? foreach ($tags as $tag) : ?>
+ <set>
+ <setSpec><?= htmlReady($tag->id) ?></setSpec>
+ <setName><?= htmlReady($tag->name) ?></setName>
+ </set>
+<? endforeach ?>
+
+ </ListSets>
+</OAI-PMH> \ No newline at end of file
diff --git a/app/views/oer/oai/noRecordsMatch.php b/app/views/oer/oai/noRecordsMatch.php
new file mode 100755
index 0000000..d778170
--- /dev/null
+++ b/app/views/oer/oai/noRecordsMatch.php
@@ -0,0 +1,10 @@
+
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?= htmlReady($currentDate) ?></responseDate>
+ <request verb=<?='"'.htmlReady($verb).'"' ?>><?= htmlReady($request_url) ?></request>
+ <error code="noRecordsMatch">No Records found.</error>
+</OAI-PMH> \ No newline at end of file
diff --git a/app/views/oer/oai/noSets.php b/app/views/oer/oai/noSets.php
new file mode 100755
index 0000000..bd1a13a
--- /dev/null
+++ b/app/views/oer/oai/noSets.php
@@ -0,0 +1,9 @@
+<?= '<?xml version="1.0" encoding="UTF-8"?>' ?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/
+ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+ <responseDate><?= htmlReady($currentDate) ?></responseDate>
+ <request verb=<?= '"'.htmlReady($verb).'"' ?>><?= htmlReady($request_url) ?></request>
+ <error code="noSetHierarchy">No sets found</error>
+</OAI-PMH>
diff --git a/app/views/online/index.php b/app/views/online/index.php
new file mode 100644
index 0000000..0c1dd81
--- /dev/null
+++ b/app/views/online/index.php
@@ -0,0 +1,128 @@
+<div class="online-list">
+ <div id="online_contacts">
+ <table class="default">
+ <caption>
+ <?= _('Kontakte') ?>
+ </caption>
+ <colgroup>
+ <col width="<?= reset(Avatar::getDimension(Avatar::SMALL)) ?>px">
+ <col>
+ <col>
+ <col width="1%">
+ </colgroup>
+ <? if (count($users['buddies']) > 0): ?>
+ <thead>
+ <tr>
+ <th colspan="2"><?= _('Name') ?></th>
+ <th><?= _('Letztes Lebenszeichen') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $last_group = false;
+ foreach ($users['buddies'] as $buddy):
+ ?>
+ <? if ($showGroups && $last_group !== $buddy['group']): ?>
+ <tr>
+ <th colspan="4">
+ <a href="<?= $controller->link_for('contact/index/' . ($buddy['group_id'] != 'all' ? $buddy['group_id'] : '')) ?>"
+ class="link-intern" style="color: #000;">
+ <?= htmlReady($buddy['group']) ?>
+ </a>
+ </th>
+ </tr>
+ <? $last_group = $buddy['group'];
+ endif;
+ ?>
+ <?= $this->render_partial('online/user-row', ['user' => $buddy]) ?>
+ <? endforeach; ?>
+ </tbody>
+ <? else: ?>
+ <? if ($contact_count === 0): ?>
+ <tbody>
+ <tr>
+ <td colspan="4">
+ <?= _('Sie haben keine Kontakte ausgewählt.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? elseif (count($users['buddies']) === 0): ?>
+ <tbody>
+ <tr>
+ <td colspan="4">
+ <?= _('Es sind keine Ihrer Kontakte online.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif; ?>
+ <? endif; ?>
+ <tfoot>
+ <tr>
+ <td colspan="4">
+ <? printf(_('Zum Adressbuch (%u Einträge) klicken Sie %shier%s.'),
+ $contact_count,
+ '<a href="' . $controller->link_for('contact') . '">', '</a>') ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <? if (!$showOnlyBuddies): ?>
+ <div id="online_buddies">
+ <table class="default">
+ <caption>
+ <?= _('Andere NutzerInnen') ?>
+ <? if ($users['others'] > 0): ?>
+ <small>
+ (<?= sprintf(_('+ %u unsichtbare NutzerInnen'), $users['others']) ?>)
+ </small>
+ <? endif; ?>
+ </caption>
+ <colgroup>
+ <col width="<?= reset(Avatar::getDimension(Avatar::SMALL)) ?>px">
+ <col>
+ <col>
+ <col width="1%">
+ </colgroup>
+ <? if (count($users['users']) > 0): ?>
+ <thead>
+ <tr>
+ <th colspan="2"><?= _('Name') ?></th>
+ <th><?= _('Letztes Lebenszeichen') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach (array_slice($users['users'], $page * $limit, $limit) as $user): ?>
+ <?= $this->render_partial('online/user-row', compact('user')) ?>
+ <? endforeach; ?>
+ </tbody>
+ <? elseif ($users['others'] > 0): ?>
+ <tbody>
+ <tr>
+ <td colspan="4">
+ <?= _('Keine sichtbaren Nutzer online.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? else: ?>
+ <tbody>
+ <tr>
+ <td colspan="4">
+ <?= _('Kein anderer Nutzer ist online.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif; ?>
+ <tfoot>
+ <tr>
+ <td colspan="4" class="actions">
+ <?= Pagination::create(count($users['users']), $page, $limit)->asLinks() ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+ <? endif; ?>
+</div>
diff --git a/app/views/online/user-row.php b/app/views/online/user-row.php
new file mode 100644
index 0000000..9bc417d
--- /dev/null
+++ b/app/views/online/user-row.php
@@ -0,0 +1,52 @@
+<tr>
+ <td>
+ <a href="<?= $controller->url_for('profile?username=' . $user['username']) ?>">
+ <?= Avatar::getAvatar($user['user_id'], $user['username'])->getImageTag(Avatar::SMALL, [
+ 'title' => $user['name']
+ ]) ?>
+ </a>
+ </td>
+ <td>
+ <a href="<?= $controller->url_for('profile?username=' . $user['username']) ?>">
+ <?= htmlReady($user['name']) ?>
+ </a>
+ <? foreach (StudipKing::is_king($user['user_id'], true) as $text) : ?>
+ <?= Icon::create('crown', 'sort', ['title' => $text]) ?>
+ <? endforeach ?>
+ </td>
+ <td style="white-space: nowrap;">
+ <?= ucfirst(reltime(time() - $user['last_action'])) ?>
+ </td>
+ <td class="actions" nowrap="nowrap">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (Config::get()->BLUBBER_GLOBAL_MESSENGER_ACTIVATE) : ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/blubber/write_to/'.$user['user_id']),
+ _('Blubber diesen Nutzer an'),
+ Icon::create('blubber'),
+ ['data-dialog' => '']
+ ) ?>
+ <? endif ?>
+ <? $actionMenu->addLink(
+ URLHelper::getURL('dispatch.php/messages/write', ['rec_uname' => $user['username']]),
+ _('Nachricht an Benutzer verschicken'),
+ Icon::create('mail', 'clickable'),
+ ['data-dialog' => 'size=50%']
+ ) ?>
+
+ <? if ($user['is_buddy']): ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('online/buddy/remove?username=' . $user['username']),
+ _('Aus den Kontakten entfernen'),
+ Icon::create('person+remove', 'clickable')
+ ) ?>
+ <? else: ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('online/buddy/add?username=' . $user['username']),
+ _('Zu den Kontakten hinzufügen'),
+ Icon::create('person+add', 'clickable')
+ ) ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </td>
+</tr>
diff --git a/app/views/privacy/index.php b/app/views/privacy/index.php
new file mode 100644
index 0000000..7f2b0e2
--- /dev/null
+++ b/app/views/privacy/index.php
@@ -0,0 +1,54 @@
+<? if (empty($plugin_data) || empty(reset($plugin_data))): ?>
+ <?= MessageBox::info(_('In dieser Kategorie sind keine Daten vorhanden.')) ?>
+<? endif; ?>
+
+<? foreach ($plugin_data as $label => $tabledata) : ?>
+ <? if ($tabledata['table_content']) : ?>
+ <article class="studip toggle <? if (!Request::isDialog() && $section) echo 'open'; ?>">
+ <header>
+ <h1>
+ <a>
+ <?= htmlReady($label) ?>,
+ <?= sprintf(_('%u Einträge'), count($tabledata['table_content'])) ?>
+ </a>
+ </h1>
+ <? if (Request::isDialog()) : ?>
+ <a href="<?= $controller->link_for("privacy/export2csv/{$tabledata['table_name']}/{$user_id}") ?>">
+ <strong><?= htmlReady($label) ?> CSV</strong>
+ </a>
+ <? endif; ?>
+ </header>
+ <section>
+ <table class="default">
+ <thead>
+ <tr>
+ <? foreach (array_keys($tabledata['table_content'][0]) as $caption) : ?>
+ <th><?= htmlReady($caption) ?></th>
+ <? endforeach; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($tabledata['table_content'] as $row) : ?>
+ <tr>
+ <? foreach ($row as $key => $value): ?>
+ <td>
+ <?= htmlReady($value) ?>
+ </td>
+ <? endforeach; ?>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ </section>
+ </article>
+
+ <? endif; ?>
+<? endforeach; ?>
+
+<div data-dialog-button>
+<? if (Request::isDialog()): ?>
+ <?= Studip\LinkButton::create(_('Zurück'), $controller->url_for("privacy/landing/{$user_id}"), ['data-dialog' => 'size=medium']); ?>
+<? else: ?>
+ <?= Studip\LinkButton::create(_('Zurück'), $controller->url_for("privacy/landing/{$user_id}")); ?>
+<? endif; ?>
+</div>
diff --git a/app/views/privacy/landing.php b/app/views/privacy/landing.php
new file mode 100644
index 0000000..3382b99
--- /dev/null
+++ b/app/views/privacy/landing.php
@@ -0,0 +1,22 @@
+<ul class="boxed-grid">
+<? foreach ($sections as $key => $row): ?>
+ <li>
+ <a href="<?= $controller->link_for("privacy/index/{$user_id}/{$key}") ?>" <? if (Request::isDialog()) echo 'data-dialog="size=big"'; ?>>
+ <h3>
+ <?= $row['icon']->asImg(false) ?>
+ <?= htmlReady($row['title']) ?>
+ </h3>
+ <p>
+ <?= htmlReady($row['description']) ?>
+ </p>
+ </a>
+ </li>
+<? endforeach; ?>
+
+<!--
+ this is pretty ugly but we need to spawn some empty elements so that the
+ last row of the flex grid won't be messed up if the boxes don't line up
+-->
+ <li></li><li></li><li></li>
+ <li></li><li></li><li></li>
+</ul>
diff --git a/app/views/privacy/print.php b/app/views/privacy/print.php
new file mode 100644
index 0000000..968c86b
--- /dev/null
+++ b/app/views/privacy/print.php
@@ -0,0 +1,25 @@
+<h1><?= sprintf(_('Personenbezogene Daten von %s'), htmlReady($user_fullname)); ?></h1>
+<? foreach ($plugin_data as $label => $tabledata) : ?>
+ <? if ($tabledata['table_content']) : ?>
+ <h3><?= htmlReady($label) ?></h3>
+ <? foreach ($tabledata['table_content'] as $row) : ?>
+ <table border="1">
+ <tbody>
+ <? foreach ($row as $key => $value) : ?>
+ <tr>
+ <th><?= htmlReady($key) ?></th>
+ <td>
+ <? if ($tabledata['table_name'] === 'log_events' && $key === 'readable_entry') : ?>
+ <?= $value ?>
+ <? else: ?>
+ <?= htmlReady($value) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ <br>
+ <? endforeach; ?>
+ <? endif; ?>
+<? endforeach; ?>
diff --git a/app/views/profile/extern.php b/app/views/profile/extern.php
new file mode 100644
index 0000000..9524837
--- /dev/null
+++ b/app/views/profile/extern.php
@@ -0,0 +1,16 @@
+<div class="responsive-visible">
+ <img src="<?= htmlReady($user['avatar_url'] ?: Avatar::getNobody()->getURL(Avatar::NORMAL)) ?>">
+</div>
+
+<? if (Config::get()->OERCAMPUS_ENABLED && $user['data']['description']) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _('Beschreibung für den OER Campus') ?></h1>
+ </header>
+ <section>
+ <?= nl2br(htmlReady($user['data']['description'])) ?>
+ </section>
+ </article>
+<? endif ?>
+<?
+
diff --git a/app/views/profile/index.php b/app/views/profile/index.php
new file mode 100644
index 0000000..e14dbec
--- /dev/null
+++ b/app/views/profile/index.php
@@ -0,0 +1,150 @@
+<div class="responsive-visible">
+ <?= Avatar::getAvatar($current_user->user_id)->getImageTag(Avatar::NORMAL) ?>
+</div>
+<section class="contentbox">
+ <header>
+ <h1>
+ <?= _('Allgemeine Informationen') ?>
+ </h1>
+ </header>
+ <section>
+ <dl>
+ <? if ($public_email): ?>
+ <dt><?= _('E-Mail') ?>:</dt>
+ <dd>
+ <a href="mailto:<?= htmlReady($public_email) ?>">
+ <?= htmlReady($public_email) ?>
+ </a>
+ </dd>
+ <? endif; ?>
+
+ <? if ($private_nr) : ?>
+ <dt><?= _('Telefon (privat)') ?>:</dt>
+ <dd><?= htmlReady($private_nr) ?></dd>
+ <? endif ?>
+
+ <? if ($private_cell) : ?>
+ <dt><?= _('Mobiltelefon') ?>:</dt>
+ <dd><?= htmlReady($private_cell) ?></dd>
+ <? endif ?>
+
+ <? if ($skype_name) : ?>
+ <dt><?= _('Skype') ?>:</dt>
+ <dd><?= htmlReady($skype_name) ?></dd>
+ <? endif ?>
+
+ <? if ($privadr) : ?>
+ <dt><?= _('Adresse (privat)') ?>:</dt>
+ <dd><?= htmlReady($privadr) ?></dd>
+ <? endif ?>
+
+ <? if ($homepage) : ?>
+ <dt><?= _('Homepage') ?>:</dt>
+ <dd><?= formatLinks($homepage) ?></dd>
+ <? endif ?>
+
+ <? if (count($study_institutes) > 0): ?>
+ <dt><?= _('Wo ich studiere') ?>:</dt>
+ <dd>
+ <ul>
+ <? foreach ($study_institutes as $inst_result) : ?>
+ <li>
+ <a href="<?= $controller->link_for('institute/overview', ['auswahl' => $inst_result->institut_id]) ?>">
+ <?= htmlReady($inst_result->institute->name) ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </dd>
+ <? endif ?>
+
+ <? if (count($institutes) > 0) : ?>
+ <?= $this->render_partial('profile/working_place') ?>
+ <? endif ?>
+
+ <? if ($current_user->user_id === $GLOBALS['user']->id) : ?>
+ <dt><?= _('Status') ?>:</dt>
+ <dd><?= htmlReady(ucfirst($current_user['perms'])) ?></dd>
+ <? endif ?>
+
+ <? if (!empty($shortDatafields)) : ?>
+ <? foreach ($shortDatafields as $name => $entry) : ?>
+ <dt><?= htmlReady($name) ?>:</dt>
+ <dd>
+ <?= $entry['content'] ?>
+ <span class="minor"><?= $entry['visible'] ?></span>
+ </dd>
+ <? endforeach ?>
+ <? endif ?>
+ </dl>
+ </section>
+
+</section>
+
+<?= $news ?>
+
+<?= $dates ?>
+
+<?= $evaluations ?>
+
+<?= $questionnaires ?>
+
+<? if (!empty($ausgabe_inhalt)) : ?>
+ <? foreach ($ausgabe_inhalt as $key => $inhalt) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= htmlReady($key) ?></h1>
+ </header>
+ <section>
+ <?= formatReady($inhalt) ?>
+ </section>
+ </article>
+ <? endforeach ?>
+<? endif ?>
+
+<? if (isset($public_files)) : ?>
+ <?= $this->render_partial('profile/public_files') ?>
+<? endif ?>
+
+<? if ($current_user['perms'] === 'dozent' && !empty($seminare)) : ?>
+ <?= $this->render_partial('profile/seminare') ?>
+<? endif ?>
+
+<? if ($show_lit && $lit_list) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= _('Literaturlisten') ?></h1>
+ </header>
+ <section>
+ <?= $lit_list ?>
+ </section>
+ </article>
+<? endif ?>
+
+<? if (!empty($longDatafields)) : ?>
+ <? foreach ($longDatafields as $name => $entry) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= htmlReady($name . ' ' . $entry['visible']) ?></h1>
+ </header>
+ <section>
+ <?= $entry['content'] ?>
+ </section>
+ </article>
+ <? endforeach ?>
+<? endif ?>
+
+<?= $hompage_plugin ?>
+
+<? if (!empty($categories)) : ?>
+ <? foreach ($categories as $cat) : ?>
+ <article class="studip">
+ <header>
+ <h1><?= htmlReady($cat['head'] . $cat['zusatz']) ?></h1>
+ </header>
+ <section>
+ <?= formatReady($cat['content']) ?>
+ </section>
+ </article>
+ <? endforeach ?>
+<? endif; ?>
diff --git a/app/views/profile/not_available.php b/app/views/profile/not_available.php
new file mode 100644
index 0000000..b4e8fb1
--- /dev/null
+++ b/app/views/profile/not_available.php
@@ -0,0 +1,4 @@
+<?= MessageBox::error(
+ _('Dieses Profil ist nicht verfügbar.'),
+ [_('Der Benutzer hat sich unsichtbar geschaltet oder ist im System nicht vorhanden.')]
+)->hideClose() ?>
diff --git a/app/views/profile/public_files.php b/app/views/profile/public_files.php
new file mode 100644
index 0000000..eb87b1a
--- /dev/null
+++ b/app/views/profile/public_files.php
@@ -0,0 +1,42 @@
+<article class="studip">
+ <header>
+ <h1>
+ <?= _('Freigegebene Dateien') ?>
+ </h1>
+ </header>
+
+ <section>
+ <? $folder = current($public_folders); ?>
+ <form method="post" action="<?= $controller->link_for('file/bulk/' . $folder->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default sortable-table documents" data-sortlist="[[2, 0]]">
+ <?= $this->render_partial('files/_files_thead', ['show_bulk_checkboxes' => true]) ?>
+ <? foreach ($public_files as $file): ?>
+ <? if ($file->isVisible($GLOBALS['user']->id)) : ?>
+ <?= $this->render_partial(
+ 'files/_fileref_tr',
+ [
+ 'file' => $file,
+ 'current_folder' => $public_folders[$file->getFolderType()->getId()],
+ 'last_visitdate' => time(),
+ 'show_bulk_checkboxes' => true
+ ]
+ ) ?>
+ <? endif ?>
+ <? endforeach ?>
+ <tfoot>
+ <tr>
+ <td colspan="7">
+ <span class="multibuttons">
+ <?= Studip\Button::create(_('Herunterladen'), 'download', [
+ 'data-activates-condition' => 'table.documents tr[data-permissions*=d] :checkbox:checked'
+ ]) ?>
+ <?= Studip\Button::create(_('Kopieren'), 'copy', ['data-dialog' => '']) ?>
+ </span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </form>
+ </section>
+</article>
diff --git a/app/views/profile/seminare.php b/app/views/profile/seminare.php
new file mode 100644
index 0000000..acb6714
--- /dev/null
+++ b/app/views/profile/seminare.php
@@ -0,0 +1,22 @@
+<article class="studip">
+ <header>
+ <h1>
+ <?= _('Veranstaltungen') ?>
+ </h1>
+ </header>
+
+ <section>
+ <? foreach ($seminare as $semester => $seminar) :?>
+ <b><?= htmlReady($semester) ?></b><br>
+
+ <? foreach ($seminar as $one) :?>
+ <a href="<?= URLHelper::getScriptLink('dispatch.php/course/details', ['sem_id' => $one->id])?>">
+ <?= htmlReady($one->getFullname('number-name')) ?>
+ <? if ($one->start_semester !== $one->end_semester) : ?>
+ (<?= htmlReady($one->getFullname('sem-duration-name')) ?>)
+ <? endif ?>
+ </a><br>
+ <?endforeach?>
+ <?endforeach?>
+ </section>
+</article> \ No newline at end of file
diff --git a/app/views/profile/widget-avatar.php b/app/views/profile/widget-avatar.php
new file mode 100644
index 0000000..e10ccf0
--- /dev/null
+++ b/app/views/profile/widget-avatar.php
@@ -0,0 +1,34 @@
+<div class="text-center avatar-widget">
+ <?= $avatar->getImageTag(Avatar::NORMAL, [
+ 'class' => 'profile-avatar',
+ 'style' => ''
+ ]) ?>
+ <?php if ($GLOBALS['perm']->have_profile_perm('user', $current_user)) : ?>
+ <div class="avatar-overlay" id="avatar-overlay"
+ accept="image/gif,image/png,image/jpeg" capture="camera"
+ data-max-size="<?= Avatar::MAX_FILE_SIZE ?>"
+ data-message-too-large="<?= _('Die hochgeladene Datei ist zu groß. Bitte wählen Sie ein anderes Bild.') ?>"
+ data-message-unaccepted="<?= _('Die hochgeladene Datei hat falsche Typ. Bitte wählen Sie ein anderes Bild.') ?>">
+ <a href="<?= URLHelper::getURL('dispatch.php/avatar/update/user/' . $current_user) ?>" data-dialog>
+ <span><?= _('Bild hochladen oder löschen.') ?> <br> <?= _('Drag & Drop oder Klicken') ?></span>
+ </a>
+ </div>
+ <?php endif ?>
+</div>
+<div class="profile-sidebar-details">
+ <? if ($kings): ?>
+ <div><?= $kings ?></div>
+ <? endif; ?>
+ <div class="minor">
+ <?= _('Profilbesuche:') ?>
+ <?= number_format($views, 0, ',', '.') ?>
+ </div>
+ <? if ($score && $score_title): ?>
+ <div class="minor">
+ <a href="<?= URLHelper::getLink('dispatch.php/score') ?>" title="<?= _('Zur Rangliste') ?>">
+ <div><?= _('Stud.IP-Punkte') ?>: <?= number_format($score, 0, ',', '.') ?></div>
+ <div><?= _('Rang') ?>: <?= htmlReady($score_title) ?></div>
+ </a>
+ </div>
+ <? endif; ?>
+</div>
diff --git a/app/views/profile/working_place.php b/app/views/profile/working_place.php
new file mode 100644
index 0000000..20df958
--- /dev/null
+++ b/app/views/profile/working_place.php
@@ -0,0 +1,45 @@
+<?php
+$fields = [
+ 'raum' => _('Raum'),
+ 'sprechzeiten' => _('Sprechzeit'),
+ 'telefon' => _('Telefon'),
+ 'fax' => _('Fax'),
+];
+?>
+
+<dt><?= _('Wo ich arbeite:') ?></dt>
+<dd>
+ <ul>
+ <? foreach ($institutes as $institute): ?>
+ <li>
+ <a href="<?= $controller->link_for('institute/overview', ['auswahl' => $institute['institut_id']]) ?>">
+ <?= htmlReady($institute['institute_name']) ?>
+ </a>
+
+ <? foreach ($fields as $key => $label): ?>
+ <? if ($institute[$key]): ?>
+ <br>
+ <strong><?= htmlReady($label) ?>:</strong>
+ <?= htmlReady($institute[$key]) ?>
+ <? endif; ?>
+ <? endforeach; ?>
+
+ <? if (!empty($institute['datafield'])): ?>
+ <? foreach ($institute['datafield'] as $datafield): ?>
+ <br>
+ <strong><?= htmlReady($datafield['name']) ?>:</strong>
+ <?= $datafield['value'] ?>
+ <? if ($datafield['show_star']): ?>*<? endif; ?>
+ <? endforeach; ?>
+ <? endif; ?>
+
+ <? if (!empty($institute['role'])): ?>
+ <table cellpadding="0" cellspacing="0" border="0">
+ <?= $institute['role'] ?>
+ </table>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+
+</dd>
diff --git a/app/views/profile_modules/index.php b/app/views/profile_modules/index.php
new file mode 100644
index 0000000..4e49495
--- /dev/null
+++ b/app/views/profile_modules/index.php
@@ -0,0 +1,102 @@
+<form action="<?= $controller->url_for('profilemodules/update', compact('username')) ?>" method="post" class="default plus">
+ <?= CSRFProtection::tokenTag() ?>
+
+<? foreach ($list as $category => $pluginlist): ?>
+ <article class="studip">
+ <header>
+ <h1><?= htmlReady($category) ?></h1>
+ </header>
+ <? foreach ($pluginlist as $id => $item): ?>
+ <section>
+ <div class="plus_basic">
+
+ <div class="element_header">
+ <input type="hidden" name="modules[<?= htmlReady($id) ?>]" value="0">
+ <input type="checkbox" value="1" class="studip-checkbox"
+ id="<?= md5($item['name']) ?>" name="modules[<?= htmlReady($id) ?>]"
+ onclick="jQuery(this).closest('form').submit()"
+ <? if ($item['activated']) echo 'checked'; ?>>
+
+ <label for="<?= md5($item['name']) ?>">
+ <strong><?= htmlReady($item['name']) ?></strong>
+ </label>
+ </div>
+
+ <div class="element_description">
+ <? if ($item['icon']): ?>
+ <?= $item['icon']->asImg(['class' => 'plugin_icon text-bottom']) ?>
+ <? endif ?>
+
+ <strong class="shortdesc">
+ <?= htmlReady($item['abstract']) ?>
+ </strong>
+ </div>
+ </div>
+
+ <? if ($config['view'] === 'openall'): ?>
+ <div class="plus_expert">
+ <div class="screenshot_holder">
+ <? if ($item['screenshots']): ?>
+ <a href="<?= htmlReady($item['screenshots'][0]['source']) ?>"
+ data-lightbox="<?= htmlReady($item['name']) ?>"
+ data-title="<?= htmlReady($item['screenshots'][0]['title']) ?>">
+ <img class="big_thumb" src="<?= htmlReady($item['screenshots'][0]['source']) ?>"
+ alt="<?= htmlReady($item['name']) ?>">
+ </a>
+
+ <? if (count($item['screenshots']) > 1): ?>
+ <div class="thumb_holder">
+ <? foreach (array_slice($item['screenshots'], 1) as $shot): ?>
+ <a href="<?= htmlReady($shot['source']) ?>"
+ data-lightbox="<?= htmlReady($item['name']) ?>"
+ data-title="<?= htmlReady($shot['title']) ?>">
+ <img class="small_thumb"
+ src="<?= htmlReady($shot['source']) ?>"
+ alt="<?= htmlReady($item['name']) ?>">
+ </a>
+
+ <? endforeach; ?>
+ </div>
+ <? endif; ?>
+ <? endif ?>
+ </div>
+
+ <div class="descriptionbox">
+ <? if ($item['keywords']): ?>
+ <ul class="keywords">
+ <? foreach ($item['keywords'] as $keyword): ?>
+ <li><?= htmlReady($keyword) ?></li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+
+ <p class="longdesc">
+ <?= htmlReady($item['description']) ?: _('Keine Beschreibung vorhanden.') ?>
+ </p>
+
+ <? if ($item['homepage']): ?>
+ <p>
+ <strong><?= _('Weitere Informationen:') ?></strong>
+ <a href="<?= htmlReady($item['homepage']) ?>">
+ <?= htmlReady($item['homepage']) ?>
+ </a>
+ </p>
+ <? endif; ?>
+
+ <? if ($item['helplink']): ?>
+ <a class="helplink" href="<?= htmlReady($item['helplink']) ?> ">
+ <?= _('...mehr') ?>
+ </a>
+ <? endif; ?>
+ </div>
+ </div>
+ <? endif; ?>
+ </section>
+ <? endforeach; ?>
+ </article>
+<? endforeach; ?>
+
+ <footer class="hidden-js">
+ <?= Studip\Button::create(_('An- / Ausschalten'), 'uebernehmen') ?>
+ </footer>
+</form>
diff --git a/app/views/public_courses/index.php b/app/views/public_courses/index.php
new file mode 100644
index 0000000..5054383
--- /dev/null
+++ b/app/views/public_courses/index.php
@@ -0,0 +1,78 @@
+<blockquote>
+ <p>
+ <?= _('Die folgenden Veranstaltungen können Sie betreten, ohne '
+ .'sich im System registriert zu haben.') ?>
+ </p>
+ <p>
+ <?= sprintf(_('In den %s blau markierten Veranstaltungen dürfen '
+ .'Sie nur lesen und Dokumente herunterladen.'),
+ '<span class="gruppe6">&nbsp;&nbsp;</span>') ?>
+ <br>
+ <?= sprintf(_('In den %s orange markierten Veranstaltungen '
+ .'können Sie sich zusätzlich mit eigenen Beiträgen '
+ .'im Forum beteiligen.'),
+ '<span class="gruppe2">&nbsp;&nbsp;</span>') ?>
+ </p>
+ <p>
+ <?= _('In der rechten Spalte können Sie sehen, was in den '
+ .'einzelnen Veranstaltungen an Inhalten vorhanden ist.') ?>
+ </p>
+</blockquote>
+
+<? if (empty($seminars)): ?>
+ <?= MessageBox::info(_('Es gibt keine Veranstaltungen, die einen freien Zugriff erlauben!'))?>
+<? else: ?>
+<table class="default">
+ <colgroup>
+ <col width="1em">
+ <col>
+ <col>
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>&nbsp;</th>
+ <th><a href="<?= URLHelper::getLink('?sortby=Name') ?>"><?= _('Name') ?></a></th>
+ <th><a href="<?= URLHelper::getLink('?sortby=status') ?>"><?=_ ('Veranstaltungstyp') ?></a></th>
+ <th><a href="<?= URLHelper::getLink('?sortby=Institut') ?>"><?= _('Einrichtung') ?></a></th>
+ <th><?= _('Inhalt') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($seminars as $id => $values): ?>
+ <tr>
+ <td class="<?= $values['Schreibzugriff'] ? 'gruppe6' : 'gruppe2' ?>">&nbsp;</td>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php?auswahl=' . $id) ?>">
+ <?= htmlReady($values['name']) ?>
+ </a>
+ </td>
+ <td><?= htmlReady($GLOBALS['SEM_TYPE'][$values['status']]['name']) ?></td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/institute/overview?auswahl=' . $values['id']) ?>">
+ <?= htmlReady($values['Institut']) ?>
+ </a>
+ </td>
+ <td style="white-space: nowrap;">
+ <? foreach ($values['navigations'] as $navigation): ?>
+ <? if (is_object($navigation) && $navigation->isVisible(true)): ?>
+ <?
+ $badge = '';
+ if ($navigation->hasBadgeNumber()) {
+ $badge = ' class="badge" data-badge-number="' . intval($navigation->getBadgeNumber()) . '"';
+ }
+ ?>
+ <a href="<?= URLHelper::getLink('seminar_main.php?auswahl='. $id . '&redirect_to=' . str_replace('?', '&', $navigation->getURL())) ?>"<?= $badge ?>>
+ <?= $navigation->getImageTag() ?>
+ </a>
+ <? else: ?>
+ <?= Assets::img('blank.gif', ['width' => 16, 'height' => 16]) ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+<? endif; ?>
diff --git a/app/views/questionnaire/_overview_questionnaire.php b/app/views/questionnaire/_overview_questionnaire.php
new file mode 100644
index 0000000..dc166a0
--- /dev/null
+++ b/app/views/questionnaire/_overview_questionnaire.php
@@ -0,0 +1,130 @@
+<tr id="questionnaire_<?= $questionnaire->id ?>">
+ <td>
+ <input type="checkbox" name="q[]" value="<?= htmlReady($questionnaire->id) ?>">
+ </td>
+ <td>
+ <a href="<?= $controller->link_for('questionnaire/answer/' . $questionnaire->id) ?>" data-dialog>
+ <?= htmlReady($questionnaire['title']) ?>
+ </a>
+ <span>
+ <?
+ $icons = [];
+ foreach ($questionnaire->questions as $question) {
+ $class = get_class($question);
+ $icons[$class] = $class::getIcon();
+ }
+ foreach ($icons as $class => $icon) {
+ echo $icon->asImg(16, ['class' => 'text-bottom', 'title' => $class::getName()])." ";
+ }
+ ?>
+ </span>
+ </td>
+ <td>
+ <? if ($questionnaire['startdate']): ?>
+ <?= date('d.m.Y H:i', $questionnaire['startdate']) ?>
+ <? else: ?>
+ <?= _('händisch') ?>
+ <? endif; ?>
+ </td>
+ <td>
+ <? if ($questionnaire['stopdate']): ?>
+ <?= date('d.m.Y H:i', $questionnaire['stopdate']) ?>
+ <? else: ?>
+ <?= _('händisch') ?>
+ <? endif; ?>
+ </td>
+ <td class="context">
+ <? if (count($questionnaire->assignments) > 0) : ?>
+ <ul class="clean">
+ <? foreach ($questionnaire->assignments as $assignment) : ?>
+ <li>
+ <? if ($assignment['range_id'] === 'start') : ?>
+ <?= _('Stud.IP Startseite')?>
+ <? elseif ($assignment['range_id'] === 'public') : ?>
+ <?= _('Öffentlich per Link')?>
+ <? endif ?>
+
+ <? if ($assignment['range_type'] === 'user') : ?>
+ <?= _('Profilseite')?>
+ <? elseif ($assignment['range_type'] === 'course') : ?>
+ <?= htmlReady(Course::find($assignment['range_id'])->name) ?>
+ <? elseif ($assignment['range_type'] === 'statusgruppe') : ?>
+ <? $statusgruppe = Statusgruppen::find($assignment['range_id']) ?>
+ <? if ($statusgruppe) : ?>
+ <?= $statusgruppe->course ? htmlReady($statusgruppe->course->name).":" : "" ?>
+ <?= $statusgruppe->institute ? htmlReady($statusgruppe->institute->name).":" : "" ?>
+ <?= htmlReady($statusgruppe->name) ?>
+ <? endif ?>
+ <? elseif ($assignment['range_type'] === 'institute') : ?>
+ <?= htmlReady(Institute::find($assignment['range_id'])->name) ?>
+ <? elseif ($assignment['range_type'] === 'plugin') : ?>
+ <?= htmlReady(Institute::find($assignment['range_id'])->name) ?>
+ <? else : ?>
+ <?
+ foreach (PluginManager::getInstance()->getPlugins("QuestionnaireAssignmentPlugin") as $plugin) {
+ $name = $plugin->getQuestionnaireAssignmentName($assignment);
+ if ($name) {
+ echo htmlReady($name);
+ }
+ }
+ ?>
+ <? endif ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? else : ?>
+ <?= _('Nirgendwo') ?>
+ <? endif ?>
+ </td>
+ <td>
+ <? $countedAnswers = $questionnaire->countAnswers() ?>
+ <?= htmlReady($countedAnswers) ?>
+ </td>
+ <td class="actions">
+ <? if ($questionnaire->isRunning() && $countedAnswers) : ?>
+ <?= Icon::create('edit', 'inactive')->asImg(20, ['title' => _('Der Fragebogen wurde gestartet und kann nicht mehr bearbeitet werden.')]) ?>
+ <? else : ?>
+ <a href="<?= $controller->link_for('questionnaire/edit/' . $questionnaire->id) ?>" data-dialog title="<?= _('Fragebogen bearbeiten') ?>">
+ <?= Icon::create('edit', 'clickable')->asImg(20) ?>
+ </a>
+ <? endif ?>
+ <a href="<?= $controller->link_for('questionnaire/context/' . $questionnaire->id) ?>" data-dialog title="<?= _('Zuweisungen bearbeiten') ?>">
+ <?= Icon::create('group2', 'clickable')->asImg(20) ?>
+ </a>
+
+ <?
+ $menu = ActionMenu::get();
+ if ($questionnaire->isRunning()) {
+ $menu->addLink(
+ $controller->url_for('questionnaire/stop/' . $questionnaire->id, in_array($range_type, ['course', 'institute']) ? ['redirect' => 'questionnaire/courseoverview'] : []),
+ _('Fragebogen beenden'),
+ Icon::create('pause', 'clickable')
+ );
+ } else {
+ $menu->addLink(
+ $controller->url_for('questionnaire/start/' .$questionnaire->id, in_array($range_type, ['course', 'institute']) ? ['redirect' => 'questionnaire/courseoverview'] : []),
+ _('Fragebogen starten'),
+ Icon::create('play', 'clickable')
+ );
+ }
+ $menu->addLink(
+ $controller->url_for('questionnaire/evaluate/' .$questionnaire->id),
+ _('Auswertung'),
+ Icon::create('stat', 'clickable'),
+ ['data-dialog' => '']
+ );
+ $menu->addLink(
+ $controller->url_for('questionnaire/export/' .$questionnaire->id),
+ _('Export als CSV'),
+ Icon::create('file-excel', 'clickable')
+ );
+ $menu->addLink(
+ $controller->url_for('questionnaire/delete/' .$questionnaire->id),
+ _('Fragebogen löschen'),
+ Icon::create('trash', 'clickable'),
+ ['data-confirm' => _('Wirklich löschen?')]
+ );
+ echo $menu->render();
+ ?>
+ </td>
+</tr>
diff --git a/app/views/questionnaire/_question.php b/app/views/questionnaire/_question.php
new file mode 100644
index 0000000..44b5612
--- /dev/null
+++ b/app/views/questionnaire/_question.php
@@ -0,0 +1,28 @@
+<? $class = get_class($question) ?>
+<fieldset data-questiontype="<?= htmlReady($class) ?>"
+ class="question <?= htmlReady(mb_strtolower($class)) ?>">
+ <legend>
+ <div style="float: right; padding-top: 3px; padding-right: 5px;">
+ <a href="#" class="move_up" title="<?= _("Frage nach oben verschieben") ?>"
+ onClick="STUDIP.Questionnaire.moveQuestionUp.call(this); return false;">
+ <?= Icon::create("arr_1up", "clickable")->asImg("20px", ['class' => "text-bottom"]) ?>
+ </a>
+ <a href="#" class="move_down" title="<?= _("Frage nach unten verschieben") ?>"
+ onClick="STUDIP.Questionnaire.moveQuestionDown.call(this); return false;">
+ <?= Icon::create("arr_1down", "clickable")->asImg("20px", ['class' => "text-bottom"]) ?>
+ </a>
+ <a href="#" onClick="var that = this; STUDIP.Dialog.confirm('<?= _("Wirklich löschen?") ?>', function () { jQuery(that).closest('fieldset').remove(); }); return false;"
+ title="<?= sprintf(_("%s löschen"), htmlReady($class::getName())) ?>">
+ <?= Icon::create("trash", "clickable")->asImg("20px", ['class' => "text-bottom"]) ?>
+ </a>
+ </div>
+ <div>
+ <?= $class::getIcon()->asImg("20px", ['class' => "text-bottom"]) ?>
+ <?= htmlReady($class::getName()) ?>
+ </div>
+
+ </legend>
+ <input type="hidden" name="neworder[]" value="<?= htmlReady($question->getId()) ?>">
+ <input type="hidden" name="question_types[<?= htmlReady($question->getId()) ?>]" value="<?= htmlReady(get_class($question)) ?>">
+ <?= $question->getEditingTemplate()->render() ?>
+</fieldset>
diff --git a/app/views/questionnaire/_widget_questionnaire.php b/app/views/questionnaire/_widget_questionnaire.php
new file mode 100644
index 0000000..111fed9
--- /dev/null
+++ b/app/views/questionnaire/_widget_questionnaire.php
@@ -0,0 +1,55 @@
+<article class="studip toggle <?= ContentBoxHelper::classes($questionnaire->id, $is_new) ?> widget_questionnaire_<?= $questionnaire->getId() ?>" data-questionnaire_id="<?= htmlReady($questionnaire->getId()) ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::switchhref($questionnaire->id, ['contentbox_type' => 'vote']) ?>">
+ <?= htmlReady($questionnaire->title) ?>
+ <?
+ $additional_context = [];
+ foreach ($questionnaire->assignments as $assignment) {
+ if ($assignment->range_type === "statusgruppe") {
+ $additional_context[] = Statusgruppen::find($assignment->range_id)->name;
+ }
+ }
+ if (count($additional_context) > 0) {
+ $additional_context = implode(", ", $additional_context);
+ if (mb_strlen($additional_context) > 65) {
+ $additional_context = mb_substr($additional_context, 0, 60)." ...";
+ }
+ echo "(".htmlReady($additional_context).")";
+ }
+ ?>
+ </a>
+ </h1>
+ <nav>
+ <a href="<?= $questionnaire->user_id ? URLHelper::getLink('dispatch.php/profile', ['username' => get_username($questionnaire->user_id)]) : '' ?>">
+ <?= $questionnaire->user_id ? htmlReady(get_fullname($questionnaire->user_id)) : '' ?>
+ </a>
+ <span>
+ <?= strftime("%d.%m.%Y", $questionnaire->mkdate) ?>
+ </span>
+ <span title="<?= _("Anzahl der Antworten") ?>">
+ <?= $questionnaire->countAnswers() ?>
+ </span>
+ <span title="<?= _("QR-Code zu diesem Fragebogen anzeigen") ?>">
+ <? $oldbase = URLHelper::setBaseURL($GLOBALS['ABSOLUTE_URI_STUDIP']) ?>
+ <a href="<?=
+ URLHelper::getLink(
+ "dispatch.php/questionnaire/answer/".$questionnaire->getId(),
+ compact('range_type', 'range_id')
+ ) ?>"
+ class="questionnaire-qr"
+ data-qr-code>
+ <? URLHelper::setBaseURL($oldbase) ?>
+ <?= Icon::create("code-qr", "clickable")->asImg(20, ['class' => "text-bottom"]) ?>
+ </a>
+ </span>
+ </nav>
+ </header>
+ <section>
+ <? if ($questionnaire->isAnswered() || $questionnaire->isStopped() || !$questionnaire->isAnswerable()) : ?>
+ <?= $this->render_partial('questionnaire/evaluate.php', ['questionnaire' => $questionnaire, 'range_type' => $range_type, 'range_id' => $range_id]); ?>
+ <? else : ?>
+ <?= $this->render_partial('questionnaire/answer.php', ['questionnaire' => $questionnaire, 'range_type' => $range_type, 'range_id' => $range_id]); ?>
+ <? endif ?>
+ </section>
+</article>
diff --git a/app/views/questionnaire/add_to_context.php b/app/views/questionnaire/add_to_context.php
new file mode 100644
index 0000000..7e2e5e7
--- /dev/null
+++ b/app/views/questionnaire/add_to_context.php
@@ -0,0 +1,23 @@
+<?
+$icons = [
+ 'user' => "person",
+ 'course' => "seminar",
+ 'institute' => "institute"
+];
+?>
+<div class="file_select_possibilities">
+ <div>
+ <a href="<?= $controller->link_for("questionnaire/edit", ['range_type' => Context::getType(), 'range_id' => Context::get()->id]) ?>"
+ data-dialog>
+ <?= Icon::create($icons[Context::getType()], Icon::ROLE_CLICKABLE)->asImg(50) ?>
+ <?= htmlReady(Context::get()->name) ?>
+ </a>
+ <? foreach ($statusgruppen as $statusgruppe) : ?>
+ <a href="<?= $controller->link_for("questionnaire/edit", ['range_type' => "statusgruppe", 'range_id' => $statusgruppe->getId()]) ?>"
+ data-dialog>
+ <?= Icon::create('group2', Icon::ROLE_CLICKABLE)->asImg(50) ?>
+ <?= htmlReady($statusgruppe->name) ?>
+ </a>
+ <? endforeach ?>
+ </div>
+</div>
diff --git a/app/views/questionnaire/answer.php b/app/views/questionnaire/answer.php
new file mode 100644
index 0000000..a4468a6
--- /dev/null
+++ b/app/views/questionnaire/answer.php
@@ -0,0 +1,62 @@
+<form
+ action="<?= URLHelper::getLink("dispatch.php/questionnaire/submit/".$questionnaire->getId()) ?>"
+ method="post"
+ enctype="multipart/form-data"
+ class="default questionnaire"
+ <? if (Request::isAjax()) : ?>
+ data-dialog
+ <? endif ?>
+ >
+ <? if ($range_type && $range_id) : ?>
+ <input type="hidden" name="range_type" value="<?= htmlReady($range_type) ?>">
+ <input type="hidden" name="range_id" value="<?= htmlReady($range_id) ?>">
+ <? endif ?>
+ <div class="questionnaire_answer">
+ <? foreach ($questionnaire->questions as $question) : ?>
+ <? $template = $question->getDisplayTemplate() ?>
+ <? if ($template) : ?>
+ <article data-question_type="<?= htmlReady(get_class($question)) ?>">
+ <?= $template->render() ?>
+ </article>
+ <? endif ?>
+ <? endforeach ?>
+ </div>
+
+ <div class="terms">
+ <? if ($questionnaire['anonymous']) : ?>
+ <?= _("Die Teilnahme ist anonym.") ?>
+ <? else : ?>
+ <?= _("Die Teilnahme ist nicht anonym.") ?>
+ <? endif ?>
+ <? if ($questionnaire['editanswers']) : ?>
+ <?= _("Sie können Ihre Antworten nachträglich ändern.") ?>
+ <? endif ?>
+ <? if ($questionnaire['stopdate']) : ?>
+ <?= sprintf(_("Sie können den Fragebogen beantworten bis zum %s um %s Uhr."), date("d.m.Y", $questionnaire['stopdate']), date("H:i", $questionnaire['stopdate'])) ?>
+ <? endif ?>
+ </div>
+
+ <div data-dialog-button style="text-align: center;">
+ <? if ($questionnaire->isAnswerable()) : ?>
+ <?= \Studip\Button::create(_("Speichern"), 'questionnaire_answer', ['onClick' => "return STUDIP.Questionnaire.beforeAnswer.call(this);"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->resultsVisible()) : ?>
+ <?= \Studip\LinkButton::create(_("Ergebnisse anzeigen"), URLHelper::getURL("dispatch.php/questionnaire/evaluate/".$questionnaire->getId()), ['data-dialog' => "1"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable() && (!$questionnaire->isRunning() || !$questionnaire->countAnswers())) : ?>
+ <?= \Studip\LinkButton::create(_("Bearbeiten"), URLHelper::getURL("dispatch.php/questionnaire/edit/".$questionnaire->getId()), ['data-dialog' => "1"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable()) : ?>
+ <?= \Studip\LinkButton::create(_("Kontext auswählen"), URLHelper::getURL("dispatch.php/questionnaire/context/".$questionnaire->getId(), ['range_type' => $range_type, 'range_id' => $range_id]), ['data-dialog' => "1"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->isCopyable()) : ?>
+ <?= \Studip\LinkButton::create(_("Kopieren"), URLHelper::getURL("dispatch.php/questionnaire/copy/".$questionnaire->getId()), ['data-dialog' => "1"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable() && (!$questionnaire->isRunning())) : ?>
+ <?= \Studip\LinkButton::create(_("Starten"), URLHelper::getURL("dispatch.php/questionnaire/start/".$questionnaire->getId(), in_array($range_type, ['course', 'insitute']) ? ['redirect' => $range_type . "/overview"] : [])) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable() && $questionnaire->isRunning()) : ?>
+ <?= \Studip\LinkButton::create(_("Beenden"), URLHelper::getURL("dispatch.php/questionnaire/stop/".$questionnaire->getId(), in_array($range_type, ['course', 'insitute']) ? ['redirect' => $range_type . "/overview"] : [])) ?>
+ <? endif ?>
+ </div>
+</form>
diff --git a/app/views/questionnaire/assign.php b/app/views/questionnaire/assign.php
new file mode 100644
index 0000000..4bf7fc5
--- /dev/null
+++ b/app/views/questionnaire/assign.php
@@ -0,0 +1,82 @@
+<form class="default" method="post" id="questionnaire-assign-form"
+ action="<?= $controller->link_for('questionnaire/assign') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($step == 0): ?>
+ <article class="studip">
+ <header><h1><?= _('Veranstaltungen suchen') ?></h1></header>
+ <section>
+ <label>
+ <?= _('Semester') ?>
+ <select name="semester_id">
+ <? foreach ($available_semesters as $available_semester): ?>
+ <option value="<?= htmlReady($available_semester->id) ?>"
+ <?= ($available_semester->id == $semester_id)
+ ? 'selected="selected"'
+ : ''
+ ?>>
+ <?= htmlReady($available_semester->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Einrichtung') ?>
+ (<?= _('optional') ?>)
+ <select name="institute_id">
+ <option value=""
+ <?= ($institute_id == '' ? 'selected="selected"' : '') ?>>
+ <?= _('(bitte wählen)') ?>
+ </option>
+ <? foreach ($available_institutes as $available_institute): ?>
+ <option value="<?= htmlReady($available_institute['Institut_id']) ?>"
+ <?= ($available_institute['Institut_id'] == $institute_id)
+ ? 'selected="selected"'
+ : ''
+ ?>>
+ <?= htmlReady($available_institute['Name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Veranstaltungstyp') ?>
+ (<?= _('optional') ?>)
+ <select name="course_type_id">
+ <option value=""
+ <?= ($course_type_id == '' ? 'selected="selected"' : '') ?>>
+ <?= dgettext('AskALotPlugin', '(bitte wählen)') ?>
+ </option>
+ <? foreach ($available_course_types as $available_course_type): ?>
+ <option value="<?= htmlReady($available_course_type['id']) ?>"
+ <?= ($available_course_type['id'] == $course_type_id)
+ ? 'selected="selected"'
+ : ''
+ ?>>
+ <?= htmlReady($available_course_type['name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <?= \Studip\Button::create(_('Suchen'), 'search_courses') ?>
+ </section>
+ </article>
+ <? elseif ($step == 1): ?>
+ <?= $this->render_partial('questionnaire/assign_step1') ?>
+ <? elseif ($step == 2): ?>
+ <?= $this->render_partial('questionnaire/assign_step2') ?>
+ <? elseif ($step == 3): ?>
+
+ <? endif ?>
+ <? if ($step >= 1): ?>
+ <input type="hidden" name="semester_id" value="<?= htmlReady($semester_id) ?>">
+ <input type="hidden" name="institute_id" value="<?= htmlReady($institute_id) ?>">
+ <input type="hidden" name="course_type_id" value="<?= htmlReady($course_type_id) ?>">
+ <? endif ?>
+ <? if ($step >= 2): ?>
+ <? if ($selected_courses): ?>
+ <? foreach ($selected_courses as $course): ?>
+ <input type="hidden" name="course_id_list[]" value="<?= htmlReady($course->id) ?>">
+ <? endforeach ?>
+ <? endif ?>
+ <? endif ?>
+</form>
diff --git a/app/views/questionnaire/assign_step1.php b/app/views/questionnaire/assign_step1.php
new file mode 100644
index 0000000..7904c82
--- /dev/null
+++ b/app/views/questionnaire/assign_step1.php
@@ -0,0 +1,70 @@
+<article class="studip">
+ <header><h1><?= _('Gefundene Veranstaltungen') ?></h1></header>
+ <section>
+ <? if ($found_courses): ?>
+ <table class="default">
+ <colgroup>
+ <col width="30px">
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" data-proxyfor=".FoundCourseListItem"
+ id="AskALotPlugin_course_select_proxy"
+ data-proxyfor="input[name='course_id_list[]']"
+ data-activates="#questionnaire_assign_step1_button">
+ </th>
+ <th><?= dgettext('AskALotPlugin', 'Veranstaltung') ?></th>
+ <th><?= dgettext('AskALotPlugin', 'Lehrende') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($found_courses as $found_course): ?>
+ <? $teachers = CourseMember::findByCourseAndStatus(
+ $found_course->id,
+ 'dozent'
+ );
+ $teacher_arr = [];
+ foreach ($teachers as $teacher) {
+ $teacher_arr[] = $teacher->getUserFullName();
+ } ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="course_id_list[]"
+ class="FoundCourseListItem"
+ value="<?= htmlReady($found_course->id) ?>">
+ </td>
+ <td>
+ <a href="<?= $controller->link_for(
+ 'course/details',
+ ['cid' => $found_course->id]
+ ) ?>" data-dialog="1">
+ <?= htmlReady($found_course->getFullName()) ?>
+ </a>
+ </td>
+ <td><?= htmlReady(implode(', ', $teacher_arr)) ?></td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <?= \Studip\Button::create(
+ _('Auswählen'),
+ 'select_courses',
+ [
+ 'id' => 'questionnaire_assign_step1_button',
+ 'disabled' => 'disabled'
+ ]
+ ) ?>
+ <? else: ?>
+ <?= MessageBox::info(
+ _('Es wurden keine zur Suche passenden Veranstaltungen gefunden!')
+ ) ?>
+ <? endif ?>
+ <?= \Studip\LinkButton::create(
+ _('Neue Suche'),
+ $controller->link_for('questionnaire/assign')
+ ) ?>
+ </section>
+</article>
diff --git a/app/views/questionnaire/assign_step2.php b/app/views/questionnaire/assign_step2.php
new file mode 100644
index 0000000..c57623e
--- /dev/null
+++ b/app/views/questionnaire/assign_step2.php
@@ -0,0 +1,84 @@
+<article class="studip">
+ <header><h1><?= _('Ausgewählte Veranstaltungen') ?></h1></header>
+ <ul>
+ <? if ($selected_courses): ?>
+ <? foreach ($selected_courses as $selected_course): ?>
+ <li>
+ <? if ($GLOBALS['perm']->have_perm('root')): ?>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/course/details',
+ [
+ 'cid' => $selected_course->id
+ ]
+ ) ?>" data-dialog="1">
+ <?= htmlReady($selected_course->getFullName()) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($selected_course->getFullName()) ?>
+ <? endif ?>
+ </li>
+ <? endforeach ?>
+ <? endif ?>
+ </ul>
+</article>
+<article class="studip">
+ <header><h1><?= _('Auswählbare Fragebögen') ?></h1></header>
+ <section>
+ <table class="default sortable-table" data-sortlist="[[2, 1]]">
+ <colgroup>
+ <col width="30px">
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="input[name='selected_questionnaire_ids[]']"
+ data-activates="#questionnaire-assign-form .step2-button">
+ </th>
+ <th data-sort="text"><?= _('Titel') ?></th>
+ <th data-sort="htmldata"><?= _('Erstellungsdatum') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($questionnaires as $questionnaire): ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="selected_questionnaire_ids[]"
+ value="<?= htmlReady($questionnaire->id) ?>"
+ <?= in_array($questionnaire->id, $selected_questionnaires)
+ ? 'checked="checked"'
+ : '' ?>>
+ </td>
+ <td><?= htmlReady($questionnaire->title) ?></td>
+ <td data-sort-value="<?= htmlReady($questionnaire->mkdate) ?>">
+ <?= date('d.m.Y', $questionnaire->mkdate) ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <label>
+ <input type="checkbox" name="delete_dates" value="1"
+ <?= $delete_dates ? 'checked="checked"' : '' ?>>
+ <?= _('Kopierte Fragebögen händisch starten und enden lassen') ?>
+ </label>
+ <?= \Studip\Button::create(
+ _('Zuweisen'),
+ 'assign',
+ [
+ 'class' => 'step2-button',
+ 'disabled' => 'disabled'
+ ]
+ ) ?>
+ <?= \Studip\Button::create(
+ _('In Veranstaltungen kopieren'),
+ 'copy',
+ [
+ 'class' => 'step2-button',
+ 'disabled' => 'disabled'
+ ]
+ ) ?>
+ </section>
+</article>
diff --git a/app/views/questionnaire/context.php b/app/views/questionnaire/context.php
new file mode 100644
index 0000000..7d7294b
--- /dev/null
+++ b/app/views/questionnaire/context.php
@@ -0,0 +1,103 @@
+<form action="<?= URLHelper::getLink("dispatch.php/questionnaire/context/".$questionnaire->getId()) ?>"
+ method="post"
+ class="default"
+ <?= Request::isAjax() ? "data-dialog" : "" ?>
+ >
+ <fieldset>
+ <legend><?= _("URL zum Fragebogen") ?></legend>
+ <input type="text" aria-label="<?= _("URL zum Fragebogen (nur lesbar)") ?>" readonly value="<?= htmlReady($GLOBALS['ABSOLUTE_URI_STUDIP']."dispatch.php/questionnaire/answer/".$questionnaire->getId()) ?>">
+ </fieldset>
+ <fieldset>
+ <legend><?= _("Freigaben bearbeiten") ?></legend>
+ <label>
+ <input type="checkbox" name="user" value="1"<?= $profile ? " checked" : "" ?>>
+ <?= _("Auf der persönlichen Profilseite") ?>
+ </label>
+ <label>
+ <input type="checkbox" name="public" value="1"<?= $public ? " checked" : "" ?>>
+ <?= _("Als öffentlicher Link für unangemeldete Nutzer") ?>
+ </label>
+ <? if ($GLOBALS['perm']->have_perm("root")) : ?>
+ <label>
+ <input type="checkbox" name="start" value="1"<?= $start ? " checked" : "" ?>>
+ <?= _("Auf der Systemstartseite") ?>
+ </label>
+ <? endif ?>
+
+ <h3><?= _("Veranstaltungen") ?></h3>
+ <ul class="clean courseselector">
+ <? foreach ($this->questionnaire->assignments as $assignment) : ?>
+ <? if ($assignment['range_type'] === "course") : ?>
+ <li>
+ <label>
+ <input type="checkbox" name="remove_sem[]" value="<?= htmlReady($assignment['range_id']) ?>" style="display: none;">
+ <? $course = Course::find($assignment['range_id']) ?>
+ <span>
+ <a href="<?= URLHelper::getLink("seminar_main.php", ['auswahl' => $course->getId()]) ?>">
+ <?= htmlReady((Config::get()->IMPORTANT_SEMNUMBER ? $course->veranstaltungsnummer." " : "").$course->name) ?>
+ </a>
+ <?= Icon::create("trash", "clickable")->asimg("20px", ['class' => "text-bottom", 'title' => _("Zuweisung zur Veranstaltung aufheben.")]) ?>
+ </span>
+ </label>
+ </li>
+ <? endif ?>
+ <? endforeach ?>
+ </ul>
+ <?= QuickSearch::get("add_seminar_id", new SeminarSearch())->render() ?>
+
+ <h3><?= _("Teilnehmergruppen in Veranstaltungen") ?></h3>
+ <ul class="clean statusgroupselector">
+ <? foreach ($this->questionnaire->assignments as $assignment) : ?>
+ <? if ($assignment['range_type'] === "statusgruppe") : ?>
+ <li>
+ <label>
+ <input type="checkbox" name="remove_statusgruppe[]" value="<?= htmlReady($assignment['range_id']) ?>" style="display: none;">
+ <? $statusgruppe = Statusgruppen::find($assignment['range_id']) ?>
+ <span>
+ <a href="<?= URLHelper::getLink("seminar_main.php", ['auswahl' => $statusgruppe->getId()]) ?>">
+ <?= htmlReady($statusgruppe->course['name'].": ".$statusgruppe->name) ?>
+ </a>
+ <?= Icon::create("trash", "clickable")->asimg("20px", ['class' => "text-bottom", 'title' => _("Zuweisung zur Veranstaltung aufheben.")]) ?>
+ </span>
+ </label>
+ </li>
+ <? endif ?>
+ <? endforeach ?>
+ </ul>
+ <?= QuickSearch::get("add_statusgruppe_id", $statusgruppesearch)->render() ?>
+
+ <? if ($GLOBALS['perm']->have_perm("admin")) : ?>
+ <h3><?= _("Einrichtungen") ?></h3>
+ <ul class="clean instituteselector">
+ <? foreach ($this->questionnaire->assignments as $assignment) : ?>
+ <? if ($assignment['range_type'] === 'institute') : ?>
+ <li>
+ <label>
+ <input type="checkbox" name="remove_inst[]" value="<?= htmlReady($assignment['range_id']) ?>" style="display: none;">
+ <span><?= htmlReady(Institute::find($assignment['range_id'])->name) ?></span>
+ <?= Icon::create('trash', 'clickable', ['title' => _("Zuweisung zur Einrichtung aufheben.")])->asImg(['class' => "text-bottom"]) ?>
+ </label>
+ </li>
+ <? endif ?>
+ <? endforeach ?>
+ </ul>
+ <?= QuickSearch::get('add_institut_id', new InstituteSearch($this->questionnaire->assignments->filter(function ($q) {
+ return $q['range_type'] === 'institute';
+ })->pluck('range_id')))->render() ?>
+ <? endif ?>
+
+ <?
+ foreach (PluginManager::getInstance()->getPlugins("QuestionnaireAssignmentPlugin") as $plugin) {
+ $template = $plugin->getQuestionnaireAssignmentEditTemplate($this->questionnaire);
+ if ($template) {
+ echo $template->render();
+ }
+ }
+ ?>
+
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= \Studip\Button::create(_("Speichern"), 'questionnaire_store_relations') ?>
+ </footer>
+</form>
diff --git a/app/views/questionnaire/edit.php b/app/views/questionnaire/edit.php
new file mode 100644
index 0000000..0cd4af6
--- /dev/null
+++ b/app/views/questionnaire/edit.php
@@ -0,0 +1,76 @@
+<form action="<?= URLHelper::getLink("dispatch.php/questionnaire/edit/".(!$questionnaire->isNew() ? $questionnaire->getId() : "")) ?>"
+ method="post" enctype="multipart/form-data"
+ class="questionnaire_edit default"
+ <?= Request::isAjax() ? "data-dialog" : "" ?> data-secure="true">
+ <input type="hidden" name="order" value="<?= htmlReady(json_encode($order)) ?>">
+ <? if (Request::get("range_id")) : ?>
+ <input type="hidden" name="range_id" value="<?= htmlReady(Request::get("range_id")) ?>">
+ <input type="hidden" name="range_type" value="<?= htmlReady(Request::get("range_type", "static")) ?>">
+ <? endif ?>
+ <fieldset>
+ <legend><?= _("Fragebogen") ?></legend>
+ <label>
+ <?= _("Titel des Fragebogens") ?>
+ <input type="text" name="questionnaire[title]" value="<?= htmlReady($questionnaire['title']) ?>" class="size-l" required>
+ </label>
+ </fieldset>
+
+ <div class="all_questions">
+ <? foreach ($questionnaire->questions as $index => $question) : ?>
+ <?= $this->render_partial("questionnaire/_question.php", compact("question")) ?>
+ <? endforeach ?>
+ </div>
+
+ <div style="text-align: right;" class="add_questions">
+ <? foreach (get_declared_classes() as $class) :
+ if (in_array('QuestionType', class_implements($class))) : ?>
+ <a href="" onClick="STUDIP.Questionnaire.addQuestion('<?= htmlReady($class) ?>'); return false;">
+ <?= $class::getIcon(true, true)->asimg("40px") ?>
+ <?= htmlReady($class::getName()) ?>
+ </a>
+ <? endif;
+ endforeach ?>
+ </div>
+
+ <fieldset class="questionnaire_metadata">
+
+ <label>
+ <?= _("Startzeitpunkt (leer lassen für manuellen Start)") ?>
+ <input type="text" name="questionnaire[startdate]" value="<?= $questionnaire['startdate'] ? date("d.m.Y H:i", $questionnaire['startdate']) : ($questionnaire->isNew() ? _("sofort") : "") ?>" data-datetime-picker>
+ </label>
+
+ <label>
+ <?= _("Endzeitpunkt (leer lassen für manuelles Ende)") ?>
+ <input type="text" name="questionnaire[stopdate]" value="<?= $questionnaire['stopdate'] ? date("d.m.Y H:i", $questionnaire['stopdate']) : "" ?>" data-datetime-picker>
+ </label>
+
+ <label>
+ <input type="checkbox" name="questionnaire[copyable]" value="1"<?= $questionnaire['copyable'] ? " checked" : "" ?>>
+ <?= _("Fragebogen zum Kopieren freigeben") ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="questionnaire[anonymous]" onChange="jQuery('#questionnaire_editanswers').toggle(!this.checked);" value="1"<?= $questionnaire['anonymous'] ? " checked" : "" ?>>
+ <?= _("Anonym teilnehmen") ?>
+ </label>
+
+ <label id="questionnaire_editanswers" <?= $questionnaire['anonymous'] ? 'style="display: none"' : '' ?>>
+ <input type="checkbox" name="questionnaire[editanswers]" value="1"<?= $questionnaire['editanswers'] || $questionnaire->isNew() ? " checked" : "" ?>>
+ <?= _("Teilnehmende dürfen ihre Antworten revidieren") ?>
+ </label>
+
+ <label>
+ <?= _("Ergebnisse an Teilnehmende") ?>
+ <select name="questionnaire[resultvisibility]">
+ <option value="always"<?= $questionnaire['resultvisibility'] === "always" ? " selected" : "" ?>><?= _("Immer.") ?></option>
+ <option value="afterending"<?= $questionnaire['resultvisibility'] === "afterending" ? " selected" : "" ?>><?= _("Nach Ende der Befragung.") ?></option>
+ <option value="never"<?= $questionnaire['resultvisibility'] === "never" ? " selected" : "" ?>><?= _("Niemals.") ?></option>
+ </select>
+ </label>
+
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= \Studip\Button::create(_("Speichern"), 'questionnaire_store') ?>
+ </footer>
+</form>
diff --git a/app/views/questionnaire/evaluate.php b/app/views/questionnaire/evaluate.php
new file mode 100644
index 0000000..258dbb0
--- /dev/null
+++ b/app/views/questionnaire/evaluate.php
@@ -0,0 +1,59 @@
+<div class="questionnaire_results questionnaire_<?= $questionnaire->getId() ?>" data-questionnaire_id="<?= $questionnaire->getId() ?>">
+
+ <? if ($questionnaire->resultsVisible()) : ?>
+ <? foreach ($questionnaire->questions as $question) : ?>
+ <article class="question_<?= $question->getId() ?>">
+ <? $template = $question->getResultTemplate() ?>
+ <?= $template ? $template->render(['anonAnswers' => $anonAnswers]) : _("Ergebnisse konnten nicht ausgewertet werden.") ?>
+ </article>
+ <? endforeach ?>
+ <? else : ?>
+ <div style="margin-top: 13px;">
+ <? if ($questionnaire['resultvisibility'] === "afterending") : ?>
+ <?= MessageBox::info(_("Die Ergebnisse des Fragebogens werden veröffentlich, wenn die Befragung abgeschlossen ist.")) ?>
+ <? else : ?>
+ <?= MessageBox::info(_("Die Ergebnisse der Befragung werden nicht über Stud.IP ausgewertet.")) ?>
+ <? endif ?>
+ </div>
+ <? endif ?>
+
+ <div class="terms">
+ <? if ($questionnaire['anonymous']) : ?>
+ <?= _("Die Teilnahme ist anonym.") ?>
+ <? else : ?>
+ <?= _("Die Teilnahme ist nicht anonym.") ?>
+ <? endif ?>
+ <? if ($questionnaire['stopdate']) : ?>
+ <?= sprintf(_("Sie können den Fragebogen beantworten bis zum %s um %s Uhr."), date("d.m.Y", $questionnaire['stopdate']), date("H:i", $questionnaire['stopdate'])) ?>
+ <? endif ?>
+ </div>
+
+ <script>
+ STUDIP.Questionnaire.lastUpdate = Math.floor(Date.now() / 1000);
+ STUDIP.Questionnaire.initialize();
+ </script>
+ <div data-dialog-button style="max-height: none; opacity: 1; text-align: center;">
+ <? if ($questionnaire->isAnswerable() && $questionnaire['editanswers']) : ?>
+ <?= \Studip\LinkButton::create($questionnaire->isAnswered() ? _("Antwort ändern") : _("Beantworten"), URLHelper::getURL("dispatch.php/questionnaire/answer/".$questionnaire->getId(), ['range_type' => $range_type, 'range_id' => $range_id]), ['data-dialog' => "1"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable()) : ?>
+ <?= \Studip\LinkButton::create(_("Ergebnisse herunterladen"), URLHelper::getURL("dispatch.php/questionnaire/export/".$questionnaire->getId())) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable() && (!$questionnaire->isRunning() || !$questionnaire->countAnswers())) : ?>
+ <?= \Studip\LinkButton::create(_("Bearbeiten"), URLHelper::getURL("dispatch.php/questionnaire/edit/".$questionnaire->getId(), ['range_type' => $range_type, 'range_id' => $range_id]), ['data-dialog' => "1"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable()) : ?>
+ <?= \Studip\LinkButton::create(_("Kontext auswählen"), URLHelper::getURL("dispatch.php/questionnaire/context/".$questionnaire->getId(), ['range_type' => $range_type, 'range_id' => $range_id]), ['data-dialog' => "1"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->isCopyable()) : ?>
+ <?= \Studip\LinkButton::create(_("Kopieren"), URLHelper::getURL("dispatch.php/questionnaire/copy/".$questionnaire->getId()), ['data-dialog' => "1"]) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable() && !$questionnaire->isRunning()) : ?>
+ <?= \Studip\LinkButton::create(_("Starten"), URLHelper::getURL("dispatch.php/questionnaire/start/".$questionnaire->getId(), in_array($range_type, ['course', 'insitute']) ? ['redirect' => $range_type . "/overview"] : [])) ?>
+ <? endif ?>
+ <? if ($questionnaire->isEditable() && $questionnaire->isRunning()) : ?>
+ <?= \Studip\LinkButton::create(_("Beenden"), URLHelper::getURL("dispatch.php/questionnaire/stop/".$questionnaire->getId(), in_array($range_type, ['course', 'insitute']) ? ['redirect' => $range_type . "/overview"] : [])) ?>
+ <? endif ?>
+
+ </div>
+</div>
diff --git a/app/views/questionnaire/overview.php b/app/views/questionnaire/overview.php
new file mode 100644
index 0000000..12319b1
--- /dev/null
+++ b/app/views/questionnaire/overview.php
@@ -0,0 +1,45 @@
+<form action="<?= $controller->link_for("questionnaire/bulkdelete", $range_type ? ['range_type' => $range_type, 'range_id' => Context::getId()]: []) ?>"
+ method="post">
+ <table class="default" id="questionnaire_overview">
+ <thead>
+ <tr>
+ <th width="20"><input type="checkbox" data-proxyfor="#questionnaire_overview > tbody input[type=checkbox]"></th>
+ <th><?= _('Fragebogen') ?></th>
+ <th><?= _('Startet') ?></th>
+ <th><?= _('Endet') ?></th>
+ <th><?= _('Eingebunden') ?></th>
+ <th><?= _('Teilnehmende') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($questionnaires)) : ?>
+ <? foreach ($questionnaires as $questionnaire) : ?>
+ <?= $this->render_partial('questionnaire/_overview_questionnaire.php', compact('questionnaire')) ?>
+ <? endforeach ?>
+ <? else : ?>
+ <tr class="noquestionnaires">
+ <td colspan="7" style="text-align: center">
+ <?= _('Sie haben noch keine Fragebögen erstellt.') ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="7">
+ <?= \Studip\Button::create(_("Löschen"), "bulkdelete", ['data-confirm' => _("Wirklich löschen?")]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
+<?php
+$actions = new ActionsWidget();
+$actions->addLink(
+ _('Fragebogen erstellen'),
+ $controller->url_for('questionnaire/add_to_context', $range_type ? ['range_type' => $range_type, 'range_id' => Context::getId()]: []),
+ Icon::create('add', 'clickable'),
+ ['data-dialog' => 'size=auto']
+);
+Sidebar::Get()->addWidget($actions);
diff --git a/app/views/questionnaire/question_types/freetext/freetext_answer.php b/app/views/questionnaire/question_types/freetext/freetext_answer.php
new file mode 100755
index 0000000..3011012
--- /dev/null
+++ b/app/views/questionnaire/question_types/freetext/freetext_answer.php
@@ -0,0 +1,19 @@
+<?php
+ $etask = $vote->etask;
+
+ $answer = $vote->getMyAnswer();
+ $answerdata = $answer['answerdata'] ? $answer['answerdata']->getArrayCopy() : [];
+?>
+
+<label>
+ <div>
+ <?= Icon::create('guestbook', Icon::ROLE_INFO)->asImg(20, ['class' => 'text-bottom']) ?>
+ <? if (isset($etask->options['mandatory']) && $etask->options['mandatory']) : ?>
+ <?= Icon::create('star', Icon::ROLE_ATTENTION)->asImg(20, ['class' => 'text-bottom', 'title' => _("Pflichtantwort")]) ?>
+ <? endif ?>
+ <?= formatReady($etask->description) ?>
+ </div>
+ <textarea name="answers[<?= $vote->getId() ?>][answerdata][text]"
+ <?= isset($etask->options['mandatory']) && $etask->options['mandatory'] ? "required" : "" ?>
+ ><?= htmlReady($answerdata['text']) ?></textarea>
+</label>
diff --git a/app/views/questionnaire/question_types/freetext/freetext_edit.php b/app/views/questionnaire/question_types/freetext/freetext_edit.php
new file mode 100755
index 0000000..1b9a044
--- /dev/null
+++ b/app/views/questionnaire/question_types/freetext/freetext_edit.php
@@ -0,0 +1,18 @@
+<?php
+ $etask = $vote->etask;
+?>
+<label>
+ <?= _('Frage') ?>
+ <textarea name="questions[<?= $vote->getId() ?>][description]"
+ class="size-l wysiwyg"
+ placeholder="<?= _('Erzählen Sie uns ...') ?>"
+ ><?= wysiwygReady($etask->description) ?></textarea>
+</label>
+
+<input type="hidden" name="questions[<?= $vote->getId() ?>][options][mandatory]" value="0">
+<label>
+ <input type="checkbox"
+ name="questions[<?= $vote->getId() ?>][options][mandatory]"
+ value="1"<?= isset($etask->options['mandatory']) && $etask->options['mandatory'] ? 'checked' : '' ?>>
+ <?= _("Pflichtfrage") ?>
+</label>
diff --git a/app/views/questionnaire/question_types/freetext/freetext_evaluation.php b/app/views/questionnaire/question_types/freetext/freetext_evaluation.php
new file mode 100755
index 0000000..6877a72
--- /dev/null
+++ b/app/views/questionnaire/question_types/freetext/freetext_evaluation.php
@@ -0,0 +1,28 @@
+<?php
+ $etask = $vote->etask;
+?>
+<h3>
+ <?= formatReady($etask->description) ?>
+</h3>
+
+
+<ul class="clean">
+<? foreach ($vote->answers as $answer) : ?>
+ <? if (trim($answer['answerdata']['text'])) : ?>
+ <li style="border: #d0d7e3 thin solid; margin: 10px; padding: 10px;">
+ <? if (!$vote->questionnaire['anonymous']) : ?>
+ <div style="margin-bottom: 7px;">
+ <? if ($answer['user_id'] && $answer['user_id'] !== 'nobody') : ?>
+ <?= Avatar::getAvatar($answer['user_id'])->getImageTag(Avatar::SMALL) ?>
+ <span style="color: #888888; font-weight: bold; font-size: 0.8em;"><?= get_fullname($answer['user_id']) ?></span>
+ <? else : ?>
+ <?= Avatar::getAvatar($answer['user_id'])->getImageTag(Avatar::SMALL) ?>
+ <span style="color: #888888; font-weight: bold; font-size: 0.8em;"><?= get_fullname($answer['user_id']) ?></span>
+ <? endif ?>
+ </div>
+ <? endif ?>
+ <?= formatReady($answer['answerdata']['text']) ?>
+ </li>
+ <? endif ?>
+<? endforeach ?>
+</ul>
diff --git a/app/views/questionnaire/question_types/test/_answer.php b/app/views/questionnaire/question_types/test/_answer.php
new file mode 100644
index 0000000..868b32e
--- /dev/null
+++ b/app/views/questionnaire/question_types/test/_answer.php
@@ -0,0 +1,18 @@
+<li>
+ <?= Assets::img('anfasser_24.png', [ 'title' => _('Antwort verschieben'), 'class' => 'move' ]) ?>
+
+ <input type="checkbox"
+ name="questions[<?= $vote->getId() ?>][task][correct][]"
+ value="<?= $index + 1 ?>"
+ title="<?= _('Ist diese Antwort korrekt?') ?>"
+ <?= $forcecorrect || $answer['score'] > 0 ? 'checked' : '' ?>>
+
+ <input type="text"
+ name="questions[<?= $vote->getId() ?>][task][answers][]"
+ value="<?= htmlReady($answer['text']) ?>"
+ placeholder="<?= _('Antwort ...') ?>"
+ aria-label="<?= _('Geben Sie eine Antwortmöglichkeit zu der von Ihnen gestellten Frage ein.') ?>">
+
+ <?= Icon::create('trash', ['title' => _('Antwort löschen')])->asImg(20, ['class' => 'text-bottom delete']) ?>
+ <?= Icon::create('add', ['title' => _('Antwort hinzufügen')])->asImg(20, ['class' => 'text-bottom add']) ?>
+</li>
diff --git a/app/views/questionnaire/question_types/test/test_edit.php b/app/views/questionnaire/question_types/test/test_edit.php
new file mode 100644
index 0000000..fd558fe
--- /dev/null
+++ b/app/views/questionnaire/question_types/test/test_edit.php
@@ -0,0 +1,62 @@
+<? $etask = $vote->etask; ?>
+
+<label>
+ <?= _('Frage') ?>
+ <textarea name="questions[<?= $vote->getId() ?>][description]"
+ class="size-l wysiwyg"
+ required><?= isset($etask->description) ? wysiwygReady($etask->description) : '' ?></textarea>
+</label>
+
+<? $emptyAnswerTemplate = $this->render_partial('questionnaire/question_types/test/_answer', [ 'vote' => $vote, 'answer' => [] ]) ?>
+<ol class="clean options" data-optiontemplate="<?= htmlReady($emptyAnswerTemplate) ?>">
+ <? if (isset($etask->task['answers'])) {
+ foreach ($etask->task['answers'] as $index => $answer) {
+ echo $this->render_partial('questionnaire/question_types/test/_answer', compact('vote', 'answer', 'index'));
+ }
+ }
+ echo $this->render_partial(
+ 'questionnaire/question_types/test/_answer',
+ [
+ 'vote' => $vote,
+ 'answer' => [],
+ 'index' => $index + 1,
+ 'forcecorrect' => !isset($etask->task['answers']) || empty($etask->task['answers'])
+ ]
+ ); ?>
+</ol>
+
+<div style="padding-left: 13px; margin-bottom: 20px;">
+ <?= tooltipIcon(_('Wählen Sie über die Auswahlboxen aus, welche Antwortmöglichkeit korrekt ist.')) ?>
+</div>
+
+<label>
+ <input type="checkbox"
+ name="questions[<?= $vote->getId() ?>][task][type]"
+ value="multiple"
+ <?= $vote->isNew() || $etask->task['type'] === 'multiple' ? 'checked' : '' ?>>
+ <?= _('Mehrere Antworten sind erlaubt.') ?>
+</label>
+
+<input type="hidden" name="questions[<?= $vote->getId() ?>][options][randomize]" value="0">
+<label>
+ <input type="checkbox"
+ name="questions[<?= $vote->getId() ?>][options][randomize]"
+ value="1"
+ <?= isset($etask->options['randomize']) && $etask->options['randomize'] ? 'checked' : '' ?>>
+ <?= _('Antworten den Teilnehmenden zufällig präsentieren.') ?>
+</label>
+
+<div style="display: none" class="delete_question"><?= _('Diese Antwortmöglichkeit wirklich löschen?') ?></div>
+
+<script>
+ jQuery(function () {
+ jQuery('.options').sortable({
+ 'axis': 'y',
+ 'containment': 'parent',
+ 'handle': '.move',
+ 'update': function () {
+ STUDIP.Questionnaire.Test.updateCheckboxValues();
+ }
+ });
+ });
+</script>
diff --git a/app/views/questionnaire/question_types/test/test_evaluation.php b/app/views/questionnaire/question_types/test/test_evaluation.php
new file mode 100644
index 0000000..6c84e66
--- /dev/null
+++ b/app/views/questionnaire/question_types/test/test_evaluation.php
@@ -0,0 +1,122 @@
+<?
+$etask = $vote->etask;
+$taskAnswers = $etask->task['answers'];
+$numTaskAnswers = count($taskAnswers);
+
+$results = array_fill(0, $numTaskAnswers, 0);
+$results_users = array_fill(0, $numTaskAnswers, []);
+$users = [];
+
+if ($numTaskAnswers > 0) {
+ foreach ($answers as $answer) {
+ if ($etask->task['type'] === 'multiple') {
+ if (is_array($answer['answerdata']['answers']) || $answer['answerdata']['answers'] instanceof Traversable) {
+ foreach ($answer['answerdata']['answers'] as $a) {
+ $results[(int)$a]++;
+ $results_users[(int)$a][] = $answer['user_id'];
+ $users[] = $answer['user_id'];
+ }
+ }
+ } else {
+ $results[(int) $answer['answerdata']['answers']]++;
+ $results_users[(int) $answer['answerdata']['answers']][] = $answer['user_id'];
+ $users[] = $answer['user_id'];
+ }
+ }
+}
+
+$users = array_unique($users);
+$labels = array_map(function ($answer) { return strip_tags(formatReady($answer['text'])); }, $taskAnswers->getArrayCopy());
+?>
+
+<h3>
+ <?= Icon::create('test', 'info')->asImg(20, ['class' => 'text-bottom']) ?>
+ <?= formatReady($etask->description) ?>
+</h3>
+
+<? if (count($vote->answers) > 0 && $numTaskAnswers > 0) : ?>
+ <div style="max-height: none; opacity: 1;"
+ id="questionnaire_<?= $vote->getId() ?>_chart"
+ class="ct-chart"></div>
+
+ <script>
+ STUDIP.Questionnaire.initTestEvaluation(
+ '#questionnaire_<?= $vote->getId() ?>_chart',
+ <?= json_encode(
+ [
+ "labels" => $labels,
+ "series" => [$results],
+ ]
+ ) ?>,
+ <?= json_encode(Request::isAjax()) ?>,
+ <?= json_encode($etask->task['type'] === 'multiple') ?>
+ );
+ </script>
+<? endif ?>
+<? if (in_array($GLOBALS['user']->id, $users) || is_array($anonAnswers)) : ?>
+<? $correctAnswered = is_array($anonAnswers) ? $vote->correctAnswered('anonymous', $anonAnswers) : $vote->correctAnswered()?>
+ <div style="max-height: none; opacity: 1; font-size: 1.4em; text-align: center;">
+ <? if ($correctAnswered) : ?>
+ <?= MessageBox::success(_("Richtig beantwortet!")) ?>
+ <? else : ?>
+ <?= MessageBox::error(_("Falsch beantwortet!")) ?>
+ <? endif ?>
+ </div>
+<? endif ?>
+
+<table class="default nohover">
+ <tbody>
+ <? $countAnswers = $vote->questionnaire->countAnswers() ?>
+ <? $userAnswer = is_array($anonAnswers) ? @$anonAnswers[0]['answerdata'] : @$answers->findBy('user_id', $GLOBALS['user']->id)->first()->answerdata ?>
+ <? if ($userAnswer instanceOf StudipArrayObject) $userAnswer = $userAnswer->getArrayCopy() ?>
+ <? foreach ($taskAnswers as $key => $answer) : ?>
+ <tr class="<?= $data['correctanswer'] ? 'correct' : 'incorrect' ?>">
+ <? $percentage = $countAnswers ? round((int) $results[$key] / $countAnswers * 100) : 0 ?>
+
+ <td style="text-align: right; background-size: <?= $percentage ?>% 100%; background-position: right center; background-image: url('<?= Assets::image_path("vote_lightgrey.png") ?>'); background-repeat: no-repeat;" width="50%">
+ <strong><?= formatReady($answer['text']) ?></strong>
+ <? if ($userAnswer) : ?>
+ <?= Icon::create((is_array($userAnswer['answers']) && in_array($key, $userAnswer['answers'])) ? 'checkbox-checked' : 'checkbox-unchecked', 'info')->asImg( ['class' => 'text-bottom']) ?>
+ <? endif ?>
+ <? if ($answer['score'] > 0) : ?>
+ <?= Icon::create('accept', 'status-green', ['title' => _('Diese Antwort ist richtig')])->asImg( ['class' => 'text-bottom']) ?>
+ <? else : ?>
+ <?= Icon::create('decline', 'status-red', ['title' => _('Eine falsche Antwort')])->asImg( ['class' => 'text-bottom']) ?>
+ <? endif ?>
+ </td>
+
+ <td style="white-space: nowrap;">
+ (<?= $percentage ?>% | <?= (int) $results[$key] ?>/<?= $countAnswers ?>)
+ </td>
+
+ <td width="50%">
+ <? if (!$vote->questionnaire['anonymous'] && $results[$key]) : ?>
+
+ <? $users = SimpleCollection::createFromArray(
+ User::findMany($results_users[$key])); ?>
+
+ <? foreach ($results_users[$key] as $index => $user_id) : ?>
+
+ <? $user = $users->findOneBy('user_id', $user_id); ?>
+
+ <? if ($user) : ?>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/profile',
+ ['username' => $user->username]
+ ) ?>">
+ <?= Avatar::getAvatar($user_id, $user->username)->getImageTag(
+ Avatar::SMALL,
+ ['title' => $user->getFullname('no_title')]
+ ) ?>
+ <? if (count($results_users[$key]) < 4) : ?>
+ <?= htmlReady($user->getFullname('no_title')) ?>
+ <? endif ?>
+ </a>
+ <? endif ?>
+ <? endforeach ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/questionnaire/question_types/vote/_answer.php b/app/views/questionnaire/question_types/vote/_answer.php
new file mode 100644
index 0000000..2b2271f
--- /dev/null
+++ b/app/views/questionnaire/question_types/vote/_answer.php
@@ -0,0 +1,10 @@
+<li>
+ <?= Assets::img('anfasser_24.png', [ 'title' => _('Antwort verschieben'), 'class' => 'move' ]) ?>
+ <input type="text"
+ name="questions[<?= $vote->getId() ?>][task][answers][]"
+ value="<?= htmlReady($answer['text']) ?>"
+ placeholder="<?= _('Antwort ...') ?>"
+ aria-label="<?= _('Geben Sie eine Antwortmöglichkeit zu der von Ihnen gestellten Frage ein.') ?>">
+ <?= Icon::create('trash', ['title' => _('Antwort löschen')])->asImg(20, ['class' => 'text-bottom delete']) ?>
+ <?= Icon::create('add', ['title' => _('Antwort hinzufügen')])->asImg(20, ['class' => 'text-bottom add']) ?>
+</li>
diff --git a/app/views/questionnaire/question_types/vote/vote_answer.php b/app/views/questionnaire/question_types/vote/vote_answer.php
new file mode 100644
index 0000000..b42ad03
--- /dev/null
+++ b/app/views/questionnaire/question_types/vote/vote_answer.php
@@ -0,0 +1,52 @@
+<?
+$etask = $vote->etask;
+
+$taskAnswers = $etask->task['answers'];
+$indexMap = count($taskAnswers) ? range(0, count($taskAnswers) - 1) : [];
+if ($etask->options['randomize']) {
+ shuffle($indexMap);
+}
+
+$response = $vote->getMyAnswer();
+$responseData = $response['answerdata'] ? $response['answerdata']->getArrayCopy() : [];
+?>
+<div <?= isset($etask->options['mandatory']) && $etask->options['mandatory'] ? ' class="mandatory"' : "" ?>>
+ <h3>
+ <?= Icon::create(is_a($vote, 'Test') ? 'test' : 'vote', 'info')->asImg(20, ['class' => 'text-bottom']) ?>
+ <? if (isset($etask->options['mandatory']) && $etask->options['mandatory']) : ?>
+ <?= Icon::create('star', Icon::ROLE_ATTENTION)->asImg(20, ['class' => 'text-bottom', 'title' => _("Pflichtantwort")]) ?>
+ <? endif ?>
+ <?= formatReady($etask->description) ?>
+ </h3>
+
+ <div class="hidden invalidation_notice">
+ <?= _("Diese Frage muss beantwortet werden.") ?>
+ </div>
+
+ <ul class="clean">
+ <? foreach ($indexMap as $index) : ?>
+ <li>
+ <label>
+
+ <? if ($etask->task['type'] === 'multiple') : ?>
+
+ <input type="checkbox"
+ name="answers[<?= $vote->getId() ?>][answerdata][answers][<?= $index ?>]"
+ value="<?= $index ?>"
+ <?= isset($responseData['answers']) && in_array($index, (array) $responseData['answers']) ? 'checked' : '' ?>>
+
+ <? else : ?>
+
+ <input type="radio"
+ name="answers[<?= $vote->getId() ?>][answerdata][answers]"
+ value="<?= $index ?>"
+ <?= isset($responseData['answers']) && $index == $responseData['answers'] ? 'checked' : '' ?>>
+ <? endif ?>
+
+ <?= formatReady($taskAnswers[$index]['text']) ?>
+
+ </label>
+ </li>
+ <? endforeach ?>
+ </ul>
+</div>
diff --git a/app/views/questionnaire/question_types/vote/vote_edit.php b/app/views/questionnaire/question_types/vote/vote_edit.php
new file mode 100644
index 0000000..f6521c0
--- /dev/null
+++ b/app/views/questionnaire/question_types/vote/vote_edit.php
@@ -0,0 +1,59 @@
+<? $etask = $vote->etask; ?>
+
+<label>
+ <?= _('Frage') ?>
+ <textarea name="questions[<?= $vote->getId() ?>][description]"
+ class="size-l wysiwyg"
+ required><?= isset($etask->description) ? wysiwygReady($etask->description) : '' ?></textarea>
+</label>
+
+<? $emptyAnswerTemplate = $this->render_partial('questionnaire/question_types/vote/_answer', ['vote' => $vote, 'answer' => []])?>
+<ol class="clean options" data-optiontemplate="<?= htmlReady($emptyAnswerTemplate) ?>">
+ <? if (isset($etask->task['answers'])) {
+ foreach ($etask->task['answers'] as $answer) {
+ echo $this->render_partial('questionnaire/question_types/vote/_answer', compact('vote', 'answer'));
+ }
+ }
+ echo $emptyAnswerTemplate;
+ ?>
+</ol>
+
+<label>
+ <input type="checkbox"
+ name="questions[<?= $vote->getId() ?>][task][type]"
+ value="multiple"
+ <?= $vote->isNew() || $etask->task['type'] === 'multiple' ? 'checked' : '' ?>>
+ <?= _("Mehrere Antworten sind erlaubt.") ?>
+</label>
+
+<input type="hidden" name="questions[<?= $vote->getId() ?>][options][mandatory]" value="0">
+<label>
+ <input type="checkbox"
+ name="questions[<?= $vote->getId() ?>][options][mandatory]"
+ value="1"<?= isset($etask->options['mandatory']) && $etask->options['mandatory'] ? 'checked' : '' ?>>
+ <?= _("Pflichtfrage") ?>
+</label>
+
+<input type="hidden" name="questions[<?= $vote->getId() ?>][options][randomize]" value="0">
+<label>
+ <input type="checkbox"
+ name="questions[<?= $vote->getId() ?>][options][randomize]"
+ value="1"
+ <?= isset($etask->options['randomize']) && $etask->options['randomize'] ? 'checked' : '' ?>>
+ <?= _('Antworten den Teilnehmenden zufällig präsentieren.') ?>
+</label>
+
+
+
+
+<div style="display: none" class="delete_question"><?= _('Diese Antwortmöglichkeit wirklich löschen?') ?></div>
+
+<script>
+ jQuery(function () {
+ jQuery(".options").sortable({
+ "axis": "y",
+ "containment": "parent",
+ "handle": ".move"
+ });
+ });
+</script>
diff --git a/app/views/questionnaire/question_types/vote/vote_evaluation.php b/app/views/questionnaire/question_types/vote/vote_evaluation.php
new file mode 100644
index 0000000..bf762b0
--- /dev/null
+++ b/app/views/questionnaire/question_types/vote/vote_evaluation.php
@@ -0,0 +1,111 @@
+<?
+$etask = $vote->etask;
+$taskAnswers = $etask->task['answers'];
+$numTaskAnswers = count($taskAnswers);
+
+$results = array_fill(0, $numTaskAnswers, 0);
+$results_users = array_fill(0, $numTaskAnswers, []);
+
+if ($numTaskAnswers > 0) {
+ foreach ($answers as $answer) {
+ if ($etask->task['type'] === 'multiple') {
+ if (is_array($answer['answerdata']['answers']) || $answer['answerdata']['answers'] instanceof Traversable) {
+ foreach ($answer['answerdata']['answers'] as $a) {
+ $results[(int)$a]++;
+ $results_users[(int)$a][] = $answer['user_id'];
+ }
+ }
+ } else {
+ if (isset($answer['answerdata']['answers'])) {
+ $results[(int) $answer['answerdata']['answers']]++;
+ $results_users[(int) $answer['answerdata']['answers']][] = $answer['user_id'];
+ }
+ }
+ }
+}
+
+$ordered_results = $results;
+arsort($ordered_results);
+$ordered_answer_options = [];
+$ordered_users = [];
+foreach ($ordered_results as $index => $value) {
+ if ($value > 0) {
+ $ordered_answer_options[] = strip_tags(formatReady($taskAnswers[$index]['text']));
+ } else {
+ unset($ordered_results[$index]);
+ }
+}
+rsort($ordered_results);
+?>
+
+<h3>
+ <?= Icon::create('vote', 'info')->asImg(20, ['class' => 'text-bottom']) ?>
+ <?= formatReady($etask->description) ?>
+</h3>
+
+<? if (count($vote->answers) > 0 && $numTaskAnswers > 0) : ?>
+ <div style="max-height: none; opacity: 1;"
+ id="questionnaire_<?= $vote->getId() ?>_chart"
+ class="ct-chart"></div>
+
+ <script>
+ STUDIP.Questionnaire.initVoteEvaluation(
+ '#questionnaire_<?= $vote->getId() ?>_chart',
+ <?= json_encode(
+ [
+ "labels" => $ordered_answer_options,
+ "series" => [$ordered_results],
+ ]
+ ) ?>,
+ <?= json_encode(Request::isAjax()) ?>,
+ <?= json_encode($etask->task['type'] === 'multiple') ?>
+ );
+ </script>
+<? endif ?>
+
+<table class="default nohover">
+ <tbody>
+ <? $countAnswers = $vote->questionnaire->countAnswers() ?>
+ <? foreach ($taskAnswers as $key => $answer) : ?>
+ <tr>
+ <? $percentage = $countAnswers ? round((int) $results[$key] / $countAnswers * 100) : 0 ?>
+
+ <td style="text-align: right; background-size: <?= $percentage ?>% 100%; background-position: right center; background-image: url('<?= Assets::image_path("vote_lightgrey.png") ?>'); background-repeat: no-repeat;" width="50%">
+ <strong><?= formatReady($answer['text']) ?></strong>
+ </td>
+
+ <td style="white-space: nowrap;">
+ (<?= $percentage ?>% | <?= (int) $results[$key] ?>/<?= $countAnswers ?>)
+ </td>
+
+ <td width="50%">
+ <? if (!$vote->questionnaire['anonymous'] && $results[$key]) : ?>
+
+ <? $users = SimpleCollection::createFromArray(
+ User::findMany($results_users[$key])); ?>
+
+ <? foreach ($results_users[$key] as $index => $user_id) : ?>
+
+ <? $user = $users->findOneBy('user_id', $user_id); ?>
+
+ <? if ($user) : ?>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/profile',
+ ['username' => $user->username]
+ ) ?>">
+ <?= Avatar::getAvatar($user_id, $user->username)->getImageTag(
+ Avatar::SMALL,
+ ['title' => $user->getFullname('no_title')]
+ ) ?>
+ <? if (count($results_users[$key]) < 4) : ?>
+ <?= htmlReady($user->getFullname('no_title')) ?>
+ <? endif ?>
+ </a>
+ <? endif ?>
+ <? endforeach ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
diff --git a/app/views/questionnaire/thank_you.php b/app/views/questionnaire/thank_you.php
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/views/questionnaire/thank_you.php
diff --git a/app/views/questionnaire/widget.php b/app/views/questionnaire/widget.php
new file mode 100644
index 0000000..393db14
--- /dev/null
+++ b/app/views/questionnaire/widget.php
@@ -0,0 +1,39 @@
+<? $allowed_to_add = ($range_id === $GLOBALS['user']->id && $range_type === "user") || ($range_id === "start" && $GLOBALS['perm']->have_perm("root")) || ($range_type === "course" && $GLOBALS['perm']->have_studip_perm("tutor", $range_id)) || ($range_type === "institute" && $GLOBALS['perm']->have_studip_perm("tutor", $range_id)) ?>
+<article class="studip questionnaire_widget" id="questionnaire_area">
+ <header>
+ <h1>
+ <?= Icon::create("evaluation", "info")->asimg("16px", ['class' => "text-bottom"]) ?>
+ <?= _('Fragebögen') ?>
+ </h1>
+ <nav>
+ <? if ($allowed_to_add) : ?>
+ <a href="<?= $controller->link_for('questionnaire/add_to_context', $range_type ? ['range_type' => $range_type, 'range_id' => Context::getId()]: []) ?>" data-dialog title="<?= _('Fragebogen hinzufügen') ?>">
+ <?= Icon::create("add", "clickable")->asimg("16px", ['class' => "text-bottom"]) ?>
+ </a>
+ <a href="<?= URLHelper::getLink("dispatch.php/questionnaire/" . ($range_type == 'course' || $range_type == 'institute' ? 'course' : ''). "overview") ?>" title="<?= _('Fragebögen verwalten') ?>">
+ <?= Icon::create("edit", "clickable")->asimg("16px", ['class' => "text-bottom"]) ?>
+ </a>
+ <? endif ?>
+ </nav>
+ </header>
+
+ <? if ($questionnaire_data): ?>
+ <? foreach ($questionnaire_data as $questionnaire): ?>
+ <?= $this->render_partial("questionnaire/_widget_questionnaire", ['questionnaire' => Questionnaire::buildExisting($questionnaire), 'range_type' => $range_type, 'range_id' => $range_id]) ?>
+ <? endforeach; ?>
+ <? elseif (!$suppress_empty_output): ?>
+ <section class="noquestionnaires">
+ <?= _('Es sind keine Fragebögen vorhanden.') ?>
+ <? if ($allowed_to_add) : ?>
+ <?= _("Um neue Fragebögen zu erstellen, klicken Sie rechts auf das Plus.") ?>
+ <? endif ?>
+ </section>
+ <? endif; ?>
+ <footer>
+ <? if (Request::get('questionnaire_showall')): ?>
+ <a href="<?= URLHelper::getLink('#questionnaire_area', ['questionnaire_showall' => 0]) ?>"><?= _('Abgelaufene Fragebögen ausblenden') ?></a>
+ <? else: ?>
+ <a href="<?= URLHelper::getLink('#questionnaire_area', ['questionnaire_showall' => 1]) ?>"><?= _('Abgelaufene Fragebögen einblenden') ?></a>
+ <? endif; ?>
+ </footer>
+</article>
diff --git a/app/views/resources/_common/_grouped_room_list.php b/app/views/resources/_common/_grouped_room_list.php
new file mode 100644
index 0000000..c9a1237
--- /dev/null
+++ b/app/views/resources/_common/_grouped_room_list.php
@@ -0,0 +1,70 @@
+<?
+/**
+Template parameters:
+- $title: The list title
+- $grouped_rooms: The rooms, grouped by RoomManager::groupRooms
+- $link_template: An optional link template where the room-ID is
+ represented by the only "%s" placeholder.
+ If $link_template is not set, the link to the booking plan
+ of the room is generated.
+- $show_in_dialog: Whether to show the room link in a dialog (true)
+ or not (false).
+*/
+?>
+<? if ($grouped_rooms) : ?>
+ <? if ($title) : ?>
+ <h1><?= htmlReady($title) ?></h1>
+ <? endif ?>
+ <? foreach ($grouped_rooms as $group) : ?>
+ <?
+ $location = $group['location'];
+ $buildings = $group['buildings'];
+ ?>
+ <div class="studip-widget-wrapper">
+ <article class="studip">
+ <header><h1><?= htmlReady($location->name) ?></h1></header>
+ <? foreach ($buildings as $building_group) : ?>
+ <?
+ $building = $building_group['building'];
+ $rooms = $building_group['rooms'];
+ ?>
+ <article class="studip toggle">
+ <header><h1><a href="#"><?= htmlReady($building->name) ?></a></h1></header>
+ <section>
+ <table class="default">
+ <thead>
+ <tr><th><?= _('Raum') ?></th></tr>
+ </thead>
+ <tbody>
+ <? foreach ($rooms as $room) : ?>
+ <?
+ $room_link = '';
+ if ($link_template) {
+ $room_link = $controller->link_for(
+ sprintf(
+ $link_template,
+ $room->id
+ )
+ );
+ } else {
+ $room_link = $room->getActionLink('booking_plan');
+ }
+ ?>
+ <tr>
+ <td>
+ <a href="<?= $room_link ?>"
+ <?= $show_in_dialog ? 'data-dialog="size=big"' : '' ?>>
+ <?= htmlReady($room->name) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </section>
+ </article>
+ <? endforeach ?>
+ </article>
+ </div>
+ <? endforeach ?>
+<? endif ?>
diff --git a/app/views/resources/_common/_permission_table.php b/app/views/resources/_common/_permission_table.php
new file mode 100644
index 0000000..c23302f
--- /dev/null
+++ b/app/views/resources/_common/_permission_table.php
@@ -0,0 +1,215 @@
+<?php
+/**
+ * Template variables:
+ * - table_id: The ID of the table. This is required for the JS code which adds
+ * new users to the table to work.
+ * - table caption: An optional table caption.
+ * - permissions: An array of ResourcePermission objects.
+ * - single_user: The User object in case the table is used in single
+ * user mode where the permissions of one specific user are displayed.
+ * - custom_columns: An associative multi-dimensional array to display
+ * additional columns.
+ * Structure:
+ * The first layer has the column names as indexes.
+ * The second layer contains an associative array with the cells
+ * for the column. That array has the permission object IDs
+ * (see permissions above) as indexes.
+ * - custom_actions: A multi-dimensional array for additional actions in the
+ * actions column. The array has the following structure:
+ * The first layer contains associative arrays where each array represents
+ * one action.
+ * The second layer consists of associative arrays with the following
+ * structure:
+ * [
+ * 'icon' => The Icon object for the action.
+ * 'title' => The descriptive title for the action.
+ * 'link_classes' => Classes which shall be added to the link element
+ * of the action.
+ * 'url' => An optional URL that shall be attached to the action's
+ * link element via the href attribute.
+ * 'js_action' => An optional JavaScript action that shall be attached
+ * to the link element using the onclick attribute.
+ * ]
+ * - show_delete_action: If the delete action shall be shown (true) or not (false).
+ * Defaults to true, if not set.
+ */
+
+//Make sure the delete action is shown when the $show_delete_action
+//template variable isn't set:
+if (!isset($show_delete_action)) {
+ $show_delete_action = true;
+}
+?>
+<table class="default sortable-table resource-permissions-table"
+ data-sortlist="[[1, 0]]"
+ <?= $table_id ? 'id="' . htmlReady($table_id) . '"' : '' ?>>
+ <? if ($table_caption): ?>
+ <caption><?= htmlReady($table_caption) ?></caption>
+ <? endif ?>
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ <col>
+ <? if ($custom_columns): ?>
+ <? foreach ($custom_columns as $column_name): ?>
+ <col>
+ <? endforeach ?>
+ <? endif ?>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="input[name='selected_permissions[]']"
+ data-activates="table.resource-permissions-table button.bulk-action">
+ </th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="htmldata"><?= _('Rechtestufe') ?></th>
+ <? if ($custom_columns): ?>
+ <? foreach (array_keys($custom_columns) as $column_name): ?>
+ <th><?= htmlReady($column_name) ?></th>
+ <? endforeach ?>
+ <? endif ?>
+ </tr>
+ </thead>
+ <? if ($show_delete_action): ?>
+ <tfoot>
+ <tr>
+ <td colspan="3">
+ <?
+ $button_attrs = [
+ 'class' => 'bulk-action',
+ 'data-activates-condition' => 'table.resource-permissions-table :checkbox:checked'
+ ];
+ ?>
+
+ <?= \Studip\Button::create(_('Löschen'), 'bulk_delete', $button_attrs) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ <tbody>
+ <? if (count($permissions)): ?>
+ <? foreach ($permissions as $permission): ?>
+ <?
+ $permission_sort_key = 10;
+ switch ($permission->perms) {
+ case 'autor':
+ {
+ $permission_sort_key = 20;
+ break;
+ }
+ case 'tutor':
+ {
+ $permission_sort_key = 30;
+ break;
+ }
+ case 'admin':
+ {
+ $permission_sort_key = 40;
+ break;
+ }
+ }
+ ?>
+ <tr data-user_id="<?= htmlReady($permission->user_id) ?>">
+ <td>
+ <input type="checkbox" name="selected_permissions[]"
+ value="<?= htmlReady($permission->user_id) ?>">
+ </td>
+ <td>
+ <? if ($permission->user instanceof User): ?>
+ <?= htmlReady($permission->user->getFullName('full_rev_username')) ?>
+ (<?= htmlReady($permission->user->perms) ?>)
+ <? else: ?>
+ <?= _('unbekannt') ?>
+ <? endif ?>
+ <input type="hidden" name="permissions[user_id][]"
+ value="<?= htmlReady($permission->user_id) ?>">
+ </td>
+ <td data-sort-value="<?= htmlReady($permission_sort_key) ?>">
+ <select name="permissions[level][]">
+ <option value="user"
+ <?=
+ $permission->perms == 'user'
+ ? 'selected="selected"'
+ : '' ?>>
+ user
+ </option>
+ <option value="autor"
+ <?=
+ $permission->perms == 'autor'
+ ? 'selected="selected"'
+ : '' ?>>
+ autor
+ </option>
+ <option value="tutor"
+ <?=
+ $permission->perms == 'tutor'
+ ? 'selected="selected"'
+ : '' ?>>
+ tutor
+ </option>
+ <option value="admin"
+ <?=
+ $permission->perms == 'admin'
+ ? 'selected="selected"'
+ : '' ?>>
+ admin
+ </option>
+ </select>
+ </td>
+ <? if ($custom_columns): ?>
+ <? foreach ($custom_columns as $column_content): ?>
+ <td>
+ <?= htmlReady($column_content[$permission->id]) ?>
+ </td>
+ <? endforeach ?>
+ <? endif ?>
+ </tr>
+ <? endforeach ?>
+ <? endif ?>
+ <tr id="resource-empty-permission-list-message"
+ <?= count($permissions) ? 'class="invisible"' : '' ?>>
+ <td colspan="3" style="text-align: center">
+ <? if ($single_user instanceof User): ?>
+ <?= $custom_empty_list_message ?: sprintf(
+ _('Es sind keine besonderen Rechte für %s vorhanden.'),
+ htmlReady($single_user->getFullName()
+ )) ?>
+ <? else: ?>
+ <?= $custom_empty_list_message ?: _('Es sind keine besonderen Rechte vorhanden.') ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <tr class="invisible resource-permission-list-template">
+ <td>
+ <input type="checkbox" name="selected_permissions[]"
+ disabled="disabled">
+ </td>
+ <td>
+ <input type="hidden" name="permissions[user_id][]">
+ </td>
+ <td>
+ <select name="permissions[level][]">
+ <option value="user">
+ user
+ </option>
+ <option value="autor" selected="selected">
+ autor
+ </option>
+ <option value="tutor">
+ tutor
+ </option>
+ <option value="admin">
+ admin
+ </option>
+ </select>
+ </td>
+ <? if ($custom_columns): ?>
+ <? foreach (array_keys($custom_columns) as $column_name): ?>
+ <td><?= htmlReady($custom_columns[$column_name]) ?></td>
+ <? endforeach ?>
+ <? endif ?>
+ </tr>
+ </tbody>
+</table>
diff --git a/app/views/resources/_common/_request_info.php b/app/views/resources/_common/_request_info.php
new file mode 100644
index 0000000..27cf18a
--- /dev/null
+++ b/app/views/resources/_common/_request_info.php
@@ -0,0 +1,103 @@
+<dl>
+ <dt><?= _('Termine') ?>:</dt>
+ <dd><?= htmlReady($request->getDateString()) ?></dd>
+ <dt><?= _('Rüstzeit')?>:</dt>
+ <dd>
+ <? $preparation_time_minutes = intval($request->preparation_time / 60) ?>
+ <?= sprintf(
+ ngettext(
+ '%d Minute',
+ '%d Minuten',
+ $preparation_time_minutes
+ ),
+ $preparation_time_minutes
+ ) ?>
+ </dd>
+ <? if ($request instanceof RoomRequest): ?>
+ <dt><?= _('Gewünschter Raum')?>:</dt>
+ <? else: ?>
+ <dt><?= _('Gewünschte Ressource')?>:</dt>
+ <? endif ?>
+ <dd>
+ <? if ($request->resource): ?>
+ <?= htmlReady($request->resource->name) ?>
+ <? else: ?>
+ <? if ($request instanceof RoomRequest): ?>
+ <?= _('Es wurde kein spezifischer Raum gewünscht.') ?>
+ <? else: ?>
+ <?= _('Es wurde keine spezifische Ressource gewünscht.') ?>
+ <? endif ?>
+ <? endif ?>
+ </dd>
+ <? if ($request->isNew()): ?>
+ <dt>
+ <? if (!($request->properties || $request->resource_id)): ?>
+ <?= _('Die Anfrage ist unvollständig, und kann so nicht dauerhaft gespeichert werden!') ?>
+ <? else: ?>
+ <?= _('Die Anfrage ist neu.') ?>
+ <? endif ?>
+ </dt>
+ <? else: ?>
+ <dt><?= _('Erstellt von') ?>:</dt>
+ <dd>
+ <?= htmlReady(
+ $request->user
+ ? $request->user->getFullName()
+ : _('unbekannt')
+ ) ?>
+ </dd>
+ <dt><?= _('Erstellt am') ?>:</dt>
+ <dd><?= date('d.m.Y H:i', $request->mkdate) ?></dd>
+ <dt><?= _('Letzte Änderung am') ?>:</dt>
+ <dd><?= date('d.m.Y H:i', $request->chdate) ?></dd>
+ <dt><?= _('Letzte Änderung von') ?>:</dt>
+ <dd>
+ <?= htmlReady(
+ $request->last_modifier
+ ? $request->last_modifier->getFullName()
+ : _('unbekannt')
+ ) ?>
+ </dd>
+ <? endif ?>
+ <? if ($request instanceof RoomRequest): ?>
+ <? if ($request->seats): ?>
+ <dt><?= _('Gewünschte Zahl an Sitzplätzen') ?>:</dt>
+ <dd><?= htmlReady($request->seats) ?></dd>
+ <? endif ?>
+ <? if ($request->category): ?>
+ <dt><?= _('Gewünschter Raumtyp') ?>:</dt>
+ <dd><?= htmlReady($request->category->name) ?></dd>
+ <? endif ?>
+ <? endif ?>
+ <? if ($request->properties): ?>
+ <? $mandatory_properties = (
+ $request instanceof RoomRequest
+ ? ['seats', 'room_type']
+ : []
+ ) ?>
+ <? foreach ($request->properties as $property): ?>
+ <? if (!in_array($property->name, $mandatory_properties)): ?>
+ <dt><?= htmlReady($property->display_name) ?></dt>
+ <dd><?= htmlReady($property->__toString()) ?></dd>
+ <? endif ?>
+ <? endforeach ?>
+ <? endif ?>
+ <dt><?= _('Bearbeitung durch') ?>:</dt>
+ <dd>
+ <?= htmlReady(
+ $request->last_modifier
+ ? $request->last_modifier->getFullName()
+ : _('unbekannt')
+ ) ?>
+ </dd>
+ <dt><?= _('Bearbeitungsstatus') ?></dt>
+ <dd><?= htmlReady($request->getStatusText()) ?></dd>
+ <? if ($request->comment) : ?>
+ <dt><?= _('Nachricht an die Administration') ?></dt>
+ <dd><?= htmlReady($request->comment) ?></dd>
+ <? endif ?>
+ <? if ($request->reply_comment) : ?>
+ <dt><?= _('Nachricht der Adminstration') ?>:</dt>
+ <dd><?= htmlReady($request->reply_comment) ?></dd>
+ <? endif ?>
+</dl>
diff --git a/app/views/resources/_common/_request_tr.php b/app/views/resources/_common/_request_tr.php
new file mode 100644
index 0000000..3a2f235
--- /dev/null
+++ b/app/views/resources/_common/_request_tr.php
@@ -0,0 +1,161 @@
+<? $range_object = $request->getRangeObject(); ?>
+<tr>
+ <td data-sort-value="<?= htmlReady($request->marked) ?>">
+ <a href="#" class="request-marking-icon"
+ data-request_id="<?= htmlReady($request->id) ?>"
+ data-marked="<?= htmlReady($request->marked) ?>"
+ title="<?= _('Markierung ändern') ?>">
+ </a>
+ </td>
+ <td>
+ <? if ($range_object instanceof Course) : ?>
+ <?= htmlReady($range_object->veranstaltungsnummer) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for('resources/room_request/resolve/' . $request->id) ?>" data-dialog="size=big"
+ title="<?= _('Anfrage auflösen') ?>">
+ <? if ($range_object instanceof Course): ?>
+ <?= htmlReady($range_object->name) ?>
+ <? elseif ($range_object instanceof User): ?>
+ <?= htmlReady($range_object->getFullName('no_title_rev')) ?>
+ <? endif ?>
+ </a>
+ </td>
+
+ <td>
+ <? if ($range_object instanceof Course): ?>
+ <?= htmlReady(
+ join(', ', $range_object->members->findBy('status', 'dozent')
+ ->limit(3)->getUserFullname('no_title_rev')
+ )
+ ) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= $request->resource ? htmlReady($request->resource->name) : '' ?>
+ </td>
+ <td>
+ <?= $request->getProperty('seats') ?>
+ </td>
+ <td>
+ <? if ($request->user instanceof User): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $request->user->username]); ?>">
+ <?= htmlReady($request->user->getFullName('no_title_rev')) ?>
+ </a>
+ <? else: ?>
+ <?= _('Unbekannt') ?>
+ <? endif ?>
+ </td>
+ <? $intervals = $request->getTimeIntervals() ?>
+ <td data-sort-value="<?= htmlReady($intervals[0]['begin']) ?>">
+ <?= $request->getTypeString() ?>
+ <? if ($request->isSimpleRequest()): ?>
+ <?
+ $begin = $request->getStartDate();
+ $end = $request->getEndDate();
+ $different_days = $begin->format('Ymd') != $end->format('Ymd');
+ ?>
+ <? if (($begin instanceof DateTime) && ($end instanceof DateTime)): ?>
+ <br>
+ <? if ($different_days): ?>
+ (<?= sprintf(
+ _('vom %1$s bis %2$s'),
+ $begin->format('d.m.Y H:i'),
+ $end->format('d.m.Y H:i')
+ ) ?>)
+ <? else: ?>
+ (<?= sprintf(
+ _('am %1$s von %2$s bis %3$s'),
+ $begin->format('d.m.Y'),
+ $begin->format('H:i'),
+ $end->format('H:i')
+ ) ?>)
+ <? endif ?>
+ <? endif ?>
+ <? else: ?>
+ <? if (count($intervals) > 1 && $intervals[0]['begin'] > 0): ?>
+ <br>
+ (<?= htmlReady(
+ sprintf(
+ _('ab %s'),
+ date('d.m.Y H:i', $intervals[0]['begin'])
+ )
+ ) ?>)
+ <? endif ?>
+ <?= tooltipIcon(join("\n", $request->getTimeIntervalStrings())) ?>
+ <? endif ?>
+ </td>
+ <? $priority = $request->getPriority() ?>
+ <td data-sort-value="<?= htmlReady($priority) ?>">
+ <?= htmlReady($priority) ?>
+ </td>
+ <td data-sort-value="<?= htmlReady($request->chdate) ?>">
+ <?= strftime('%x', $request->chdate) ?>
+ </td>
+ <td class="actions">
+ <? $action_menu = ActionMenu::get()
+ ->addLink(
+ $controller->link_for('resources/room_request/resolve/' . $request->id),
+ _('Anfrage auflösen'),
+ Icon::create('room-request'),
+ [
+ 'data-dialog' => 'size=big'
+ ])
+ ->addLink(
+ $controller->link_for('resources/room_request/decline/' . $request->id, ['single-request' => 1]),
+ _('Anfrage ablehnen'),
+ Icon::create('decline'),
+ [
+ 'data-dialog' => 'size=big'
+ ])
+ ->addLink(
+ $controller->link_for('resources/room_request/decline/' . $request->id, ['delete' => 1]),
+ _('Anfrage löschen'),
+ Icon::create('trash'),
+ [
+ 'data-dialog' => 'size=big'
+ ])
+ ?>
+ <?
+ $edit_url = '';
+ $edit_url_attributes = [];
+ if ($GLOBALS['perm']->have_studip_perm('tutor', $request->getRangeId())) {
+ $edit_url = $controller->link_for(
+ 'course/room_requests/request_summary/' . $request->id,
+ ['cid' => $request->getRangeId()]
+ );
+ $edit_url_attributes = ['target' => '_blank'];
+ } elseif ($request->isSimpleRequest() && !$request->isReadOnlyForUser($current_user)) {
+ $edit_url = $controller->link_for('resources/room_request/edit/' . $request->id);
+ $edit_url_attributes = ['data-dialog' => 'size=auto'];
+ }
+ if ($edit_url && $edit_urL_attributes) {
+ $action_menu->addLink(
+ $edit_url,
+ _('Anfrage bearbeiten'),
+ Icon::create('edit'),
+ $edit_url_attributes
+ );
+ }
+ if ($range_object instanceof Course) {
+ $action_menu->addLink(
+ URLHelper::getLink('dispatch.php/course/details', ['cid' => $range_object->id]),
+ _('Veranstaltungsdetails'),
+ Icon::create('seminar'),
+ ['data-dialog' => 'size=auto']
+ );
+ }
+
+ if ($range_object instanceof User) {
+ $action_menu->addLink(
+ URLHelper::getLink('dispatch.php/profile', ['username' => $range_object->username]),
+ _('Profil anzeigen'),
+ Icon::create('person'),
+ ['target' => '_blank']
+ );
+ }
+ ?>
+ <?= $action_menu->render() ?>
+ </td>
+</tr> \ No newline at end of file
diff --git a/app/views/resources/_common/_resource_tr.php b/app/views/resources/_common/_resource_tr.php
new file mode 100644
index 0000000..0cc3b59
--- /dev/null
+++ b/app/views/resources/_common/_resource_tr.php
@@ -0,0 +1,291 @@
+<?
+/**
+ * This is a general table row template for resources.
+ *
+ * Template variables:
+ *
+ * $resource: A Resource object.
+ * $booking_plan_link_on_name: Boolean: Whether the link to the booking plan
+ * shall be wrapped around the name (true) or not (false). In the latter
+ * case, the link will point to the info dialog of the resource instead.
+ * $show_global_admin_actions: Boolean: Whether to display actions which are
+ * designed for users with global 'admin' resource permissions.
+ * Defaults to false (do not show actions).
+ * $show_admin_actions: Boolean: Whether to display actions which are
+ * designed for users with 'admin' resource permissions.
+ * Defaults to false (do not show actions).
+ * $show_tutor_actions: Boolean: Whether to display actions which are
+ * designed for users with 'tutor' resource permissions.
+ * Defaults to false (do not show actions).
+ * $show_autor_actions: Boolean: Whether to display actions which are
+ * designed for users with 'autor' resource permissions.
+ * Defaults to false (do not show actions).
+ * $show_user_actions: Boolean: Whether to display actions which are
+ * designed for users with 'user' resource permissions.
+ * Defaults to false (do not show actions).
+ * $user_has_booking_rights: Boolean: Whether the user for which this template
+ * is rendered has booking rights on the resource (true) or not (false).
+ * $checkbox_data: Array: Data for an optional checkbox at the start
+ * of the row. If this is not set no checkbox is shown.
+ * The checkbox will get the resource-ID as value.
+ * Special array indexes:
+ * 'name' => The name of the checkbox. This index must be set.
+ * 'checked' => Boolean: True, if the checkbox shall be set (checked).
+ * false if it shall be unset (unchecked). Defaults to false.
+ * All other indexes will be added as HTML attributes.
+ * $show_picture: Boolean: Whether to display the resource picture or not.
+ * Defaults to false (do not show picture).
+ * $show_full_name: Boolean: Whether to display the full name
+ * (with resource type) or just the name field from the database.
+ * Defaults to false (do not show full name).
+ * $clipboard_range_type: String: The range type for the drag and drop
+ * functionality of the clipboard system.
+ * Defaults to 'Resource'.
+ * $additional_properties: Array: Additional properties
+ * that shall be displayed in extra columns.
+ * $additional_columns: Array: Additional columns for the table.
+ * This array contains HTML code for each column (without the td element).
+ * $additional_actions: Array: Additional actions for the action menu.
+ * This array contains associative arrays where each of those arrays
+ * has the following structure and indexes:
+ *
+ * $position_index => [
+ * 0 => Link
+ * 1 => Label
+ * 2 => Icon
+ * 3 => Link attributes
+ * ]
+ *
+ * $position_index is a string consisting of four letters with the
+ * first letter being either '0' or another letter. Depending on the
+ * value of $position_index the additional actions are placed
+ * before or after a standard action.
+ * The indexes for the standard actions are:
+ * - '0010': Show details
+ * - '0020': Show booking plan
+ * - '0030': Show semester plan
+ * - '0040': Manage permissions
+ * - '0050': Manage temporary permissions
+ * - '0060': Edit resource
+ * - '0070': Book resource
+ * - '0080': Mass deletion of bookings
+ * - '0090': Export bookings
+ * - '0100': Show files
+ * - '0110': Delete resource
+ */
+?>
+<tr>
+ <? if ($checkbox_data && $checkbox_data['name']): ?>
+ <?
+ if ($checkbox_data['checked']) {
+ $checkbox_data['checked'] = 'checked';
+ }
+ ?>
+ <td>
+ <input type="checkbox" class="select-resource"
+ value="<?= htmlReady($resource->id) ?>"
+ <?= arrayToHtmlAttributes($checkbox_data) ?>>
+ </td>
+ <? endif ?>
+ <td>
+ <a href="<?= (
+ $booking_plan_link_on_name
+ ? $resource->getActionLink('booking_plan')
+ : $resource->getActionLink('show')
+ ) ?>"
+ <?= $user_has_booking_rights ? '' : 'data-dialog' ?>
+ data-id="<?= htmlReady($resource->id) ?>"
+ data-range_type="<?= $clipboard_range_type
+ ? htmlReady($clipboard_range_type)
+ : 'Resource' ?>"
+ data-name="<?= htmlReady($resource->name) ?>"
+ class="clipboard-draggable-item">
+ <? if ($show_picture): ?>
+ <? $picture_url = $resource->getPictureUrl(); ?>
+ <? if ($picture_url): ?>
+ <img class="small-resource-picture"
+ src="<?= htmlReady($picture_url) ?>">
+ <? else: ?>
+ <?= $resource->getIcon('clickable') ?>
+ <? endif ?>
+ <span class="text-bottom">
+ <?= htmlReady(
+ $show_full_name
+ ? $resource->getFullName()
+ : $resource->name
+ ) ?>
+ </span>
+ <? else: ?>
+ <?= htmlReady($resource->name) ?>
+ <?= Icon::create('link-intern')->asImg(['class' => 'text-bottom']) ?>
+ <? endif ?>
+ </a>
+ <? if ($resource_tooltip): ?>
+ <span class="text-bottom">
+ <?= tooltipIcon($resource_tooltip) ?>
+ </span>
+ <? endif ?>
+ </td>
+ <? if ($additional_properties): ?>
+ <? foreach ($additional_properties as $additional_property): ?>
+ <td>
+ <? $value = null;
+ $property = $resource->getPropertyObject($additional_property);
+ if ($property instanceof ResourceProperty) {
+ $value = $property->__toString();
+ } elseif($resource->isField($additional_property)) {
+ //There is a SORM field with the name $additional_property.
+ $value = $resource->__get($additional_property);
+ }
+ ?>
+ <?= htmlReady($value) ?>
+ </td>
+ <? endforeach ?>
+ <? endif ?>
+ <? if ($additional_columns): ?>
+ <? foreach ($additional_columns as $column): ?>
+ <td>
+ <?= htmlReady($column) ?>
+ </td>
+ <? endforeach ?>
+ <? endif ?>
+ <? if ($show_user_actions || $show_autor_actions
+ || $show_tutor_actions || $show_admin_actions
+ || $show_global_admin_actions || $additional_actions): ?>
+ <td class="actions">
+ <?
+ //Build the actions as array. Ordering is done by array indexes.
+
+ $actions = [];
+ $action_menu = ActionMenu::get();
+ if ($show_user_actions) {
+ $actions['0010'] = [
+ $resource->getActionLink('show'),
+ _('Details'),
+ Icon::create('info-circle'),
+ ['data-dialog' => 'size=auto']
+ ];
+
+ $actions['0020'] = [
+ $resource->getActionLink('booking_plan'),
+ _('Belegungsplan'),
+ Icon::create('timetable')
+ ];
+
+ $actions['0030'] = [
+ $resource->getActionLink('semester_plan'),
+ _('Semester-Belegungsplan'),
+ Icon::create('timetable'),
+ ['target' => '_blank']
+ ];
+ if ($show_admin_actions) {
+ $actions['0040'] = [
+ $resource->getActionLink('permissions'),
+ _('Berechtigungen verwalten'),
+ Icon::create('roles2'),
+ ['data-dialog' => 'size=auto']
+ ];
+ $actions['0050'] = [
+ $resource->getActionLink('temporary_permissions'),
+ _('Temporäre Berechtigungen verwalten'),
+ Icon::create('roles2'),
+ ['data-dialog' => 'size=auto']
+ ];
+ $actions['0060'] = [
+ $resource->getActionLink('edit'),
+ _('Bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ ];
+ }
+ if ($show_autor_actions) {
+ $actions['0070'] = [
+ $resource->getActionLink(
+ 'assign-undecided',
+ [
+ 'no_reload' => '1'
+ ]
+ ),
+ _('Buchen'),
+ Icon::create('lock-locked'),
+ [
+ 'data-dialog' => 'size=big'
+ ]
+ ];
+ if ($show_global_admin_actions) {
+ $actions['0080'] = [
+ $resource->getActionLink(
+ 'delete_bookings',
+ [
+ 'no_reload' => '1'
+ ]
+ ),
+ _('Buchungen löschen'),
+ Icon::create('trash'),
+ ['data-dialog' => 'size=auto']
+ ];
+ }
+ }
+ if ($show_user_actions) {
+ $actions['0090'] = [
+ $resource->getActionLink('export_bookings'),
+ _('Buchungen exportieren'),
+ Icon::create('file-excel'),
+ ['data-dialog' => 'size=auto']
+ ];
+ }
+ $actions['0100'] = [
+ $resource->getActionLink('files'),
+ _('Dateien anzeigen'),
+ Icon::create(
+ $resource->hasFiles()
+ ? 'folder-full'
+ : 'folder-empty'
+ ),
+ []
+ ];
+ if ($show_global_admin_actions) {
+ $actions['0110'] = [
+ $resource->getActionLink('delete'),
+ _('Löschen'),
+ Icon::create('trash'),
+ ['data-dialog' => '']
+ ];
+ }
+ } else {
+ if ($resource->propertyExists('booking_plan_is_public')) {
+ if ($resource->booking_plan_is_public) {
+ $actions['0020'] = [
+ $resource->getActionLink('booking_plan'),
+ _('Belegungsplan anzeigen'),
+ Icon::create('timetable'),
+ [
+ 'target' => '_blank'
+ ]
+ ];
+ }
+ }
+ }
+ //Add additional actions for the action menu, if set:
+ if (is_array($additional_actions)) {
+ $actions = array_merge($actions, $additional_actions);
+ }
+ //Now we sort the actions by key:
+ ksort($actions);
+
+ //And finally we add the actions to the action menu:
+ foreach ($actions as $action) {
+ if (is_array($action)) {
+ $action_menu->addLink(
+ $action[0],
+ $action[1],
+ $action[2],
+ is_array($action[3]) ? $action[3] : []
+ );
+ }
+ }
+ ?>
+ <?= $action_menu->render() ?>
+ </td>
+ <? endif ?>
+</tr>
diff --git a/app/views/resources/_common/_resource_tree_item.php b/app/views/resources/_common/_resource_tree_item.php
new file mode 100644
index 0000000..204aa2e
--- /dev/null
+++ b/app/views/resources/_common/_resource_tree_item.php
@@ -0,0 +1,31 @@
+<?php
+$children = $resource->children;
+$has_children = count($children) > 0;
+?>
+<article class="studip <?= $has_children ? 'toggle' : ''?> <?= $open ? 'open' : ''?>">
+ <header>
+ <h1>
+ <a href="#"><?= htmlReady($resource->getFullName()) ?></a>
+ </h1>
+ <a href="<?= $resource->getActionLink('show') ?>" data-dialog>
+ <?= Icon::create('info-circle') ?>
+ </a>
+ </header>
+ <? if ($has_children) : ?>
+ <section>
+ <? foreach ($children as $child) : ?>
+ <?= $this->render_partial(
+ 'resources/_common/_resource_tree_item',
+ [
+ 'resource' => $child,
+ 'open' => false
+ ]
+ ) ?>
+ <? endforeach ?>
+ </section>
+ <? else : ?>
+ <section>
+ <?= htmlReady($resource->description) ?>
+ </section>
+ <? endif ?>
+</article>
diff --git a/app/views/resources/_common/_room_search_result.php b/app/views/resources/_common/_room_search_result.php
new file mode 100644
index 0000000..1da06b0
--- /dev/null
+++ b/app/views/resources/_common/_room_search_result.php
@@ -0,0 +1,105 @@
+<article class="studip room-list-item">
+ <header class="widget-header">
+ <h1><?= Assets::img(
+ 'anfasser_24.png',
+ [
+ 'class' => 'clipboard-draggable-item',
+ 'data-id' => $room->id,
+ 'data-range_type' => 'Room',
+ 'data-name' => $room->name
+ ]
+ ) ?><?= htmlReady($room->name) ?></h1>
+ <?
+ $actions = ActionMenu::get();
+ $actions->addLink(
+ $room->getActionLink('show'),
+ _('Raumdetails anzeigen'),
+ Icon::create('info-circle'),
+ ['data-dialog' => '']
+ );
+ if ($room->userHasPermission($current_user, 'autor')) {
+ $actions->addLink(
+ $room->getActionLink('booking_plan'),
+ _('Wochenbelegung'),
+ Icon::create('timetable'),
+ ['target' => '_blank']
+ );
+ $actions->addLink(
+ $room->getActionLink('semester_plan'),
+ _('Semesterbelegung'),
+ Icon::create('timetable'),
+ ['target' => '_blank']
+ );
+ } else {
+ $actions->addLink(
+ $room->getActionLink('booking_plan'),
+ _('Belegungsplan'),
+ Icon::create('timetable'),
+ ['data-dialog' => 'size=big']
+ );
+ $actions->addLink(
+ $room->getActionLink('semester_plan'),
+ _('Semesterbelegung'),
+ Icon::create('timetable'),
+ ['data-dialog' => 'size=big']
+ );
+ }
+ if ($room->requestable && $room->userHasRequestRights($current_user)) {
+ $actions->addLink(
+ $room->getActionLink('request'),
+ _('Raum anfragen'),
+ Icon::create('room-request'),
+ ['data-dialog' => 'size=auto']
+ );
+ }
+ if ($room->building) {
+ $actions->addLink(
+ ResourceManager::getMapUrlForResourcePosition(
+ $room->building->getPropertyObject('geo_coordinates')
+ ),
+ _('Zum Lageplan'),
+ Icon::create('globe'),
+ ['target' => '_blank']
+ );
+ }
+ if ($clipboard_widget_id) {
+ $actions->addLink(
+ '#',
+ _('Zur Raumgruppe hinzufügen'),
+ IcoN::create('add'),
+ [
+ 'class' => 'clipboard-add-item-button',
+ 'data-range_type' => 'Room',
+ 'data-range_id' => $room->id,
+ 'data-clipboard_id' => $clipboard_widget_id
+ ]
+ );
+ }
+ ?>
+ <?= $actions->render() ?>
+ </header>
+ <section>
+ <p class="description">
+ <?= htmlReady($room->description) ?>
+ </p>
+ <section class="properties-and-actions">
+ <ul class="property-list">
+ <? if ($room->room_type): ?>
+ <li><?= htmlReady($room->room_type) ?></li>
+ <? endif ?>
+ <? if ($room->seats): ?>
+ <li>
+ <?= sprintf(
+ ngettext(
+ '%d Sitzplatz',
+ '%d Sitzplätze',
+ $room->seats
+ ),
+ $room->seats
+ ) ?>
+ </li>
+ <? endif ?>
+ </ul>
+ </section>
+ </section>
+</article>
diff --git a/app/views/resources/_common/_room_thead.php b/app/views/resources/_common/_room_thead.php
new file mode 100644
index 0000000..da08545
--- /dev/null
+++ b/app/views/resources/_common/_room_thead.php
@@ -0,0 +1,21 @@
+<thead>
+ <tr>
+ <th><?= _('Raumname') ?></th>
+ <th><?= _('Sitzplätze') ?></th>
+ <? if ($additional_properties): ?>
+ <? foreach ($additional_properties as $display_name): ?>
+ <th>
+ <?= htmlReady($display_name) ?>
+ </th>
+ <? endforeach ?>
+ <? endif ?>
+ <? if ($additional_columns): ?>
+ <? foreach ($additional_columns as $column_name): ?>
+ <th>
+ <?= htmlReady($column_name) ?>
+ </th>
+ <? endforeach ?>
+ <? endif ?>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+</thead>
diff --git a/app/views/resources/_common/_room_tr.php b/app/views/resources/_common/_room_tr.php
new file mode 100644
index 0000000..7950211
--- /dev/null
+++ b/app/views/resources/_common/_room_tr.php
@@ -0,0 +1,78 @@
+<?
+/**
+ * This is a specialisation of the _resource_tr template for rooms.
+ *
+ * Template variables:
+ *
+ * $room: A Room object.
+ * $show_admin_actions: Boolean: Whether to display actions which are
+ * designed for users with 'admin' resource permissions.
+ * Defaults to false (do not show actions).
+ * $show_tutor_actions: Boolean: Whether to display actions which are
+ * designed for users with 'tutor' resource permissions.
+ * Defaults to false (do not show actions).
+ * $show_autor_actions: Boolean: Whether to display actions which are
+ * designed for users with 'autor' resource permissions.
+ * Defaults to false (do not show actions).
+ * $show_user_actions: Boolean: Whether to display actions which are
+ * designed for users with 'user' resource permissions.
+ * Defaults to false (do not show actions).
+ * $user_has_booking_rights: Boolean: Whether the user for which this template
+ * is rendered has booking rights on the resource (true) or not (false).
+ * $show_room_picture: Boolean: Whether to display the room picture or not.
+ * Defaults to false (do not show picture).
+ * $additional_properties: Array: Additional properties
+ * that shall be displayed in extra columns.
+ * $additional_columns: Array: Additional columns for the table.
+ * $additional_actions: Array: Additional actions for the action menu.
+ * This array contains associative arrays where each of those arrays
+ * has the following structure and indexes:
+ * [
+ * 0 => Link
+ * 1 => Label
+ * 2 => Icon
+ * 3 => Link attributes
+ * ]
+ */
+?>
+
+<?
+$room_actions = [];
+if ($room->requestable && $show_autor_actions) {
+ $room_actions = [
+ '0071' => [
+ $room->getActionLink('request_list'),
+ _('Anfragen auflösen'),
+ Icon::create('room-request'),
+ ['target' => '_blank']
+ ]
+ ];
+} ?>
+
+<?= $this->render_partial(
+ 'resources/_common/_resource_tr.php',
+ [
+ 'checkbox_data' => $checkbox_data,
+ 'resource' => $room,
+ 'booking_plan_link_on_name' => true,
+ 'resource_tooltip' => $room_tooltip,
+ 'show_global_admin_actions' => $show_global_admin_actions,
+ 'show_admin_actions' => $show_admin_actions,
+ 'show_tutor_actions' => $show_tutor_actions,
+ 'show_autor_actions' => $show_autor_actions,
+ 'show_user_actions' => $show_user_actions,
+ 'user_has_booking_rights' => $user_has_booking_rights,
+ 'show_picture' => true,
+ 'show_full_name' => false,
+ 'additional_properties' => ['seats'],
+ 'clipboard_range_type' => 'Room',
+ 'additional_actions' => (
+ is_array($additional_actions)
+ ? array_merge(
+ $room_actions,
+ $additional_actions
+ )
+ : $room_actions
+ )
+ ]
+) ?>
diff --git a/app/views/resources/_common/building.php b/app/views/resources/_common/building.php
new file mode 100644
index 0000000..7eae032
--- /dev/null
+++ b/app/views/resources/_common/building.php
@@ -0,0 +1,33 @@
+<article class="resource-object">
+ <header class="resource-header">
+ <h2><?= htmlReady(
+ ($building->number
+ ? $building->number->state
+ : '' ) .
+ $building->name) ?></h2>
+ </header>
+ <section class="resource-details">
+ <img class="resource-picture" src="<?= $building->getImageUrl() ?>">
+
+ <p><?= htmlReady($building->description) ?></p>
+ <dl>
+ <dt><?= _('Adresse') ?></dt>
+ <dd><?= htmlReady($building->address->state) ?>
+ <a href="<?= ResourceManager::getMapUrlForResourcePosition(
+ $building->geo_coordinates
+ ) ?>">
+ <?= Icon::create('place')->asImg(16) ?>
+ </a>
+ </dd>
+ <dt><?= _('Verantwortliche Person') ?></dt>
+ <dd>
+ <?= $building->facility_manager
+ ? htmlReady($building->facility_manager->getFullName())
+ : '&#x1f4a9; ' . _('unbekannt') ?>
+ </dd>
+ </dl>
+ <? if ($building->disability_friendly): ?>
+ <strong>&#x2713; <?= _('Das Gebäude ist behindertengerecht ausgestattet.') ?></strong>
+ <? endif ?>
+ </section>
+</article>
diff --git a/app/views/resources/_common/location.php b/app/views/resources/_common/location.php
new file mode 100644
index 0000000..c9f8735
--- /dev/null
+++ b/app/views/resources/_common/location.php
@@ -0,0 +1,19 @@
+<article class="resource-object">
+ <header class="resource-header">
+ <h2><?= htmlReady($location->name) ?></h2>
+ </header>
+ <section class="resource-details">
+ <img class="resource-picture" src="<?= $building->getImageUrl() ?>">
+ <p><?= htmlReady($location->description) ?></p>
+ <dl>
+ <dt><?= _('Adresse') ?></dt>
+ <dd><?= htmlReady($location->getAddress()) ?>
+ <a href="<?= ResourceManager::getMapUrlForResourcePosition(
+ $location->geo_coordinates
+ ) ?>">
+ <?= Icon::create('place')->asImg(16) ?>
+ </a>
+ </dd>
+ </dl>
+ </section>
+</article>
diff --git a/app/views/resources/admin/booking_log.php b/app/views/resources/admin/booking_log.php
new file mode 100644
index 0000000..70d3c1d
--- /dev/null
+++ b/app/views/resources/admin/booking_log.php
@@ -0,0 +1,104 @@
+<? if ($bookings): ?>
+ <table class="default">
+ <caption>
+ <? if ($show_all_records): ?>
+ <? if ($resource): ?>
+ <?= sprintf(
+ _('%1$s: Alle Buchungen von %2$s'),
+ htmlReady($resource->getFullName()),
+ htmlReady($user->getFullName())
+ ) ?>
+ <? else: ?>
+ <?= sprintf(
+ _('Alle Buchungen von %s'),
+ htmlReady($user->getFullName())
+ ) ?>
+ <? endif ?>
+ <? else: ?>
+ <? if ($resource): ?>
+ <?= sprintf(
+ _('%1$s: Aktuelle und zukünftige Buchungen von %2$s'),
+ htmlReady($resource->getFullName()),
+ htmlReady($user->getFullName())
+ ) ?>
+ <? else: ?>
+ <?= sprintf(
+ _('Aktuelle und zukünftige Buchungen von %s'),
+ htmlReady($user->getFullName())
+ ) ?>
+ <? endif ?>
+ <? endif ?>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Buchungszeiträume') ?></th>
+ <th><?= _('Interner Kommentar') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($bookings as $booking): ?>
+ <tr>
+ <td>
+ <? $intervals = $booking->getTimeIntervals() ?>
+ <? if ($intervals): ?>
+ <ul class="default">
+ <? foreach ($intervals as $interval): ?>
+ <li>
+ <?= date('d.m.Y H:i', $interval->begin) ?>
+ -
+ <?= date('d.m.Y H:i', $interval->end) ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? else: ?>
+ <?= date('d.m.Y H:i', $booking->begin) ?>
+ -
+ <?= date('d.m.Y H:i', $booking->end) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= htmlReady($booking->internal_comment) ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? else: ?>
+ <?= MessageBox::info(
+ _('Es liegen keine Buchungen vor!')
+ ) ?>
+<? endif ?>
+<div data-dialog-button>
+ <? if ($show_all_records): ?>
+ <?= \Studip\LinkButton::create(
+ _('Nur aktuelle und zukünftige Buchungen anzeigen'),
+ URLHelper::getURL(
+ 'dispatch.php/resources/admin/booking_log/' . $user->id
+ . ($resource
+ ? '/' . $resource->id
+ : ''
+ )
+ ),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <? else: ?>
+ <?= \Studip\LinkButton::create(
+ _('Auch stattgefundene Buchungen anzeigen'),
+ URLHelper::getURL(
+ 'dispatch.php/resources/admin/booking_log/' . $user->id
+ . ($resource
+ ? '/' . $resource->id
+ : ''
+ ),
+ [
+ 'show_all_records' => '1'
+ ]
+ ),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <? endif ?>
+</div>
diff --git a/app/views/resources/admin/categories.php b/app/views/resources/admin/categories.php
new file mode 100644
index 0000000..0b69231
--- /dev/null
+++ b/app/views/resources/admin/categories.php
@@ -0,0 +1,76 @@
+<? if ($categories): ?>
+ <table class="default resource-categories">
+ <colspan>
+ <col style="width: 20px">
+ <col style="width: 50%">
+ <col style="width: 30%">
+ <col style="width:10%">
+ <col class="actions">
+ </colspan>
+ <thead>
+ <tr>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Klassenname') ?></th>
+ <th><?= _('System-Kategorie') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($categories as $category): ?>
+ <tr>
+ <td>
+ <?= $category->getIcon()->asImg(20) ?>
+ </td>
+ <td><?= htmlReady($category->name) ?></td>
+ <td><?= htmlReady($category->class_name) ?></td>
+ <td style="text-align: center">
+ <?= Icon::create(
+ sprintf('checkbox-%s', $category->system ? 'checked' : 'unchecked'),
+ Icon::ROLE_INFO
+ ) ?>
+ </td>
+ <td class="actions">
+ <?php
+ $actions = ActionMenu::get()
+ ->conditionAll($category->hasResources())
+ ->addLink(
+ $controller->url_for(
+ 'resources/category/show_resources/' . $category->id
+ ),
+ _('Alle Ressourcen anzeigen'),
+ Icon::create('log'),
+ ['data-dialog' => 'size=auto'])
+ ->addLink(
+ $controller->url_for(
+ 'resources/category/details', $category
+ ),
+ _('Details anzeigen'),
+ Icon::create('info-circle'),
+ ['data-dialog' => 'size=auto']
+ )
+ ->conditionAll(true)
+ ->addLink(
+ $controller->url_for(
+ 'resources/category/edit/' . $category->id
+ ),
+ _('Bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto'])
+ ->condition($category->system == '0')
+ ->addLink(
+ $controller->url_for(
+ 'resources/category/delete/' . $category->id
+ ),
+ _('Löschen'),
+ Icon::create('trash'),
+ ['data-dialog' => 'size=auto']
+ );
+ echo $actions->render();
+ ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? endif ?>
diff --git a/app/views/resources/admin/configuration.php b/app/views/resources/admin/configuration.php
new file mode 100644
index 0000000..3b72cc9
--- /dev/null
+++ b/app/views/resources/admin/configuration.php
@@ -0,0 +1,118 @@
+<form class="default" method="post"
+ action="<?= URLHelper::getLink('dispatch.php/resources/admin/configuration')?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grundeinstellungen') ?></legend>
+ <label>
+ <input type="hidden" name="resources_enable" value="0">
+ <input type="checkbox" name="resources_enable" value="1"
+ <?= $config->RESOURCES_ENABLE == '1'
+ ? 'checked="checked"'
+ : ''?>>
+ <?= _('Raumverwaltung aktivieren') ?>
+ </label>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Anzeigeoptionen') ?></legend>
+ <label>
+ <input type="checkbox" name="resources_allow_view_resource_occupation"
+ value="1"
+ <?= $config->RESOURCES_ALLOW_VIEW_RESOURCE_OCCUPATION == '1'
+ ? 'checked="checked"'
+ : ''?>>
+ <?= _('Belegungen sind sichtbar für alle Nutzer') ?>
+ </label>
+ <? if ($colours): ?>
+ <? foreach ($colours as $colour): ?>
+ <label>
+ <?= htmlReady(
+ $colour->description
+ ? $colour->description
+ : $colour->color_id
+ ) ?>
+ <input type="color" name="colours[<?= htmlReady($colour->colour_id) ?>]"
+ value="<?= htmlReady($colour) ?>">
+ </label>
+ <? endforeach ?>
+ <? endif ?>
+ <label>
+ <?= _('URL für Kartendienst') ?>
+ <input type="text" name="resources_map_service_url"
+ placeholder="https://www.openstreetmap.org/#map=17/LATITUDE/LONGITUDE"
+ value="<?= htmlReady($config->RESOURCES_MAP_SERVICE_URL) ?>">
+ <?= _('Die URL muss zwei Platzhalter enhalten: LATITUDE für die Längenangabe und LONGITUDE für die Breitenangabe.') ?>
+ </label>
+ <label>
+ <?= _('Ab welcher Uhrzeit sollen Belegungen in der Standardansicht des Belegungsplans angezeigt werden?')?>
+ <input type="text" name="resources_booking_plan_start_hour"
+ placeholder="HH:MM"
+ value="<?= htmlReady($resources_booking_plan_start_hour) ?>">
+ </label>
+ <label>
+ <?= _('Bis zu welcher Uhrzeit sollen Belegungen in der Standardansicht des Belegungsplans angezeigt werden?')?>
+ <input type="text" name="resources_booking_plan_end_hour"
+ placeholder="HH:MM"
+ value="<?= htmlReady($resources_booking_plan_end_hour) ?>">
+ </label>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Raumanfragen') ?></legend>
+ <label>
+ <input type="checkbox" name="resources_allow_room_requests"
+ value="1"
+ <?= $config->RESOURCES_ALLOW_ROOM_REQUESTS == '1'
+ ? 'checked="checked"'
+ : ''?>>
+ <?= _('Ressourcenanfragen sind eingeschaltet') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="resources_allow_room_property_requests"
+ value="1"
+ <?= $config->RESOURCES_ALLOW_ROOM_PROPERTY_REQUESTS == '1'
+ ? 'checked="checked"'
+ : ''?>>
+ <?= _('Ressourceneigenschaften dürfen bei einer Anfrage gewünscht werden') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="resources_direct_room_requests_only"
+ value="1"
+ <?= $config->RESOURCES_DIRECT_ROOM_REQUESTS_ONLY == '1'
+ ? 'checked="checked"'
+ : ''?>>
+ <?= _('Nur konkrete Raumanfragen erlauben') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="resources_display_current_requests_in_overview"
+ value="1"
+ <?= $config->RESOURCES_DISPLAY_CURRENT_REQUESTS_IN_OVERVIEW == '1'
+ ? 'checked="checked"'
+ : ''?>>
+ <?= _('Aktuelle Raumanfragen auf der Übersichtsseite anzeigen') ?>
+ </label>
+ <label>
+ <?= _('Ab welchem Prozentwert (für den Anteil an Belegungen) sollen Einzelbelegungen statt Serienbelegungen durchgeführt werden, wenn es zu Überschneidungen kommt?')?>
+ <input type="number" name="resources_allow_single_assign_percentage"
+ min="0" max="100" step="1"
+ value="<?= htmlReady($config->RESOURCES_ALLOW_SINGLE_ASSIGN_PERCENTAGE) ?>">
+ </label>
+ <label>
+ <?= _('Ab welcher Anzahl an Einzelterminen sollen diese zusammengefasst zu einer Gruppe bearbeitet werden?') ?>
+ <input type="number" name="resources_allow_single_date_grouping"
+ value="<?= htmlReady($config->RESOURCES_ALLOW_SINGLE_DATE_GROUPING) ?>">
+ </label>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Buchen von Räumen und Ressourcen') ?></legend>
+ <label>
+ <?= _('Wie lange darf die Rüstzeit vor dem Beginn einer Buchung maximal dauern? (Angabe in Minuten)') ?>
+ <input type="number" name="resources_max_preparation_time"
+ value="<?= htmlReady($config->RESOURCES_MAX_PREPARATION_TIME) ?>">
+ </label>
+ <label>
+ <?= _('Was ist die kürzeste erlaubte Dauer einer Buchung in Minuten?') ?>
+ <input type="number" name="resources_min_booking_time"
+ value="<?= htmlReady($config->RESOURCES_MIN_BOOKING_TIME) ?>">
+ </label>
+ </fieldset>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+</form>
diff --git a/app/views/resources/admin/global_locks.php b/app/views/resources/admin/global_locks.php
new file mode 100644
index 0000000..e4c55df
--- /dev/null
+++ b/app/views/resources/admin/global_locks.php
@@ -0,0 +1,54 @@
+<? if ($current_lock): ?>
+ <?= MessageBox::info(
+ sprintf(
+ _('Die Raumverwaltung ist vom %1$s bis zum %2$s gesperrt.'),
+ date('d.m.Y H:i', $current_lock->begin),
+ date('d.m.Y H:i', $current_lock->end)
+ )
+ ) ?>
+<? endif ?>
+<? if ($future_locks): ?>
+ <table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Beginn') ?></th>
+ <th><?= _('Ende') ?></th>
+ <th><?= _('Typ der Sperrung') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($future_locks as $lock): ?>
+ <tr>
+ <td><?= date('d.m.Y H:i', $lock->begin) ?></td>
+ <td><?= date('d.m.Y H:i', $lock->end) ?></td>
+ <td><?= $lock->getTypeString() ?></td>
+ <td class="actions">
+ <?= ActionMenu::get()
+ ->addLink(
+ $controller->url_for('resources/global_locks/edit/' . $lock->id),
+ _('Sperrung bearbeiten'),
+ Icon::create('edit'),
+ [
+ 'data-dialog' => 'size=auto'
+ ])
+ ->addLink(
+ $controller->url_for('resources/global_locks/delete/' . $lock->id),
+ _('Sperrung löschen'),
+ Icon::create('trash'),
+ [
+ 'data-dialog' => 'size=auto'
+ ]
+ )
+ ->render();
+ ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? else: ?>
+ <?= MessageBox::info(
+ _('Es sind keine gegenwärtigen und zukünftigen Sperren der Raumverwaltung hinterlegt.')
+ ) ?>
+<? endif ?>
diff --git a/app/views/resources/admin/permissions.php b/app/views/resources/admin/permissions.php
new file mode 100644
index 0000000..85ebfda
--- /dev/null
+++ b/app/views/resources/admin/permissions.php
@@ -0,0 +1 @@
+<?= $other_controllers_html ?>
diff --git a/app/views/resources/admin/properties.php b/app/views/resources/admin/properties.php
new file mode 100644
index 0000000..ac0b97a
--- /dev/null
+++ b/app/views/resources/admin/properties.php
@@ -0,0 +1,68 @@
+<? if ($properties): ?>
+ <table class="default sortable-table" id="Resources_PropertyTable"
+ data-sortlist="[[0, 0]]">
+ <thead>
+ <tr>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="text"><?= _('Angezeigter Name') ?></th>
+ <th data-sort="text"><?= _('Typ') ?></th>
+ <th><?= _('Minimale Rechtestufe für Änderungen') ?></th>
+ <th><?= _('Mögliches Suchkriterium') ?></th>
+ <th><?= _('Verwendung in Kategorien') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($properties as $property): ?>
+ <tr>
+ <td><?= htmlReady($property->name) ?></td>
+ <td>
+ <?= htmlReady(
+ trim($property->display_name)
+ ? $property->display_name
+ : $property->name
+ ) ?>
+ </td>
+ <td><?= htmlReady($property->type) ?></td>
+ <td><?= htmlReady($property->write_permission_level) ?></td>
+ <td><?= $property->searchable ? _('ja') : _('nein') ?></td>
+ <td>
+ <? if (is_array($categories[$property->id])): ?>
+ <?= htmlReady(implode(', ', $categories[$property->id])) ?>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <form method="post" class="default"
+ action="<?= $controller->url_for('resources/property/delete/' . $property->id)?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <a href="<?=$controller->url_for('resources/property/edit/' . $property->id)?>"
+ data-dialog="size=auto">
+ <?= Icon::create('edit')->asImg(
+ [
+ 'title' => _('Bearbeiten')
+ ]
+ ) ?>
+ </a>
+ <? if (!$property->system): ?>
+ <?= Icon::create('trash')->asInput(
+ [
+ 'title' => _('Löschen'),
+ 'data-confirm' => sprintf(
+ _('Soll die Eigenschaft "%s" wirklich gelöscht werden?'
+ ),
+ htmlReady($property->name)
+ )
+ ]
+ ) ?>
+ <? endif ?>
+ </form>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? else: ?>
+ <?= MessageBox::info(
+ _('Es sind keine Eigenschaften definiert!')
+ ) ?>
+<? endif ?>
diff --git a/app/views/resources/admin/property_groups.php b/app/views/resources/admin/property_groups.php
new file mode 100644
index 0000000..0146474
--- /dev/null
+++ b/app/views/resources/admin/property_groups.php
@@ -0,0 +1,162 @@
+<form class="default" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($property_groups): ?>
+ <table class="default">
+ <caption><?= _('Eigenschaftsgruppen')?></caption>
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th colspan="4">
+ <p>
+ <?= _('Die ausgewählten Gruppen werden beim Speichern gelöscht bzw. die ausgewählten Eigenschaften aus der Gruppe entfernt.') ?>
+ </p>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </th>
+ </tr>
+ <tr>
+ <th>
+ <label>
+ <input type="checkbox"
+ title="<?= _('Alle Gruppen löschen') ?>"
+ data-proxyfor="input[name='selected_groups[]']">
+ </label>
+ </th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Eigenschaften') ?></th>
+ <th><?= _('Position') ?></th>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr>
+ <td colspan="4">
+ <p>
+ <?= _('Die ausgewählten Gruppen werden beim Speichern gelöscht bzw. die ausgewählten Eigenschaften aus der Gruppe entfernt.') ?>
+ </p>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <tbody>
+ <? foreach ($property_groups as $group): ?>
+ <tr>
+ <td>
+ <input type="checkbox" title="<?= _('Gruppe löschen') ?>"
+ name="selected_groups[]"
+ data-proxyfor="input[name='selected_group_properties[<?= htmlReady($group->id) ?>][]']"
+ value="<?= htmlReady($group->id) ?>">
+ </td>
+ <td>
+ <input type="text"
+ name="edited_group_names[<?= htmlReady($group->id) ?>]"
+ value="<?= htmlReady($group->name) ?>">
+ </td>
+ <td></td>
+ <td>
+ <input type="num" value="<?= htmlReady($group->position) ?>"
+ name="group_position[<?= htmlReady($group->id) ?>]">
+ </td>
+ </tr>
+ <? foreach ($group->properties as $property): ?>
+ <tr>
+ <td>
+ <input type="checkbox"
+ title="<?= _('Aus der Gruppe entfernen') ?>"
+ name="selected_group_properties[<?= htmlReady($group->id) ?>][]"
+ value="<?= htmlReady($property->id) ?>">
+ </td>
+ <td></td>
+ <td>
+ <?= htmlReady($property->__toString())?>
+ (<?= htmlReady($property->type)?>)
+ </td>
+ <td>
+ <input type="num"
+ value="<?= htmlReady($property->property_group_pos)?>"
+ name="property_position[<?= htmlReady($property->id)?>]">
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? else: ?>
+ <?= MessageBox::info(
+ _('Es sind keine Eigenschaftsgruppen vorhanden!')
+ ) ?>
+ <? endif ?>
+
+ <? if ($ungrouped_properties): ?>
+ <table class="default">
+ <caption><?= _('Ungruppierte Eigenschaften')?></caption>
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ title="<?= _('Alle Eigenschaften zu einer neuen Gruppe hinzufügen') ?>"
+ data-proxyfor="input[name='selected_properties[]']">
+ </th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Angezeigter Name') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Gruppe zuweisen') ?></th>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr>
+ <td colspan="5">
+ <label class="undecorated">
+ <?= _('Neue Gruppe anlegen') ?>
+ <input type="text" name="new_group_name"
+ value="<?= htmlReady($new_group_name)?>">
+ </label>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <tbody>
+ <? foreach ($ungrouped_properties as $property): ?>
+ <tr>
+ <td>
+ <input type="checkbox"
+ title="<?= _('Zu einer neuen Gruppe hinzufügen') ?>"
+ name="selected_properties[]"
+ value="<?= htmlReady($property->id) ?>">
+ </td>
+ <td><?= htmlReady($property->name) ?></td>
+ <td><?= htmlReady($property->__toString()) ?></td>
+ <td><?= htmlReady($property->type) ?></td>
+ <td>
+ <? if ($property_groups): ?>
+ <select name="property_move[<?= htmlReady($property->id)?>]">
+ <option value=""
+ <?= $property_move[$property->id] == ''
+ ? 'selected="selected"'
+ : '' ?>></option>
+ <? foreach ($property_groups as $group): ?>
+ <option value="<?= htmlReady($group->id) ?>"
+ <?= $property_move[$property->id] == $group->id
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($group->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? endif ?>
+</form>
diff --git a/app/views/resources/admin/separable_rooms.php b/app/views/resources/admin/separable_rooms.php
new file mode 100644
index 0000000..ec87f40
--- /dev/null
+++ b/app/views/resources/admin/separable_rooms.php
@@ -0,0 +1,173 @@
+<form class="default" method="post"
+ action="<?= URLHelper::getLink('dispatch.php/resources/admin/separable_rooms') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($building_id): ?>
+ <input type="hidden" name="building_id"
+ value="<?= htmlReady($building_id) ?>">
+ <? else: ?>
+ <select name="building_id">
+ <? foreach ($buildings as $building): ?>
+ <option value="<?= htmlReady($building->id) ?>"
+ <?= $building->id == $building_id
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($building->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <?= \Studip\Button::create(_('Gebäude auswählen'), 'select_building') ?>
+ <? endif ?>
+ <? if ($building_id): ?>
+ <? if ($separable_rooms): ?>
+ <table class="default">
+ <caption><?= sprintf(_('%s: Teilbare Räume'), htmlReady($building->name)) ?></caption>
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th style="width: 2em;">
+ <input type="checkbox"
+ data-proxyfor="<?= (
+ $separable_rooms
+ ? "input[name='selected_separable_rooms[]'"
+ : "input[name='selected_single_rooms[]'"
+ ) ?>]">
+ </th>
+ <th><?= _('Raumname') ?></th>
+ <th><?= _('Raumteile') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr>
+ <td colspan="5">
+ <? if ($separable_rooms): ?>
+ <?= \Studip\Button::create(
+ _('Teilbare Räume löschen'),
+ 'bulk_delete_separable_rooms'
+ ) ?>
+ <?= \Studip\Button::create(
+ _('Raumteile löschen'),
+ 'bulk_delete_room_parts'
+ ) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ </tfoot>
+ <tbody>
+ <? foreach ($separable_rooms as $separable_room): ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="selected_separable_rooms[]"
+ value="<?= htmlReady($separable_room->id) ?>">
+ </td>
+ <td><?= htmlReady($separable_room->name) ?></td>
+ <td></td>
+ <td class="actions">
+ <?= Icon::create('trash')->asInput(
+ [
+ 'name' => 'delete_separable_room['
+ . $separable_room->id . ']',
+ 'class' => 'text-bottom'
+ ]
+ ) ?>
+ </td>
+ </tr>
+ <? foreach ($separable_room->parts as $room_part): ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="selected_room_parts[]"
+ value="<?= htmlReady($room_part->id) ?>">
+ </td>
+ <td></td>
+ <td><?= htmlReady($room_part->getRoomName()) ?></td>
+ <td class="actions">
+ <?= Icon::create('trash')->asInput(
+ [
+ 'name' => 'delete_room_part['
+ . $room_part->id
+ . ']',
+ 'data-confirm' => _('Wollen Sie den Raum wirklich entfernen?'),
+ 'class' => 'text-bottom'
+ ]
+ ) ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? endif ?>
+ <? if ($single_rooms) : ?>
+ <table class="default">
+ <caption><?= sprintf(_('%s: Einzelne Räume'), htmlReady($building->name)) ?></caption>
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th style="width: 2em;">
+ <input type="checkbox"
+ data-proxyfor="input[name='selected_single_rooms[]']">
+ </th>
+ <th><?= _('Raumname') ?></th>
+ </tr>
+ </thead>
+ <tfoot>
+ <? if ($separable_rooms): ?>
+ <tr>
+ <td colspan="2">
+ <select name="separable_room_id">
+ <? foreach ($separable_rooms as $separable_room): ?>
+ <option value="<?= htmlReady($separable_room->id) ?>">
+ <?= htmlReady($separable_room->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <?= \Studip\Button::create(
+ _('Raumteil(e) zu teilbarem Raum hinzufügen'),
+ 'add_room_part'
+ ) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <tr>
+ <td colspan="2">
+ <input type="text" name="separable_room_name"
+ value="<?= htmlReady($separable_room_name) ?>"
+ placeholder="<?= _('Name des neuen teilbaren Raumes') ?>">
+ <?= \Studip\Button::create(
+ _('Neuen teilbaren Raum erzeugen'),
+ 'create_separable_room'
+ ) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <tbody>
+ <? if (($single_rooms) && ($separable_rooms)): ?>
+ <tr>
+ <th colspan="3">
+ <input type="checkbox"
+ data-proxyfor="input[name='selected_single_rooms[]']">
+ </th>
+ </tr>
+ <? endif ?>
+ <? foreach ($single_rooms as $room): ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="selected_single_rooms[]"
+ value="<?= htmlReady($room->id) ?>">
+ </td>
+ <td><?= htmlReady($room->name) ?></td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? endif ?>
+ <? endif ?>
+</form>
diff --git a/app/views/resources/admin/user_permissions.php b/app/views/resources/admin/user_permissions.php
new file mode 100644
index 0000000..9035b95
--- /dev/null
+++ b/app/views/resources/admin/user_permissions.php
@@ -0,0 +1,213 @@
+<? if ($user): ?>
+ <div>
+ <dl>
+ <dt><?= _('Globale Berechtigung') ?></dt>
+ <dd>
+ <? if ($global_permission): ?>
+ <?= htmlReady($global_permission->perms) ?>
+ <? if ($current_global_lock and ($global_permission->perms != 'admin')): ?>
+ <?= Icon::create('exclaim', 'attention')->asImg(
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('Die Berechtigung kann zurzeit aufgrund einer globalen Sperrung der Raumverwaltung nicht genutzt werden!')
+ ]
+ )?>
+ <? endif ?>
+ <? else: ?>
+ <?= _('keine') ?>
+ <? endif ?>
+ </dd>
+ <dt><?= _('Aktivität') ?></dt>
+ <dd title="<?= htmlReady($last_activity_date) ?>">
+ <? if ($last_activity): ?>
+ <? if ($last_activity->y): ?>
+ <?= sprintf(
+ ngettext(
+ 'Inaktiv seit mehr als einem Jahr',
+ 'Inaktiv seit mehr als %d Jahren',
+ $last_activity->y
+ ),
+ $last_activity->y
+ ) ?>
+ <? elseif ($last_activity->m): ?>
+ <?= sprintf(
+ ngettext(
+ 'Inaktiv seit mehr als einem Monat',
+ 'Inaktiv seit mehr als %d Monaten',
+ $last_activity->m
+ ),
+ $last_activity->m
+ ) ?>
+ <? elseif ($last_activity->d): ?>
+ <? if ($last_activity->d == 1): ?>
+ <?= _('Gestern zuletzt aktiv.') ?>
+ <? elseif ($last_activity->d == 2): ?>
+ <?= _('Vorgestern zuletzt aktiv.') ?>
+ <? else: ?>
+ <?= sprintf(
+ _('Inaktiv seit %d Tagen'),
+ $last_activity->d
+ ) ?>
+ <? endif ?>
+ <? else: ?>
+ <?= _('Innerhalb der letzten 24 Stunden zuletzt aktiv gewesen.') ?>
+ <? endif ?>
+ <? elseif ($last_activity === null): ?>
+ <?= _('keine') ?>
+ <? else: ?>
+ <?= _('Fehler') ?>
+ <? endif ?>
+ </dd>
+ </dl>
+ <? if ($last_activity !== null): ?>
+ <?= \Studip\LinkButton::create(
+ _('Liste mit Buchungen anzeigen'),
+ URLHelper::getLink(
+ 'dispatch.php/resources/admin/booking_log/'
+ . $user->id
+ ),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <? endif ?>
+ </div>
+ <? if ($temporary_permissions): ?>
+ <table class="default resources_permissions-table sortable-table"
+ data-sortlist="[[0, 0]]">
+ <caption>
+ <?= _('Temporäre Berechtigungen') ?>
+ </caption>
+ <thead>
+ <tr>
+ <th data-sort="text"><?= _('Name der Ressource') ?></th>
+ <th data-sort="1"><?= _('Berechtigung') ?></th>
+ <th><?= _('Gültigkeit') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($temporary_permissions as $permission): ?>
+ <tr>
+ <td>
+ <?= htmlReady($permission->resource->getDerivedClassInstance()) ?>
+ </td>
+ <td>
+ <?= htmlReady($permission->perms) ?>
+ <? if ($current_global_lock and ($permission->perms != 'admin')): ?>
+ <?= Icon::create('exclaim', 'attention')->asImg(
+ '20px',
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('Die Berechtigung kann aufgrund einer globalen Sperrung der Raumverwaltung zurzeit nicht genutzt werden!')
+ ]
+ )?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= date('d.m.Y H:i', $permission->begin) ?>
+ -
+ <?= date('d.m.Y H:i', $permission->end) ?>
+ </td>
+ <td class="actions">
+ <a href="<?= $permission->resource->getActionLink(
+ 'temporary_permissions',
+ [
+ 'user_id' => $permission->user_id
+ ]
+ ) ?>" data-dialog>
+ <?= Icon::create('edit')->asImg(
+ '20px',
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('Berechtigung bearbeiten')
+ ]
+ ) ?>
+ </a>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/admin/booking_log/'
+ . $user->id
+ . '/'
+ . $permission->resource_id
+ ) ?>" data-dialog>
+ <?= Icon::create('log')->asImg(
+ [
+ 'class' => 'text-bottom',
+ 'title' => 'Liste mit Buchungen anzeigen'
+ ]
+ ) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? endif ?>
+ <? if ($permissions): ?>
+ <table class="default resources_permissions-table sortable-table"
+ data-sortlist="[[0, 0]]">
+ <caption>
+ <?= _('Dauerhafte Berechtigungen') ?>
+ </caption>
+ <thead>
+ <tr>
+ <th data-sort="text"><?= _('Name der Ressource') ?></th>
+ <th data-sort="text"><?= _('Berechtigung') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($permissions as $permission): ?>
+ <tr>
+ <td>
+ <?= htmlReady($permission->resource->getDerivedClassInstance()) ?>
+ </td>
+ <td>
+ <?= htmlReady($permission->perms) ?>
+ <? if ($current_global_lock and ($permission->perms != 'admin')): ?>
+ <?= Icon::create('exclaim', 'attention')->asImg(
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('Die Berechtigung kann zurzeit aufgrund einer globalen Sperrung der Raumverwaltung nicht genutzt werden!')
+ ]
+ )?>
+ <? endif ?>
+ </td>
+ <td class="actions">
+ <a href="<?= $permission->resource->getActionLink(
+ 'permissions',
+ [
+ 'user_id' => $permission->user_id
+ ]
+ ) ?>" data-dialog>
+ <?= Icon::create('edit')->asImg(
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('Berechtigung bearbeiten')
+ ]
+ ) ?>
+ </a>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/admin/booking_log/'
+ . $user->id
+ . '/'
+ . $permission->resource_id
+ ) ?>" data-dialog>
+ <?= Icon::create('log')->asImg(
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('Liste mit Buchungen anzeigen')
+ ]
+ ) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? endif ?>
+<? else: ?>
+ <?= MessageBox::info(
+ _('Es wurde keine Person ausgewählt!')
+ ) ?>
+<? endif ?>
diff --git a/app/views/resources/booking/_add_edit_form.php b/app/views/resources/booking/_add_edit_form.php
new file mode 100644
index 0000000..bd02f0a
--- /dev/null
+++ b/app/views/resources/booking/_add_edit_form.php
@@ -0,0 +1,606 @@
+<? if ($show_form): ?>
+ <form class="default create-booking-form" method="post"
+ name="create_booking"
+ action="<?= ($booking !== null) && ($mode == 'edit')
+ ? $controller->link_for('resources/booking/edit/' . $booking->id)
+ : $controller->link_for('resources/booking/add/' . $resource_or_clipboard_id . '/' . $booking_type);
+ ?>"
+ data-dialog="<?= $no_reload ? 'size=auto' : 'reload-on-close' ?>">
+ <input type="hidden" name="origin_url"
+ value="<?= htmlReady($origin_url) ?>">
+ <? if ($resources) : ?>
+ <? foreach ($resources as $resource): ?>
+ <input type="hidden" name="resource_ids[]"
+ value="<?= htmlReady($resource->id) ?>">
+ <? endforeach ?>
+ <? endif ?>
+ <input type="hidden"
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($show_booking_type_selection): ?>
+ <div class="fieldset-row">
+ <fieldset class="booking-type-selection">
+ <legend><?= _('Bitte wählen Sie einen der folgenden Buchungstypen aus:') ?></legend>
+ <select name="booking_type" autofocus>
+ <option value="0"
+ <?= $booking_type == '0'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('Buchung') ?>
+ </option>
+ <option value="1"
+ <?= $booking_type == '1'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('Reservierung') ?>
+ </option>
+ <option value="2"
+ <?= $booking_type == '2'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('Sperrbuchung') ?>
+ </option>
+ </select>
+ </fieldset>
+ </div>
+ <? endif ?>
+ <div class="fieldset-row">
+ <fieldset class="resource-booking-time-fields">
+ <legend><?= _('Zeitbereich') ?></legend>
+ <label>
+ <?= _('Uhrzeit (von - bis)') ?>
+ <div class="hgroup">
+ <input type="text" name="begin_time" class="has-time-picker size-s"
+ value="<?= htmlReady($begin->format('H:i')) ?>"
+ pattern="([0-9]|[0-1][0-9]|2[0-3]):[0-5][0-9]"
+ id="BookingStartTimeInput">
+ <input type="text" name="end_time" class="has-time-picker size-s"
+ value="<?= htmlReady($end->format('H:i')) ?>"
+ pattern="([0-9]|[0-1][0-9]|2[0-3]):[0-5][0-9]"
+ id="BookingEndTimeInput">
+ </div>
+ </label>
+
+ <label>
+ <?= _('Datum (von - bis)') ?>
+ <div class="indented-form-line manual-time-fields">
+ <? $single_day = ($begin->format('d.m.Y') == $end->format('d.m.Y')); ?>
+
+ <div id="begin_date-weekdays" class="hgroup">
+ <span id="1"
+ class="<?= $begin->format('N') == 1 ? '' : 'invisible'; ?>"><?= _('Montag'); ?></span>
+ <span id="2"
+ class="<?= $begin->format('N') == 2 ? '' : 'invisible'; ?>"><?= _('Dienstag'); ?></span>
+ <span id="3"
+ class="<?= $begin->format('N') == 3 ? '' : 'invisible'; ?>"><?= _('Mittwoch'); ?></span>
+ <span id="4"
+ class="<?= $begin->format('N') == 4 ? '' : 'invisible'; ?>"><?= _('Donnerstag'); ?></span>
+ <span id="5"
+ class="<?= $begin->format('N') == 5 ? '' : 'invisible'; ?>"><?= _('Freitag'); ?></span>
+ <span id="6"
+ class="<?= $begin->format('N') == 6 ? '' : 'invisible'; ?>"><?= _('Samstag'); ?></span>
+ <span id="7"
+ class="<?= $begin->format('N') == 7 ? '' : 'invisible'; ?>"><?= _('Sonntag'); ?></span>
+
+ <input type="text" name="begin_date" class="has-date-picker"
+ value="<?= htmlReady($begin->format('d.m.Y')) ?>"
+ id="BookingStartDateInput">
+ </div>
+
+ <div id="end_date-weekdays" class="hgroup" <?= ($single_day) ? 'style="display:none;"' : ''; ?>>
+ <span id="1"
+ class="<?= $end->format('N') == 1 ? '' : 'invisible'; ?>"><?= _('Montag'); ?></span>
+ <span id="2"
+ class="<?= $end->format('N') == 2 ? '' : 'invisible'; ?>"><?= _('Dienstag'); ?></span>
+ <span id="3"
+ class="<?= $end->format('N') == 3 ? '' : 'invisible'; ?>"><?= _('Mittwoch'); ?></span>
+ <span id="4"
+ class="<?= $end->format('N') == 4 ? '' : 'invisible'; ?>"><?= _('Donnerstag'); ?></span>
+ <span id="5"
+ class="<?= $end->format('N') == 5 ? '' : 'invisible'; ?>"><?= _('Freitag'); ?></span>
+ <span id="6"
+ class="<?= $end->format('N') == 6 ? '' : 'invisible'; ?>"><?= _('Samstag'); ?></span>
+ <span id="7"
+ class="<?= $end->format('N') == 7 ? '' : 'invisible'; ?>"><?= _('Sonntag'); ?></span>
+
+ <input type="text" name="end_date" class="has-date-picker"
+ value="<?= htmlReady($end->format('d.m.Y')) ?>"
+ id="BookingEndDateInput">
+ </div>
+ </div>
+
+ <label>
+ <input type="checkbox" id="multiday" <?= $single_day ? '' : 'checked'; ?>
+ name="multiple_days" value="1"
+ onClick="$('#end_date-weekdays').toggle();">
+ <?= _('Mehrtägig') ?>
+ </label>
+ </label>
+
+
+ <div class="time-option-container invisible">
+ <label>
+ <span id="RepetitionEndLabel"><?= _('Ende der Wiederholung') ?></span>
+ <span id="BlockEndLabel"><?= _('Ende des Terminblocks') ?></span>
+ <input id="RepetitionEndInput" type="text" name="repetition_end" class="has-date-picker size-s"
+ value="<?= $repetition_end->format('d.m.Y') ?>">
+ <input id="HiddenRepetitionEndInput" type="hidden" name="repetition_end"
+ value="<?= $repetition_end->format('d.m.Y') ?>" disabled>
+ </label>
+
+ <input type="hidden" name="semester_id" value="<?= $semester_id ?>">
+
+ <label>
+ <input type="radio" name="selected_end" value="manual"
+ <?= (!$semester_id || ($selected_end == 'manual'))
+ ? 'checked="checked"'
+ : '' ?>
+ class="manual-time-option">
+ <?= _('Enddatum manuell festlegen.') ?>
+ </label>
+ <label>
+ <input type="radio" name="selected_end"
+ value="semester_course_end"
+ <?= !$semester_id ? 'disabled="disabled"' : '' ?>
+ <?= ($semester_id && ($selected_end == 'semester_course_end'))
+ ? 'checked="checked"'
+ : '' ?>
+ class="semester-time-option">
+ <input type="hidden" name="semester_course_end_date"
+ value="<?= date('d.m.Y', $semesters[$semester_id]->vorles_ende); ?>">
+ <?= sprintf(
+ _('Ende der Vorlesungszeit des Semesters %s'),
+ sprintf(
+ '<span id="semester_course_name">%s</span>',
+ htmlReady($semesters[$semester_id]->name)
+ )
+ ) ?>
+ </label>
+ <br>
+ </div>
+
+
+ <? if ($booking_type != '2'): ?>
+ <label>
+ <?= _('Rüstzeit (Minuten)') ?>
+ <input type="number" name="preparation_time"
+ value="<?= htmlReady($preparation_time) ?>"
+ min="0"
+ max="<?= htmlReady($max_preparation_time) ?>">
+ </label>
+ <? endif ?>
+
+ <span class="notification-span <?= ($booking_type != '2') ? 'invisible' : '' ?>" data-booking_type="2">
+ <label>
+ <input type="checkbox" name="notification_enabled"
+ value="1"
+ <?= $notification_enabled
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Alle betroffenen Personen über die Sperrbuchung benachrichtigen.') ?>
+ </label>
+ </span>
+
+ <? if ($separable_rooms_selected): ?>
+ <label class="separable-room-booking">
+ <input type="checkbox" name="book_other_room_parts"
+ value="1"
+ <?= $book_other_room_parts
+ ? 'checked="checked"'
+ : '' ?>>
+ <span data-booking_type="2"
+ <?= $booking_type == '2' ? '' : 'style="display:none;"' ?>>
+ <?= _('Alle anderen Teilräume ebenfalls sperren.') ?>
+ </span>
+ <span data-booking_type="1"
+ <?= $booking_type == '1' ? '' : 'style="display:none;"' ?>>
+ <?= _('Alle anderen Teilräume ebenfalls reservieren.') ?>
+ </span>
+ <span data-booking_type="0"
+ <?= (!$booking_type or $booking_type == '0')
+ ? ''
+ : 'style="display:none;"' ?>>
+ <?= _('Alle anderen Teilräume ebenfalls buchen.') ?>
+ </span>
+ </label>
+ <? endif ?>
+ </fieldset>
+
+ <section class="fieldset-row inner-row">
+ <fieldset id="BookingTypeFieldset">
+ <legend><?= _('Art des Termins') ?></legend>
+ <div class="booking-type-item">
+ <label>
+ <input type="radio" name="booking_style" value="single"
+ <?= empty($block_booking) || $booking_style == 'single'
+ ? 'checked="checked"'
+ : '' ?>
+ class="booking-type-item">
+ <?= _('Einzeltermin') ?>
+ </label>
+ <label title="<?= _('Konvolut'); ?>">
+ <input type="radio" name="booking_style" value="block"
+ <?= !empty($block_booking) || $booking_style == 'block' ? 'checked="checked"' : '' ?>
+ class="booking-type-item">
+ <?= _('Terminblock') ?>
+ </label>
+ <label>
+ <input type="radio" name="booking_style" value="repeat"
+ <?= $booking_style == 'repeat' ? 'checked="checked"' : '' ?>
+ class="booking-type-item">
+ <?= _('Wiederholungstermine') ?>
+ </label>
+
+ </div>
+ </fieldset>
+
+ <fieldset id="BlockBookingFieldset"
+ class="block-booking-item <?= $booking_style == 'block'
+ ? ''
+ : 'invisible' ?>">
+ <legend><?= _('Terminblock') ?></legend>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="each_day"
+ <?= in_array('each_day', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Jeden Tag') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="mon_fri"
+ <?= in_array('mon_fri', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Mo-Fr') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="mon"
+ <?= in_array('mon', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Montags') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="tue"
+ <?= in_array('tue', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Dienstags') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="wed"
+ <?= in_array('wed', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Mittwochs') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="thu"
+ <?= in_array('thu', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Donnerstags') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="fri"
+ <?= in_array('fri', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Freitags') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="sat"
+ <?= in_array('sat', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Samstags') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="block_booking[]"
+ value="sun"
+ <?= in_array('sun', $block_booking)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Sonntags') ?>
+ </label>
+ </fieldset>
+
+ <fieldset id="RepetitionBookingFieldset" class="repetition-booking-item
+ <?= $booking_style == 'repeat' ? '' : 'invisible' ?>">
+ <legend><?= _('Wiederholungstermine') ?></legend>
+
+ <div class="repetition-booking-item">
+ <label>
+ <input type="radio" name="repetition_style" value="daily"
+ <?= $repetition_style == 'daily' ? 'checked="checked"' : '' ?>
+ class="repetition-booking-item"
+ data-activates="#RepeatIntervalSelectField-Daily"
+ data-deactivates="#RepeatIntervalSelectField-Weekly">
+ <?= _('Tägliche Wiederholung') ?>
+ </label>
+ <div class="hgroup indented-form-line">
+ <select name="repetition_interval" id="RepeatIntervalSelectField-Daily"
+ <?= $repetition_style != 'daily' ? 'disabled' : '' ?>>
+ <option value="1"
+ <?= $repetition_interval == '1'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jeden Tag') ?>
+ </option>
+ <option value="2"
+ <?= $repetition_interval == '2'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jeden zweiten Tag') ?>
+ </option>
+ <option value="3"
+ <?= $repetition_interval == '3'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jeden dritten Tag') ?>
+ </option>
+ <option value="4"
+ <?= $repetition_interval == '4'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jeden vierten Tag') ?>
+ </option>
+ <option value="5"
+ <?= $repetition_interval == '5'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jeden fünften Tag') ?>
+ </option>
+ <option value="6"
+ <?= $repetition_interval == '6'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jeden sechsten Tag') ?>
+ </option>
+ </select>
+ </div>
+ <label>
+ <input type="radio" name="repetition_style" value="weekly"
+ <?= $repetition_style == 'weekly' ? 'checked="checked"' : '' ?>
+ class="repetition-booking-item"
+ data-activates="#RepeatIntervalSelectField-Weekly"
+ data-deactivates="#RepeatIntervalSelectField-Daily">
+ <?= _('Wöchentliche Wiederholung') ?>
+ </label>
+ <div class="hgroup indented-form-line">
+ <select name="repetition_interval" id="RepeatIntervalSelectField-Weekly"
+ <?= $repetition_style != 'weekly' ? 'disabled' : '' ?>>
+ <option value="1"
+ <?= $repetition_interval == '1'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jede Woche') ?>
+ </option>
+ <option value="2"
+ <?= $repetition_interval == '2'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jede zweite Woche') ?>
+ </option>
+ <option value="3"
+ <?= $repetition_interval == '3'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jede dritte Woche') ?>
+ </option>
+ <option value="4"
+ <?= $repetition_interval == '4'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jede vierte Woche') ?>
+ </option>
+ <option value="5"
+ <?= $repetition_interval == '5'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('jede fünfte Woche') ?>
+ </option>
+ </select>
+ </div>
+ <label>
+ <input type="radio" name="repetition_style" value="monthly"
+ <?= $repetition_style == 'monthly' ? 'checked="checked"' : '' ?>
+ class="repetition-booking-item">
+ <?= _('Monatliche Wiederholung') ?>
+ </label>
+ </div>
+ </fieldset>
+ </section>
+ </div>
+ <div class="fieldset-row">
+ <fieldset>
+ <legend><?= _('Personen') ?></legend>
+ <? if ($booking->assigned_user instanceof User): ?>
+ <p>
+ <a href="<?= $controller->link_for(
+ 'profile',
+ ['username' => $booking->assigned_user->username]
+ ) ?>" target="_blank">
+ <?= htmlReady($booking->assigned_user->getFullName()) ?>
+ </a>
+ <a href="<?= $controller->link_for(
+ 'messages/write',
+ ['rec_uname' => $booking->assigned_user->username]
+ ) ?>" data-dialog="size=auto">
+ <?= Icon::create('mail')->asImg(
+ '20px',
+ ['class' => 'text-bottom']
+ ) ?>
+ </a>
+ <input type="hidden" name="assigned_user_id"
+ value="<?= htmlReady($booking->range_id) ?>">
+ </p>
+ <label class="assigned-user-label">
+ <?= _('Eine andere nutzende Person auswählen') ?>
+ <div class="assigned-user-search-wrapper">
+ <?= $assigned_user_search->render() ?>
+ <?= Icon::create('refresh')->asImg(
+ '20px', ['class' => 'delete-assigned-user-icon']
+ ) ?>
+ </div>
+ </label>
+ <? else: ?>
+ <label class="assigned-user-label">
+ <?= _('Die nutzende Person zur Buchung') ?>
+ <div class="assigned-user-search-wrapper">
+ <?= $assigned_user_search->render() ?>
+ <?= Icon::create('refresh')->asImg(
+ '20px', ['class' => 'delete-assigned-user-icon']
+ ) ?>
+ </div>
+ </label>
+ <? endif ?>
+ <? if ($booking->booking_user): ?>
+ <p style="margin-top:1em;margin-bottom:0;">
+ <?= htmlReady(
+ _('Gebucht von:')
+ ) ?>
+ <a href="<?= $controller->link_for(
+ 'profile',
+ ['username' => $booking->booking_user->username]
+ ) ?>" target="_blank">
+ <?= htmlReady($booking->booking_user->getFullName()) ?>
+ </a>
+ <a href="<?= $controller->link_for(
+ 'messages/write',
+ ['rec_uname' => $booking->booking_user->username]
+ ) ?>" data-dialog="size=auto">
+ <?= Icon::create('mail')->asImg(
+ '20px',
+ ['class' => 'text-bottom']
+ ) ?>
+ </a>
+ <? if ($mode == 'edit'): ?>
+ <span style="padding-left: 1em;">
+ <?= sprintf(
+ _('Letzte Änderung am %s'),
+ date('d.m.Y', $booking->chdate)
+ ) ?>
+ </span>
+ <? endif ?>
+ </p>
+ <? endif ?>
+ </fieldset>
+ <fieldset class="description">
+ <legend><?= _('Buchungstext') ?></legend>
+ <label>
+ <textarea name="description" <?= !$show_booking_type_selection ? 'autofocus' : ''?>><?= htmlReady($description) ?></textarea>
+ </label>
+ </fieldset>
+ </div>
+ <div class="fieldset-row">
+ <fieldset class="comment-fieldset">
+ <legend data-booking_type="1"
+ <?= $booking_type == '1' ? '' : 'style="display:none;"' ?>>
+ <?= _('Interner Kommentar zur Reservierung') ?>
+ </legend>
+ <legend data-booking_type="2"
+ <?= $booking_type == '2' ? '' : 'style="display:none;"' ?>>
+ <?= _('Interner Kommentar zur Sperrbuchung') ?>
+ </legend>
+ <legend data-booking_type="3"
+ <?= $booking_type == '3' ? '' : 'style="display:none;"' ?>>
+ <?= _('Interner Kommentar zur geplanten Buchung') ?>
+ </legend>
+ <legend data-booking_type="0"
+ <?= (($booking_type == '0') || !$booking_type)
+ ? ''
+ : 'style="display:none;"' ?>>
+ <?= _('Interner Kommentar zur Buchung') ?>
+ </legend>
+ <label>
+ <textarea name="internal_comment"><?= htmlReady($internal_comment) ?></textarea>
+ </label>
+ </fieldset>
+ <fieldset class="overwrite-fieldset <?= ($booking_type != '2') ? 'invisible' : '' ?>" data-booking_type="2">
+ <legend><?= _('Vorhandene Buchungen überschreiben') ?></legend>
+ <label>
+ <input type="checkbox" value="1"
+ name="overwrite_bookings"
+ <?= $overwrite_bookings ? 'checked="checked"' : '' ?>>
+ <?= _('Vorhandene Buchungen überschreiben') ?>
+ </label>
+ </fieldset>
+ <? if ($booking): ?>
+ <? $intervals = $booking->getTimeIntervals(); ?>
+ <? if (count($intervals) > 1): ?>
+ <fieldset class="singledates">
+ <legend><?= _('Einzelbuchungen') ?></legend>
+ <? $wdays = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'] ?>
+
+ <table class="default">
+ <? foreach ($intervals as $interval): ?>
+ <tr data-interval_id="<?= htmlReady($interval->id) ?>"
+ class="booking-list-interval">
+ <td class="booking-list-interval-date
+ <?= $interval->takes_place ? '' : ' not-taking-place' ?>
+ ">
+ <? if (date('d.m.Y', $interval['begin']) == date('d.m.Y', $interval['end'])): ?>
+ <?= $wdays[intVal(date('w', $interval['begin']))]
+ . ' ' . date('d.m.Y, H:i', $interval['begin'])
+ . date(' - H:i', $interval['end']) ?>
+ <? else: ?>
+ <?= $wdays[intVal(date('w', $interval['begin']))]
+ . ' ' . date('d.m.Y, H:i', $interval['begin']) ?>
+ -
+ <?= $wdays[intVal(date('w', $interval['end']))]
+ . ' ' . date('d.m.Y, H:i', $interval['end']) ?>
+
+ <? endif ?>
+ </td>
+ <td class="booking-list-interval-actions">
+ <a class="takes-place-delete takes-place-status-toggle
+ <?= $interval->takes_place ? '' : ' invisible'; ?>
+ "
+ data-interval_id="<?= htmlReady($interval->id) ?>">
+ <?= Icon::create('trash')->asImg(
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('löschen')
+ ]
+ ) ?>
+ </a>
+
+ <a class="takes-place-revive takes-place-status-toggle
+ <?= $interval->takes_place ? ' invisible' : ''; ?>
+ "
+ data-interval_id="<?= htmlReady($interval->id) ?>">
+ <?= Icon::create('trash+decline')->asImg(
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('wiederherstellen')
+ ]
+ ) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </table>
+ </fieldset>
+ <? endif ?>
+ <? endif ?>
+ </div>
+ <div data-dialog-button>
+ <? if ($show_reservation_overwrite_button): ?>
+ <?= \Studip\Button::create(
+ _('Reservierungen entfernen und buchen'),
+ 'overwrite_and_save'
+ ) ?>
+ <? else: ?>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ <? endif ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/booking/add.php b/app/views/resources/booking/add.php
new file mode 100644
index 0000000..7b1708e
--- /dev/null
+++ b/app/views/resources/booking/add.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/booking/_add_edit_form') ?>
diff --git a/app/views/resources/booking/add_from_request.php b/app/views/resources/booking/add_from_request.php
new file mode 100644
index 0000000..e7c3d37
--- /dev/null
+++ b/app/views/resources/booking/add_from_request.php
@@ -0,0 +1,50 @@
+<? if ($show_form): ?>
+ <form class="default" method="post"
+ action="<?= URLHelper::getLink(
+ 'dispatch.php/resources/booking/add_from_request/'
+ . $resource->id
+ . '/'
+ . $request->id
+ )?>"
+ <?= Request::isDialog() ? 'data-dialog="size=auto; reload-on-close"' : '' ?>>
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Details zur Anfrage') ?></legend>
+ <h3><?= _('Angefragte Zeiträume')?></h3>
+ <ul>
+ <? $appointments = explode("\n", $request->getDateString()) ?>
+ <? foreach ($appointments as $appointment): ?>
+ <li><?= htmlReady($appointment) ?></li>
+ <? endforeach ?>
+ </ul>
+ <h3><?= _('Zu buchende Ressource') ?></h3>
+ <?= htmlReady($resource->getFullName()) ?>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Buchungsoptionen') ?></legend>
+ <label>
+ <?= _('Rüstzeit (Minuten)') ?>
+ <input type="number" min="0"
+ max="<?= htmlReady($max_preparation_time) ?>"
+ value="<?= htmlReady($preparation_time) ?>"
+ name="preparation_time">
+ </label>
+ <label>
+ <input type="checkbox" name="notify_lecturers" value="1"
+ <?= $notify_lecturers ? 'checked="checked"' : ''?>>
+ <?= _('Lehrende über die Buchung benachrichtigen') ?>
+ </label>
+ <label>
+ <?= _('Beschreibung') ?>
+ <textarea name="description"><?= htmlReady($description) ?></textarea>
+ </label>
+ <label>
+ <?= _('Interner Kommentar zur Buchung') ?>
+ <textarea name="internal_comment"><?= htmlReady($internal_comment) ?></textarea>
+ </label>
+ </fieldset>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/booking/copy.php b/app/views/resources/booking/copy.php
new file mode 100644
index 0000000..d33fa6f
--- /dev/null
+++ b/app/views/resources/booking/copy.php
@@ -0,0 +1,51 @@
+<? if ($show_form): ?>
+ <? if ($available_resources): ?>
+
+ <form class="default" method="post"
+ action="<?= $this->controller->link_for('resources/booking/copy/' . $booking->id) ?>"
+ data-dialog="size=auto">
+ <?= CSRFProtection::tokenTag() ?>
+ <label>
+ <? if ($booking->resource->class_name == 'Room'): ?>
+ <?= _('Zielraum auswählen') ?>
+ <?= tooltipIcon(_('In welchen Raum bzw. welche Räume soll die Buchung kopiert werden?')) ?>
+ <? else: ?>
+ <?= _('Zielressource auswählen') ?>
+ <?= tooltipIcon(_('In welche Ressource(n) soll die Buchung kopiert werden?')) ?>
+ <? endif ?>
+ <select name="selected_resource_ids[]" multiple class="nested-select" required>
+ <option class="is-placeholder"><?= _('Bitte auswählen') ?></option>
+ <? foreach ($available_resources as $resource): ?>
+ <option value="<?= htmlReady($resource->id) ?>"
+ <?= in_array($resource->id, $selected_resource_ids) ? 'selected' : '' ?>>
+ <?= htmlReady($resource->getFullName()) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <?= $this->render_partial(
+ 'resources/booking/index.php',
+ [
+ 'booking' => $booking,
+ 'hide_buttons' => true
+ ]
+ ) ?>
+ <div data-dialog-button>
+ <?= \Studip\LinkButton::create(
+ _('Zurück'),
+ $controller->url_for('resources/booking/edit/' . $booking->id),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <?= \Studip\Button::create(_('Kopieren'), 'save') ?>
+ </div>
+ </form>
+ <? else: ?>
+ <? if ($booking->resource->class_name == 'Room'): ?>
+ <?= MessageBox::info(_('Es sind keine Räume verfügbar, in die die Buchung kopiert werden kann!')) ?>
+ <? else: ?>
+ <?= MessageBox::info(_('Es sind keine Ressourcen verfügbar, in die die Buchung kopiert werden kann!')) ?>
+ <? endif ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/booking/copy_to_semester.php b/app/views/resources/booking/copy_to_semester.php
new file mode 100644
index 0000000..61c1242
--- /dev/null
+++ b/app/views/resources/booking/copy_to_semester.php
@@ -0,0 +1,42 @@
+<? if ($show_form): ?>
+ <form class="default" method="post"
+ action="<?= $this->controller->link_for(
+ 'resources/booking/copy/' . $booking->id
+ ) ?>" data-dialog>
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Zielsemester' )?></legend>
+ <label>
+ <?= _('In welches Semester soll die Buchung kopiert werden?') ?>
+ <select name="semester_id">
+ <? foreach ($available_semesters as $semester): ?>
+ <option value="<?= htmlReady($semester->id) ?>"
+ <?= $semester_id == $semester->id
+ ? 'selected="selected"'
+ : '' ?>
+ data-start_week="<?= htmlReady($semester->getFirstSemesterWeek()) ?>"
+ data-end_week="<?= htmlReady($semester->getLastSemesterWeek()) ?>">
+ <?= htmlReady($semester->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <?= _('In welcher Kalenderwoche soll die Buchung stattfinden?') ?>
+ <select name="semester_week">
+ <? foreach ($available_semester_weeks as $index => $name): ?>
+ <option value="<?= htmlReady($index) ?>"
+ <?= $semester_week == $index
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Kopieren'), 'copy') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/booking/delete.php b/app/views/resources/booking/delete.php
new file mode 100644
index 0000000..718f279
--- /dev/null
+++ b/app/views/resources/booking/delete.php
@@ -0,0 +1,31 @@
+<? if ($show_question): ?>
+ <form class="default" method="post" action="<?= $controller->link_for('resources/booking/delete/' . $booking->id) ?>"
+ data-dialog="reload-on-close">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= MessageBox::warning(
+ _('Soll die folgende Buchung wirklich gelöscht werden?')
+ ) ?>
+ <? if ($show_details): ?>
+ <?= $this->render_partial(
+ 'resources/booking/index',
+ [
+ 'booking' => $booking,
+ 'hide_buttons' => true
+ ]
+ ) ?>
+ <? endif ?>
+ <div data-dialog-button>
+ <?= \Studip\LinkButton::create(
+ _('Zurück'),
+ $controller->url_for('resources/booking/edit/' . $booking->id),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <?= \Studip\Button::create(
+ _('Löschen'),
+ 'confirm'
+ ) ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/booking/duplicate.php b/app/views/resources/booking/duplicate.php
new file mode 100644
index 0000000..7b1708e
--- /dev/null
+++ b/app/views/resources/booking/duplicate.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/booking/_add_edit_form') ?>
diff --git a/app/views/resources/booking/edit.php b/app/views/resources/booking/edit.php
new file mode 100644
index 0000000..1f8e48b
--- /dev/null
+++ b/app/views/resources/booking/edit.php
@@ -0,0 +1,33 @@
+<?= $this->render_partial('resources/booking/_add_edit_form') ?>
+
+<div data-dialog-button>
+ <?= \Studip\LinkButton::create(
+ _('Duplizieren'),
+ $controller->url_for('resources/booking/duplicate/' . $booking->id),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <?= \Studip\LinkButton::create(
+ _('Kopieren'),
+ $controller->url_for('resources/booking/copy/' . $booking->id),
+ [
+ 'data-dialog' => 'size=auto'
+ ]
+ ) ?>
+ <?= \Studip\LinkButton::create(
+ _('Verschieben'),
+ $controller->url_for('resources/booking/move/' . $booking->id),
+ [
+ 'data-dialog' => 'size=auto'
+ ]
+ ) ?>
+ <?= \Studip\LinkButton::create(
+ _('Löschen'),
+ $controller->url_for('resources/booking/delete/' . $booking->id),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+</div>
+
diff --git a/app/views/resources/booking/index.php b/app/views/resources/booking/index.php
new file mode 100644
index 0000000..bad9819
--- /dev/null
+++ b/app/views/resources/booking/index.php
@@ -0,0 +1,175 @@
+<? if ($booking): ?>
+ <? if ($user_has_user_perms): ?>
+ <p>
+ <?= sprintf(
+ _('Letzte Änderung am %s'),
+ date('d.m.Y', $booking->chdate)
+ ) ?>
+ </p>
+ <? endif ?>
+ <h3><?= _('Gebuchte Ressource') ?></h3>
+ <? $derived_resource = $booking->resource
+ ? $booking->resource->getDerivedClassInstance()
+ : null ?>
+ <?= $derived_resource
+ ? $derived_resource->getFullName()
+ : _('unbekannt') ?>
+
+ <h3><?= _('Zeiträume') ?></h3>
+ <?
+ $cycle_date = $booking->assigned_course_date->cycle;
+ $booking_has_metadate = ($cycle_date instanceof SeminarCycleDate);
+ ?>
+ <? $intervals = $booking->getTimeIntervals() ?>
+ <? if (count($intervals) == 1) : ?>
+ <div>
+ <?= $intervals[0] ?>
+ </div>
+ <? if ($booking_has_metadate) :?>
+ <div><?= _('Diese Buchung ist Teil der folgenden Terminserie:') ?></div>
+ <?= htmlReady($cycle_date->toString('full')) ?>
+ <? endif ?>
+ <? elseif ($intervals): ?>
+ <ul>
+ <? foreach ($intervals as $interval): ?>
+ <li>
+ <?= $interval ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? else: ?>
+ <?= _('Nicht verfügbar') ?>
+ <? endif ?>
+
+ <? if ($booking->booking_type == '2'): ?>
+ <? if ($user_has_user_perms): ?>
+ <h3><?= _('Gesperrt für:') ?></h3>
+ <?= htmlReady($booking->getAssignedUserName()) ?>
+ <? endif ?>
+ <h3><?= _('Sperrung vorgenommen von:') ?></h3>
+ <?= $booking->booking_user
+ ? htmlReady($booking->booking_user->getFullName())
+ : _('unbekannt') ?>
+ <? elseif ($booking->booking_type == '1'): ?>
+ <? if ($user_has_user_perms): ?>
+ <h3><?= _('Reserviert für:') ?></h3>
+ <?= htmlReady($booking->getAssignedUserName()) ?>
+ <? endif ?>
+ <h3><?= _('Reservierung vorgenommen von:') ?></h3>
+ <?= $booking->booking_user
+ ? htmlReady($booking->booking_user->getFullName())
+ : _('unbekannt') ?>
+ <? else: ?>
+ <? if ($user_has_user_perms): ?>
+ <h3><?= _('Gebucht von:') ?></h3>
+ <? if ($booking->booking_user) :?>
+ <a href="<?= URLHelper::getScriptLink(
+ 'dispatch.php/profile',
+ ['username' => $booking->booking_user->username]
+ ) ?>">
+ <?= htmlReady($booking->booking_user->getFullName()) ?>
+ </a>
+ <a href="<?= URLHelper::getScriptLink(
+ 'dispatch.php/messages/write',
+ ['rec_uname' => $booking->booking_user->username]
+ ) ?>" data-dialog="size=auto">
+ <?= Icon::create('mail')->asImg(20, ['class' => 'text-bottom']) ?>
+ </a>
+ <? else :?>
+ <?= _('unbekannt') ?>
+ <? endif ?>
+ <? endif ?>
+ <? endif ?>
+ <? if ($booking->getAssignedUserType() === 'course'): ?>
+ <h3><?= _('Gebucht für:') ?></h3>
+ <a href="<?= URLHelper::getScriptLink(
+ 'dispatch.php/course/details/index/'
+ . $booking->getAssignedUser()->id
+ ) ?>" data-dialog>
+ <?= htmlReady($booking->getAssignedUserName(), true, true) ?>
+ <?= Icon::create(
+ 'link-intern',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => _('Veranstaltungsdetails anzeigen'),
+ 'class' => 'text-bottom'
+ ]
+ ) ?>
+ </a>
+ <? if (Seminar_Perm::get()->have_studip_perm('dozent', $booking->getAssignedUser()->id)): ?>
+ <div>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/timesrooms', [ 'cid' => $booking->getAssignedUser()->id]) ?>">
+ <?=_('Verwaltung von Zeiten und Räumen')?>
+ <?= Icon::create(
+ 'schedule',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'title' => _('Verwaltung von Zeiten und Räumen'),
+ 'class' => 'text-bottom'
+ ]) ?>
+ </a>
+ </div>
+ <? endif ?>
+ <? elseif ($booking->getAssignedUserType() === 'user') : ?>
+ <? if (($booking->assigned_user->visible == 'yes') ||
+ ($booking->assigned_user->id == $GLOBALS['user']->id) ||
+ $user_has_user_perms) : ?>
+ <h3><?= _('Gebucht für:') ?></h3>
+ <a href="<?= URLHelper::getScriptLink(
+ 'dispatch.php/profile',
+ ['username' => $booking->assigned_user->username]
+ ) ?>">
+ <?= htmlReady($booking->assigned_user->getFullName()) ?>
+ </a>
+ <a href="<?= URLHelper::getScriptLink(
+ 'dispatch.php/messages/write',
+ ['rec_uname' => $booking->assigned_user->username]
+ ) ?>" data-dialog="size=auto">
+ <?= Icon::create('mail')->asImg(20, ['class' => 'text-bottom']) ?>
+ </a>
+ <? endif ?>
+ <? else : ?>
+ <?= htmlReady($booking->description) ?>
+ <? endif ?>
+ <? if ($make_comment_editable): ?>
+ <form class="default" method="post"
+ action="<?= htmlReady(
+ $controller->link_for('resources/booking/index/' . $booking->id)
+ ) ?>" data-dialog="reload-on-close">
+ <?= CSRFProtection::tokenTag() ?>
+ <? endif ?>
+ <? if ($show_internal_comment): ?>
+ <h3><?= _('Interner Kommentar zur Buchung') ?>:</h3>
+ <? if ($make_comment_editable): ?>
+ <textarea name="internal_comment"><?= htmlReady($booking->internal_comment) ?></textarea>
+ <? else: ?>
+ <?= htmlReady($booking->internal_comment) ?>
+ <? endif ?>
+ <? endif ?>
+ <? if ((Request::isDialog() || $make_comment_editable) && !$hide_buttons): ?>
+ <div data-dialog-button>
+ <? if ($make_comment_editable): ?>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ <? if (!$booking->isReadOnlyForUser($current_user)): ?>
+ <?= \Studip\LinkButton::create(
+ _('Bearbeiten'),
+ $controller->url_for('resources/booking/edit/' . $booking->id),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <?= \Studip\LinkButton::create(
+ _('Löschen'),
+ $controller->url_for('resources/booking/delete/' . $booking->id),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <? endif ?>
+ <? endif ?>
+ </div>
+ <? endif ?>
+ <? if ($make_comment_editable): ?>
+ </form>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/booking/move.php b/app/views/resources/booking/move.php
new file mode 100644
index 0000000..f1f9cda
--- /dev/null
+++ b/app/views/resources/booking/move.php
@@ -0,0 +1,55 @@
+<? if ($show_form): ?>
+ <? if ($available_resources): ?>
+ <form class="default" method="post"
+ action="<?= $this->controller->link_for('resources/booking/move/' . $booking->id) ?>" data-dialog="size=auto">
+ <?= CSRFProtection::tokenTag() ?>
+ <label>
+ <? if ($booking->resource->class_name == 'Room'): ?>
+ <?= _('Zielraum auswählen') ?>
+ <?= tooltipIcon(_('In welchen Raum soll die Buchung verschoben werden?')) ?>
+ <? else: ?>
+ <?= _('Zielressource auswählen') ?>
+ <?= tooltipIcon(_('In welche Ressource soll die Buchung verschoben werden?')) ?>
+ <? endif ?>
+
+ <select name="selected_resource_id" class="nested-select">
+ <? foreach ($available_resources as $resource): ?>
+ <? if ($resource->id == $booking->resource->id) continue; ?>
+ <option value="<?= htmlReady($resource->id) ?>"
+ <?= in_array($resource->id, $selected_resource_ids) ? 'selected' : '' ?>>
+ <?= htmlReady($resource->getFullName()) ?>
+ </option>
+
+ <? endforeach ?>
+ </select>
+ </label>
+ <?= $this->render_partial(
+ 'resources/booking/index.php',
+ [
+ 'booking' => $booking,
+ 'hide_buttons' => true
+ ]
+ ) ?>
+ <div data-dialog-button>
+ <?= \Studip\LinkButton::create(
+ _('Zurück'),
+ $controller->url_for('resources/booking/edit/' . $booking->id),
+ [
+ 'data-dialog' => '1'
+ ]
+ ) ?>
+ <?= \Studip\Button::create(_('Verschieben'), 'save') ?>
+ </div>
+ </form>
+ <? else: ?>
+ <? if ($booking->resource->class_name == 'Room'): ?>
+ <?= MessageBox::info(
+ _('Es sind keine Räume verfügbar, in die die Buchung verschoben werden kann!')
+ ) ?>
+ <? else: ?>
+ <?= MessageBox::info(
+ _('Es sind keine Ressourcen verfügbar, in die die Buchung verschoben werden kann!')
+ ) ?>
+ <? endif ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/building/_add_edit_form.php b/app/views/resources/building/_add_edit_form.php
new file mode 100644
index 0000000..37e8666
--- /dev/null
+++ b/app/views/resources/building/_add_edit_form.php
@@ -0,0 +1,68 @@
+<? if ($show_form): ?>
+ <? $url = ($mode == 'add')
+ ? $controller->link_for('resources/building/add', ['category_id' => $category_id])
+ : $controller->link_for('resources/building/edit/' . $building->id) ?>
+ <form class="default" method="post" action="<?= $url ?>"
+ data-dialog="reload-on-close">
+
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label>
+ <?= _('Name des Gebäudes') ?>
+ <input type="text" name="name" value="<?= htmlReady($name) ?>">
+ </label>
+ <label>
+ <?= _('Beschreibungstext') ?>
+ <input type="text" name="description" value="<?= htmlReady($description) ?>">
+ </label>
+ <label>
+ <?= _('Standort / Hierarchie') ?>
+ <select name="parent_id">
+ <option value=""><?= _('Bitte wählen') ?></option>
+ <? foreach ($possible_parents as $resource): ?>
+ <option value="<?= htmlReady($resource->id) ?>"
+ <?= $parent_id == $resource->id ? 'selected="selected"' : '' ?>>
+ <?= htmlReady('/' . implode('/', ResourceManager::getHierarchyNames($resource))) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Gebäudenummer') ?>
+ <input type="text" name="number" value="<?= htmlReady($number) ?>">
+ </label>
+ <label>
+ <?= _('Adresse') ?>
+ <input type="text" name="address" value="<?= htmlReady($address) ?>">
+ </label>
+ <? if ($GLOBALS['perm']->have_perm('root')): ?>
+ <label>
+ <?= _('Sortierposition') ?>
+ <input type="text" name="sort_position" value="<?= htmlReady($sort_position) ?>">
+ </label>
+ <? endif ?>
+ <?= $this->render_partial(
+ '../../templates/resources/position_attribute_form_part.php',
+ [
+ 'property_name' => 'geo_coordinates',
+ 'latitude' => $latitude,
+ 'longitude' => $longitude,
+ 'altitude' => $altitude
+ ]
+ ) ?>
+ </fieldset>
+ <? if ($grouped_defined_properties): ?>
+ <?= $this->render_partial(
+ 'resources/resource/_standard_properties_form_part.php',
+ [
+ 'grouped_defined_properties' => $grouped_defined_properties,
+ 'property_data' => $property_data
+ ]
+ ) ?>
+ <? endif ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'confirmed') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/building/add.php b/app/views/resources/building/add.php
new file mode 100644
index 0000000..4f2517d
--- /dev/null
+++ b/app/views/resources/building/add.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/building/_add_edit_form.php') ?>
diff --git a/app/views/resources/building/delete.php b/app/views/resources/building/delete.php
new file mode 100644
index 0000000..b0ee168
--- /dev/null
+++ b/app/views/resources/building/delete.php
@@ -0,0 +1,13 @@
+<? if ($show_form): ?>
+ <?= MessageBox::warning(
+ _('Soll das folgende Gebäude wirklich gelöscht werden?')
+ ) ?>
+ <form class="default" method="post" data-dialog="reload-on-close"
+ action="<?= $controller->link_for('resources/building/delete/' . $building->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('resources/building/index', ['building' => $building]) ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Löschen'), 'save') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/building/edit.php b/app/views/resources/building/edit.php
new file mode 100644
index 0000000..4f2517d
--- /dev/null
+++ b/app/views/resources/building/edit.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/building/_add_edit_form.php') ?>
diff --git a/app/views/resources/building/index.php b/app/views/resources/building/index.php
new file mode 100644
index 0000000..140bbfe
--- /dev/null
+++ b/app/views/resources/building/index.php
@@ -0,0 +1,113 @@
+<? if ($building): ?>
+ <nav class="resource-hierarchy">
+ <? if ($building->location): ?>
+ <a href="<?= $building->location->getActionLink('show') ?>" <?= (Request::isDialog()) ? 'data-dialog' : ''; ?>>
+ <?= htmlReady($building->location->name) ?>
+ </a>
+ &gt;
+ <? endif ?>
+ <?= htmlReady($building->name) ?>
+ </nav>
+ <? if (!empty($building_details)) : ?>
+ <dl>
+ <? foreach ($building_details as $title => $building_detail) : ?>
+ <dt>
+ <?= $title ?>
+ </dt>
+ <dd>
+ <?= htmlReady($building_detail) ?>
+ </dd>
+ <? endforeach ?>
+ </dl>
+ <? endif ?>
+ <? if ($building->description): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Beschreibung und Hinweise') ?></h1>
+ </header>
+ <section>
+ <p class="resource-description-text"><?= htmlReady($building->description) ?></p>
+ </section>
+ </section>
+ <? endif ?>
+
+ <div data-dialog-button>
+ <? if (Request::isDialog()) : ?>
+ <? if ($geo_coordinates_object instanceof ResourceProperty): ?>
+ <?= \Studip\LinkButton::create(
+ _('Zum Lageplan'),
+ ResourceManager::getMapUrlForResourcePosition($geo_coordinates_object),
+ ['target' => '_blank']
+ ) ?>
+ <? endif ?>
+ <?= \Studip\LinkButton::createEdit(
+ _('Bearbeiten'),
+ $building->getActionURL('edit'),
+ [
+ 'data-dialog' => 'size=auto'
+ ]
+ ) ?>
+ <? endif ?>
+ </div>
+ <?
+ $property_groups = $building->getGroupedProperties(
+ ['geo_coordinates', 'number', 'address']
+ );
+ ?>
+ <? if (count($property_groups)): ?>
+ <?= $this->render_partial(
+ 'resources/resource/_standard_properties_display_part.php',
+ [
+ 'property_groups' => $property_groups
+ ]
+ ) ?>
+ <? endif ?>
+
+<? endif ?>
+
+<? $resource_folder = $building->getFolder(); ?>
+<? if ($resource_folder && $resource_folder->getFiles()): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Dateien') ?></h1>
+ </header>
+ <table class="default sortable-table" data-sortlist="[[2, 0]]">
+ <?= $this->render_partial('files/_files_thead') ?>
+ <? foreach ($resource_folder->getFiles() as $file): ?>
+ <? if ($file->isVisible($GLOBALS['user']->id)) : ?>
+ <?= $this->render_partial(
+ 'files/_fileref_tr',
+ [
+ 'file' => $file,
+ 'current_folder' => $resource_folder,
+ 'last_visitdate' => time()
+ ]
+ ) ?>
+ <? endif ?>
+ <? endforeach ?>
+ </table>
+ </section>
+<? endif ?>
+
+<? if ($building->children): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Räume') ?></h1>
+ </header>
+ <section>
+ <ul class="list-unstyled">
+ <? foreach ($building->findChildrenByClassName('Room') as $child): ?>
+ <li>
+ <a href="<?= $controller->link_for('resources/room/index/' . $child->id); ?>"
+ <?= (Request::isDialog()) ? 'data-dialog' : ''; ?>>
+ <?= $child->getIcon('clickable')->asImg(
+ ['class' => 'text-bottom']
+ ) ?>
+ <?= htmlReady($child->name); ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </section>
+ </section>
+<? endif ?> \ No newline at end of file
diff --git a/app/views/resources/building/lock.php b/app/views/resources/building/lock.php
new file mode 100644
index 0000000..d80f04b
--- /dev/null
+++ b/app/views/resources/building/lock.php
@@ -0,0 +1,21 @@
+<? if ($show_form): ?>
+<form class="default" method="post" data-dialog="reload-on-close"
+ action="<?= $controller->link_for('resources/building/lock/' . $building->id) ?>">
+ <fieldset>
+ <legend><?= _('Bitte Sperrzeiten auswählen') ?></legend>
+ <label>
+ <?= _('Startzeitpunkt') ?>
+ <input type="text" class="has-date-picker" name="begin_date" value="<?= htmlReady($begin->format('d.m.Y')) ?>">
+ <input type="text" class="has-time-picker" name="begin_time" value="<?= htmlReady($begin->format('H:i')) ?>">
+ </label>
+ <label>
+ <?= _('Endzeitpunkt') ?>
+ <input type="text" class="has-date-picker" name="end_date" value="<?= htmlReady($end->format('d.m.Y')) ?>">
+ <input type="text" class="has-time-picker" name="end_time" value="<?= htmlReady($end->format('H:i')) ?>">
+ </label>
+ </fieldset>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Sperren'), 'confirmed') ?>
+ </div>
+</form>
+<? endif ?>
diff --git a/app/views/resources/building/new.php b/app/views/resources/building/new.php
new file mode 100644
index 0000000..0cacb75
--- /dev/null
+++ b/app/views/resources/building/new.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/building/_new_edit_form.php') ?>
diff --git a/app/views/resources/building/select_category.php b/app/views/resources/building/select_category.php
new file mode 100644
index 0000000..429cfa8
--- /dev/null
+++ b/app/views/resources/building/select_category.php
@@ -0,0 +1,18 @@
+<? if ($categories) : ?>
+<form method="get" action="<?= $controller->link_for('resources/building/add' . $room_id) ?>" class="default"
+ data-dialog="size=auto">
+ <label>
+ <?= _('Gebäudekategorie') ?>
+ <select name="category_id" required>
+ <option value=""><?= _('Bitte eine Gebäudekategorie auswählen:') ?></option>
+ <? foreach ($categories as $category) : ?>
+ <option value="<?= $category->id ?>">
+ <?= htmlReady($category->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Auswählen')) ?>
+ </footer>
+<? endif ?>
diff --git a/app/views/resources/category/_add_edit_form.php b/app/views/resources/category/_add_edit_form.php
new file mode 100644
index 0000000..d5e0853
--- /dev/null
+++ b/app/views/resources/category/_add_edit_form.php
@@ -0,0 +1,157 @@
+<? if ($show_form): ?>
+ <form class="default resource-category-form"
+ method="post"
+ action="<?= ($mode == 'add')
+ ? URLHelper::getLink(
+ 'dispatch.php/resources/category/add'
+ )
+ : URLHelper::getLink(
+ 'dispatch.php/resources/category/edit/' . $category->id
+ ) ?>"
+ data-dialog="reload-on-close">
+
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label>
+ <?= _('Name der Kategorie') ?>
+ <input type="text" name="name" value="<?= htmlReady($name) ?>">
+ </label>
+ <label>
+ <?= _('Beschreibungstext') ?>
+ <input type="text" name="description" value="<?= htmlReady($description) ?>">
+ </label>
+ <label>
+ <?= _('Name der Datenklasse') ?>
+ <select name="class_name">
+ <? foreach ($class_names as $possible_class_name): ?>
+ <option value="<?= htmlReady($possible_class_name) ?>"
+ <?= $class_name == $possible_class_name ? 'selected="selected"' : ''?>>
+ <?= htmlReady($possible_class_name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <p><?= _('Hinweis: Je nach gewählter Datenklasse werden automatisch weitere Eigenschaften zur Kategorie hinzugefügt.') ?></p>
+ </label>
+ <label>
+ <?= _('Icon-Nummer') ?>
+ <input type="number" name="iconnr" value="<?= htmlReady($iconnr) ?>"
+ min="0" max="4" step="1">
+ </label>
+ </fieldset>
+ <fieldset class="Properties">
+ <legend><?= _('Eigenschaften') ?></legend>
+ <table class="default resource-category-properties-table">
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Wünschbar') ?></th>
+ <th><?= _('Geschützt') ?></th>
+ <th class="actions"><?= _('Löschen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if ($previously_set_properties): ?>
+ <? foreach ($previously_set_properties as $property): ?>
+ <tr data-property_id="<?= htmlReady($property['id']) ?>">
+ <td>
+ <span><?= htmlReady($property['name']) ?></span>
+ <input type="hidden" value="1"
+ name="prop[<?= htmlReady($property['id']) ?>]">
+ </td>
+ <td>
+ <input type="checkbox" value="1"
+ name="prop_requestable[<?= htmlReady($property['id']) ?>]"
+ <?= $property['requestable'] ? 'checked="checked"' : '' ?>>
+ </td>
+ <td>
+ <input type="checkbox" value="1"
+ name="prop_protected[<?= htmlReady($property['id']) ?>]"
+ <?= $property['protected'] ? 'checked="checked"' : '' ?>>
+ </td>
+ <td class="actions">
+ <? if ($property['system']) : ?>
+ <?= tooltipIcon(
+ _('Dies ist eine Systemeigenschaft, die nicht gelöscht werden darf!')
+ ) ?>
+ <? else : ?>
+ <a title="<?= _('Löschen') ?>" class="delete-action">
+ <?= Icon::create('trash')->asImg(20) ?>
+ </a>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? endif ?>
+ <? if ($set_properties): ?>
+ <? foreach ($set_properties as $property): ?>
+ <tr data-property_id="<?= htmlReady($property['id']) ?>">
+ <td>
+ <span><?= htmlReady($property['name']) ?></span>
+ <input type="hidden" value="1"
+ name="prop[<?= htmlReady($property['id']) ?>]">
+ </td>
+ <td>
+ <input type="checkbox" value="1"
+ name="prop_requestable[<?= htmlReady($property['id']) ?>]"
+ <?= $property['requestable'] ? 'checked="checked"' : '' ?>>
+ </td>
+ <td>
+ <input type="checkbox" value="1"
+ name="prop_protected[<?= htmlReady($property['id']) ?>]"
+ <?= $property['protected'] ? 'checked="checked"' : '' ?>>
+ </td>
+ <td class="actions">
+ <a title="<?= _('Löschen') ?>" class="delete-action">
+ <?= Icon::create('trash')->asImg(20) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? endif ?>
+ </tbody>
+ <tfoot>
+ <tr class="template invisible">
+ <td>
+ <span class="name"></span>
+ <input class="property-input"
+ type="hidden" value="1">
+ </td>
+ <td>
+ <input class="requestable-input"
+ type="checkbox" value="1">
+ </td>
+ <td>
+ <input class="protected-input"
+ type="checkbox" value="1">
+ </td>
+ <td class="actions">
+ <a title="<?= _('Löschen') ?>" class="delete-action">
+ <?= Icon::create('trash')->asImg(20) ?>
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="6">
+ <select class="available-property-select">
+ <? foreach ($available_properties as $ap): ?>
+ <option value="<?= htmlReady($ap->id) ?>"
+ <?= in_array($ap->id, array_keys($previously_set_properties))
+ ? 'disabled="disabled"'
+ : '' ?>>
+ <?= htmlReady($ap) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <?= Icon::create('add')->asImg(20, ['class' => 'add-action']) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </fieldset>
+
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'confirmed') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/category/add.php b/app/views/resources/category/add.php
new file mode 100644
index 0000000..affb95e
--- /dev/null
+++ b/app/views/resources/category/add.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/category/_add_edit_form.php') ?>
diff --git a/app/views/resources/category/delete.php b/app/views/resources/category/delete.php
new file mode 100644
index 0000000..769a1d2
--- /dev/null
+++ b/app/views/resources/category/delete.php
@@ -0,0 +1,52 @@
+<? if ($show_form): ?>
+ <?= MessageBox::warning(
+ _('Soll die folgende Ressourcenkategorie wirklich gelöscht werden?')
+ ) ?>
+ <form method="post" data-dialog="reload-on-close" class="default"
+ action="<?= URLHelper::getLink(
+ 'dispatch.php/resources/category/delete/' . $category->id) ?>">
+ <fieldset>
+ <legend><?= _('Informationen') ?></legend>
+ <dl>
+ <dt><?= _('Name') ?></dt>
+ <dd><?= htmlReady($category->name) ?></dd>
+ <dt><?= _('Zugehörige Klasse') ?></dt>
+ <dd><?= htmlReady($category->class_name) ?></dd>
+ </dl>
+ </fieldset>
+ <? if ($category_has_resources): ?>
+ <fieldset>
+ <legend><?= _('Zuweisen von Ressourcen') ?></legend>
+ <p><?= _('Die zu dieser Kategorie gehörenden Ressourcen müssen einer anderen Kategorie zugewiesen oder gelöscht werden!') ?></p>
+ <label>
+ <input type="radio" name="resource_handling" value="reassign"
+ <?= $resource_handling == 'reassign' ? 'checked="checked"' : '' ?>
+ data-activates="select#new_resource_category_select">
+ <?= _('Ressourcen der folgenden Kategorie zuordnen:') ?>
+ <select id="new_resource_category_select"
+ name="new_category_id"
+ <?= $resource_handling == 'reassign' ? '' : 'disabled="disabled"' ?>>
+ <option value="" <?= !$new_category_id ? 'selected="selected"' : '' ?>>
+ <?= _('bitte wählen') ?>
+ </option>
+ <? foreach ($alternative_categories as $alt_cat): ?>
+ <option value="<?= htmlReady($alt_cat->id) ?>"
+ <?= $new_category_id == $alt_cat->id ? 'selected="selected"' : '' ?>>
+ <?= htmlReady($alt_cat->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <input type="radio" name="resource_handling" value="delete"
+ data-deactivates="select#new_resource_category_select"
+ <?= $resource_handling == 'delete' ? 'checked="checked"' : '' ?>>
+ <?= _('Ressourcen unwiderruflich löschen') ?>
+ </label>
+ </fieldset>
+ <? endif ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Löschen'), 'confirmed') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/category/details.php b/app/views/resources/category/details.php
new file mode 100644
index 0000000..59eea31
--- /dev/null
+++ b/app/views/resources/category/details.php
@@ -0,0 +1,33 @@
+<? if ($category->description) : ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Beschreibung') ?></h1>
+ </header>
+ <section>
+ <?= htmlReady($category->description) ?>
+ </section>
+ </section>
+<? endif ?>
+
+<? if ($category->property_definitions): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Eigenschaften') ?></h1>
+ </header>
+ <section>
+ <ul class="list-unstyled">
+ <? foreach ($category->property_definitions as $definition): ?>
+ <li>
+ <?= Icon::create('checkbox-checked')->asImg(['class' => 'text-bottom']) ?>
+ <? if ($definition->system): ?>
+ <strong><?= htmlReady($definition) ?></strong>
+ <? else: ?>
+ <?= htmlReady($definition) ?>
+ <? endif ?>
+ [<?= htmlReady($definition->type) ?>]
+ </li>
+ <? endforeach ?>
+ </ul>
+ </section>
+ </section>
+<? endif ?>
diff --git a/app/views/resources/category/edit.php b/app/views/resources/category/edit.php
new file mode 100644
index 0000000..affb95e
--- /dev/null
+++ b/app/views/resources/category/edit.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/category/_add_edit_form.php') ?>
diff --git a/app/views/resources/category/show_resources.php b/app/views/resources/category/show_resources.php
new file mode 100644
index 0000000..51cc433
--- /dev/null
+++ b/app/views/resources/category/show_resources.php
@@ -0,0 +1,36 @@
+<? if ($resources): ?>
+<table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ <th><?= _('Eigenschaften') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($resources as $resource): ?>
+ <tr>
+ <td>
+ <a href="<?= $resource->getActionLink('show') ?>">
+ <?= htmlReady($resource->name) ?>
+ </a>
+ </td>
+ <td><?= htmlReady($resource->description) ?></td>
+ <td>
+ <? if ($resource->properties): ?>
+ <ul>
+ <? foreach ($resource->properties as $property): ?>
+ <? if ($property->definition): ?>
+ <li><?= htmlReady($property->getFullName()) ?></li>
+ <? endif ?>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+</table>
+<? else: ?>
+<?= MessageBox::info(_('Es gibt keine Ressourcen in der gewählten Ressourcenkategorie!')) ?>
+<? endif ?>
diff --git a/app/views/resources/export/resource_bookings.php b/app/views/resources/export/resource_bookings.php
new file mode 100644
index 0000000..39933de
--- /dev/null
+++ b/app/views/resources/export/resource_bookings.php
@@ -0,0 +1,38 @@
+<? if ($resource): ?>
+ <form class="default" method="post"
+ action="<?= $controller->link_for('resources/export/bookings')?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($resource instanceof Room): ?>
+ <input type="hidden" name="selected_rooms[]"
+ value="<?= htmlReady($resource->id)?>">
+ <? else: ?>
+ <input type="hidden" name="selected_resources[]"
+ value="<?= htmlReady($resource->id)?>">
+ <? endif ?>
+ <article class="widget">
+ <header><?= _('Zeitbereich auswählen') ?></header>
+ <section>
+ <label>
+ <?= _('Startzeitpunkt') ?>
+ <input type="text" class="has-date-picker" ="1"
+ name="begin_date" value="<?= $begin->format('d.m.Y') ?>">
+ <input type="text" class="has-time-picker" name="begin_time"
+ value="<?= $begin->format('H:i')?>">
+ </label>
+ <label>
+ <?= _('Endzeitpunkt') ?>
+ <input type="text" class="has-date-picker" name="end_date"
+ value="<?= $end->format('d.m.Y') ?>">
+ <input type="text" class="has-time-picker" name="end_time"
+ value="<?= $end->format('H:i')?>">
+ </label>
+ </section>
+ </article>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Exportieren'),
+ 'export'
+ ) ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/export/select_booking_sources.php b/app/views/resources/export/select_booking_sources.php
new file mode 100644
index 0000000..527de27
--- /dev/null
+++ b/app/views/resources/export/select_booking_sources.php
@@ -0,0 +1,106 @@
+<? if ($available_rooms || $available_clipboards): ?>
+ <form class="default" method="post"
+ action="<?= $controller->link_for('resources/export/bookings') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Zeitbereich auswählen') ?></legend>
+ <label class="col-2">
+ <?= _('Startzeitpunkt') ?>
+ <input type="text" class="has-date-picker size-s" name="begin_date"
+ value="<?= $begin->format('d.m.Y') ?>">
+ <input type="text" class="has-time-picker size-s" name="begin_time"
+ value="<?= $begin->format('H:i')?>">
+ </label>
+ <label class="col-2">
+ <?= _('Endzeitpunkt') ?>
+ <input type="text" class="has-date-picker size-s" name="end_date"
+ value="<?= $end->format('d.m.Y') ?>">
+ <input type="text" class="has-time-picker size-s" name="end_time"
+ value="<?= $end->format('H:i')?>">
+ </label>
+ </fieldset>
+ <? if ($available_rooms): ?>
+ <table class="default">
+ <caption>
+ <?= sprintf(
+ ngettext(
+ '%u Raum',
+ '%u Räume',
+ count($available_rooms)
+ ),
+ count($available_rooms)
+ ) ?>
+ </caption>
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" data-proxyfor="input[name='selected_rooms[]']">
+ </th>
+ <th><?= _('Räume') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($available_rooms as $room): ?>
+ <tr>
+ <td>
+ <input type="checkbox"
+ name="selected_rooms[]"
+ value="<?= htmlReady($room->id) ?>">
+ </td>
+ <td>
+ <?= htmlReady($room->name) ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? endif ?>
+ <? if ($available_clipboards): ?>
+ <table class="default">
+ <caption>
+ <?= sprintf(
+ ngettext(
+ '%u Raumgruppe',
+ '%u Raumgruppen',
+ count($available_clipboards)
+ ),
+ count($available_clipboards)
+ ) ?>
+ </caption>
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" data-proxyfor="input[name='selected_clipboards[]']">
+ </th>
+ <th><?= _('Raumgruppen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($available_clipboards as $clipboard): ?>
+ <tr>
+ <td>
+ <input type="checkbox"
+ name="selected_clipboards[]"
+ value="<?= htmlReady($clipboard->id) ?>">
+ </td>
+ <td>
+ <?= htmlReady($clipboard->name) ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? endif ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Liste mit Buchungen exportieren')) ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/global_locks/_add_edit_form.php b/app/views/resources/global_locks/_add_edit_form.php
new file mode 100644
index 0000000..2faacf6
--- /dev/null
+++ b/app/views/resources/global_locks/_add_edit_form.php
@@ -0,0 +1,45 @@
+<? if ($show_form): ?>
+ <form class="default" action="<?= $action_link ?>" method="post"
+ data-dialog="reload-on-close">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset class="global-lock-time-fields">
+ <legend><?= _('Zeitraum') ?></legend>
+ <label>
+ <?= _('Startdatum') ?>
+ <input type="text" name="begin_date" class="has-date-picker""
+ value="<?= htmlReady($begin->format('d.m.Y'))?>">
+ </label>
+ <label>
+ <?= _('Startzeitpunkt') ?>
+ <input type="text" name="begin_time" class="has-time-picker"
+ value="<?= htmlReady($begin->format('H:i'))?>">
+ </label>
+ <label>
+ <?= _('Enddatum') ?>
+ <input type="text" name="end_date" class="has-date-picker"
+ value="<?= htmlReady($end->format('d.m.Y'))?>">
+ </label>
+ <label>
+ <?= _('Endzeitpunkt') ?>
+ <input type="text" name="end_time" class="has-time-picker"
+ value="<?= htmlReady($end->format('H:i'))?>">
+ </label>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Typ der Sperrung') ?></legend>
+ <select name="selected_type">
+ <? foreach ($defined_types as $id => $label): ?>
+ <option value="<?= htmlReady($id)?>"
+ <?= $id == $selected_type
+ ? 'selected="selected"'
+ : ''?>>
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </fieldset>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/global_locks/add.php b/app/views/resources/global_locks/add.php
new file mode 100644
index 0000000..e5205de
--- /dev/null
+++ b/app/views/resources/global_locks/add.php
@@ -0,0 +1,6 @@
+<?= $this->render_partial(
+ 'resources/global_locks/_add_edit_form.php',
+ [
+ 'action_link' => URLHelper::getLink('dispatch.php/resources/global_locks/add')
+ ]
+) ?>
diff --git a/app/views/resources/global_locks/delete.php b/app/views/resources/global_locks/delete.php
new file mode 100644
index 0000000..357c7dc
--- /dev/null
+++ b/app/views/resources/global_locks/delete.php
@@ -0,0 +1,24 @@
+<? if ($show_data): ?>
+ <form class="default"
+ action="<?= URLHelper::getLink(
+ 'dispatch.php/resources/global_locks/delete/' . $lock->id
+ ) ?>"
+ method="post" data-dialog="reload-on-close">
+ <?= CSRFProtection::tokenTag() ?>
+ <h2><?= _('Soll die folgende Sperrung wirklich gelöscht werden?') ?></h2>
+ <dl>
+ <dt><?= _('Startzeitpunkt') ?></dt>
+ <dd><?= date('d.m.Y H:i', $lock->begin) ?></dd>
+ <dt><?= _('Endzeitpunkt') ?></dt>
+ <dd><?= date('d.m.Y H:i', $lock->end) ?></dd>
+ <dt><?= _('Typ der Sperrung') ?></dt>
+ <dd><?= htmlReady($lock->getTypeString()) ?></dd>
+ </dl>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Löschen'),
+ 'delete'
+ ) ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/global_locks/edit.php b/app/views/resources/global_locks/edit.php
new file mode 100644
index 0000000..59f9232
--- /dev/null
+++ b/app/views/resources/global_locks/edit.php
@@ -0,0 +1,8 @@
+<?= $this->render_partial(
+ 'resources/global_locks/_add_edit_form.php',
+ [
+ 'action_link' => URLHelper::getLink(
+ 'dispatch.php/resources/global_locks/edit/' . $lock->id
+ )
+ ]
+) ?>
diff --git a/app/views/resources/location/_add_edit_form.php b/app/views/resources/location/_add_edit_form.php
new file mode 100644
index 0000000..3cc40ea
--- /dev/null
+++ b/app/views/resources/location/_add_edit_form.php
@@ -0,0 +1,48 @@
+<? if ($show_form): ?>
+ <form class="default" method="post" action="<?= ($mode == 'add')
+ ? $controller->link_for('resources/location/add', ['category_id' => $category_id])
+ : $controller->link_for('resources/location/edit/' . $location->id) ?>"
+ data-dialog="reload-on-close">
+
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label>
+ <?= _('Name des Standortes') ?>
+ <input type="text" name="name" value="<?= htmlReady($name) ?>">
+ </label>
+ <label>
+ <?= _('Beschreibungstext') ?>
+ <input type="text" name="description" value="<?= htmlReady($description) ?>">
+ </label>
+ <? if ($GLOBALS['perm']->have_perm('root')): ?>
+ <label>
+ <?= _('Sortierposition') ?>
+ <input type="text" name="sort_position"
+ value="<?= htmlReady($sort_position) ?>">
+ </label>
+ <? endif ?>
+ <?= $this->render_partial(
+ '../../templates/resources/position_attribute_form_part.php',
+ [
+ 'property_name' => 'geo_coordinates',
+ 'latitude' => $latitude,
+ 'longitude' => $longitude,
+ 'altitude' => $altitude
+ ]
+ ) ?>
+ </fieldset>
+ <? if ($defined_properties) : ?>
+ <?= $this->render_partial(
+ 'resources/resource/_standard_properties_form_part.php',
+ [
+ 'defined_properties' => $defined_properties,
+ 'property_data' => $property_data
+ ]
+ ) ?>
+ <? endif ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/location/add.php b/app/views/resources/location/add.php
new file mode 100644
index 0000000..7031a60
--- /dev/null
+++ b/app/views/resources/location/add.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/location/_add_edit_form.php') ?>
diff --git a/app/views/resources/location/delete.php b/app/views/resources/location/delete.php
new file mode 100644
index 0000000..67a8a22
--- /dev/null
+++ b/app/views/resources/location/delete.php
@@ -0,0 +1,13 @@
+<? if ($show_form): ?>
+ <?= MessageBox::warning(
+ _('Soll der folgende Standort wirklich gelöscht werden?')
+ ) ?>
+ <form class="default" method="post" data-dialog="reload-on-close"
+ action="<?= $controller->link_for('resources/location/delete/' . $location->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('resources/location/index', ['location' => $location]) ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Löschen'), 'save') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/location/edit.php b/app/views/resources/location/edit.php
new file mode 100644
index 0000000..7031a60
--- /dev/null
+++ b/app/views/resources/location/edit.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/location/_add_edit_form.php') ?>
diff --git a/app/views/resources/location/index.php b/app/views/resources/location/index.php
new file mode 100644
index 0000000..ae28197
--- /dev/null
+++ b/app/views/resources/location/index.php
@@ -0,0 +1,87 @@
+<? if ($location): ?>
+ <? if ((string)$location->description !== '') : ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Beschreibung und Hinweise') ?></h1>
+ </header>
+ <section>
+ <?= htmlReady($location->description) ?>
+ </section>
+ </section>
+ <? endif ?>
+
+ <? if (Request::isDialog()) : ?>
+ <? if ($geo_coordinates_object instanceof ResourceProperty) : ?>
+ <div data-dialog-button>
+ <?= \Studip\LinkButton::create(
+ _('Zum Lageplan'),
+ ResourceManager::getMapUrlForResourcePosition($geo_coordinates_object),
+ ['target' => '_blank']
+ ) ?>
+ </div>
+ <?= \Studip\LinkButton::createEdit(
+ _('Bearbeiten'),
+ $location->getActionURL('edit'),
+ [
+ 'data-dialog' => 'size=auto'
+ ]
+ ) ?>
+ <? endif ?>
+ <? endif ?>
+ <? $property_groups = $location->getGroupedProperties($other_properties) ?>
+ <? if (count($property_groups)): ?>
+ <?= $this->render_partial(
+ 'resources/resource/_standard_properties_display_part.php',
+ [
+ 'property_groups' => $property_groups
+ ]
+ ) ?>
+ <? endif ?>
+
+ <? $resource_folder = $location->getFolder(); ?>
+ <? if ($resource_folder && $resource_folder->getFiles()): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Dateien') ?></h1>
+ </header>
+ <table class="default sortable-table" data-sortlist="[[2, 0]]">
+ <?= $this->render_partial('files/_files_thead') ?>
+ <? foreach ($resource_folder->getFiles() as $file): ?>
+ <? if ($file->isVisible($GLOBALS['user']->id)) : ?>
+ <?= $this->render_partial(
+ 'files/_fileref_tr',
+ [
+ 'file' => $file,
+ 'current_folder' => $resource_folder,
+ 'last_visitdate' => time()
+ ]
+ ) ?>
+ <? endif ?>
+ <? endforeach ?>
+ </table>
+ </section>
+ <? endif ?>
+
+ <? if (count($location->children)): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Gebäude') ?></h1>
+ </header>
+ <section>
+ <ul class="list-unstyled">
+ <? foreach ($location->findChildrenByClassName('Building') as $child): ?>
+ <li>
+ <a href="<?= $controller->link_for('resources/building/index/' . $child->id); ?>"
+ <?= (Request::isDialog()) ? 'data-dialog' : ''; ?>>
+ <?= $child->getIcon('clickable')->asImg(
+ ['class' => 'text-bottom']
+ ) ?>
+ <?= htmlReady($child->name); ?>
+ </a>
+ </li>
+ <? endforeach ?>
+ </ul>
+ </section>
+ </section>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/location/select_category.php b/app/views/resources/location/select_category.php
new file mode 100644
index 0000000..02a2f77
--- /dev/null
+++ b/app/views/resources/location/select_category.php
@@ -0,0 +1,18 @@
+<? if ($categories) : ?>
+<form method="get" action="<?= $controller->link_for('resources/location/add' . $room_id) ?>" class="default"
+ data-dialog="size=auto">
+ <label>
+ <?= _('Standortkategorie') ?>
+ <select name="category_id" required>
+ <option value=""><?= _('Bitte eine Standortkategorie auswählen:') ?></option>
+ <? foreach ($categories as $category) : ?>
+ <option value="<?= $category->id ?>">
+ <?= htmlReady($category->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Auswählen')) ?>
+ </footer>
+<? endif ?>
diff --git a/app/views/resources/messages/index.php b/app/views/resources/messages/index.php
new file mode 100644
index 0000000..a2e0d0d
--- /dev/null
+++ b/app/views/resources/messages/index.php
@@ -0,0 +1,143 @@
+<form class="default resources_messages-form" method="post" data-dialog="size=auto"
+ action="<?= URLHelper::getLink('dispatch.php/resources/messages/index') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Raumauswahl') ?></legend>
+ <label>
+ <input type="radio" name="room_selection" value="search"
+ <?= ($room_selection == 'search' or !$clipboards)
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Auswahl anhand von Suchergebnissen') ?>
+ <?
+ if ($room_selection != 'search') {
+ $room_search->setAttributes(
+ [
+ 'disabled' => 'disabled'
+ ]
+ );
+ }
+ ?>
+ <?= $room_search->render() ?>
+ <div class="selection-area">
+ <span class="selected-room template invisible">
+ <input type="hidden" name="room_ids[]">
+ <span></span>
+ <?= Icon::create('trash')->asImg(
+ [
+ 'class' => 'remove-icon text-bottom'
+ ]
+ ) ?>
+ </span>
+ <? if ($selected_rooms): ?>
+ <? foreach ($selected_rooms as $room): ?>
+ <span class="selected-room">
+ <input type="hidden" name="room_ids[]"
+ value="<?= htmlReady($room->id) ?>">
+ <span><?= htmlReady($room->name) ?></span>
+ <?= Icon::create('trash')->asImg(
+ [
+ 'class' => 'remove-icon text-bottom'
+ ]
+ ) ?>
+ </span>
+ <? endforeach ?>
+ <? endif ?>
+ </div>
+ </label>
+ <label>
+ <input type="radio" name="room_selection" value="clipboard"
+ <?= ($room_selection == 'clipboard' and $clipboards)
+ ? 'checked="checked"'
+ : '' ?>
+ <?= !$clipboards ? 'disabled="disabled"' : '' ?>>
+ <?= _('Auswahl anhand einer individuellen Raumgruppe') ?>
+ <? if ($clipboards): ?>
+ <select name="clipboard_id"
+ <?= $room_selection != 'clipboard'
+ ? 'disabled="disabled"'
+ : '' ?>>
+ <? foreach ($clipboards as $clipboard): ?>
+ <option value="<?= htmlReady($clipboard->id) ?>"
+ <?= $clipboard_id == $clipboard->id
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($clipboard->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ </label>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Empfängerkreis auswählen') ?></legend>
+ <label>
+ <input type="radio" name="recipient_selection" value="permission"
+ <?= $recipient_selection == 'permission'
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Alle Personen mit einer bestimmten Rechtestufe.') ?>
+ </label>
+ <label>
+ <input type="radio" name="recipient_selection" value="booking"
+ <?= $recipient_selection == 'booking'
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Alle Personen, die von Buchungen im folgenden Zeitraum betroffen sind.') ?>
+ </label>
+ </fieldset>
+ <fieldset id="RecipientMode_Permission"
+ <?= $recipient_selection != 'permission'
+ ? 'style="display: none;"'
+ : '' ?>>
+ <legend>
+ <?= _('Auswahl anhand der minimalen Rechtestufe') ?>
+ </legend>
+ <label>
+ <?= _('Sende die Rundmail an alle Personen, die mindestens die folgende Rechtestufe an den ausgewählten Räumen haben:') ?>
+ <select name="min_permission">
+ <option value="user"
+ <?= $min_permission == 'user' ? 'selected="selected"' : ''?>>
+ user
+ </option>
+ <option value="autor"
+ <?= $min_permission == 'autor' ? 'selected="selected"' : ''?>>
+ autor
+ </option>
+ <option value="tutor"
+ <?= $min_permission == 'tutor' ? 'selected="selected"' : ''?>>
+ tutor
+ </option>
+ <option value="admin"
+ <?= $min_permission == 'admin' ? 'selected="selected"' : ''?>>
+ admin
+ </option>
+ </select>
+ </label>
+ </fieldset>
+ <fieldset id="RecipientMode_Booking"
+ <?= $recipient_selection != 'booking'
+ ? 'style="display: none;"'
+ : '' ?>>
+ <legend>
+ <?= _('Auswahl anhand von Buchungen in einem Zeitraum') ?>
+ </legend>
+ <label>
+ <?= _('Beginn') ?>
+ <input type="text" name="begin_date" class="has-date-picker"
+ value="<?= $begin->format('d.m.Y') ?>">
+ <input type="text" name="begin_time" class="has-time-picker"
+ value="<?= $begin->format('H:i') ?>">
+ </label>
+ <label>
+ <?= _('Ende') ?>
+ <input type="text" name="end_date" class="has-date-picker"
+ value="<?= $end->format('d.m.Y') ?>">
+ <input type="text" name="end_time" class="has-time-picker"
+ value="<?= $end->format('H:i') ?>">
+ </label>
+ </fieldset>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Mail verfassen'), 'write_mail') ?>
+ </div>
+</form>
diff --git a/app/views/resources/print/clipboard_rooms.php b/app/views/resources/print/clipboard_rooms.php
new file mode 100644
index 0000000..b5b4a0d
--- /dev/null
+++ b/app/views/resources/print/clipboard_rooms.php
@@ -0,0 +1,169 @@
+<? if (!$print_schedules): ?>
+ <form class="default" method="post"
+ action="<?= $controller->link_for('resources/print/clipboard_rooms') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($clipboard_selected): ?>
+ <input type="hidden" name="clipboard_id" value="<?= htmlReady($selected_clipboard_id) ?>">
+ <input type="hidden" name="schedule_type" value="<?= htmlReady($schedule_type) ?>">
+ <input type="hidden" name="date" value="<?= htmlReady($selected_date_string) ?>">
+ <fieldset>
+ <? if (!$available_rooms): ?>
+ <?= MessageBox::info(
+ sprintf(
+ _('In der Raumgruppe %s sind keine Räume vorhanden!'),
+ htmlReady($selected_clipboard->name)
+ )
+ ) ?>
+ <? else: ?>
+ <legend>
+ <?= htmlReady(
+ sprintf(
+ _('Bitte Räume aus der Raumgruppe %s auswählen'),
+ htmlReady($selected_clipboard->name)
+ )
+ ) ?>
+ </legend>
+ <ul>
+ <? foreach ($available_rooms as $room): ?>
+ <li>
+ <label>
+ <input type="checkbox" value="<?= htmlReady($room->id) ?>"
+ checked="checked"
+ name="selected_room_ids[]">
+ <?= htmlReady($room->getFullName()) ?>
+ </label>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ </fieldset>
+ <div data-dialog-button>
+ <? if ($available_rooms): ?>
+ <?= \Studip\Button::create(
+ _('Drucken'),
+ 'print'
+ ) ?>
+ <? endif ?>
+ <?= \Studip\Button::create(
+ _('Raumgruppe neu wählen'),
+ 'null'
+ ) ?>
+ </div>
+ <? else: ?>
+ <? if(count($available_clipboards)) : ?>
+ <fieldset>
+ <label>
+ <?= _('Individuelle Raumgruppe') ?>:
+ <select name="clipboard_id">
+ <? foreach ($available_clipboards as $clipboard): ?>
+ <option value="<?= htmlReady($clipboard->id) ?>">
+ <?= htmlReady($clipboard->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Art des Belegungsplanes') ?>:
+ <select name="schedule_type">
+ <option value="w"
+ <?= $selected_schedule == 'w'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('Wochenplan') ?>
+ </option>
+ <option value="w+we"
+ <?= $selected_schedule == 'w+we'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('Wochenplan inklusive Wochenende') ?>
+ </option>
+ <option value="d"
+ <?= $selected_schedule == 'd'
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= _('Tagesplan') ?>
+ </option>
+ </select>
+ </label>
+ <label>
+ <?= _('Datum')?>:
+ <input type="text" name="date"
+ value="<?= date('d.m.Y') ?>"
+ class="has-date-picker">
+ </label>
+ </fieldset>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Weiter zur Raumauswahl'),
+ 'select_clipboard'
+ ) ?>
+ </div>
+ <? else :?>
+ <?= MessageBox::info(
+ _('Sie müssen zunächst Raumgruppen erstellen'),
+ [
+ sprintf(
+ _('Klicken %shier%s, um ein Raumgruppen anzulegen.'),
+ '<a href="' . URLHelper::getLink('dispatch.php/room_management/overview/rooms') . '">',
+ '</a>')
+ ]
+ )?>
+ <? endif ?>
+ <? endif ?>
+ </form>
+<? else: ?>
+ <? if (Request::get("allday")) {
+ $min_time = '00:00:00';
+ $max_time = '24:00:00';
+ } else {
+ $min_time = Config::get()->RESOURCES_BOOKING_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->RESOURCES_BOOKING_PLAN_END_HOUR . ':00';
+ } ?>
+ <?
+ PageLayout::setTitle('');
+ ?>
+ <? foreach ($selected_rooms as $room): ?>
+ <section class="booking-plan-area">
+ <h1>
+ <?= sprintf(
+ _('%s: Belegungsplan'),
+ htmlReady($room->getFullName())
+ ) ?>
+ </h1>
+ <?= \Studip\Fullcalendar::create(
+ '',
+ [
+ 'editable' => true,
+ 'selectable' => false,
+ 'studip_urls' => [],
+ 'minTime' => ($min_time),
+ 'maxTime' => ($max_time),
+ 'allDaySlot' => false,
+ 'header' => [
+ 'left' => 'dayGridMonth,timeGridWeek,timeGridDay',
+ 'right' => 'prev,next'
+ ],
+ 'defaultView' =>
+ in_array(Request::get("defaultView"), ['dayGridMonth','timeGridWeek','timeGridDay'])
+ ? Request::get("defaultView")
+ : 'timeGridWeek',
+ 'defaultDate' => Request::get("defaultDate", $print_date),
+ 'eventSources' => [
+ [
+ 'url' => URLHelper::getURL(
+ 'api.php/resources/resource/'
+ . $room->id . '/booking_plan'
+ ),
+ 'method' => 'GET',
+ 'extraParams' => [
+ 'booking_types' => [0,1,2],
+ 'display_requests' => 1
+ ]
+ ]
+ ]
+ ],
+ ['class' => 'resource-plan']
+ ) ?>
+ </section>
+ <? endforeach ?>
+<? endif ?>
diff --git a/app/views/resources/print/individual_booking_plan.php b/app/views/resources/print/individual_booking_plan.php
new file mode 100644
index 0000000..54672d6
--- /dev/null
+++ b/app/views/resources/print/individual_booking_plan.php
@@ -0,0 +1,36 @@
+<? if (Request::get("allday")) {
+ $min_time = '00:00:00';
+ $max_time = '24:00:00';
+ } else {
+ $min_time = Config::get()->RESOURCES_BOOKING_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->RESOURCES_BOOKING_PLAN_END_HOUR . ':00';
+ } ?>
+<section class="individual-booking-plan">
+ <?= \Studip\Fullcalendar::create(
+ _('Belegungsplan'),
+ [
+ 'eventSources' => [
+ [
+ 'url' => URLHelper::getURL(
+ 'api.php/resources/resource/' . $resource->id . '/booking_plan'
+ ),
+ 'method' => 'GET',
+ 'extraParams' => [
+ 'booking_types' => [0,1,2]
+ ]
+ ]
+ ],
+ 'minTime' => ($min_time),
+ 'maxTime' => ($max_time),
+ 'allDaySlot' => false,
+ 'defaultView' =>
+ in_array(Request::get("defaultView"), ['dayGridMonth','timeGridWeek','timeGridDay'])
+ ? Request::get("defaultView")
+ : 'timeGridWeek',
+ 'defaultDate' => Request::get("defaultDate"),
+ 'editable' => false
+ ],
+ ['class' => 'individual-booking-plan'],
+ 'resources-fullcalendar'
+ ) ?>
+</section>
diff --git a/app/views/resources/property/_add_edit_form.php b/app/views/resources/property/_add_edit_form.php
new file mode 100644
index 0000000..66cd7f9
--- /dev/null
+++ b/app/views/resources/property/_add_edit_form.php
@@ -0,0 +1,67 @@
+<label>
+ <?= _('Name') ?>
+ <input type="text" value="<?= htmlReady($name) ?>" name="name"
+ <?= $property->system ? 'readonly="readonly"' : '' ?>>
+</label>
+<label>
+ <?= _('Beschreibung') ?>
+ <?= I18N::textarea('description', $description) ?>
+</label>
+<label>
+ <?= _('Typ') ?>
+ <select name="type" class="size-s"
+ <?= $property->system ? 'disabled="disabled"' : '' ?>>
+ <? foreach ($defined_types as $defined_type): ?>
+ <option value="<?= htmlReady($defined_type) ?>"
+ <?= $defined_type == $type
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($defined_type) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+</label>
+<label>
+ <?= _('Minimale Rechtestufe für Änderungen') ?>
+ <select name="write_permission_level" class="size-l"
+ <?= $property->system ? 'disabled="disabled"' : '' ?>>
+ <? foreach(['user', 'autor', 'tutur', 'admin'] as $level) : ?>
+ <option value="<?= $level?>"
+ <?= $write_permission_level === $level ? 'selected="selected"' : '' ?>>
+ <?= $level?>
+ </option>
+ <? endforeach ?>
+ <option value="admin-global"
+ <?= $write_permission_level == 'admin-global' ? 'selected="selected"' : '' ?>>
+ <?= _('Globaler Raumadmin') ?>
+ </option>
+ </select>
+</label>
+<label>
+ <?= _('Mögliche Werte') ?>
+ <input type="text" name="options" value="<?= htmlReady($options) ?>"
+ <?= $property->system ? 'readonly="readonly"' : '' ?>>
+</label>
+<label>
+ <?= _('Angezeigter Name') ?>
+ <?= I18N::input('display_name', $display_name) ?>
+</label>
+<input type="checkbox" name="searchable" id="searchable" class="studip-checkbox"
+ <?= $searchable ? 'checked="checked"' : '' ?>
+ <?= $property->system ? 'disabled="disabled"' : '' ?>>
+<label for="searchable">
+ <?= _('Diese Eigenschaft kann zur Suche genutzt werden.') ?>
+</label>
+<input type="checkbox" value="1" name="info_label" id="info_label" class="studip-checkbox"
+ <?= $info_label ? 'checked="checked"' : '' ?>>
+<label for="info_label">
+ <?= _('Diese Eigenschaft soll im Info-Icon zu einem Raum angezeigt werden.') ?>
+</label>
+<input type="checkbox" name="range_search" value="1" class="studip-checkbox" id="range_search"
+ <?= $range_search
+ ? 'checked="checked"'
+ : '' ?>
+ <?= $property->system ? 'disabled="disabled"' : '' ?>>
+<label for="range_search">
+ <?= _('Suchkriterium mit Intervall') ?>
+</label>
diff --git a/app/views/resources/property/add.php b/app/views/resources/property/add.php
new file mode 100644
index 0000000..8a665ff
--- /dev/null
+++ b/app/views/resources/property/add.php
@@ -0,0 +1,15 @@
+<? if ($show_form): ?>
+ <form class="default" method="post"
+ action="<?= URLHelper::getLink(
+ 'dispatch.php/resources/property/add'
+ )?>" data-dialog="reload-on-close">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('resources/property/_add_edit_form.php') ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Speichern'),
+ 'save'
+ ) ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/property/edit.php b/app/views/resources/property/edit.php
new file mode 100644
index 0000000..86c017e
--- /dev/null
+++ b/app/views/resources/property/edit.php
@@ -0,0 +1,15 @@
+<? if ($show_form): ?>
+<form class="default" method="post"
+ action="<?= URLHelper::getLink(
+ 'dispatch.php/resources/property/edit/' . $property->id
+ )?>" data-dialog="reload-on-close">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('resources/property/_add_edit_form.php') ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Speichern'),
+ 'save'
+ ) ?>
+ </div>
+</form>
+<? endif ?>
diff --git a/app/views/resources/resource/_add_edit_form.php b/app/views/resources/resource/_add_edit_form.php
new file mode 100644
index 0000000..661988e
--- /dev/null
+++ b/app/views/resources/resource/_add_edit_form.php
@@ -0,0 +1,49 @@
+<? if ($show_form): ?>
+ <form class="default" method="post"
+ action="<?= ($mode == 'add')
+ ? URLHelper::getLink('dispatch.php/resources/resource/add')
+ : URLHelper::getLink('dispatch.php/resources/resource/edit/' . $resource->id) ?>"
+ data-dialog="reload-on-close">
+
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <? if ($mode == 'add'): ?>
+ <input type="hidden" name="category_id"
+ value="<?= htmlReady($category->id) ?>">
+ <? endif ?>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label>
+ <?= _('Name') ?>
+ <input type="text" name="name" value="<?= htmlReady($name) ?>">
+ </label>
+ <label>
+ <?= _('Beschreibungstext') ?>
+ <input type="text" name="description" value="<?= htmlReady($description) ?>">
+ </label>
+ <? if ($GLOBALS['perm']->have_perm('root')): ?>
+ <label>
+ <?= _('Elternressource') ?>
+ <?= $parent_search->render() ?>
+ </label>
+ <label>
+ <?= _('Sortierposition') ?>
+ <input type="text" name="sort_position"
+ value="<?= htmlReady($sort_position) ?>">
+ </label>
+ <? endif ?>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Eigenschaften') ?></legend>
+ <?= $this->render_partial(
+ 'resources/resource/_standard_properties_form_part.php',
+ [
+ 'grouped_defined_properties' => $grouped_defined_properties,
+ 'property_data' => $property_data
+ ]
+ ) ?>
+ </fieldset>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'confirmed') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/resource/_standard_properties_display_part.php b/app/views/resources/resource/_standard_properties_display_part.php
new file mode 100644
index 0000000..0cf4fb1
--- /dev/null
+++ b/app/views/resources/resource/_standard_properties_display_part.php
@@ -0,0 +1,101 @@
+<?
+/**
+ * Template documentation:
+ * This template expects the $properties parameter to be present.
+ * That parameter must contain ResourceProperty objects.
+ */
+?>
+<? if ($property_groups): ?>
+ <? foreach ($property_groups as $name => $properties): ?>
+ <? $properties = array_filter($properties, function ($p) {
+ return !empty($p->state);
+ }); ?>
+ <? if (!count($properties)) continue; ?>
+ <section class="contentbox">
+ <header>
+ <h1>
+ <? if ($name): ?>
+ <?= htmlReady($name) ?>
+ <? else: ?>
+ <?= _('Weitere Eigenschaften') ?>
+ <? endif ?>
+ </h1>
+ </header>
+
+ <table class="default">
+ <colgroup>
+ <col style="width: 70%">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <?= _('Name') ?>
+ </th>
+ <th>
+ <?= _('Wert') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($properties as $property): ?>
+ <tr>
+ <td>
+ <?= htmlReady(
+ $property->display_name
+ ? $property->display_name
+ : $property->name
+ ) ?>
+ </td>
+ <td>
+ <? if ($property->definition->type == 'bool'): ?>
+ <? if ($property->state): ?>
+ <?= _('ja') ?>
+ <? else: ?>
+ <?= _('nein') ?>
+ <? endif ?>
+ <? elseif ($property->definition->type == 'user'): ?>
+ <?
+ $user = User::findByUsername($property->state);
+ if (!$user) {
+ //Find by ID:
+ $user = User::find($property->state);
+ }
+ ?>
+ <? if ($user instanceof User): ?>
+ <a href="<?= $controller->link_for(
+ 'profile',
+ ['username' => $user->username]
+ ) ?>" target="_blank">
+ <?= htmlReady($user->getFullName()) ?>
+ </a>
+ <a href="<?= $controller->link_for(
+ 'messages/write',
+ ['rec_uname' => $user->username]
+ ) ?>" data-dialog>
+ <?= Icon::create('mail')->asImg(
+ ['class' => 'text-bottom']
+ ) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($property->state) ?>
+ <? endif ?>
+ <? elseif ($property->definition->type == 'url'): ?>
+ <a href="<?= htmlReady($property->state) ?>"
+ target="_blank">
+ <?= htmlReady($property->state) ?>
+ <?= Icon::create('link-extern')->asImg(
+ ['class' => 'text-bottom']
+ ) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($property->state) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </section>
+ <? endforeach ?>
+<? endif ?>
diff --git a/app/views/resources/resource/_standard_properties_form_part.php b/app/views/resources/resource/_standard_properties_form_part.php
new file mode 100644
index 0000000..d4b5149
--- /dev/null
+++ b/app/views/resources/resource/_standard_properties_form_part.php
@@ -0,0 +1,30 @@
+<?
+/**
+ * Template documentation:
+ * This template expects the following parameters to be present:
+ *
+ * - $defined_properties: An array of ResourcePropertyDefinition objects.
+ * - $property_data: An array with the property states where the array keys
+ * represent the property-IDs and the array items represent the corresponding
+ * property values.
+ */
+?>
+<? if ($grouped_defined_properties): ?>
+ <? foreach ($grouped_defined_properties as $group_name => $properties): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= htmlReady($group_name) ?></h1>
+ </header>
+ <section>
+ <? foreach ($properties as $property): ?>
+ <?= $property->toHtmlInput(
+ $property_data[$property->id],
+ '',
+ true,
+ true
+ ) ?>
+ <? endforeach ?>
+ </section>
+ </section>
+ <? endforeach ?>
+<? endif ?>
diff --git a/app/views/resources/resource/add.php b/app/views/resources/resource/add.php
new file mode 100644
index 0000000..f1f4200
--- /dev/null
+++ b/app/views/resources/resource/add.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/resource/_add_edit_form.php') ?>
diff --git a/app/views/resources/resource/booking_plan.php b/app/views/resources/resource/booking_plan.php
new file mode 100644
index 0000000..dc8852d
--- /dev/null
+++ b/app/views/resources/resource/booking_plan.php
@@ -0,0 +1,53 @@
+<? if (Request::get("allday")) {
+ $min_time = '00:00:00';
+ $max_time = '24:00:00';
+ } else {
+ $min_time = Config::get()->RESOURCES_BOOKING_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->RESOURCES_BOOKING_PLAN_END_HOUR . ':00';
+ } ?>
+<?= \Studip\Fullcalendar::create(
+ _('Belegungsplan'),
+ [
+ 'minTime' => ($min_time),
+ 'maxTime' => ($max_time),
+ 'allDaySlot' => false,
+ 'defaultView' =>
+ in_array(Request::get("defaultView"), ['dayGridMonth','timeGridWeek','timeGridDay'])
+ ? Request::get("defaultView")
+ : 'timeGridWeek',
+ 'defaultDate' => Request::get("defaultDate"),
+ 'eventSources' => [
+ [
+ 'url' => URLHelper::getLink(
+ 'api.php/resources/resource/'
+ . htmlReady($resource->id) . '/booking_plan'
+ ),
+ 'method' => 'GET',
+ 'extraParams' => [
+ 'booking_types' => [0,1,2],
+ 'display_requests' => 0
+ ]
+ ]
+ ]
+ ],
+ [],
+ 'resources-fullcalendar'
+) ?>
+<ul class="map-key-list">
+ <? foreach ($table_keys as $key): ?>
+ <li class="map-key">
+ <span style="background-color:<?= $key['colour'] ?>">
+ &nbsp;
+ </span>
+ <?= htmlReady($key['text']) ?>
+ </li>
+ <li class="map-key">
+ <?= Icon::create('refresh', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Wiederholungstermin') ?>
+ </li>
+ <li class="map-key">
+ <?= Icon::create('chat2', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Kommentar') ?>
+ </li>
+ <? endforeach ?>
+</ul>
diff --git a/app/views/resources/resource/delete.php b/app/views/resources/resource/delete.php
new file mode 100644
index 0000000..a23d094
--- /dev/null
+++ b/app/views/resources/resource/delete.php
@@ -0,0 +1,11 @@
+<? if ($show_form): ?>
+<form class="default" method="post" data-dialog="reload-on-close"
+ action="<?= URLHelper::getLink('dispatch.php/room_management/resource/delete/' . $resource->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <h1><?= _('Soll die folgende Ressource wirklich gelöscht werden?') ?></h1>
+ <?= $this->render_partial('resources/resource/index.php', ['resource' => $resource]) ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Löschen'), 'confirmed') ?>
+ </div>
+</form>
+<? endif ?>
diff --git a/app/views/resources/resource/delete_bookings.php b/app/views/resources/resource/delete_bookings.php
new file mode 100644
index 0000000..2a2f31d
--- /dev/null
+++ b/app/views/resources/resource/delete_bookings.php
@@ -0,0 +1,36 @@
+<? if ($show_form): ?>
+ <form class="default" method="post"
+ data-dialog="size-auto<?= !$no_reload ? ';reload-on-close' : ''?>"
+ action="<?= $controller->link_for('resources/resource/delete_bookings/' . $resource_id_parameter) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Zeitbereich zum Löschen von Buchungen wählen') ?></legend>
+ <label class="col-3">
+ <?= _('Startdatum') ?>
+ <input type="text" class="has-date-picker size-s" name="begin_date"
+ value="<?= $begin->format('d.m.Y') ?>">
+ </label>
+ <label class="col-3">
+ <?= _('Enddatum') ?>
+ <input type="text" class="has-date-picker size-s" name="end_date"
+ value="<?= $end->format('d.m.Y') ?>">
+ </label>
+ <label class="col-3">
+ <?= _('Startuhrzeit') ?>
+ <input type="text" class="has-time-picker size-s" name="begin_time"
+ value="<?= $begin->format('H:i') ?>">
+ </label>
+ <label class="col-3">
+ <?= _('Enduhrzeit') ?>
+ <input type="text" class="has-time-picker size-s" name="end_time"
+ value="<?= $end->format('H:i') ?>">
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Buchungen löschen'),
+ 'delete'
+ ) ?>
+ </footer>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/resource/edit.php b/app/views/resources/resource/edit.php
new file mode 100644
index 0000000..f1f4200
--- /dev/null
+++ b/app/views/resources/resource/edit.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/resource/_add_edit_form.php') ?>
diff --git a/app/views/resources/resource/export_bookings.php b/app/views/resources/resource/export_bookings.php
new file mode 100644
index 0000000..b9fdf43
--- /dev/null
+++ b/app/views/resources/resource/export_bookings.php
@@ -0,0 +1,38 @@
+<? if ($resource): ?>
+ <form class="default" method="post"
+ action="<?= $controller->link_for('resources/export/bookings')?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($resource instanceof Room): ?>
+ <input type="hidden" name="selected_rooms[]"
+ value="<?= htmlReady($resource->id)?>">
+ <? else: ?>
+ <input type="hidden" name="selected_resources[]"
+ value="<?= htmlReady($resource->id)?>">
+ <? endif ?>
+ <article class="widget">
+ <header><?= _('Zeitbereich auswählen') ?></header>
+ <section>
+ <label>
+ <?= _('Startzeitpunkt') ?>
+ <input type="text" class="datepicker" name="begin_date"
+ value="<?= $begin->format('d.m.Y') ?>">
+ <input type="time" name="begin_time"
+ value="<?= $begin->format('H:i')?>">
+ </label>
+ <label>
+ <?= _('Endzeitpunkt') ?>
+ <input type="text" class="datepicker" name="end_date"
+ value="<?= $end->format('d.m.Y') ?>">
+ <input type="time" name="end_time"
+ value="<?= $end->format('H:i')?>">
+ </label>
+ </section>
+ </article>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Exportieren'),
+ 'export'
+ ) ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/resource/files.php b/app/views/resources/resource/files.php
new file mode 100644
index 0000000..dd3df9a
--- /dev/null
+++ b/app/views/resources/resource/files.php
@@ -0,0 +1,102 @@
+<? if ($folder): ?>
+ <form method="post" action="<?= $controller->link_for('file/bulk/' . $folder->getId()) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="parent_folder_id" value="<?= $folder->getId() ?>">
+ <table class="default documents sortable-table" data-sortlist="[[2, 0]]" data-folder_id="<?= $folder->getId() ?>">
+ <caption>
+ <a href="<?= $controller->url_for('resources/resource/files/' . $resource->id)?>"
+ title="<?= _('Zum Hauptordner') ?>">
+ <?= Icon::create('folder-home-full', 'clickable')->asImg(30, ['class' => 'text-bottom']) ?>
+ </a>
+ <?= htmlReady($resource->getFullName()) ?></caption>
+ <?= $this->render_partial('files/_files_thead') ?>
+ <tbody>
+ <? if (count($folder_files)): ?>
+ <? foreach($folder_files as $file): ?>
+ <? if ($file->isVisible($GLOBALS['user']->id)) : ?>
+ <?= $this->render_partial(
+ 'files/_fileref_tr',
+ [
+ 'file' => $file,
+ 'current_folder' => $folder,
+ 'controllerpath' => 'resources/resource/files',
+ 'last_visitdate' => $last_visitdate
+ ]
+ ) ?>
+ <? endif ?>
+ <? endforeach ?>
+ <? else: ?>
+ <tr class="empty">
+ <td colspan="7">
+ <?= _('Dieser Ordner ist leer') ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="7">
+ <span class="multibuttons">
+ <?= Studip\Button::create(
+ _('Herunterladen'),
+ 'download'
+ ) ?>
+ <? if ($folder->isWritable($GLOBALS['user']->id)): ?>
+ <?= Studip\Button::create(
+ _('Verschieben'),
+ 'move',
+ [
+ 'data-dialog' => '',
+ 'disabled' => 'disabled'
+ ]
+ ) ?>
+ <? endif ?>
+ <? if ($folder->isReadable($GLOBALS['user']->id)): ?>
+ <?= Studip\Button::create(
+ _('Kopieren'),
+ 'copy',
+ [
+ 'data-dialog' => '',
+ 'disabled' => '',
+ ]
+ ) ?>
+ <? endif ?>
+ <? if ($folder->isWritable($GLOBALS['user']->id)): ?>
+ <?= Studip\Button::create(
+ _('Löschen'),
+ 'delete', [
+ 'disabled' => '',
+ 'data-confirm' => _('Soll die Auswahl wirklich gelöscht werden?')
+ ]
+ ) ?>
+ <? endif ?>
+ <? if ($folder->isWritable($GLOBALS['user']->id)): ?>
+ <?= Studip\LinkButton::create(
+ _('Dokument hinzufügen'),
+ '#',
+ [
+ 'onclick' => 'STUDIP.Files.openAddFilesWindow(); return false;'
+ ]
+ ) ?>
+ <? endif ?>
+ </span>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </form>
+ <? if ($GLOBALS['user']->id !== 'nobody'): ?>
+ <?= $this->render_partial('file/upload_window.php') ?>
+ <?= $this->render_partial(
+ 'file/add_files_window.php',
+ [
+ 'folder_id' => $folder->getId(),
+ 'hidden' => true,
+ 'upload_type' => FileManager::getUploadTypeConfig(
+ $folder->range_id,
+ $GLOBALS['user']->id
+ )
+ ]
+ ) ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/resource/index.php b/app/views/resources/resource/index.php
new file mode 100644
index 0000000..eb47a3e
--- /dev/null
+++ b/app/views/resources/resource/index.php
@@ -0,0 +1,34 @@
+<? if ($resource instanceof Resource): ?>
+ <? if ($resource->description): ?>
+ <p><?= htmlReady($resource->description) ?></p>
+ <? endif ?>
+ <? if ($resource->properties): ?>
+ <h2><?= _('Eigenschaften') ?></h2>
+ <?= $this->render_partial(
+ 'resources/resource/_standard_properties_display_part.php',
+ [
+ 'property_groups' => $resource->getGroupedProperties()
+ ]
+ ) ?>
+ <? endif ?>
+
+ <? $resource_folder = $resource->getFolder(); ?>
+ <? if($resource_folder && $resource_folder->getFiles() && !$hide_files): ?>
+ <h2><?= _('Dateien') ?></h2>
+ <table class="default sortable-table" data-sortlist="[[2, 0]]">
+ <?= $this->render_partial('files/_files_thead') ?>
+ <? foreach($resource_folder->getFiles() as $file): ?>
+ <? if ($file->isVisible($GLOBALS['user']->id)) : ?>
+ <?= $this->render_partial(
+ 'files/_fileref_tr',
+ [
+ 'file' => $file,
+ 'current_folder' => $resource_folder,
+ 'last_visitdate' => time()
+ ]
+ ) ?>
+ <? endif ?>
+ <? endforeach ?>
+ </table>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/resource/lock.php b/app/views/resources/resource/lock.php
new file mode 100644
index 0000000..86f9dbc
--- /dev/null
+++ b/app/views/resources/resource/lock.php
@@ -0,0 +1,25 @@
+<? if ($show_form): ?>
+<form class="default" method="post" data-dialog="reload-on-close"
+ action="<?= URLHelper::getLink('dispatch.php/resources/resource/lock/' . $resource->id) ?>">
+ <fieldset>
+ <legend><?= _('Bitte Sperrzeiten auswählen') ?></legend>
+ <label>
+ <?= _('Startzeitpunkt') ?>
+ <input type="text" name="begin_date" class="has-date-picker"
+ value="<?= htmlReady($begin->format('d.m.Y')) ?>">
+ <input type="text" name="begin_time" class="has-time-picker"
+ value="<?= htmlReady($begin->format('H:i')) ?>">
+ </label>
+ <label>
+ <?= _('Endzeitpunkt') ?>
+ <input type="text" name="end_date" class="has-date-picker"
+ value="<?= htmlReady($end->format('d.m.Y')) ?>">
+ <input type="text" name="end_time" class="has-time-picker"
+ value="<?= htmlReady($end->format('H:i')) ?>">
+ </label>
+ </fieldset>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Sperren'), 'save') ?>
+ </div>
+</form>
+<? endif ?>
diff --git a/app/views/resources/resource/permissions.php b/app/views/resources/resource/permissions.php
new file mode 100644
index 0000000..b0e82d9
--- /dev/null
+++ b/app/views/resources/resource/permissions.php
@@ -0,0 +1,72 @@
+<form class="default" method="post"
+ action="<?= ($custom_form_action_link
+ ? $custom_form_action_link
+ : ($single_user_mode
+ ? $resource->getActionLink(
+ 'permissions',
+ [
+ 'user_id' => $user->id
+ ]
+ )
+ : ($resource
+ ? $resource->getActionLink('permissions')
+ : URLHelper::getLink(
+ 'dispatch.php/resources/admin/permissions/global'
+ )
+ )
+ )
+ ) ?>"
+ <?= (Request::isDialog()
+ ? (
+ $single_user_mode
+ ? 'data-dialog="reload-on-close"'
+ : 'data-dialog'
+ )
+ : '') ?>>
+ <? if ($custom_hidden_fields): ?>
+ <? foreach ($custom_hidden_fields as $name => $content): ?>
+ <? if (is_array($content)): ?>
+ <? foreach ($content as $item): ?>
+ <input type="hidden" name="<?= htmlReady($name) ?>"
+ value="<?= htmlReady($item) ?>">
+ <? endforeach ?>
+ <? else: ?>
+ <input type="hidden" name="<?= htmlReady($name) ?>"
+ value="<?= htmlReady($content) ?>">
+ <? endif ?>
+ <? endforeach ?>
+ <? endif ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial(
+ 'resources/_common/_permission_table.php',
+ [
+ 'permissions' => $permissions,
+ 'custom_empty_list_message' => $custom_empty_list_message,
+ 'table_id' => $table_id,
+ 'single_user' => $user
+ ]
+ ) ?>
+ <? if (!$single_user_mode): ?>
+ <p>
+ <label>
+ <?= _('Person hinzufügen') ?>
+ <?= $user_search->render() ?>
+ </label>
+ </p>
+ <? if ($course_search): ?>
+ <p>
+ <label>
+ <?= _('Teilnehmende aus Veranstaltung hinzufügen') ?>
+ <?= $course_search->render() ?>
+ </label>
+ </p>
+ <? endif ?>
+ <? endif ?>
+
+ <div data-dialog-button>
+ <?= \Studip\Button::create(
+ ($custom_save_button_text ? $custom_save_button_text : _('Speichern')),
+ 'save'
+ ) ?>
+ </div>
+</form>
diff --git a/app/views/resources/resource/temporary_permissions.php b/app/views/resources/resource/temporary_permissions.php
new file mode 100644
index 0000000..31478ef
--- /dev/null
+++ b/app/views/resources/resource/temporary_permissions.php
@@ -0,0 +1,247 @@
+<form class="default" id="resource-temporary-permissions" method="post"
+ action="<?= ($single_user_mode
+ ? $resource->getActionLink(
+ 'temporary_permissions',
+ [
+ 'user_id' => $user->id
+ ]
+ )
+ : $resource->getActionLink('temporary_permissions')
+ ) ?>"
+ <?= (Request::isDialog()
+ ? (
+ $single_user_mode
+ ? 'data-dialog="reload-on-close"'
+ : 'data-dialog'
+ )
+ : '') ?>>
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default sortable-table temporary-permission-list" id="TemporaryPermissionList"
+ data-sortlist="[[1, 0]]">
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" class="bulk-proxy"
+ data-proxyfor="input.selected-temporary-permission"
+ data-activates="table.temporary-permission-list button.bulk-action">
+ </th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="htmldata"><?= _('Rechtestufe') ?></th>
+ <th><?= _('Gültig von') ?></th>
+ <th><?= _('Gültig bis') ?></th>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr>
+ <td colspan="5">
+ <?
+ $button_attrs = ['class' => 'bulk-action'];
+ ?>
+ <?= \Studip\Button::create(_('Löschen'), 'bulk_delete', $button_attrs) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <tbody>
+ <? if (count($temp_permissions)): ?>
+ <? foreach ($temp_permissions as $permission): ?>
+ <?
+ $permission_sort_key = 10;
+ switch ($permission->perms) {
+ case 'autor': {
+ $permission_sort_key = 20;
+ break;
+ } case 'tutor': {
+ $permission_sort_key = 30;
+ break;
+ } case 'admin': {
+ $permission_sort_key = 40;
+ break;
+ }
+ }
+ ?>
+ <tr data-temp-perms="1" class="resource-temporary-permission-row">
+ <input type="hidden" name="permissions[permission_id][<?= htmlReady('existing_' . $permission->id) ?>]"
+ value="<?= htmlReady($permission->id) ?>">
+ <td>
+ <input type="checkbox" class="selected-temporary-permission"
+ name="selected_permission_ids[<?= htmlReady('existing_' . $permission->id) ?>]"
+ value="<?= htmlReady($permission->id) ?>">
+ </td>
+ <td>
+ <?= htmlReady($permission->user->getFullName('full_rev_username')) ?>
+ (<?= htmlReady($permission->user->perms) ?>)
+ <input type="hidden" name="permissions[user_id][<?= htmlReady('existing_' . $permission->id) ?>]"
+ value="<?= htmlReady($permission->user_id)?>">
+ </td>
+ <td data-sort-value="<?= htmlReady($permission_sort_key) ?>">
+ <select name="permissions[level][<?= htmlReady('existing_' . $permission->id) ?>]">
+ <option value="user"
+ <?=
+ $permission->perms == 'user'
+ ? 'selected="selected"'
+ : '' ?>>
+ user
+ </option>
+ <option value="autor"
+ <?=
+ $permission->perms == 'autor'
+ ? 'selected="selected"'
+ : '' ?>>
+ autor
+ </option>
+ <option value="tutor"
+ <?=
+ $permission->perms == 'tutor'
+ ? 'selected="selected"'
+ : '' ?>>
+ tutor
+ </option>
+ <option value="admin"
+ <?=
+ $permission->perms == 'admin'
+ ? 'selected="selected"'
+ : '' ?>>
+ admin
+ </option>
+ </select>
+ </td>
+ <td class="DateTime">
+ <input type="text" class="has-date-picker"
+ name="permissions[begin_date][<?= htmlReady('existing_' . $permission->id) ?>]"
+ value="<?= date('d.m.Y', $permission->begin)?>">
+ <input type="text" class="has-time-picker"
+ name="permissions[begin_time][<?= htmlReady('existing_' . $permission->id) ?>]"
+ value="<?= date('H:i', $permission->begin)?>">
+ </td>
+ <td class="DateTime">
+ <input type="text" class="has-date-picker"
+ name="permissions[end_date][<?= htmlReady('existing_' . $permission->id) ?>]"
+ value="<?= date('d.m.Y', $permission->end)?>">
+ <input type="text" class="has-time-picker"
+ name="permissions[end_time][<?= htmlReady('existing_' . $permission->id) ?>]"
+ value="<?= date('H:i', $permission->end)?>">
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? endif ?>
+ <tr id="ResourceEmptyPermissionListMessage"
+ <?= count($temp_permissions) ? 'class="invisible"' : ''?>>
+ <td colspan="3"></td>
+ </tr>
+ <tr class="invisible resource-temporary-permission-row resource-permission-list-template"
+ data-temp-perms="1">
+ <td>
+ <input type="checkbox"
+ name="selected_permission_ids[]"
+ disabled="disabled"
+ value="">
+ </td>
+ <td>
+ <input type="hidden" name="permissions[user_id][]"
+ value="USERID">
+ </td>
+ <td>
+ <select name="permissions[level][]">
+ <option value="user">
+ user
+ </option>
+ <option value="autor" selected="selected">
+ autor
+ </option>
+ <option value="tutor">
+ tutor
+ </option>
+ <option value="admin">
+ admin
+ </option>
+ </select>
+ </td>
+ <td class="DateTime">
+ <input type="text" name="permissions[begin_date][]">
+ <input type="text" name="permissions[begin_time][]">
+ </td>
+ <td class="DateTime">
+ <input type="text" name="permissions[end_date][]">
+ <input type="text" name="permissions[end_time][]">
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <input type="checkbox" class="invisible bulk-datetime-enable">
+ <fieldset class="bulk-datetime">
+ <legend>
+ <?= _('Neuen Zeitbereich für die ausgewählten Berechtigungen setzen') ?>
+ </legend>
+
+ <div class="col-2">
+ <label>
+ <?= _('Beginn') ?>
+ <input type="text" name="bulk_begin_date"
+ class="has-date-picker"
+ value="<?= htmlReady(
+ $bulk_begin
+ ? $bulk_begin->format('d.m.Y')
+ : date('d.m.Y')
+ ) ?>">
+ <input type="text" name="bulk_begin_time"
+ class="has-time-picker"
+ value="<?= htmlReady(
+ $bulk_begin
+ ? $bulk_begin->format('H:i')
+ : date('H:i')
+ ) ?>">
+ </label>
+ </div>
+ <div class="col-2">
+ <label>
+ <?= _('Ende') ?>
+ <input type="text" name="bulk_end_date"
+ class="has-date-picker"
+ value="<?= htmlReady(
+ $bulk_end
+ ? $bulk_end->format('d.m.Y')
+ : date('d.m.Y')
+ ) ?>">
+ <input type="text" name="bulk_end_time"
+ class="has-time-picker"
+ value="<?= htmlReady(
+ $bulk_end
+ ? $bulk_end->format('H:i')
+ : date('H:i')
+ ) ?>">
+ </label>
+ </div>
+ <!--<div>
+ <?= \Studip\Button::create(
+ _('Speichern'),
+ 'bulk_save'
+ ) ?>
+ </div>-->
+ </fieldset>
+
+<? if (!$single_user_mode): ?>
+ <fieldset>
+ <legend>
+ <?= _('Person hinzufügen') ?>
+ </legend>
+ <label>
+ <?= $user_search->render() ?>
+ </label>
+ </fieldset>
+
+ <? if ($course_search): ?>
+ <fieldset>
+ <legend>
+ <?= _('Teilnehmende aus Veranstaltung hinzufügen') ?>
+ </legend>
+ <label>
+ <?= $course_search->render() ?>
+ </label>
+ </fieldset>
+ <? endif ?>
+<? endif ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ </div>
+</form>
diff --git a/app/views/resources/room/_add_edit_form.php b/app/views/resources/room/_add_edit_form.php
new file mode 100644
index 0000000..6cd3fd2
--- /dev/null
+++ b/app/views/resources/room/_add_edit_form.php
@@ -0,0 +1,69 @@
+<? if ($show_form): ?>
+ <form class="default" method="post" action="<?= ($mode == 'add')
+ ? $controller->url_for('resources/room/add')
+ : $controller->url_for('resources/room/edit/' . $room->id) ?>"
+ data-dialog="reload-on-close">
+
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="category_id" value="<?= htmlReady($category_id) ?>">
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label>
+ <?= _('Der Raum befindet sich in folgender Hierarchie:') ?>
+ <select name="parent_id">
+ <? foreach ($building_hierarchies as $building_id => $hierarchy): ?>
+ <option value="<?= htmlReady($building_id) ?>"
+ <?= ($building_id == $parent_id) ? 'selected="selected"' : '' ?>>
+ <?= htmlReady($hierarchy) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Name des Raumes') ?>
+ <input type="text" name="name" value="<?= htmlReady($room->name) ?>">
+ </label>
+ <label>
+ <?= _('Beschreibungstext') ?>
+ <input type="text" name="description" value="<?= htmlReady($room->description) ?>">
+ </label>
+ <label>
+ <input type="checkbox" name="requestable" value="1"
+ <?= $room->requestable ? 'checked="checked"' : '' ?>>
+ <?= _('Raum ist wünschbar') ?>
+ </label>
+ <label>
+ <?= _('Raumtyp') ?>
+ <input type="text" name="room_type" value="<?= htmlReady($room_type) ?>">
+ </label>
+ <label>
+ <?= _('Sitzplätze') ?>
+ <input type="number" name="seats" value="<?= htmlReady($seats) ?>">
+ </label>
+ <label>
+ <input type="checkbox" name="booking_plan_is_public" value="1"
+ <?= $booking_plan_is_public ? 'checked="checked"' : '' ?>>
+ <?= _('Raumplan ist öffentlich zugänglich') ?>
+ </label>
+ <? if ($GLOBALS['perm']->have_perm('root')): ?>
+ <label>
+ <?= _('Sortierposition') ?>
+ <input type="text" name="sort_position"
+ value="<?= htmlReady($sort_position) ?>">
+ </label>
+ <? endif ?>
+ </fieldset>
+ <? if ($grouped_defined_properties): ?>
+ <?= $this->render_partial(
+ 'resources/resource/_standard_properties_form_part.php',
+ [
+ 'grouped_defined_properties' => $grouped_defined_properties,
+ 'property_data' => $property_data
+ ]
+ ) ?>
+ <? endif ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'confirmed') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/room/add.php b/app/views/resources/room/add.php
new file mode 100644
index 0000000..f47f848
--- /dev/null
+++ b/app/views/resources/room/add.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/room/_add_edit_form.php') ?>
diff --git a/app/views/resources/room/delete.php b/app/views/resources/room/delete.php
new file mode 100644
index 0000000..c4c0e32
--- /dev/null
+++ b/app/views/resources/room/delete.php
@@ -0,0 +1,14 @@
+<? if ($show_form): ?>
+<form class="default" method="post" data-dialog="reload-on-close"
+ action="<?= $controller->link_for('resources/room/delete/' . $room->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <h1><?= _('Soll der folgende Raum wirklich gelöscht werden?') ?></h1>
+ <?= $this->render_partial('resources/room/index.php', [
+ 'room' => $room,
+ 'grouped_properties' => $room->getGroupedProperties()
+ ]) ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Löschen'), 'confirmed') ?>
+ </div>
+</form>
+<? endif ?>
diff --git a/app/views/resources/room/edit.php b/app/views/resources/room/edit.php
new file mode 100644
index 0000000..f47f848
--- /dev/null
+++ b/app/views/resources/room/edit.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/room/_add_edit_form.php') ?>
diff --git a/app/views/resources/room/index.php b/app/views/resources/room/index.php
new file mode 100644
index 0000000..a68bfc9
--- /dev/null
+++ b/app/views/resources/room/index.php
@@ -0,0 +1,113 @@
+<nav class="resource-hierarchy">
+ <? if ($room->building->location): ?>
+ <a href="<?= $room->building->location->getActionLink('show') ?>" <?= (Request::isDialog()) ? 'data-dialog' : ''; ?>>
+ <?= htmlReady($room->building->location->name) ?>
+ </a>
+ &gt;
+ <? endif ?>
+ <? if ($room->building): ?>
+ <a href="<?= $room->building->getActionLink('show') ?>" <?= (Request::isDialog()) ? 'data-dialog' : ''; ?>>
+ <?= htmlReady($room->building->name) ?>
+ </a>
+ &gt;
+ <? endif ?>
+ <?= htmlReady($room->name) ?>
+</nav>
+
+<section class="contentbox">
+ <header>
+ <h1><?= _('Beschreibung und Hinweise') ?></h1>
+ </header>
+ <section>
+ <? if ($room->description): ?>
+ <p><?= htmlReady($room->description) ?></p>
+ <? endif ?>
+ <ul>
+ <? if ($room->room_type): ?>
+ <li><?= htmlReady($room->room_type) ?></li>
+ <? endif ?>
+ <li>
+ <?= sprintf(
+ ngettext('%d Sitzplatz', '%d Sitzplätze', intval($room->seats)), intval($room->seats)
+ ) ?>
+ </li>
+ </ul>
+ </section>
+</section>
+
+<? if ($grouped_properties): ?>
+ <?= $this->render_partial(
+ 'resources/resource/_standard_properties_display_part.php',
+ [
+ 'property_groups' => $grouped_properties
+ ]
+ ) ?>
+<? endif ?>
+
+<? $resource_folder = $room->getFolder(); ?>
+<? if ($resource_folder && $resource_folder->getFiles()): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Dateien') ?></h1>
+ </header>
+ <table class="default sortable-table" data-sortlist="[[2, 0]]">
+ <?= $this->render_partial('files/_files_thead') ?>
+ <? foreach ($resource_folder->getFiles() as $file): ?>
+ <? if ($file->isVisible($GLOBALS['user']->id)) : ?>
+ <?= $this->render_partial(
+ 'files/_fileref_tr',
+ [
+ 'file' => $file,
+ 'current_folder' => $resource_folder,
+ 'last_visitdate' => time()
+ ]
+ ) ?>
+ <? endif ?>
+ <? endforeach ?>
+ </table>
+ </section>
+<? endif ?>
+
+<footer data-dialog-button>
+ <? if ($room->userHasPermission(User::findCurrent(), 'autor')) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Wochenbelegung'),
+ $room->getActionURL('booking_plan')
+ ) ?>
+ <?= \Studip\LinkButton::create(
+ _('Semesterbelegung'),
+ $room->getActionURL('semester_plan')
+ ) ?>
+ <? elseif ($room->bookingPlanVisibleForUser(User::findCurrent())) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Belegungsplan'),
+ $room->getActionURL('booking_plan'),
+ ['data-dialog' => 'size=big']) ?>
+ <?= \Studip\LinkButton::create(
+ _('Semesterbelegung'),
+ $room->getActionURL('semester_plan'),
+ ['data-dialog' => 'size=big']) ?>
+ <? endif ?>
+ <? if ($room->building) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Zum Lageplan'),
+ ResourceManager::getMapUrlForResourcePosition(
+ $room->building->getPropertyObject('geo_coordinates')
+ )
+ ) ?>
+ <? endif ?>
+ <?= \Studip\LinkButton::createEdit(
+ _('Bearbeiten'),
+ $room->getActionURL('edit'),
+ [
+ 'data-dialog' => 'size=auto'
+ ]
+ ) ?>
+ <? if (!$current_user_is_resource_autor && $room->requestable) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Raum anfragen'),
+ $room->getActionURL('request'),
+ ['data-dialog' => 'size=auto']) ?>
+ <? endif ?>
+</footer>
+
diff --git a/app/views/resources/room/select_category.php b/app/views/resources/room/select_category.php
new file mode 100644
index 0000000..7d2249b
--- /dev/null
+++ b/app/views/resources/room/select_category.php
@@ -0,0 +1,19 @@
+<? if ($categories) : ?>
+ <form method="get" action="<?= $controller->url_for('resources/room/add/' . $room_id) ?>" class="default"
+ data-dialog="size=auto">
+ <label>
+ <?= _('Raumkategorie') ?>
+ <select name="category_id" required>
+ <option value=""><?= _('Bitte eine Raumkategorie auswählen:') ?></option>
+ <? foreach ($categories as $category) : ?>
+ <option value="<?= $category->id ?>">
+ <?= htmlReady($category->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Auswählen')) ?>
+ </footer>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/room_group/permissions.php b/app/views/resources/room_group/permissions.php
new file mode 100644
index 0000000..bb3eaf8
--- /dev/null
+++ b/app/views/resources/room_group/permissions.php
@@ -0,0 +1,66 @@
+<? if ($rooms): ?>
+ <table class="default">
+ <caption><?= _('Räume') ?></caption>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Sitzplätze') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($rooms as $room): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_room_tr.php',
+ [
+ 'room' => $room,
+ //The permissions view is only accessible
+ //for admin users.
+ 'show_user_actions' => false,
+ 'show_autor_actions' => false,
+ 'show_tutor_actions' => false,
+ 'show_admin_actions' => false
+ ]
+ ) ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <? if ($show_form): ?>
+ <?= $this->render_partial(
+ 'resources/resource/permissions',
+ [
+ 'custom_empty_list_message' => _('Es sind keine gemeinsamen Rechte für die oben aufgeführten Räume vorhanden.'),
+ 'custom_save_button_text' => _('Zuweisen'),
+ 'custom_form_action_link' => URLHelper::getLink('dispatch.php/resources/room_group/permissions/' . $clipboard->id),
+ 'custom_hidden_fields' => [
+ 'resource_ids[]' => $room_ids
+ ],
+ 'permissions' => $common_permissions,
+ 'table_caption' => _('Gemeinsame Rechte'),
+ 'table_id' => 'RoomGroupCommonPermissionTable',
+ 'user_search' => $user_search
+ ]
+ ) ?>
+ <? if ($partial_permissions): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_permission_table.php',
+ [
+ 'permissions' => $partial_permissions,
+ 'custom_columns' => [
+ _('Raum') => $permission_room_list
+ ],
+ 'custom_actions' => [
+ [
+ 'icon' => Icon::create('arr_2up'),
+ 'title' => _('Berechtigung für alle Räume übernehmen'),
+ 'link_classes' => 'apply-to-all-action'
+ ]
+ ],
+ 'show_delete_action' => false,
+ 'table_caption' => _('Spezielle Rechte'),
+ 'user_search' => $user_search
+ ]
+ ) ?>
+ <? endif ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/room_planning/_sidebar_date_selection.php b/app/views/resources/room_planning/_sidebar_date_selection.php
new file mode 100644
index 0000000..34962e6
--- /dev/null
+++ b/app/views/resources/room_planning/_sidebar_date_selection.php
@@ -0,0 +1,20 @@
+<?php
+ if(Request::submitted('defaultDate')){
+ $submitted_date = explode('-', Request::get('defaultDate'));
+ $default_date = $submitted_date[2] . '.' . $submitted_date[1] . '.' . $submitted_date[0];
+ } else {
+ $default_date = strftime('%x', time());
+ }
+?>
+<?= \Studip\Button::create(
+ _('Heute'),
+ 'today',
+ [
+ 'id' => 'booking-plan-jmpdate-button',
+ 'onClick' => "$('#booking-plan-jmpdate').val('". strftime('%x', time()) ."');$('#booking-plan-jmpdate-submit').trigger('click');"
+ ]
+ ); ?>
+
+<input id="booking-plan-jmpdate" type="text"
+ name="booking-plan-jmpdate" value="<?= $default_date; ?>">
+ <?= Icon::create('accept', 'clickable')->asInput(['id'=>'booking-plan-jmpdate-submit', 'class' => 'text-top']) ?>
diff --git a/app/views/resources/room_planning/booking_plan.php b/app/views/resources/room_planning/booking_plan.php
new file mode 100644
index 0000000..6750af1
--- /dev/null
+++ b/app/views/resources/room_planning/booking_plan.php
@@ -0,0 +1,129 @@
+<? if ($resource): ?>
+ <? if (Request::get("allday")) {
+ $min_time = '00:00:00';
+ $max_time = '24:00:00';
+ } else {
+ $min_time = Config::get()->RESOURCES_BOOKING_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->RESOURCES_BOOKING_PLAN_END_HOUR . ':00';
+ } ?>
+
+ <section id="booking_plan_header"
+ class="studip-fullcalendar-header booking-plan-header"
+ data-semester-begin="" data-semester-end="">
+ <span id="booking-plan-header-resource-name-line">
+ <? if ($resource instanceof Room) : ?>
+ <?= htmlReady($resource->name) ?>
+ <span id="booking-plan-header-seats">
+ <?= htmlReady(sprintf(_('%d Sitzplätze'), $resource->seats)) ?>
+ </span>
+ <? else : ?>
+ <?= htmlReady($resource->name) ?>
+ <? endif ?>
+ <span id="booking-plan-header-semrow">
+ <strong>
+ <span id="booking-plan-header-semname"></span>
+ <span id="booking-plan-header-semweek-part">
+ <span id="booking-plan-header-semweek"></span>
+ </span>
+ </strong>
+ </span>
+ </span>
+ <? if ($resource->getProperty('room_administrator')): ?>
+ <div id="booking-plan-header-room_administrator-line">
+ <a href="<?= $resource->getProperty('room_administrator');?>">
+ <?= Icon::create('person', Icon::ROLE_CLICKABLE, ['class' => 'text-bottom']); ?>
+ <?= $resource->getPropertyObject('room_administrator')->display_name; ?>
+ </a>
+ </div>
+ <? endif; ?>
+ <? if ($resource->getProperty('administration_url')): ?>
+ <div id="booking-plan-header-administration_url-line">
+ <a href="<?= $resource->getProperty('administration_url');?>">
+ <?= Icon::create('link-extern', Icon::ROLE_CLICKABLE, ['class' => 'text-bottom']); ?>
+ <?= $resource->getPropertyObject('administration_url')->display_name; ?>
+ </a>
+ </div>
+ <? endif; ?>
+ </section>
+ <?= \Studip\Fullcalendar::create(
+ _('Belegungsplan'),
+ [
+ 'editable' => true,
+ 'selectable' => ($fullcalendar_studip_urls['add'] != null),
+ 'studip_urls' => $fullcalendar_studip_urls,
+ 'minTime' => ($min_time),
+ 'maxTime' => ($max_time),
+ 'allDaySlot' => false,
+ 'header' => [
+ 'left' => 'dayGridMonth,timeGridWeek,timeGridDay',
+ 'right' => 'prev,next'
+ ],
+ 'weekNumbers' => true,
+ 'views' => [
+ 'dayGridMonth' => [
+ 'eventTimeFormat' => ['hour' => 'numeric', 'minute' => '2-digit'],
+ 'displayEventEnd' => true
+ ],
+ 'timeGridWeek' => [
+ 'columnHeaderFormat' => [ 'weekday' => 'short', 'year' => 'numeric', 'month' => '2-digit', 'day' => '2-digit', 'omitCommas' => true ]
+ ],
+ 'timeGridDay' => [
+ 'columnHeaderFormat' => [ 'weekday' => 'long', 'year' => 'numeric', 'month' => '2-digit', 'day' => '2-digit', 'omitCommas' => true ]
+ ]
+ ],
+ 'defaultView' =>
+ in_array(Request::get("defaultView"), ['dayGridMonth','timeGridWeek','timeGridDay'])
+ ? Request::get("defaultView")
+ : 'timeGridWeek',
+ 'defaultDate' => Request::get("defaultDate"),
+ 'eventSources' => [
+ [
+ 'url' => URLHelper::getURL(
+ 'api.php/resources/resource/' . $resource->id . '/booking_plan'
+ ),
+ 'method' => 'GET',
+ 'extraParams' => [
+ 'booking_types' => $booking_types,
+ 'display_requests' => $anonymous_view ? 0 : 1,
+ 'display_all_requests' => $display_all_requests ? 1 : 0
+ ]
+ ]
+ ]
+ ],
+ ['class' => 'resource-plan'],
+ 'resources-fullcalendar'
+ ) ?>
+ <ul class="map-key-list">
+ <? foreach ($table_keys as $key): ?>
+ <li class="map-key">
+ <span style="background-color:<?= $key['colour'] ?>">
+ &nbsp;
+ </span>
+ <?= htmlReady($key['text']) ?>
+ </li>
+ <? endforeach ?>
+ <li class="map-key">
+ <?= Icon::create('refresh', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Wiederholungstermin') ?>
+ </li>
+ <li class="map-key">
+ <?= Icon::create('chat2', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Kommentar') ?>
+ </li>
+ </ul>
+<? else: ?>
+ <? if ($rooms): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_grouped_room_list.php',
+ [
+ 'grouped_rooms' => RoomManager::groupRooms($rooms),
+ 'link_template' => $selection_link_template,
+ 'show_in_dialog' => false
+ ]
+ ) ?>
+ <? else: ?>
+ <?= MessageBox::error(
+ _('Es wurde kein Raum ausgewählt und Sie haben keine Berechtigungen an Räumen!')
+ ) ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/room_planning/overbooked_rooms.php b/app/views/resources/room_planning/overbooked_rooms.php
new file mode 100644
index 0000000..34c6f45
--- /dev/null
+++ b/app/views/resources/room_planning/overbooked_rooms.php
@@ -0,0 +1,55 @@
+<? if (count($overbooked_rooms)): ?>
+ <table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Raumname') ?></th>
+ <th><?= _('Sitzplätze') ?></th>
+ <th><?= _('Anzahl Teilnehmende der Veranstaltung') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($overbooked_rooms as $room): ?>
+ <tr>
+ <td><?= htmlReady($room->name) ?></td>
+ <td><?= htmlReady($room->seats) ?></td>
+ <td>
+ <? if ($courses[$room->id]): ?>
+ <ul>
+ <? foreach ($courses[$room->id] as $course): ?>
+ <li>
+ <?= htmlReady($course['name']) ?>
+ <?= htmlReady(
+ sprintf(
+ _('%d Teilnehmende'),
+ $course['participants']
+ )
+ ) ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ </td>
+ <td>
+ <?
+ $actions = ActionMenu::get();
+ $actions->addLink(
+ $room->getActionLink('booking_plan'),
+ Icon::create('timetable'),
+ _('Belegungsplan anzeigen'),
+ [
+ 'target' => '_blank'
+ ]
+ );
+ ?>
+ <? $actions->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? else: ?>
+ <?= PageLayout::postInfo(
+ _('Es liegen keine überbuchten Räume vor.')
+ ) ?>
+<? endif ?>
diff --git a/app/views/resources/room_planning/semester_plan.php b/app/views/resources/room_planning/semester_plan.php
new file mode 100644
index 0000000..773191e
--- /dev/null
+++ b/app/views/resources/room_planning/semester_plan.php
@@ -0,0 +1,160 @@
+<? if ($resource) : ?>
+ <? if (Request::get("allday")) {
+ $min_time = '00:00:00';
+ $max_time = '24:00:00';
+ } else {
+ $min_time = Config::get()->RESOURCES_BOOKING_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->RESOURCES_BOOKING_PLAN_END_HOUR . ':00';
+ } ?>
+
+ <? if ($resource instanceof Room) : ?>
+ <? if (Request::isDialog()) : ?>
+ <section class="fullcalendar-dialogwidget-container">
+ <div class="fullcalendar-dialogwidget-widget">
+ <div class="fullcalendar-dialogwidget-widget-header">
+ <?= _('Semester auswählen') ?>
+ </div>
+ <div class="fullcalendar-dialogwidget-widget-content">
+ <form action="<?= $plan_link ?>" method="get" data-dialog="size=big">
+ <input type="hidden" name="resource_id"
+ value="<?= htmlReady($resource->id) ?>">
+ <input type="hidden" value="0" name="allday">
+ <select class="fullcalendar-dialogwidget-selectlist submit-upon-select"
+ name="semester_id">
+ <? foreach ($dialog_semesters as $sem) : ?>
+ <option value="<?= htmlReady($sem->id) ?>"
+ title="<?= htmlReady($sem->name) ?>"
+ <?= ($current_semester_id == $sem->id)
+ ? 'selected="selected"' : '' ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <noscript>
+ <button type="submit" class="button"
+ name="Zuweisen"><?= _('Zuweisen') ?></button>
+ </noscript>
+ </form>
+ </div>
+ </div>
+ </section>
+ <? endif ?>
+
+ <section class="studip-fullcalendar-header <?= Request::isDialog()?'fullcalendar-dialog':'';?>"
+ data-semester-begin="" data-semester-end="">
+ <div id="booking-plan-header-resource-name-line">
+ <? if ($resource instanceof Room) : ?>
+ <?= htmlReady($resource->name) ?>,
+ <?= htmlReady(sprintf(_('%d Sitzplätze'), $resource->seats)) ?>,
+ <? else : ?>
+ <?= htmlReady($resource->name) ?>
+ <? endif ?>
+ <span id="booking-plan-header-semrow">
+ <strong>
+ <?= _('Semester') ?>
+ <span id="booking-plan-header-semname"><?= htmlReady($semester->name) ?></span>
+ <span id="booking-plan-header-semspan">
+ <? if (Request::get("semester_timerange") == 'fullsem') : ?>
+ <?= sprintf('(%1$s - %2$s)', date('d.m.Y',$semester->beginn), date('d.m.Y', $semester->ende)); ?>
+ <? else : ?>
+ <?= sprintf('(%1$s - %2$s)', date('d.m.Y',$semester->vorles_beginn), date('d.m.Y', $semester->vorles_ende)); ?>
+ <? endif ?>
+ </span>
+ </strong>
+ </span>
+ </div>
+ <? if ($resource->getProperty('room_administrator')): ?>
+ <div id="booking-plan-header-room_administrator-line">
+ <a href="<?= $resource->getProperty('room_administrator');?>">
+ <?= Icon::create('person', Icon::ROLE_CLICKABLE, ['class' => 'text-bottom']); ?>
+ <?= $resource->getPropertyObject('room_administrator')->display_name; ?>
+ </a>
+ </div>
+ <? endif; ?>
+ <? if ($resource->getProperty('administration_url')): ?>
+ <div id="booking-plan-header-administration_url-line">
+ <a href="<?= $resource->getProperty('administration_url');?>">
+ <?= Icon::create('link-extern', Icon::ROLE_CLICKABLE, ['class' => 'text-bottom']); ?>
+ <?= $resource->getPropertyObject('administration_url')->display_name; ?>
+ </a>
+ </div>
+ <? endif; ?>
+ </section>
+ <? endif ?>
+ <?= \Studip\Fullcalendar::create(
+ _('Semesterplan'),
+ [
+ 'editable' => true,
+ 'selectable' => ($fullcalendar_studip_urls['add'] != null),
+ 'studip_urls' => $fullcalendar_studip_urls,
+ 'minTime' => ($min_time),
+ 'maxTime' => ($max_time),
+ 'allDaySlot' => false,
+ 'columnHeaderFormat' => ['weekday'=> 'short'],
+ 'header' => [
+ 'left' => '',
+ 'right' => ''
+ ],
+ 'defaultView' =>
+ in_array(Request::get("defaultView"), ['dayGridMonth','timeGridWeek','timeGridDay'])
+ ? Request::get("defaultView")
+ : 'timeGridWeek',
+ 'defaultDate' => ((Request::get("semester_timerange") == 'fullsem') ? date('Y-m-d',$semester->beginn) : date('Y-m-d',$semester->vorles_beginn)),
+ 'eventSources' => [
+ [
+ 'url' => URLHelper::getURL(
+ sprintf(
+ 'api.php/resources/resource/%s/semester_plan',
+ htmlReady($resource->id)
+ )
+ ),
+ 'method' => 'GET',
+ 'extraParams' => [
+ 'booking_types' => [0,1,2],
+ 'semester_id' => $semester->id,
+ 'semester_timerange' => Request::get("semester_timerange", 'vorles'),
+ 'display_requests' => 1,
+ 'display_all_requests' => $display_all_requests ? 1 : 0
+ ]
+ ]
+ ],
+ 'nowIndicator' => false
+ ],
+ ['class' => 'resource-plan semester-plan'],
+ 'resources-fullcalendar'
+ ) ?>
+ <ul class="map-key-list">
+ <? foreach ($table_keys as $key): ?>
+ <li class="map-key">
+ <span style="background-color:<?= $key['colour'] ?>">
+ &nbsp;
+ </span>
+ <?= htmlReady($key['text']) ?>
+ </li>
+ <? endforeach ?>
+ <li class="map-key">
+ <?= Icon::create('refresh', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Wiederholungstermin') ?>
+ </li>
+ <li class="map-key">
+ <?= Icon::create('chat2', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Kommentar') ?>
+ </li>
+ </ul>
+<? elseif ($rooms): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_grouped_room_list.php',
+ [
+ 'grouped_rooms' => RoomManager::groupRooms($rooms),
+ 'link_template' => $selection_link_template
+ ]
+ ) ?>
+<? else: ?>
+ <?= MessageBox::error(
+ _('Es wurde kein Raum ausgewählt und Sie haben keine Berechtigungen an Räumen!')
+ ) ?>
+<? endif ?>
+
+<div data-dialog-button>
+ <?= Request::isDialog()?\Studip\LinkButton::create(_('Drucken'), $sem_url, ['class' => 'print_action']):'' ?>
+</div>
diff --git a/app/views/resources/room_request/_add_edit_form.php b/app/views/resources/room_request/_add_edit_form.php
new file mode 100644
index 0000000..94c90f3
--- /dev/null
+++ b/app/views/resources/room_request/_add_edit_form.php
@@ -0,0 +1,55 @@
+<? if ($show_form): ?>
+ <form class="default" method="post" action="<?= $form_action_link ?>" data-dialog="reload-on-close">
+ <input type="hidden" name="origin_url" value="<?= htmlReady($origin_url) ?>">
+ <input type="checkbox" id="multiday" <?= ($begin_date_str != $end_date_str) ? 'checked' : ''; ?>
+ onClick="$('#end_date_section').toggle();" class="studip-checkbox">
+ <label for="multiday">
+ <?= _('Mehrtägig') ?>
+ </label>
+ <section>
+ <label class="col-2" style="min-width: 40%">
+ <?= _('Startdatum') ?>
+ <input type="text" name="begin_date" class="has-date-picker size-s"
+ value="<?= htmlReady($begin_date_str) ?>">
+ </label>
+ <label id="end_date_section"
+ style="min-width: 40%;<?= ($begin_date_str == $end_date_str) ? 'display: none;' : ''; ?>"
+ class="col-2">
+ <?= _('Enddatum') ?>
+ <input type="text" name="end_date" class="has-date-picker size-s"
+ value="<?= htmlReady($end_date_str) ?>">
+ </label>
+ </section>
+ <section>
+ <label class="col-2">
+ <?= _('Startuhrzeit') ?>
+ <input type="text" name="begin_time" class="has-time-picker size-s"
+ value="<?= htmlReady($begin_time_str) ?>">
+ </label>
+ <label class="col-2">
+ <?= _('Enduhrzeit') ?>
+ <input type="text" name="end_time" class="has-time-picker size-s"
+ value="<?= htmlReady($end_time_str) ?>">
+ </label>
+ </section>
+ <label>
+ <?= _('Rüstzeit') ?>
+ <input type="number" name="preparation_time" value="<?= htmlReady($preparation_time) ?>" min="0"
+ max="<?= htmlReady($max_preparation_time) ?>" class="size-s">
+ </label>
+ <label>
+ <?= _('Anfragetext') ?>
+ <textarea name="comment"><?= htmlReady($comment) ?></textarea>
+ </label>
+ <footer data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern'), 'save') ?>
+ <? if ($request): ?>
+ <?= \Studip\LinkButton::create(
+ _('Löschen'),
+ $controller->url_for('resources/room_request/delete/' . $request->id),
+ ['data-dialog' => '1']
+ ) ?>
+ <? endif ?>
+ </footer>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/room_request/add.php b/app/views/resources/room_request/add.php
new file mode 100644
index 0000000..cec36dc
--- /dev/null
+++ b/app/views/resources/room_request/add.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/room_request/_add_edit_form.php') ?>
diff --git a/app/views/resources/room_request/decline.php b/app/views/resources/room_request/decline.php
new file mode 100644
index 0000000..188c4bb
--- /dev/null
+++ b/app/views/resources/room_request/decline.php
@@ -0,0 +1,56 @@
+<form class="default" method="post" id="decline-request"
+ action="<?= $controller->link_for('resources/room_request/decline/' . $request->id) ?>"
+ data-dialog>
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($show_form): ?>
+ <? if ($delete_mode): ?>
+ <input type="hidden" name="delete" value="1">
+ <?= MessageBox::warning(
+ _('Soll die folgende Anfrage wirklich gelöscht werden?')
+ ) ?>
+ <? else: ?>
+ <?= MessageBox::warning(
+ _('Soll die folgende Anfrage wirklich abgelehnt werden?')
+ ) ?>
+ <? endif ?>
+ <fieldset>
+ <legend><?= _('Informationen zur Anfrage') ?></legend>
+ <?= $this->render_partial(
+ 'resources/room_request/index',
+ [
+ 'request' => $request
+ ]
+ ) ?>
+ </fieldset>
+ <? if (!$delete_mode): ?>
+ <fieldset>
+ <legend><?= _('Kommentar zur Ablehnung der Anfrage') ?></legend>
+ <textarea name="reply_comment"><?= $reply_comment ?></textarea>
+ </fieldset>
+ <? endif ?>
+ <? endif ?>
+ <footer data-dialog-button>
+ <? if ($prev_request) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Vorherige Anfrage'),
+ $controller->declineURL($prev_request),
+ ['data-dialog' => 'size=big']
+ ) ?>
+ <? endif ?>
+ <?= \Studip\LinkButton::create(
+ _('Zurück'),
+ $controller->resolveURL($request->id),
+ ['data-dialog' => 'size=big']
+ ) ?>
+ <? if ($show_form) : ?>
+ <?= \Studip\Button::createAccept($delete_mode ? _('Löschen') : _('Ablehnen'), 'confirm') ?>
+ <? endif ?>
+ <? if ($next_request) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Nächste Anfrage'),
+ $controller->declineURL($next_request),
+ ['data-dialog' => 'size=big']
+ ) ?>
+ <? endif ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/resources/room_request/delete.php b/app/views/resources/room_request/delete.php
new file mode 100644
index 0000000..dc111ab
--- /dev/null
+++ b/app/views/resources/room_request/delete.php
@@ -0,0 +1,15 @@
+<? if ($show_form): ?>
+ <form class="default" method="post" data-dialog="reload-on-close"
+ action="<?= $controller->link_for(
+ 'resources/room_request/delete/' . $request->id
+ )?>">
+ <?= MessageBox::info(
+ _('Soll die folgende Anfrage wirklich gelöscht werden?')
+ ) ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $this->render_partial('resources/_common/_request_info.php') ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Löschen'), 'delete') ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/resources/room_request/edit.php b/app/views/resources/room_request/edit.php
new file mode 100644
index 0000000..cec36dc
--- /dev/null
+++ b/app/views/resources/room_request/edit.php
@@ -0,0 +1 @@
+<?= $this->render_partial('resources/room_request/_add_edit_form.php') ?>
diff --git a/app/views/resources/room_request/index.php b/app/views/resources/room_request/index.php
new file mode 100644
index 0000000..883dba0
--- /dev/null
+++ b/app/views/resources/room_request/index.php
@@ -0,0 +1,3 @@
+<? if ($request): ?>
+ <?= $this->render_partial('resources/_common/_request_info.php') ?>
+<? endif ?>
diff --git a/app/views/resources/room_request/overview.php b/app/views/resources/room_request/overview.php
new file mode 100644
index 0000000..4a92208
--- /dev/null
+++ b/app/views/resources/room_request/overview.php
@@ -0,0 +1,61 @@
+<? if ($requests): ?>
+ <form class="default" method="post"
+ action="<?= $controller->link_for('room_request/assign') ?>">
+ <table class="default sortable-table request-list" data-sortlist="[[8, 0]]">
+ <caption>
+ <?= sprintf(
+ ngettext(
+ 'Anfragenliste (%d Anfrage)',
+ 'Anfragenliste (%d Anfragen)',
+ $count_requests
+ ),
+ $count_requests
+ ) ?>
+ </caption>
+ <thead>
+ <tr>
+ <th data-sort="htmldata">
+ <?= Icon::create('radiobutton-checked')->asImg(
+ [
+ 'title' => _('Markierung')
+ ]
+ ) ?>
+ </th>
+ <th data-sort="text"><?= _('Nr.') ?></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="text"><?= _('Lehrende Person(en)') ?></th>
+ <th data-sort="text"><?= _('Raum') ?></th>
+ <th data-sort="text"><?= _('Plätze') ?></th>
+ <th data-sort="text"><?= _('Anfragende Person') ?></th>
+ <th data-sort="htmldata"><?= _('Art') ?></th>
+ <th data-sort="htmldata"><?= _('Dringlichkeit') ?></th>
+ <th data-sort="num"><?= _('letzte Änderung') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($requests as $request): ?>
+ <? if ($request->getTimeIntervals()) : ?>
+ <?= $this->render_partial(
+ 'resources/_common/_request_tr',
+ ['request' => $request]
+ ) ?>
+ <? endif ?>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="11">
+ <section style="float: right">
+ <?= $pagination->asLinks(function ($page) use ($controller) {
+ return $controller->url_for("resources/room_request/overview/{$page}");
+ }) ?>
+ </section>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </form>
+<? else: ?>
+ <?= MessageBox::info(_('Es sind keine Anfragen vorhanden!')) ?>
+<? endif ?>
diff --git a/app/views/resources/room_request/planning.php b/app/views/resources/room_request/planning.php
new file mode 100644
index 0000000..9b645a6
--- /dev/null
+++ b/app/views/resources/room_request/planning.php
@@ -0,0 +1,305 @@
+<form method="get" class="default" action="<?= $controller->planning() ?>">
+ <fieldset>
+ <legend><?= _('Raumauswahl') ?></legend>
+
+ <select name="room_id" aria-labelledby="<?= _('Bitte wählen Sie einen Raum aus') ?>" onchange="this.form.submit()">
+ <option value=""><?= _('Bitte wählen') ?></option>
+ <? foreach ($this->available_rooms as $room) : ?>
+ <option value="<?= $room->id ?>" <?= $resource && $resource->id === $room->id ? 'selected' : '' ?>>
+ <?= htmlReady($room->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </fieldset>
+</form>
+<? if ($resource): ?>
+ <?
+ $min_time = Config::get()->INSTITUTE_COURSE_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->INSTITUTE_COURSE_PLAN_END_HOUR . ':00';
+ $default_date = (Request::get("semester_timerange") == 'fullsem') ? $semester->beginn : $semester->vorles_beginn;
+ ?>
+ <? if ($resource instanceof Room) : ?>
+ <section class="studip-fullcalendar-header <?= Request::isDialog() ? 'fullcalendar-dialog' : ''; ?>"
+ data-semester-begin="" data-semester-end="">
+ <div id="booking-plan-header-resource-name-line">
+ <? if ($resource instanceof Room) : ?>
+ <?= htmlReady($resource->name) ?>,
+ <?= htmlReady(sprintf(_('%d Sitzplätze'), $resource->seats)) ?>
+ <? else : ?>
+ <?= htmlReady($resource->name) ?>
+ <? endif ?>
+ <span id="booking-plan-header-semrow">,
+ <strong>
+ <?= _('Semester') ?>
+ <span id="booking-plan-header-semname"><?= htmlReady($semester->name) ?></span>
+ <span id="booking-plan-header-semspan">
+ <? if (Request::get("semester_timerange") == 'fullsem') : ?>
+ <?= sprintf('(%1$s - %2$s)', date('d.m.Y', $semester->beginn), date('d.m.Y', $semester->ende)); ?>
+ <? else : ?>
+ <?= sprintf('(%1$s - %2$s)', date('d.m.Y', $semester->vorles_beginn), date('d.m.Y', $semester->vorles_ende)); ?>
+ <? endif ?>
+ </span>
+ </strong>
+ </span>
+ </div>
+ <? if ($resource->getProperty('room_administrator')): ?>
+ <div id="booking-plan-header-room_administrator-line">
+ <a href="<?= $resource->getProperty('room_administrator'); ?>">
+ <?= Icon::create('person', Icon::ROLE_CLICKABLE, ['class' => 'text-bottom']); ?>
+ <?= $resource->getPropertyObject('room_administrator')->display_name; ?>
+ </a>
+ </div>
+ <? endif; ?>
+ <? if ($resource->getProperty('administration_url')): ?>
+ <div id="booking-plan-header-administration_url-line">
+ <a href="<?= $resource->getProperty('administration_url'); ?>">
+ <?= Icon::create('link-extern', Icon::ROLE_CLICKABLE, ['class' => 'text-bottom']); ?>
+ <?= $resource->getPropertyObject('administration_url')->display_name; ?>
+ </a>
+ </div>
+ <? endif; ?>
+ </section>
+ <? endif ?>
+ <?= \Studip\Fullcalendar::create(
+ _('Semesterplan'),
+ [
+ 'editable' => true,
+ 'selectable' => ($fullcalendar_studip_urls['add'] != null),
+ 'studip_urls' => $fullcalendar_studip_urls,
+ 'minTime' => ($min_time),
+ 'maxTime' => ($max_time),
+ 'allDaySlot' => false,
+ 'columnHeaderFormat' => ['weekday' => 'short'],
+ 'header' => [
+ 'left' => '',
+ 'right' => ''
+ ],
+ 'defaultView' =>
+ in_array(Request::get("defaultView"), ['dayGridMonth', 'timeGridWeek', 'timeGridDay'])
+ ? Request::get("defaultView")
+ : 'timeGridWeek',
+ 'defaultDate' => date('Y-m-d', $default_date),
+ 'eventSources' => [
+ [
+ 'url' => URLHelper::getURL(
+ sprintf(
+ 'api.php/resources/resource/%s/semester_plan',
+ htmlReady($resource->id)
+ )
+ ),
+ 'method' => 'GET',
+ 'extraParams' => [
+ 'booking_types' => [0, 1, 2],
+ 'semester_id' => $semester->id,
+ 'semester_timerange' => Request::get("semester_timerange", 'vorles'),
+ 'display_requests' => 0,
+ 'display_all_requests' => $display_all_requests ? 1 : 0
+ ]
+ ]
+ ],
+ 'nowIndicator' => false
+ ],
+ ['class' => 'request-plan resource-plan semester-plan'],
+ 'resources-fullcalendar'
+ ) ?>
+ <ul class="map-key-list">
+ <? foreach ($table_keys as $key): ?>
+ <li class="map-key">
+ <span style="background-color:<?= $key['colour'] ?>">
+ &nbsp;
+ </span>
+ <?= htmlReady($key['text']) ?>
+ </li>
+ <? endforeach ?>
+ <li class="map-key">
+ <?= Icon::create('refresh', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Wiederholungstermin') ?>
+ </li>
+ <li class="map-key">
+ <?= Icon::create('chat2', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Kommentar') ?>
+ </li>
+ </ul>
+ <?= \Studip\Button::create(
+ _('Im Plan gezeigte Anfragen buchen'),
+ 'bulk-book-requests',
+ ['disabled' => 'disabled']
+ ); ?>
+<? else: ?>
+ <?= MessageBox::info(_('Es wurde kein Raum ausgewählt!')) ?>
+<? endif ?>
+
+<? if ($requests && $resource): ?>
+ <form class="default" method="post"
+ action="<?= $controller->link_for('room_request/assign') ?>">
+ <table id="external-events" class="default request-list">
+ <caption><?= _('Anfragen'); ?></caption>
+ <thead>
+ <tr>
+ <th data-sort="text"><?= _('Datum/Uhrzeit') ?></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="text"><?= _('Lehrende Person(en)') ?></th>
+ <th data-sort="text"><?= _('Plätze') ?></th>
+ <th data-sort="text"><?= _('Gewünschter Raum') ?></th>
+ <th data-sort="text"><?= _('Anfragende Person') ?></th>
+ <th data-sort="htmldata"><?= _('Art') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $planner_start = new DateTime();
+ $planner_start->setTimestamp($default_date); ?>
+ <? $request_list = []; ?>
+
+ <? foreach ($requests as $request) {
+
+ $range_object = $request->getRangeObject();
+ $intervals = $request->getTimeIntervals();
+
+ if ($request->getGroupedTimeIntervals(true)) {
+ foreach ($request->getGroupedTimeIntervals(true) as $metadate_id => $data) {
+ $timesort = '';
+ if ($data['metadate'] instanceof SeminarCycleDate) {
+ $date_string = $data['metadate']->toString('short');
+ $timesort = $data['metadate']['weekday'] . str_replace(':', '', $data['metadate']['start_time']);
+
+ $interval_data = [];
+ $interval_data['date'] = $date_string;
+ $interval_data['metadate'] = $data['metadate'];
+ $interval_data['interval'] = '';
+ $interval_data['request'] = $request;
+ $request_list[$timesort][$range_object->id][] = $interval_data;
+
+ } else {
+ foreach ($data['intervals'] as $time_interval) {
+ $date_string1 = sprintf(
+ '%1$s. %2$s',
+ getWeekday(date('w', $time_interval['begin'])),
+ date('d.m', $time_interval['begin'])
+ );
+ $date_string2 = sprintf(
+ '%1$s - %2$s',
+ date('H:i', $time_interval['begin']),
+ date('H:i', $time_interval['end'])
+ );
+ $date_string = $date_string1 . ', ' . $date_string2;
+ $timesort = date('w', $time_interval['begin']) . date('His', $time_interval['begin']);
+ $interval_data = [];
+ $interval_data['date'] = $date_string;
+ $interval_data['metadate'] = '';
+ $interval_data['interval'] = $time_interval;
+ $interval_data['request'] = $request;
+ $request_list[$timesort][$range_object->id][] = $interval_data;
+ }
+ }
+ }
+ }
+ } ?>
+
+ <? ksort($request_list); ?>
+ <? foreach ($request_list as $sortdate => $daterequests): ?>
+ <? foreach ($daterequests as $range_object_id => $requestsintervals): ?>
+ <? foreach ($requestsintervals as $requestsinterval): ?>
+
+ <? $request = $requestsinterval['request']; ?>
+ <? $range_object = $request->getRangeObject(); ?>
+ <? if ($range_object instanceof Course) {
+ $displayname = htmlReady($range_object->getFullName('number-type-name'));
+ } elseif ($range_object instanceof User) {
+ $displayname = htmlReady($range_object->getFullName('no_title_rev'));
+ } ?>
+ <?
+ $range_str = '';
+ if ($requestsinterval['metadate']) {
+ if ($requestsinterval['metadate'] instanceof SeminarCycleDate) {
+ $range_str = 'SeminarCycleDate_' . $requestsinterval['metadate']->id;
+ $cdates = $requestsinterval['metadate']->getAllDates();
+ if ($cdates[0]) {
+ $begin = new DateTime();
+ $begin->setTimestamp($cdates[0]->date);
+ $end = new DateTime();
+ $end->setTimestamp($cdates[0]->end_time);
+ }
+ }
+
+ } else if ($requestsinterval['interval']) {
+ $range_str = $requestsinterval['interval']['range'] . '_' . $requestsinterval['interval']['range_id'];
+ $begin = new DateTime();
+ $begin->setTimestamp($requestsinterval['interval']['begin']);
+ $end = new DateTime();
+ $end->setTimestamp($requestsinterval['interval']['end']);
+ } else {
+ $begin = $request->getStartDate();
+ $end = $request->getEndDate();
+ }
+ $studip_weekday_begin = ($begin->format('w') == 0) ? '7' : $begin->format('w');
+ $studip_weekday_end = ($end->format('w') == 0) ? '7' : $end->format('w');
+ ?>
+ <tr class="fc-request-event"
+ data-event-id="<?= $request->id . '_' . $sortdate ?>"
+ data-event-request="<?= $request->id ?>"
+ data-event-title="<?= htmlReady($displayname) ?>"
+ data-event-begin="<?= $begin->format('Y-m-d') . 'T' . $begin->format('H:i:s') . '+02:00'; ?>"
+ data-event-end="<?= $end->format('Y-m-d') . 'T' . $end->format('H:i:s') . '+02:00'; ?>"
+ data-event-studip_weekday_begin="<?= $studip_weekday_begin; ?>"
+ data-event-studip_weekday_end="<?= $studip_weekday_end; ?>"
+ data-event-color="<?= $event_color; ?>"
+ data-event-drop-url=""
+ data-event-tooltip=""
+ data-event-resource="<?= $resource->id; ?>"
+ data-event-metadate="<?= $range_str; ?>"
+ data-event-view_urls_edit="<?= $controller->url_for(
+ 'resources/room_request/resolve/' . $request->id,
+ [
+ 'searched_room_id' => $resource->id,
+ 'alternatives_selection' => 'room_search',
+ 'selected_rooms' => [$range_str => $resource->id],
+ 'reload-on-close' => 1
+ ]); ?>"
+ style="cursor:pointer"
+ >
+ <td>
+ <?= $requestsinterval['date']; ?>
+ </td>
+ <td>
+ <?= $displayname; ?>
+ </td>
+
+ <td>
+ <? if ($range_object instanceof Course): ?>
+ <?= htmlReady(
+ join(', ', $range_object->members->findBy('status', 'dozent')
+ ->limit(3)->getUserFullname('no_title_rev')
+ )
+ ) ?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= $request->getProperty('seats') ?>
+ </td>
+ <td>
+ <?= $request->resource ? htmlReady($request->resource->name) : '' ?>
+ </td>
+ <td>
+ <? if ($request->user instanceof User): ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile', ['username' => $request->user->username]); ?>">
+ <?= htmlReady($request->user->getFullName('no_title_rev')) ?>
+ </a>
+ <? else: ?>
+ <?= _('Unbekannt') ?>
+ <? endif ?>
+ </td>
+ <td>
+ <?= $request->getTypeString() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? endforeach ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </form>
+<? endif ?>
+
+<? if (!$requests && $resource) : ?>
+ <?= MessageBox::info(_('Es sind keine Anfragen vorhanden!')) ?>
+<? endif ?> \ No newline at end of file
diff --git a/app/views/resources/room_request/rerequest_booking.php b/app/views/resources/room_request/rerequest_booking.php
new file mode 100644
index 0000000..48f34db
--- /dev/null
+++ b/app/views/resources/room_request/rerequest_booking.php
@@ -0,0 +1,23 @@
+<form class="default" method="post"
+ action="<?= URLHelper::getLink(
+ 'dispatch.php/resources/room_request/rerequest_booking/' . $booking->id
+ ) ?>"
+ data-dialog="reload-on-close">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= MessageBox::warning(
+ _('Soll die folgende Buchung wirklich gelöscht werden?')
+ ) ?>
+ <?= $this->render_partial(
+ 'resources/booking/index',
+ [
+ 'booking' => $booking,
+ 'hide_buttons' => true
+ ]
+ ) ?>
+ <div data-dialog-button>
+ <?= \Studip\Button::create(
+ _('Löschen und Anfrage erstellen'),
+ 'delete_confirm'
+ ) ?>
+ </div>
+ </form>
diff --git a/app/views/resources/room_request/resolve.php b/app/views/resources/room_request/resolve.php
new file mode 100644
index 0000000..1d5e2e4
--- /dev/null
+++ b/app/views/resources/room_request/resolve.php
@@ -0,0 +1,389 @@
+<form id="resolve-request" class="default" method="post"
+ data-dialog="size=big;<?= Request::submitted('reload-on-close') ? 'reload-on-close' : ''; ?>"
+ action="<?= $controller->link_for('resources/room_request/resolve/' . $request->id) ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <? if ($show_info) : ?>
+ <article class="studip left-part">
+ <header>
+ <h1>
+ <?= _('Informationen zur Anfrage') ?>
+ </h1>
+ <?php
+ $tooltip_info = htmlReady(
+ sprintf(
+ _('Anfrage erstellt am %1$s von %2$s'),
+ date('d.m.Y H:i', $request->mkdate),
+ ($request->user
+ ? $request->user->getFullName()
+ : '')
+ )
+ );
+ $tooltip_info .= '<br>';
+ $tooltip_info .= htmlReady(
+ sprintf(
+ _('Letzte Änderung am %1$s von %2$s'),
+ date('d.m.Y H:i', $request->chdate),
+ ($request->last_modifier
+ ? $request->last_modifier->getFullName()
+ : '')
+ )
+ );
+ echo tooltipHtmlIcon($tooltip_info);
+ ?>
+ </header>
+ <section>
+ <dl>
+ <? if ($request->course): ?>
+ <dt><?= _('Veranstaltung') ?></dt>
+ <dd><?= htmlReady($request->course->getFullName()) ?></dd>
+ <? $lecturers = CourseMember::findByCourseAndStatus($request->course->id, 'dozent') ?>
+ <dt><?= _('Lehrende') ?></dt>
+ <dd>
+ <? if (count($lecturers) == 1): ?>
+ <?= htmlReady($lecturers[0]->getUserFullname()) ?>
+ <? else: ?>
+ <ul>
+ <? foreach ($lecturers as $lecturer): ?>
+ <li><?= htmlReady($lecturer->getUserFullname()) ?></li>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ </dd>
+ <? endif ?>
+ <? if ($request->course): ?>
+ <dt><?= _('Anzahl Teilnehmende') ?></dt>
+ <dd>
+ <?= htmlReady($request->course->getNumParticipants()) ?>
+ </dd>
+ <? endif ?>
+ <dt><?= _('Art der Anfrage') ?></dt>
+ <dd><?= htmlReady($request->getTypeString()) ?></dd>
+ <? if ($request_semester_string): ?>
+ <dt><?= _('Semester')?></dt>
+ <dd><?= htmlReady($request_semester_string) ?></dd>
+ <? endif ?>
+ <dt><?= _('Angeforderte Belegungszeiten') ?></dt>
+ <dd>
+ <? $dates = $request->getDateString(true) ?>
+ <? if ($dates) : ?>
+ <?= implode('<br>', $dates) ?>
+ <? endif ?>
+ </dd>
+
+ <? if ($room_request->preparation_time): ?>
+ <? $preparation_time_minutes = intval($room_request->preparation_time / 60) ?>
+ <dt><?= _('Rüstzeit') ?></dt>
+ <dd>
+ <?= htmlReady(
+ sprintf(
+ ngettext(
+ '%d Minute',
+ '%d Minuten',
+ $preparation_time_minutes
+ ),
+ $preparation_time_minutes
+ )
+ ) ?>
+ </dd>
+ <? endif ?>
+ <? if ($request->properties) : ?>
+ <dt><?= _('Gewünschte Raumeigenschaften') ?></dt>
+ <dd>
+ <table>
+ <tbody>
+ <? foreach ($request->properties as $property): ?>
+ <tr>
+ <td><?= htmlReady($property->display_name) ?></td>
+ <td><?= htmlReady((string)$property) ?></td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </dd>
+ <? endif ?>
+ <? if ($request->resource) : ?>
+ <dt><?= _('Gewünschter Raum') ?></dt>
+ <dd>
+ <?= htmlReady($request->resource->name) ?>
+ </dd>
+ <? endif ?>
+ <? if ($request->comment) : ?>
+ <dt><?= _('Kommentar des Anfragenden') ?></dt>
+ <dd><?= htmlReady($request->comment) ?></dd>
+ <? endif ?>
+ <dt><?= _('Antwort') ?></dt>
+ <? if ($request->closed == 0) : ?>
+ <dd>
+ <textarea name="reply_comment"><?= htmlReady($room_request->reply_comment) ?></textarea>
+ </dd>
+ <? else : ?>
+ <dd><?= htmlReady($request->reply_comment) ?></dd>
+ <? endif ?>
+ </dl>
+ </section>
+ </article>
+ <? if ($show_form): ?>
+ <? if ($expand_metadates) : ?>
+ <input type="hidden" value="1" name="force_expand_metadates">
+ <? endif ?>
+ <article class="right-part">
+ <article class="studip">
+ <header><h1><?= _('Auswahl alternative Räume') ?></h1></header>
+ <section>
+ <? if ($clipboards) : ?>
+ <label>
+ <input type="radio" name="alternatives_selection" value="clipboard"
+ <?= $alternatives_selection == 'clipboard'
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Auswahl anhand einer Raumgruppe') ?>
+ <select name="selected_clipboard_id">
+ <? foreach ($clipboards as $clipboard): ?>
+ <option value="<?= htmlReady($clipboard->id) ?>"
+ <?= $selected_clipboard_id == $clipboard->id
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($clipboard->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif ?>
+ <label>
+ <input type="radio" name="alternatives_selection" value="room_search"
+ <?= $alternatives_selection == 'room_search'
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Raumsuche') ?>
+ <?= $room_search->render() ?>
+ </label>
+ <label>
+ <input type="radio" name="alternatives_selection" value="my_rooms"
+ <?= $alternatives_selection == 'my_rooms'
+ ? 'checked="checked"'
+ : '' ?>>
+ <? if ($user_is_global_autor): ?>
+ <?= _('Alle Räume') ?>
+ <? else: ?>
+ <?= _('Alle meine Räume') ?>
+ <? endif ?>
+ </label>
+ <? if (!$config->RESOURCES_DIRECT_ROOM_REQUESTS_ONLY): ?>
+ <label>
+ <input type="radio" name="alternatives_selection" value="request"
+ <?= $alternatives_selection == 'request'
+ ? 'checked="checked"'
+ : '' ?>>
+ <?= _('Suche anhand der gewünschten Raumeigenschaften') ?>
+ </label>
+ <? endif ?>
+ <?= \Studip\Button::create(_('Auswählen'), 'select_alternatives') ?>
+ </section>
+ </article>
+ <article class="studip notification-settings">
+ <header><h1><?= _('Benachrichtigung über die Auflösung der Anfrage') ?></h1></header>
+ <section>
+ <label>
+ <input type="radio" name="notification_settings" value="creator"
+ <?= $notification_settings == 'creator'
+ ? 'checked="checked"'
+ : ''
+ ?>>
+ <?= _('Nur die erstellende Person benachrichtigen.') ?>
+ </label>
+ <label>
+ <input type="radio" name="notification_settings" value="creator_and_lecturers"
+ <?= $notification_settings == 'creator_and_lecturers'
+ ? 'checked="checked"'
+ : ''
+ ?>>
+ <?= _('Die erstellende Person und alle Lehrenden benachrichtigen.') ?>
+ </label>
+ </section>
+ </article>
+ </article>
+ <article class="studip assign-dates">
+ <header><h1><?= _('Termine zuordnen') ?></h1></header>
+ <div>
+ <table id="resolve-dates-table" class="default">
+ <thead>
+ <tr>
+ <th class="nowrap"><?= _('Raum') ?></th>
+ <? if (count($request_time_intervals) > 1) : ?>
+ <th class="nowrap"><?= _('Alle Termine') ?></th>
+ <? endif ?>
+ <? foreach ($request_time_intervals as $metadate_id => $data): ?>
+ <? if ($data['metadate'] instanceof SeminarCycleDate) : ?>
+ <?php
+ $date_string1 = getWeekday($data['metadate']->weekday);
+ $date_string2 = sprintf(
+ '%02s:%02s - %02s:%02s',
+ $data['metadate']->start_hour,
+ $data['metadate']->start_minute,
+ $data['metadate']->end_hour,
+ $data['metadate']->end_minute
+ );
+ ?>
+ <th class="nowrap">
+ <?= htmlReady($date_string1) ?>
+ <br>
+ <?= htmlReady($date_string2) ?>
+ </th>
+ <? else : ?>
+ <? foreach ($data['intervals'] as $time_interval) : ?>
+ <?
+ $date_string1 = sprintf(
+ '%1$s., %2$s',
+ getWeekday(date('w', $time_interval['begin'])),
+ date('d.m', $time_interval['begin'])
+ );
+ $date_string2 = sprintf(
+ '%1$s - %2$s',
+ date('H:i', $time_interval['begin']),
+ date('H:i', $time_interval['end'])
+ );
+ ?>
+ <th class="nowrap">
+ <?= htmlReady($date_string1) ?>
+ <br>
+ <?= htmlReady($date_string2) ?>
+ </th>
+ <? endforeach ?>
+ <? endif ?>
+ <? endforeach ?>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="nohover">
+ <td><?= _('Keine Auswahl') ?></td>
+ <? if (count($request_time_intervals) > 1) : ?>
+ <td>
+ <input type="checkbox" data-proxyfor="input.radio-null"
+ name="all_in_room" value="">
+ </td>
+ <? endif ?>
+ <? foreach ($request_time_intervals as $metadate_id => $data): ?>
+ <? if (($data['metadate'] instanceof SeminarCycleDate)) : ?>
+ <?
+ $range_index = 'SeminarCycleDate' . '_' . $metadate_id;
+ $room_radio_name = 'selected_rooms[' . $range_index . ']';
+ ?>
+ <td>
+ <input type="radio" name="<?= htmlReady($room_radio_name) ?>"
+ class="text-bottom radio-null"
+ value=""
+ <?= $selected_dates[$range_index] == null
+ ? 'checked="checked"'
+ : '' ?>>
+ </td>
+ <? else : ?>
+ <? $i = 0 ?>
+ <? foreach ($data['intervals'] as $interval) : ?>
+ <?
+ $range_index = $interval['range'] . '_' . $interval['range_id'];
+ $room_radio_name = 'selected_rooms[' . $range_index . ']';
+ ?>
+ <td>
+ <input type="radio" name="<?= htmlReady($room_radio_name) ?>"
+ class="radio-null text-bottom"
+ value=""
+ <?= $selected_dates[$range_index] == null
+ ? 'checked="checked"'
+ : '' ?>>
+ </td>
+ <? $i++ ?>
+ <? endforeach ?>
+ <? endif ?>
+ <? endforeach ?>
+ </tr>
+ <? if ($request_resource instanceof Room): ?>
+ <?= $this->render_partial(
+ 'resources/room_request/resolve_room_tr.php',
+ [
+ 'room' => $request_resource,
+ 'time_intervals' => $request_time_intervals,
+ 'availability' => $room_availability[$request_resource->id],
+ 'underload' => $room_underload[$room_request->resource_id],
+ 'selected_dates' => $selected_rooms
+ ]
+ ) ?>
+ <? endif ?>
+ <? if ($alternative_rooms): ?>
+ <? foreach ($alternative_rooms as $room): ?>
+ <?= $this->render_partial(
+ 'resources/room_request/resolve_room_tr.php',
+ [
+ 'room' => $room,
+ 'time_intervals' => $request_time_intervals,
+ 'availability' => $this->room_availability[$room->id],
+ 'underload' => $room_underload[$room->id],
+ 'selected_dates' => $selected_rooms
+ ]
+ ) ?>
+ <? endforeach ?>
+ <? endif ?>
+ </tbody>
+ </table>
+ </div>
+ </article>
+ <? endif ?>
+ <? endif ?>
+ <footer data-dialog-button>
+ <? if ($prev_request) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Vorherige Anfrage'),
+ $controller->resolveURL($prev_request),
+ ['data-dialog' => 'size=big']
+ ) ?>
+ <? endif ?>
+ <? if ($show_form) : ?>
+ <? if ($show_force_resolve_button): ?>
+ <?= \Studip\Button::create(_('Anfrage trotzdem auflösen'), 'force_resolve') ?>
+ <? else: ?>
+ <?= \Studip\Button::create(_('Anfrage auflösen'), 'resolve') ?>
+ <? endif ?>
+ <? if ($request->isSimpleRequest()
+ && !$request->isReadOnlyForUser($current_user)): ?>
+ <?= \Studip\LinkButton::create(
+ _('Anfrage bearbeiten'),
+ $controller->editURL($request->id),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? elseif ($GLOBALS['perm']->have_studip_perm('tutor', $request->getRangeId())): ?>
+ <?= \Studip\LinkButton::create(
+ _('Anfrage bearbeiten'),
+ URLHelper::getURL(
+ 'dispatch.php/course/room_requests/request_summary/' . $request->id,
+ ['cid' => $request->getRangeId()]
+ )
+ ) ?>
+ <? endif ?>
+ <?= \Studip\LinkButton::create(
+ _('Anfrage ablehnen'),
+ $controller->declineURL($request->id),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <?= \Studip\LinkButton::create(
+ _('Anfrage löschen'),
+ $controller->declineURL($request->id, ['delete' => '1']),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? if ($show_expand_metadates_button) : ?>
+ <?= \Studip\Button::create(_('Terminserien expandieren'), 'expand_metadates') ?>
+ <? endif ?>
+ <? if (Request::submitted('expand_metadates')) : ?>
+ <?= \Studip\Button::create(
+ _('Terminserien zusammenklappen'),
+ 'fold_metadates'
+ ) ?>
+ <? endif ?>
+ <? endif ?>
+ <? if ($next_request) : ?>
+ <?= \Studip\LinkButton::create(
+ _('Nächste Anfrage'),
+ $controller->resolveURL($next_request),
+ ['data-dialog' => 'size=big']
+ ) ?>
+ <? endif ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/resources/room_request/resolve_room_tr.php b/app/views/resources/room_request/resolve_room_tr.php
new file mode 100644
index 0000000..fb95c29
--- /dev/null
+++ b/app/views/resources/room_request/resolve_room_tr.php
@@ -0,0 +1,93 @@
+<tr class="nohover">
+ <td class="nowrap">
+ <? if ($room->bookingPlanVisibleForUser($current_user)): ?>
+ <?
+ $booking_plan_params = [];
+ if ($time_intervals[0]['begin']) {
+ $booking_plan_params = [
+ 'defaultDate' => date('Y-m-d', $time_intervals[0]['begin'])
+ ];
+ }
+ ?>
+ <a href="<?= $controller->link_for(
+ 'resources/room_planning/booking_plan/' . $room->id,
+ $booking_plan_params
+ ) ?>" target="_blank"
+ title="<?= _('Zum Belegungsplan') ?>">
+ <?= htmlReady($room->name) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($room->name) ?>
+ <? endif ?>
+ <?= tooltipIcon($room->room_type) ?>
+ – <?= htmlReady(sprintf('%d Sitzplätze', $room->seats)) ?>
+ <? if ($underload) : ?>
+ [<?= htmlReady($underload) ?>%]
+ <? endif ?>
+ </td>
+ <? if (count($time_intervals) > 1) : ?>
+ <td>
+ <input type="checkbox" data-proxyfor="input.radio-<?= htmlReady($room->id) ?>"
+ name="all_in_room" value="<?= htmlReady($room->id) ?>"
+ <?= $room_availability_share[$room->id] <= 0.0 ? 'disabled="disabled"' : '' ?>>
+ <? if ($room_availability_share[$room->id] >= 1.0) : ?>
+ <?= Icon::create('check-circle', Icon::ROLE_STATUS_GREEN)->asImg(['class' => 'text-bottom']) ?>
+ <? elseif ($room_availability_share[$room->id] <= 0.0) : ?>
+ <?= Icon::create('decline-circle', Icon::ROLE_STATUS_RED)->asImg(['class' => 'text-bottom']) ?>
+ <? else : ?>
+ <?= Icon::create('exclaim-circle', Icon::ROLE_STATUS_YELLOW)->asImg(['class' => 'text-bottom']) ?>
+ <? endif ?>
+ </td>
+ <? endif ?>
+ <? foreach ($time_intervals as $metadate_id => $data): ?>
+ <? if (($data['metadate'] instanceof SeminarCycleDate)) : ?>
+ <?
+ $available = $metadate_available[$room->id][$metadate_id];
+ $range_index = 'SeminarCycleDate' . '_' . $metadate_id;
+ $room_radio_name = 'selected_rooms[' . $range_index . ']';
+ ?>
+ <td>
+ <? if ($available): ?>
+ <input type="radio" name="<?= htmlReady($room_radio_name) ?>"
+ class="text-bottom radio-<?= htmlReady($room->id) ?>"
+ value="<?= htmlReady($room->id) ?>"
+ <?= $selected_dates[$range_index] == $room->id
+ ? 'checked="checked"'
+ : ''?>>
+ <?= Icon::create('check-circle', Icon::ROLE_STATUS_GREEN)->asImg(['class' => 'text-bottom']) ?>
+ <? else: ?>
+ <input type="radio" name="<?= htmlReady($room_radio_name) ?>"
+ value="1" disabled="disabled"
+ class="text-bottom">
+ <?= Icon::create('decline-circle', Icon::ROLE_STATUS_RED)->asImg(['class' => 'text-bottom']) ?>
+ <? endif ?>
+ </td>
+ <? else : ?>
+ <? $i = 0 ?>
+ <? foreach($data['intervals'] as $interval) : ?>
+ <?
+ $available = $availability[$metadate_id][$i];
+ $range_index = $interval['range'] . '_' . $interval['range_id'];
+ $room_radio_name = 'selected_rooms[' . $range_index . ']';
+ ?>
+ <td>
+ <? if ($available): ?>
+ <input type="radio" name="<?= htmlReady($room_radio_name) ?>"
+ class="text-bottom radio-<?= htmlReady($room->id) ?>"
+ value="<?= htmlReady($room->id) ?>"
+ <?= $selected_dates[$range_index] == $room->id
+ ? 'checked="checked"'
+ : ''?>>
+ <?= Icon::create('check-circle', Icon::ROLE_STATUS_GREEN)->asImg(['class' => 'text-bottom']) ?>
+ <? else: ?>
+ <input type="radio" name="<?= htmlReady($room_radio_name) ?>"
+ value="1" disabled="disabled"
+ class="text-bottom">
+ <?= Icon::create('decline-circle', Icon::ROLE_STATUS_RED)->asImg(['class' => 'text-bottom']) ?>
+ <? endif ?>
+ </td>
+ <? $i++ ?>
+ <? endforeach ?>
+ <? endif ?>
+ <? endforeach ?>
+</tr>
diff --git a/app/views/resources/search/rooms.php b/app/views/resources/search/rooms.php
new file mode 100644
index 0000000..b48d95d
--- /dev/null
+++ b/app/views/resources/search/rooms.php
@@ -0,0 +1,38 @@
+<? if (is_array($rooms) && count($rooms)): ?>
+ <? foreach ($rooms as $room): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_room_search_result.php',
+ [
+ 'room' => $room,
+ 'show_user_actions' => $room->userHasPermission(
+ $current_user,
+ 'user'
+ ),
+ 'show_autor_actions' => $room->userHasPermission(
+ $current_user,
+ 'autor'
+ ),
+ 'show_tutor_actions' => $room->userHasPermission(
+ $current_user,
+ 'tutor'
+ ),
+ 'show_admin_actions' => $room->userHasPermission(
+ $current_user,
+ 'admin'
+ ),
+ 'cliboard_widget_id' => $clipboard_widget_id
+ ]
+ ) ?>
+ <? endforeach ?>
+<? else: ?>
+ <? if ($form_submitted && !$has_errors): ?>
+ <?= MessageBox::info(
+ _('Es wurden keine Räume gefunden, die zu den angegebenen Suchkriterien passen!')
+ ) ?>
+ <? endif ?>
+ <? if (!$form_submitted): ?>
+ <?= MessageBox::info(
+ _('Wählen Sie Suchkriterien oder ein Element im Ressourcenbaum, um Räume zu finden.')
+ ) ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/resources/statistics/room_load.php b/app/views/resources/statistics/room_load.php
new file mode 100644
index 0000000..462611a
--- /dev/null
+++ b/app/views/resources/statistics/room_load.php
@@ -0,0 +1,4 @@
+<div>Gebucht: <?= $booked_share * 100 ?> %</div>
+<div>Gesperrt: <?= $locked_share * 100 ?> %</div>
+<div>Ungenutzt: <?= $unused_share * 100 ?> %</div>
+
diff --git a/app/views/room_management/overview/buildings.php b/app/views/room_management/overview/buildings.php
new file mode 100644
index 0000000..7443986
--- /dev/null
+++ b/app/views/room_management/overview/buildings.php
@@ -0,0 +1,94 @@
+<? if ($buildings): ?>
+ <form class="default" method="post"
+ action="<?= URLHelper::getLink('dispatch.php/room_management/overview/buildings') ?>">
+ <table class="default building-list">
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ <col>
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox" class="proxy"
+ data-proxyfor="input[name='building_ids[]']"
+ data-activates="table.building-list button.bulk-action">
+ </th>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Nummer') ?></th>
+ <th><?= _('Adresse') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr>
+ <td colspan="5">
+ <?
+ $button_attrs = [
+ 'class' => 'bulk-action',
+ 'data-activates-condition' => 'table.building-list :checkbox:checked'
+ ];
+ if (!$building_ids) {
+ $button_attrs['disabled'] = 'disabled';
+ }
+ ?>
+ <?= \Studip\Button::create(
+ _('Raumgruppen für Gebäude erstellen'),
+ 'create_clipboards',
+ $button_attrs
+ ) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <tbody>
+ <? foreach ($buildings as $building): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_resource_tr.php',
+ [
+ 'resource' => $building,
+ 'booking_plan_on_link_name' => false,
+ 'show_global_admin_actions' => $user_is_global_resource_admin,
+ 'show_admin_actions' => $building->userHasPermission(
+ $user,
+ 'admin'
+ ),
+ 'show_tutor_actions' => $building->userHasPermission(
+ $user,
+ 'tutor'
+ ),
+ 'show_autor_actions' => $building->userHasPermission(
+ $user,
+ 'autor'
+ ),
+ 'show_user_actions' => $building->userHasPermission(
+ $user,
+ 'user'
+ ),
+ 'checkbox_data' => [
+ 'name' => 'building_ids[]',
+ 'checked' => in_array($building->id, $building_ids)
+ ],
+ 'show_picture' => true,
+ 'show_full_name' => false,
+ 'additional_properties' => [
+ 'number',
+ 'address'
+ ],
+ 'additional_actions' => [
+ '0020' => null,
+ '0030' => null,
+ '0040' => null,
+ '0050' => null,
+ '0070' => null,
+ '0080' => null,
+ '0090' => null
+ ]
+ ]
+ ) ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </form>
+<? endif ?>
diff --git a/app/views/room_management/overview/index.php b/app/views/room_management/overview/index.php
new file mode 100644
index 0000000..181462d
--- /dev/null
+++ b/app/views/room_management/overview/index.php
@@ -0,0 +1,127 @@
+<section class="overview-action-tile-container studip-widget-wrapper">
+ <? if ($show_resource_actions): ?>
+ <article class="overview-action-tile studip">
+ <header class="widget-header"><h1><?= _('Raumplanung') ?></h1></header>
+ <ul>
+ <? if ($room_requests_activated) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/room_request/overview') ?>">
+ <?= _('Anfragenliste') ?>
+ </a>
+ </li>
+ <? endif ?>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/room_planning/booking_plan') ?>">
+ <?= _('Belegungsplan') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/location/index') ?>">
+ <?= _('Struktur') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/room_management/planning/index') ?>">
+ <?= _('Gruppenbelegungspläne') ?>
+ </a>
+ </li>
+ </ul>
+ </article>
+ <? endif ?>
+
+ <? if ($user_is_global_resource_admin): ?>
+ <article class="overview-action-tile studip">
+ <header class="widget-header"><h1><?= _('Export') ?></h1></header>
+ <ul>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/export/select_booking_sources') ?>">
+ <?= _('Raumgruppen auswählen') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/export/select_booking_sources',
+ ['select_rooms' => '1']) ?>">
+ <?= _('Räume auswählen') ?>
+ </a>
+ </li>
+ </ul>
+ </article>
+ <article class="overview-action-tile studip">
+ <header class="widget-header"><h1><?= _('Administration') ?></h1></header>
+ <ul>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/admin/permissions/global') ?>">
+ <?= _('Globale Berechtigungen verwalten') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/admin/global_locks') ?>">
+ <?= _('Globale Sperren verwalten') ?>
+ </a>
+ </li>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/admin/user_permissions') ?>">
+ <?= _('Ressourcen-Berechtigungen verwalten') ?>
+ </a>
+ </li>
+ <? if ($user_is_root) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink(
+ 'dispatch.php/resources/admin/configuration') ?>">
+ <?= _('Konfigurationsoptionen') ?>
+ </a>
+ </li>
+ <? endif ?>
+ </ul>
+ </article>
+ <? endif ?>
+</section>
+<? if ($room_requests && count($room_requests)) : ?>
+<br>
+ <table class="default request-list">
+ <caption><?= _('Aktuelle Raumanfragen') ?></caption>
+ <thead>
+ <tr>
+ <th>
+ <?= Icon::create('radiobutton-checked')->asImg(
+ [
+ 'class' => 'text-bottom',
+ 'title' => _('Markierung')
+ ]
+ ) ?>
+ </th>
+ <th data-sort="text"><?= _('Nr.') ?></th>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="text"><?= _('Lehrende Person(en)') ?></th>
+ <th data-sort="text"><?= _('Raum') ?></th>
+ <th data-sort="text"><?= _('Plätze') ?></th>
+ <th data-sort="text"><?= _('Anfragende Person') ?></th>
+ <th data-sort="htmldata"><?= _('Art') ?></th>
+ <th data-sort="htmldata"><?= _('Dringlichkeit') ?></th>
+ <th data-sort="num"><?= _('letzte Änderung') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($room_requests as $room_request): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_request_tr',
+ ['request' => $room_request]
+ )?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? elseif ($display_current_requests) : ?>
+ <?= MessageBox::info(
+ _('Es liegen keine aktuellen Raumanfragen vor!')
+ ) ?>
+<? endif ?> \ No newline at end of file
diff --git a/app/views/room_management/overview/locations.php b/app/views/room_management/overview/locations.php
new file mode 100644
index 0000000..c90a6cc
--- /dev/null
+++ b/app/views/room_management/overview/locations.php
@@ -0,0 +1,55 @@
+<? if ($locations): ?>
+ <table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Adresse') ?></th>
+ <th><?= _('Webseite') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($locations as $location): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_resource_tr.php',
+ [
+ 'resource' => $location,
+ 'booking_plan_link_on_name' => false,
+ 'show_global_admin_actions' => $user_is_global_resource_admin,
+ 'show_admin_actions' => $location->userHasPermission(
+ $user,
+ 'admin'
+ ),
+ 'show_tutor_actions' => $location->userHasPermission(
+ $user,
+ 'tutor'
+ ),
+ 'show_autor_actions' => $location->userHasPermission(
+ $user,
+ 'autor'
+ ),
+ 'show_user_actions' => $location->userHasPermission(
+ $user,
+ 'user'
+ ),
+ 'show_picture' => true,
+ 'show_full_name' => false,
+ 'additional_properties' => [
+ 'address',
+ 'website'
+ ],
+ 'additional_actions' => [
+ '0020' => null,
+ '0030' => null,
+ '0040' => null,
+ '0050' => null,
+ '0070' => null,
+ '0080' => null,
+ '0090' => null
+ ]
+ ]
+ ) ?>
+ <? endforeach ?>
+ <tbody>
+ </table>
+<? endif ?>
diff --git a/app/views/room_management/overview/public_booking_plans.php b/app/views/room_management/overview/public_booking_plans.php
new file mode 100644
index 0000000..e0c0c53
--- /dev/null
+++ b/app/views/room_management/overview/public_booking_plans.php
@@ -0,0 +1,4 @@
+<?= $this->render_partial(
+ 'resources/_common/_grouped_room_list.php',
+ ['grouped_rooms' => $grouped_rooms]
+) ?>
diff --git a/app/views/room_management/overview/rooms.php b/app/views/room_management/overview/rooms.php
new file mode 100644
index 0000000..4a743a8
--- /dev/null
+++ b/app/views/room_management/overview/rooms.php
@@ -0,0 +1,48 @@
+<? if ($rooms): ?>
+ <table class="default sortable-table rooms-list">
+ <thead>
+ <tr>
+ <th data-sort="text"><?= _('Name') ?></th>
+ <th data-sort="number"><?= _('Sitzplätze') ?></th>
+ <th data-sort="text"><?= _('Raumkategorie') ?></th>
+ <th data-sort="text"><?= _('Raumtyp') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($rooms as $room): ?>
+ <?= $this->render_partial(
+ 'resources/_common/_room_tr.php',
+ [
+ 'room' => $room,
+ 'show_global_admin_actions' => $show_global_admin_actions,
+ 'show_admin_actions' => $room->userHasPermission(
+ $user,
+ 'admin'
+ ),
+ 'show_tutor_actions' => $room->userHasPermission(
+ $user,
+ 'tutor'
+ ),
+ 'show_autor_actions' => $room->userHasPermission(
+ $user,
+ 'autor'
+ ),
+ 'show_user_actions' => $room->userHasPermission(
+ $user,
+ 'user'
+ ),
+ 'user_has_booking_rights' => $room->userHasBookingRights(
+ $user
+ ),
+ 'show_room_picture' => true,
+ 'additional_columns' => [
+ $room->category->name,
+ $room->room_type,
+ ]
+ ]
+ ) ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? endif ?>
diff --git a/app/views/room_management/overview/structure.php b/app/views/room_management/overview/structure.php
new file mode 100644
index 0000000..243aadd
--- /dev/null
+++ b/app/views/room_management/overview/structure.php
@@ -0,0 +1,9 @@
+<? foreach ($locations as $index => $location) : ?>
+ <?= $this->render_partial(
+ 'resources/_common/_resource_tree_item.php',
+ [
+ 'resource' => $location,
+ 'open' => (count($locations) === 1 || $index === 0)
+ ]
+ ) ?>
+<? endforeach ?>
diff --git a/app/views/room_management/planning/booking_comments.php b/app/views/room_management/planning/booking_comments.php
new file mode 100644
index 0000000..72e3edd
--- /dev/null
+++ b/app/views/room_management/planning/booking_comments.php
@@ -0,0 +1,129 @@
+<? if ($data): ?>
+ <table class="default" <?= $standalone ? 'style="border: 1px solid black; border-collapse: collapse;"' : '' ?>>
+ <thead>
+ <tr>
+ <th <?= $standalone ? 'style="border: 1px solid black; width: 12.5%;"' : '' ?>>
+ <?= htmlReady(
+ sprintf(
+ _('%d. Kalenderwoche'),
+ $date->format('W')
+ )
+ ) ?>
+ </th>
+ <th <?= $standalone ? 'style="border: 1px solid black; width: 12.5%;"' : '' ?>>
+ <?= _('Montag') ?>
+ <div>
+ <?= date(
+ 'd.m.Y',
+ strtotime('this week monday', $date->getTimestamp())
+ ) ?>
+ </div>
+ </th>
+ <th <?= $standalone ? 'style="border: 1px solid black; width: 12.5%;"' : '' ?>>
+ <?= _('Dienstag') ?>
+ <div>
+ <?= date(
+ 'd.m.Y',
+ strtotime('this week tuesday', $date->getTimestamp())
+ ) ?>
+ </div>
+ </th>
+ <th <?= $standalone ? 'style="border: 1px solid black; width: 12.5%;"' : '' ?>>
+ <?= _('Mittwoch') ?>
+ <div>
+ <?= date(
+ 'd.m.Y',
+ strtotime('this week wednesday', $date->getTimestamp())
+ ) ?>
+ </div>
+ </th>
+ <th <?= $standalone ? 'style="border: 1px solid black; width: 12.5%;"' : '' ?>>
+ <?= _('Donnerstag') ?>
+ <div>
+ <?= date(
+ 'd.m.Y',
+ strtotime('this week thursday', $date->getTimestamp())
+ ) ?>
+ </div>
+ </th>
+ <th <?= $standalone ? 'style="border: 1px solid black; width: 12.5%;"' : '' ?>>
+ <?= _('Freitag') ?>
+ <div>
+ <?= date(
+ 'd.m.Y',
+ strtotime('this week friday', $date->getTimestamp())
+ ) ?>
+ </div>
+ </th>
+ <th <?= $standalone ? 'style="border: 1px solid black; width: 12.5%;"' : '' ?>>
+ <?= _('Samstag') ?>
+ <div>
+ <?= date(
+ 'd.m.Y',
+ strtotime('this week saturday', $date->getTimestamp())
+ ) ?>
+ </div>
+ </th>
+ <th <?= $standalone ? 'style="border: 1px solid black; width: 12.5%;"' : '' ?>>
+ <?= _('Sonntag') ?>
+ <div>
+ <?= date(
+ 'd.m.Y',
+ strtotime('this week sunday', $date->getTimestamp())
+ ) ?>
+ </div>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($data as $row): ?>
+ <tr>
+ <? foreach ($row as $i => $cell): ?>
+ <? if ($i == 0): ?>
+ <td <?= $standalone
+ ? 'style="border: 1px solid black; min-height: 60px; height: 60px;"'
+ : '' ?>>
+ <?= htmlReady($cell) ?>
+ </td>
+ <? else: ?>
+ <td <?= $standalone
+ ? 'style="border: 1px solid black; min-height: 60px; height: 60px;"'
+ : '' ?>>
+ <? if ($cell): ?>
+ <? foreach ($cell as $day_item): ?>
+ <div <?= $standalone
+ ? 'style="margin-bottom: 1em;"'
+ : '' ?>>
+ <div>
+ <strong>
+ <?= htmlReady($day_item[0]) ?>
+ </strong>
+ </div>
+ <?= htmlReady($day_item[1]) ?>
+ </div>
+ <? endforeach ?>
+ <? endif ?>
+ </td>
+ <? endif ?>
+ <? endforeach ?>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? else: ?>
+ <? if ($standalone): ?>
+ <p>
+ <?= sprintf(
+ _('In der %d. Kalenderwoche sind keine Buchungen mit Kommentaren vorhanden!'),
+ $date->format('W')
+ ) ?>
+ </p>
+ <? else: ?>
+ <?= MessageBox::info(
+ sprintf(
+ _('In der %d. Kalenderwoche sind keine Buchungen mit Kommentaren vorhanden!'),
+ $date->format('W')
+ )
+ ) ?>
+ <? endif ?>
+<? endif ?>
diff --git a/app/views/room_management/planning/booking_comments_html_export_frame.php b/app/views/room_management/planning/booking_comments_html_export_frame.php
new file mode 100644
index 0000000..4cfa84c
--- /dev/null
+++ b/app/views/room_management/planning/booking_comments_html_export_frame.php
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>
+ <?= htmlReady(
+ sprintf(
+ _('Kalenderwoche: %d. Woche'),
+ $date->format('W')
+ )
+ ) ?>
+ </title>
+ </head>
+ <body>
+ <?= $this->render_partial(
+ 'booking_comments.php',
+ [
+ 'data' => $data,
+ 'standalone' => true
+ ]
+ ) ?>
+ </body>
+</html>
diff --git a/app/views/room_management/planning/copy_bookings.php b/app/views/room_management/planning/copy_bookings.php
new file mode 100644
index 0000000..5f2ce6e
--- /dev/null
+++ b/app/views/room_management/planning/copy_bookings.php
@@ -0,0 +1,247 @@
+<? if ($step == 1): ?>
+ <? if ($rooms): ?>
+ <form class="default" method="post" data-dialog="size=auto"
+ action="<?= $controller->link_for('room_management/planning/copy_bookings')?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Verfügbare Räume') ?></legend>
+ <table class="default">
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="input[name='selected_room_ids[]']">
+ </th>
+ <th><?= _('Name')?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($rooms as $room): ?>
+ <tr>
+ <td>
+ <input type="checkbox"
+ name="selected_room_ids[]"
+ value="<?= htmlReady($room->id) ?>"
+ <?= in_array($room->id, $selected_room_ids)
+ ? 'checked="checked"'
+ : ''?>>
+ </td>
+ <td><?= htmlReady($room->name)?></td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Semester') ?></legend>
+ <label>
+ <?= _('Aus welchem Semester sollen Buchungen kopiert werden?') ?>
+ <select name="source_semester_id">
+ <? foreach ($available_semesters as $semester): ?>
+ <option value="<?= htmlReady($semester->id)?>"
+ <?= $semester->id == $source_semester_id
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($semester->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <label>
+ <input type="checkbox" name="sem_week_selected" value="1"
+ data-activates="input[type='number'][name='selected_sem_week']"
+ <?= $sem_week_selected ? 'checked="checked"' : ''?>>
+ <?= _('Buchungen sollen erst ab der folgenden Semesterwoche kopiert werden:') ?>
+ <input type="number" min="1" max="53" name="selected_sem_week"
+ value="<?= htmlReady($selected_sem_week) ?>">
+ </label>
+ </fieldset>
+ <div data-dialog-button="1">
+ <?= \Studip\Button::create(
+ _('Auswählen'),
+ 'select_rooms'
+ ) ?>
+ </div>
+ </form>
+ <? else: ?>
+ <?= MessageBox::error(
+ _('Die gewählte Raumgruppe ist leer!')
+ ) ?>
+ <? endif ?>
+<? elseif ($step == 2): ?>
+ <form class="default" method="post" data-dialog="size=auto"
+ action="<?= $controller->link_for('room_management/planning/copy_bookings')?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <? foreach ($selected_room_ids as $room_id): ?>
+ <input type="hidden" name="selected_room_ids[]"
+ value="<?= htmlReady($room_id) ?>">
+ <? endforeach ?>
+ <input type="hidden" name="source_semester_id"
+ value="<?= htmlReady($source_semester_id)?>">
+ <input type="hidden" name="sem_week_selected"
+ value="<?= htmlReady($sem_week_selected) ?>">
+ <input type="hidden" name="selected_sem_week"
+ value="<?= htmlReady($selected_sem_week) ?>">
+ <fieldset>
+ <legend><?= _('Buchungen') ?></legend>
+ <table class="default">
+ <colgroup>
+ <col class="checkbox">
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="input[name='selected_booking_ids[]']">
+ </th>
+ <th><?= _('Raum') ?></th>
+ <th><?= _('Zeitbereiche')?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($bookings as $booking): ?>
+ <tr>
+ <td>
+ <input type="checkbox"
+ name="selected_booking_ids[]"
+ value="<?= htmlReady($booking->id) ?>">
+ </td>
+ <td><?= htmlReady($booking->resource->name)?></td>
+ <td>
+ <? if ($booking_time_ranges[$booking->id]): ?>
+ <ul>
+ <? foreach ($booking_time_ranges[$booking->id] as $str): ?>
+ <?= htmlReady($str) ?>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Zielsemester') ?></legend>
+ <label>
+ <?= _('In welches Semester sollen die Buchungen kopiert werden?') ?>
+ <select name="target_semester_id">
+ <? foreach ($available_target_semesters as $semester): ?>
+ <option value="<?= htmlReady($semester->id)?>"
+ <?= $semester->id == $target_semester_id
+ ? 'selected="selected"'
+ : '' ?>>
+ <?= htmlReady($semester->name) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+ <div data-dialog-button="1">
+ <?= \Studip\Button::create(
+ _('Zurück'),
+ 'step1',
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <?= \Studip\Button::create(
+ _('Prüfen'),
+ 'test_copy'
+ ) ?>
+ </div>
+ </form>
+<? elseif ($step == 3): ?>
+ <form class="default" method="post"
+ action="<?= $controller->link_for('room_management/planning/copy_bookings')?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <? foreach ($selected_room_ids as $room_id): ?>
+ <input type="hidden" name="selected_room_ids[]"
+ value="<?= htmlReady($room_id) ?>">
+ <? endforeach ?>
+ <input type="hidden" name="source_semester_id"
+ value="<?= htmlReady($source_semester_id)?>">
+ <input type="hidden" name="sem_week_selected"
+ value="<?= htmlReady($sem_week_selected) ?>">
+ <input type="hidden" name="selected_sem_week"
+ value="<?= htmlReady($selected_sem_week) ?>">
+ <? foreach ($selected_booking_ids as $booking_id): ?>
+ <input type="hidden" name="selected_booking_ids[]"
+ value="<?= htmlReady($booking_id) ?>">
+ <? endforeach ?>
+ <input type="hidden" name="target_semester_id"
+ value="<?= htmlReady($target_semester_id)?>">
+
+ <fieldset>
+ <legend><?= _('Prüfung der Machbarkeit') ?></legend>
+ <table class="default">
+ <thead>
+ <tr>
+ <th><?= _('Buchungszeitraum') ?></th>
+ <th><?= _('Raum') ?></th>
+ <th><?= _('Verfügbar') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($booking_copy_data as $data): ?>
+ <tr>
+ <td>
+ <? if ($data['time_intervals']): ?>
+ <ul>
+ <? foreach ($data['time_intervals'] as $interval): ?>
+ <li>
+ <?= htmlReady(date('d.m.Y H:i', $interval['begin'])) ?>
+ -
+ <?= htmlReady(date('d.m.Y H:i', $interval['end'])) ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? endif ?>
+ </td>
+ <td>
+ <?= htmlReady($data['original']->resource->name) ?>
+ </td>
+ <td>
+ <?= Icon::create(
+ (
+ $data['available']
+ ? 'accept'
+ : 'decline'
+ ),
+ (
+ $data['available']
+ ? 'status-green'
+ : 'status-red'
+ )
+ )->asImg('20px', ['class' => 'text-bottom']) ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </fieldset>
+ <div data-dialog-button="1">
+ <?= \Studip\Button::create(
+ _('Zurück'),
+ 'step2',
+ ['data-dialog' => 'size=normal']
+ ) ?>
+ <? if ($show_copy_button) : ?>
+ <?= \Studip\Button::create(
+ _('Kopieren'),
+ 'copy',
+ ['data-dialog' => 'size=normal']
+ ) ?>
+ <? else : ?>
+ <?= \Studip\Button::create(
+ _('Liste mit Buchungen herunterladen'),
+ 'download_booking_list'
+ ) ?>
+ <? endif ?>
+ </div>
+ </form>
+<? endif ?>
diff --git a/app/views/room_management/planning/index.php b/app/views/room_management/planning/index.php
new file mode 100644
index 0000000..5e79966
--- /dev/null
+++ b/app/views/room_management/planning/index.php
@@ -0,0 +1,96 @@
+<? if ($no_clipboard): ?>
+ <?= MessageBox::info(
+ _('Es wurde keine Raumgruppe ausgewählt!')
+ ) ?>
+<? elseif ($no_rooms): ?>
+ <?= MessageBox::info(
+ _('Die gewählte Raumgruppe enthält keine Räume!')
+ ) ?>
+<? else: ?>
+ <? if (Request::get("allday")) {
+ $min_time = '00:00:00';
+ $max_time = '24:00:00';
+ } else {
+ $min_time = Config::get()->RESOURCES_BOOKING_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->RESOURCES_BOOKING_PLAN_END_HOUR . ':00';
+ } ?>
+ <section class="studip-fullcalendar-header booking-plan-header"
+ data-semester-begin="" data-semester-end="">
+ <div>
+ <?= _('Raumgruppe') ?>
+ <span id="booking-plan-header-roomgroup"><?= htmlReady($clipboard->name) ?></span>
+ <span id="booking-plan-header-semrow">
+ <strong>
+ <?= _('KW') ?>
+ <span id="booking-plan-header-calweek"></span>
+ (<span id="booking-plan-header-calbegin"></span>)
+ <span id="booking-plan-header-semname"></span>
+ <span id="booking-plan-header-semweek-part">
+ <span id="booking-plan-header-semweek"></span>
+ </span>
+ </strong>
+ </span>
+ </div>
+ </section>
+
+ <?= \Studip\Fullcalendar::create(
+ _('Belegungsplan'),
+ [
+ 'resources' => $scheduler_resources,
+ 'resourceLabelText' => _('Raum'),
+ 'editable' => true,
+ 'selectable' => $all_rooms_booking_rights,
+ 'studip_urls' => $fullcalendar_studip_urls,
+ 'minTime' => ($min_time),
+ 'maxTime' => ($max_time),
+ 'allDaySlot' => false,
+ 'header' => [
+ 'left' => '',//'resourceTimelineMonth,resourceTimelineWeek,resourceTimelineDay',
+ 'right' => 'prev,next'
+ ],
+ 'slotLabelFormat' => [
+ ['hour'=> '2-digit',
+ 'hour12' => false]
+ ],
+ 'defaultView' =>
+ in_array(Request::get("defaultView"), ['resourceTimelineMonth', 'resourceTimelineWeek', 'resourceTimelineDay'])
+ ? Request::get("defaultView")
+ : 'resourceTimelineDay',
+ 'defaultDate' => Request::get("defaultDate"),
+ 'eventSources' => [
+ [
+ 'url' => URLHelper::getLink(
+ 'api.php/room_clipboard/'
+ . htmlReady($clipboard->id) . '/booking_plan'
+ ),
+ 'method' => 'GET',
+ 'extraParams' => [
+ 'booking_types' => $booking_types,
+ 'display_requests' => 1,
+ 'display_all_requests' => $display_all_requests ? 1 : 0
+ ]
+ ]
+ ]
+ ],
+ ['class' => 'resource-plan room-group-booking-plan'],
+ 'resources-fullcalendar'
+ ) ?>
+ <ul class="map-key-list">
+ <? foreach ($table_keys as $key): ?>
+ <li class="map-key">
+ <span style="background-color:<?= $key['colour'] ?>">
+ &nbsp;
+ </span>
+ <?= htmlReady($key['text']) ?>
+ </li>
+ <? endforeach ?>
+ <li class="map-key">
+ <?= Icon::create('refresh', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Wiederholungstermin') ?>
+ </li>
+ <li class="map-key">
+ <?= Icon::create('chat2', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Kommentar') ?>
+ </li>
+ </ul>
+<? endif ?>
diff --git a/app/views/room_management/planning/semester_plan.php b/app/views/room_management/planning/semester_plan.php
new file mode 100644
index 0000000..85d6924
--- /dev/null
+++ b/app/views/room_management/planning/semester_plan.php
@@ -0,0 +1,100 @@
+<? if ($no_clipboard): ?>
+ <?= MessageBox::info(
+ _('Es wurde keine Raumgruppe ausgewählt!')
+ ) ?>
+<? elseif ($no_rooms): ?>
+ <?= MessageBox::info(
+ _('Die gewählte Raumgruppe enthält keine Räume!')
+ ) ?>
+<? else: ?>
+ <? if (Request::get("allday")) {
+ $min_time = '00:00:00';
+ $max_time = '24:00:00';
+ } else {
+ $min_time = Config::get()->RESOURCES_BOOKING_PLAN_START_HOUR . ':00';
+ $max_time = Config::get()->RESOURCES_BOOKING_PLAN_END_HOUR . ':00';
+ } ?>
+
+ <section class="studip-fullcalendar-header"
+ data-semester-begin="" data-semester-end="">
+ <div>
+ <?= _('Raumgruppe') ?>
+ <span id="booking-plan-header-roomgroup"><?= htmlReady($clipboard->name) ?>,</span>
+ <span id="booking-plan-header-semrow">
+ <strong>
+ <?= _('Semester')?>
+ <span id="booking-plan-header-semname"><?= htmlReady($semester->name) ?></span>
+ <span id="booking-plan-header-semspan">
+ <? if (Request::get("semester_timerange") == 'fullsem') : ?>
+ <?= sprintf('(%1$s - %2$s)', date('d.m.Y',$semester->beginn), date('d.m.Y', $semester->ende)); ?>
+ <? else : ?>
+ <?= sprintf('(%1$s - %2$s)', date('d.m.Y',$semester->vorles_beginn), date('d.m.Y', $semester->vorles_ende)); ?>
+ <? endif ?>
+ </span>
+ </strong>
+ </span>
+ </div>
+ </section>
+
+ <?= \Studip\Fullcalendar::create(
+ _('Semesterplan'),
+ [
+ 'resources' => $scheduler_resources,
+ 'resourceLabelText' => _('Raum'),
+ 'minTime' => ($min_time),
+ 'maxTime' => ($max_time),
+ 'allDaySlot' => false,
+ 'slotLabelFormat' => [
+ ['weekday'=> 'short'], // top level of text
+ ['hour'=> '2-digit',
+ 'hour12' => false] // lower level of text
+ ],
+ 'header' => [
+ 'left' => '',
+ 'right' => ''
+ ],
+ 'defaultView' =>
+ in_array(Request::get("defaultView"), ['resourceTimelineMonth', 'resourceTimelineWeek', 'resourceTimelineDay'])
+ ? Request::get("defaultView")
+ : 'resourceTimelineWeek',
+ 'defaultDate' => ((Request::get("semester_timerange") == 'fullsem') ? date('Y-m-d',$semester->beginn) : date('Y-m-d',$semester->vorles_beginn)),
+ 'eventSources' => [
+ [
+ 'url' => URLHelper::getLink(
+ 'api.php/room_clipboard/'
+ . htmlReady($clipboard->id) . '/semester_plan'
+ ),
+ 'method' => 'GET',
+ 'extraParams' => [
+ 'booking_types' => $booking_types,
+ 'semester_id' => $semester->id,
+ 'semester_timerange' => Request::get("semester_timerange", 'vorles'),
+ 'display_requests' => 1,
+ 'display_all_requests' => $display_all_requests ? 1 : 0
+ ]
+ ]
+ ],
+ 'nowIndicator' => false
+ ],
+ ['class' => 'resource-plan semester-plan room-group-booking-plan'],
+ 'resources-fullcalendar'
+ ) ?>
+ <ul class="map-key-list">
+ <? foreach ($table_keys as $key): ?>
+ <li class="map-key">
+ <span style="background-color:<?= $key['colour'] ?>">
+ &nbsp;
+ </span>
+ <?= htmlReady($key['text']) ?>
+ </li>
+ <? endforeach ?>
+ <li class="map-key">
+ <?= Icon::create('refresh', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Wiederholungstermin') ?>
+ </li>
+ <li class="map-key">
+ <?= Icon::create('chat2', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?>
+ <?= _('Kommentar') ?>
+ </li>
+ </ul>
+<? endif ?>
diff --git a/app/views/score/index.php b/app/views/score/index.php
new file mode 100644
index 0000000..55c55be
--- /dev/null
+++ b/app/views/score/index.php
@@ -0,0 +1,124 @@
+<table class="default">
+ <caption>
+ <span class="actions" style="font-size: 0.9em;">
+ <?= _('Ihre Punkte:') ?>
+ <strong><?= number_format($this->current_user_score, 0, ',', '.') ?></strong>
+ <div class="hidden-small-down">(<?= Score::getTitel($this->current_user_score, $this->current_user->geschlecht) ?>)</div>
+ </span>
+ <?= _('Stud.IP-Rangliste')?>
+ </caption>
+ <colgroup>
+ <col width="3%">
+ <col width="1%">
+ <col width="50%">
+ <col class="hidden-small-down" width="15%">
+ <col width="15%">
+ <col class="hidden-small-down" width="15%">
+ <col class="hidden-small-down" width="1%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><div class="hidden-small-down"><?= _('Platz') ?></div></th>
+ <th></th>
+ <th><?= _('Name') ?></th>
+ <th class="hidden-small-down"></th>
+ <th><?= _('Punkte') ?></th>
+ <th class="hidden-small-down"><?= _('Titel') ?></th>
+ <th class="hidden-small-down"></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($persons as $index => $person): ?>
+ <tr>
+ <td style="text-align: right;">
+ <?= $offset + $index + 1 ?>.
+ </td>
+ <td>
+ <?= Avatar::getAvatar($person['user_id'], $person['username'])
+ ->getImageTag(Avatar::SMALL, ['title' => $person['fullname']])
+ ?>
+ </td>
+ <td>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username='. $person['username']) ?>">
+ <?= htmlReady($person['fullname']) ?>
+ </a>
+ <? foreach ($person['is_king'] as $type => $text): ?>
+ <?= Icon::create('crown', Icon::ROLE_SORT, ['title' => $text])->asImg(16, ["alt" => $text, "class" => 'text-top']) ?>
+ <? endforeach ?>
+ </td>
+ <td class="hidden-small-down">
+ <?
+ $content = Assets::img('blank.gif', ['width' => 16]) . ' ';
+
+ // News
+ if ($news = $person['newscount']) {
+ $tmp = sprintf(ngettext('Eine persönliche Ankündigung', '%s persönliche Ankündigungen', $news), $news);
+ $content .= sprintf(
+ '<a href="%s">%s</a> ',
+ URLHelper::getLink('dispatch.php/profile?username=' . $person['username']),
+ Icon::create('news', Icon::ROLE_CLICKABLE, ['title' => $tmp])->asImg()
+ );
+ } else {
+ $content .= Assets::img('blank.gif', ['width' => 16]) . ' ';
+ }
+
+ // Votes
+ if ($vote = $person['votecount']) {
+ $tmp = sprintf(ngettext('Eine Umfrage', '%s Umfragen', $vote), $vote);
+ $content .= sprintf(
+ '<a href="%s">%s</a> ',
+ URLHelper::getLink('dispatch.php/profile?username=' . $person['username'] . '#questionnaire_area'),
+ Icon::create('vote', Icon::ROLE_CLICKABLE, ['title' => $tmp])->asImg()
+ );
+ } else {
+ $content .= Assets::img('blank.gif', ['width' => 16]) . ' ';
+ }
+
+ // Termine
+ if ($termin = $person['eventcount']) {
+ $tmp = sprintf(ngettext('Ein Termin', '%s Termine', $termin), $termin);
+ $content .= sprintf(
+ '<a href="%s">%s</a> ',
+ URLHelper::getLink('dispatch.php/profile?username=' . $person['username'] . '#a'),
+ Icon::create('schedule', Icon::ROLE_CLICKABLE, ['title' => $tmp])->asImg()
+ );
+ } else {
+ $content .= Assets::img('blank.gif', ['width' => 16]) . ' ';
+ }
+
+ $content .= Assets::img('blank.gif', ['width' => 16]) . ' ';
+
+ echo $content;
+ ?>
+ </td>
+ <td><?= number_format($person['score'], 0, ',', '.') ?></td>
+ <td class="hidden-small-down" ><?= Score::getTitel($person['score'], $person['geschlecht']) ?></td>
+ <td class="hidden-small-down" style="text-align: right">
+ <? if($person['user_id'] == $GLOBALS['user']->id): ?>
+ <a href="<?= $controller->url_for('score/unpublish') ?>">
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE, ['title' => _('Ihren Wert von der Liste löschen')])
+ ->asImg(16, ["class" => 'text-top'])
+ ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+<? if (ceil($numberOfPersons / $max_per_page) > 1): ?>
+ <tfoot>
+ <tr>
+ <td colspan="7" style="text-align: right">
+ <?= $GLOBALS['template_factory']->render('shared/pagechooser',
+ [
+ 'perPage' => $max_per_page,
+ 'num_postings' => $numberOfPersons,
+ 'page' => $page,
+ 'pagelink' => 'dispatch.php/score/%u'
+ ]
+ ) ?>
+ </td>
+ </tr>
+ </tfoot>
+<? endif ?>
+</table>
diff --git a/app/views/search/angebot/detail.php b/app/views/search/angebot/detail.php
new file mode 100644
index 0000000..0947e0b
--- /dev/null
+++ b/app/views/search/angebot/detail.php
@@ -0,0 +1,19 @@
+<?= $this->render_partial('search/breadcrumb') ?>
+<section class="contentbox">
+ <header>
+ <h1><?= htmlReady($fach->name) . ' (' . htmlReady($abschluss->name) . ') - ' . _('Angebotene Studiengänge') ?></h1>
+ </header>
+ <ul class="mvv-result-list">
+ <? foreach($studiengaenge as $studiengang):?>
+ <li>
+ <a href="<?= $controller->url_for($url, $studiengang->id) ?>"><?= htmlReady($studiengang->getDisplayName()) ?></a>
+ <? if ($studiengang->getValue('beschreibung')) : ?>
+ <a data-dialog href="<?= $this->controller->url_for('/info', $studiengang->id) ?>">
+ <?= Icon::create('info-circle', 'clickable', ['title' => _('Informationen zum Studiengang')]); ?>
+ </a>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+</section>
+
diff --git a/app/views/search/angebot/index.php b/app/views/search/angebot/index.php
new file mode 100644
index 0000000..7eb401f
--- /dev/null
+++ b/app/views/search/angebot/index.php
@@ -0,0 +1,41 @@
+<?php
+// function link_chars(&$char,
+// $key,
+// $pattern) {
+// $char = sprintf($pattern, $key, ucfirst($key));
+// }
+//
+// array_walk($chars,
+// function (&$char) {
+// $char = sprintf('<a href="#%s">%s</a>', $char, ucfirst($char));
+// });
+?>
+<nav style="font-weight: bold">
+ <ul class="list-pipe-separated">
+ <? foreach ($chars as $char): ?>
+ <li>
+ <a href="#<?= $char ?>"><?= ucfirst($char) ?></a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+</nav>
+<? foreach ($faecher as $char => $abschluesse): ?>
+<article class="studip toggle">
+ <header>
+ <h1>
+ <a name="<?= $char ?>">
+ <?= ucfirst($char); ?>
+ </a>
+ </h1>
+ </header>
+ <ul class="list-unstyled">
+ <? foreach ($abschluesse as $fach): ?>
+ <li>
+ <a href="<?= $controller->link_for($url, $fach['fach_id'], $fach['abschluss_id']) ?>">
+ <?= htmlReady($fach['name']) ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+</article>
+<? endforeach; ?>
diff --git a/app/views/search/angebot/info.php b/app/views/search/angebot/info.php
new file mode 100644
index 0000000..676d06f
--- /dev/null
+++ b/app/views/search/angebot/info.php
@@ -0,0 +1,2 @@
+<h1><?= sprintf(_('Informationen zum Studiengang: %s'), $studiengang->getDisplayName()); ?></h1>
+<div style="padding:10px;"><?= formatReady($studiengang->getValue('beschreibung'))?></div> \ No newline at end of file
diff --git a/app/views/search/archive/index.php b/app/views/search/archive/index.php
new file mode 100644
index 0000000..4ad5c45
--- /dev/null
+++ b/app/views/search/archive/index.php
@@ -0,0 +1,145 @@
+<form class="default" method="get" action="<?= $controller->link_for('search/archive') ?>">
+ <input type="hidden" name="my_courses_only" value="<?= (int) $my_courses_only ?>">
+
+ <fieldset>
+ <legend>
+ <?= _('Suche im Veranstaltungsarchiv') ?>
+ </legend>
+
+ <label class="col-3">
+ <?= _('Name der Veranstaltung') ?>
+ <input autofocus type="text" name="criteria"
+ minlength="<?= $controller::NEEDLE_MIN_LENGTH ?>"
+ placeholder="<?= _('Veranstaltung suchen') ?>"
+ value="<?= htmlReady($criteria) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Name des/der Lehrenden') ?>
+ <input type="text" name="teacher"
+ minlength="<?= $controller::NEEDLE_MIN_LENGTH ?>"
+ placeholder="<?= _('Lehrende suchen') ?>"
+ value="<?= htmlReady($teacher) ?>">
+ </label>
+
+ <label class="col-3">
+ <?= _('Semester') ?>
+ <select name="semester">
+ <option value=""><?= _('alle') ?></option>
+ <? foreach ($semesters as $one) : ?>
+ <option value="<?= htmlReady($one) ?>" <? if ($semester === $one) echo 'selected'; ?>>
+ <?= htmlReady($one) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label class="col-3">
+ <?= _('Einrichtung') ?>
+ <select name="institute">
+ <option value=""><?= _('alle') ?></option>
+ <? foreach ($institutes as $one) : ?>
+ <option value="<?= htmlReady($one) ?>" <? if ($institute === $one) echo 'selected'; ?>>
+ <?= htmlReady($one) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ </fieldset>
+ <footer>
+ <?= Studip\Button::create(_('Suchen')) ?>
+ <?= Studip\LinkButton::create(
+ _('Zurücksetzen'),
+ $controller->url_for('search/archive')
+ ) ?>
+ </footer>
+</form>
+
+<? if ($courses) : ?>
+ <br>
+ <form action="" method="post">
+ <table class="default withdetails">
+ <colgroup>
+ <col>
+ <col width="20%">
+ <col width="20%">
+ <col width="20%">
+ <col width="120px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th><?= _('Lehrende') ?></th>
+ <th><?= _('Einrichtungen') ?></th>
+ <th><?= _('Semester') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($courses as $course) : ?>
+ <tr <? if (count($courses) === 1) echo 'class="open"'; ?>>
+ <td onclick="jQuery(this).closest('tr').toggleClass('open'); return false;">
+ <?= htmlReady($course->name) ?>
+ </td>
+ <td><?= htmlReady($course->dozenten) ?></td>
+ <td><?= htmlReady($course->institute) ?></td>
+ <td><?= htmlReady($course->semester) ?></td>
+ <td class="actions">
+ <? if (archiv_check_perm($course->id)) : ?>
+ <a href="<?= $controller->link_for("archive/overview/{$course->id}") ?>" data-dialog>
+ <?= Icon::create('info-circle') ?>
+ </a>
+ <? endif ?>
+
+ <? if ($course->archiv_file_id && archiv_check_perm($course->id)): ?>
+ <a href="<?= FileManager::getDownloadLinkForArchivedCourse($course, false) ?>">
+ <?= Icon::create('file-archive') ?>
+ </a>
+ <? endif ?>
+ <? if ($course->archiv_protected_file_id && in_array(archiv_check_perm($course->id), ['tutor', 'dozent', 'admin'])): ?>
+ <a href="<?= FileManager::getDownloadLinkForArchivedCourse($course, true) ?>">
+ <?= Icon::create('file-archive') ?>
+ </a>
+ <? endif ?>
+ <? if (archiv_check_perm($course->id)): ?>
+ <a href="<?= $controller->link_for("archive/forum/{$course->id}") ?>" data-dialog>
+ <?= Icon::create('forum') ?>
+ </a>
+ <a href="<?= $controller->link_for("archive/wiki/{$course->id}") ?>" data-dialog>
+ <?= Icon::create('wiki') ?>
+ </a>
+ <? endif ?>
+ <? if (archiv_check_perm($course->id) === 'admin'): ?>
+ <?= Icon::create('trash')->asInput(tooltip2(_('Löschen')) + [
+ 'formaction' => URLHelper::getURL(
+ "dispatch.php/archive/delete/{$course->id}",
+ compact('criteria', 'teacher', 'semester', 'institute', 'my_courses_only')
+ ),
+ 'data-confirm' => sprintf(
+ _('Soll die Veranstaltung %1$s wirklich aus dem Archiv gelöscht werden?'),
+ htmlReady($course->name)
+ ),
+ 'class' => 'text-top',
+ ]) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <tr class="details nohover">
+ <td colspan="5" class="detailscontainer">
+ <ul class="default nohover">
+ <li>
+ <strong><?= _('Fakultät') ?>:</strong>
+ <?= htmlReady($course->fakultaet) ?>
+ </li>
+ <li>
+ <strong><?= _('Bereich') ?>:</strong>
+ <?= htmlReady($course->studienbereiche) ?>
+ </li>
+ </ul>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ </form>
+<? endif ?>
diff --git a/app/views/search/breadcrumb.php b/app/views/search/breadcrumb.php
new file mode 100644
index 0000000..da6c3717
--- /dev/null
+++ b/app/views/search/breadcrumb.php
@@ -0,0 +1,28 @@
+<div style="padding-bottom: 20px;">
+<? $bc_points = $this->breadcrumb->getTrail(); ?>
+<? $sum_points = count($bc_points) - 1; ?>
+<? $index = 0; ?>
+<? foreach($bc_points as $type => $point):?>
+ <? $id2 = reset(array_values((array) $point['add'])); ?>
+ <? $link = $controller->link_for('/' . $point['actn'], $point['id'], $id2); ?>
+ <? if (is_array($point['add'])) : ?>
+ <? $mvv_object = $type::find($point['id']); ?>
+ <? if ($mvv_object && $type == 'Fach' && $additional_object = Abschluss::find($point['add']['Abschluss'])) : ?>
+ <a href="<?= $link ?>"><?= htmlReady($mvv_object->getDisplayName() . ' (' . $additional_object->name . ')') ?></a>
+ <? endif; ?>
+ <? if ($mvv_object && $type == 'StgteilBezeichnung' && $additional_object = StudiengangTeil::find($point['add']['StudiengangTeil'])) : ?>
+ <a href="<?= $link ?>"><?= htmlReady($mvv_object->getDisplayName() . ': ' . $additional_object->getDisplayName(ModuleManagementModel::DISPLAY_FACH)) ?></a>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($type == 'StudiengangTeil' && $mvv_object = $type::find($point['id'])) : ?>
+ <a href="<?= $link ?>"><?= htmlReady($mvv_object->getDisplayName(ModuleManagementModel::DISPLAY_FACH)) ?></a>
+ <? elseif ($point['id'] && $mvv_object = $type::find($point['id'])) : ?>
+ <a href="<?= $link ?>"><?= htmlReady($mvv_object->getDisplayName(0)) ?></a>
+ <? else : ?>
+ <a href="<?= $link ?>"><?= htmlReady($point['name']) ?></a>
+ <? endif; ?>
+ <? endif; ?>
+ <? if ($point['actn'] == $controller->action) break; ?>
+ <?= $index++ < $sum_points ? '>' : null; ?>
+<? endforeach; ?>
+</div>
diff --git a/app/views/search/courses/index.php b/app/views/search/courses/index.php
new file mode 100644
index 0000000..63b9dc4
--- /dev/null
+++ b/app/views/search/courses/index.php
@@ -0,0 +1,2 @@
+<?
+$sem_browse_obj->do_output();
diff --git a/app/views/search/globalsearch/index.php b/app/views/search/globalsearch/index.php
new file mode 100644
index 0000000..e85aa8f
--- /dev/null
+++ b/app/views/search/globalsearch/index.php
@@ -0,0 +1,54 @@
+<form class="default" onsubmit="return false;" autocomplete="off">
+ <div id="div-search-input" class="input-group files-search">
+ <input type="text" autofocus name="searchtext" id="search-input"
+ value="<?= htmlReady($_SESSION['search_text']) ?>"
+ placeholder="<?= _('Was suchen Sie?') ?>">
+
+ <span class="input-group-append">
+ <button type="submit" class="button" id="search-btn">
+ <?= Icon::create('search')->asImg(['title' => _('Suche starten')]) ?>
+ </button>
+
+ <button type="submit" class="button" id="reset-search">
+ <?= Icon::create('decline')->asImg(['title' => _('Suche zurücksetzen')]) ?>
+ </button>
+
+ </span>
+ </div>
+</form>
+
+<div id="search-active-filters">
+ <h5><?= _('Aktive Filter') . ': ' ?></h5>
+ <div class="filter-items"></div>
+</div>
+
+<div id="search">
+ <div id="searching-gif">
+ <?= _('Suche...') ?>
+ </div>
+
+ <div id="search-term-invalid">
+ <?= MessageBox::warning(sprintf(
+ _('Leider ist Ihr Suchbegriff zu kurz. Der Suchbegriff muss mindestens "%s" Zeichen lang sein.'),
+ '<span class="searchtermlen"></span>'
+ )) ?>
+ </div>
+
+ <div id="search-results" data-loading-text="<?= _('Suche...') ?>"
+ data-all-results="<?= _('Filter aufheben') ?>"
+ data-searchterm="<?= htmlReady(Request::get('q')) ?>"
+ data-category="<?= htmlReady(Request::get('category')) ?>"
+ data-img-add="<?= htmlReady(Icon::create('add')->asImg(['title' => _('Unterveranstaltungen anzeigen')])) ?>"
+ data-img-remove="<?= htmlReady(Icon::create('remove')->asImg(['title' => _('Unterveranstaltungen ausblenden')])) ?>"
+ data-results-per-type="<?= Config::get()->GLOBALSEARCH_MAX_RESULT_OF_TYPE ?>"
+ data-filters="<?= htmlReady(json_encode($filters)) ?>">
+ </div>
+
+ <div id="search-no-result">
+ <?= MessageBox::warning(sprintf(
+ _('Leider konnten zu Ihrem Suchbegriff "%s" keine Treffer gefunden werden. '
+ . ' Haben Sie sich vielleicht verschrieben?'),
+ '<span class="searchterm"></span>'
+ )) ?>
+ </div>
+</div>
diff --git a/app/views/search/module/_drill_down_list.php b/app/views/search/module/_drill_down_list.php
new file mode 100644
index 0000000..4a38a00
--- /dev/null
+++ b/app/views/search/module/_drill_down_list.php
@@ -0,0 +1,58 @@
+<? if ($drill_down_id) : ?>
+<div style="width: 100%; text-align:right;">
+ <a href="<?= $controller->url_for('search/module/reset_drilldown') ?>">
+ <?= _('Auswahl aufheben') ?>
+ <?= Icon::create('decline', 'clickable', ['title' => _('Auswahl aufheben')])->asImg(); ?>
+ </a>
+</div>
+<? endif; ?>
+<? /*
+<dl style="margin:0;">
+<? foreach ($lists as $list) : ?>
+ <? if (count($list['objects'])) : ?>
+ <dt style="font-weight:bold;margin:5px 0;"><?= $list['name'] ?></dt>
+ <dd>
+ <ul style="list-style-type:none; margin:0; padding:0;">
+ <? foreach ($list['objects'] as $object) : ?>
+ <li style="margin:5px 0;">
+ <a href="<?= $controller->url_for('search/module/drilldown', array('type' => get_class($object), 'id' => $object->getId())) ?>">
+ <?= htmlReady($object->getDisplayName()) . ' (' . /*$object->count_module .*/ ')' ?>
+ <? /* <? if ($object->getId() == $drill_down_id) : ?>
+ <?= Icon::create('accept', 'clickable', array('title' => _('Bereich ausgewählt')))->asImg(); ?>
+ <? endif; ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </dd>
+ <? endif; ?>
+<? endforeach; ?>
+</dl>
+ */ ?>
+
+
+<form action="<?= $controller->link_for('/index') ?>" method="post">
+ <select name="actlist" style="margin:0;" class="submit-upon-select">
+ <? foreach ($lists as $lname => $list) : ?>
+ <option value="<?= $lname ?>" <?= $lname == $act_list ? 'selected' :''; ?>><?= $list['name'] ?></option>
+ <? endforeach; ?>
+ </select>
+</form>
+<dl style="margin:0;">
+ <? if (count($lists[$act_list]['objects'])) : ?>
+ <dd>
+ <ul style="list-style-type:none; margin:0; padding:0;">
+ <? foreach ($lists[$act_list]['objects'] as $object) : ?>
+ <li style="margin:5px 0;">
+ <a href="<?= $controller->url_for('search/module/drilldown', ['type' => get_class($object), 'id' => $object->getId()]) ?>">
+ <?= htmlReady($object->getDisplayName()) . ' (' . $object->count_module . ')' ?>
+ <? if ($object->getId() == $drill_down_id) : ?>
+ <?= Icon::create('accept', 'clickable', ['title' => _('Bereich ausgewählt')])->asImg(); ?>
+ <? endif; ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </dd>
+ <? endif; ?>
+</dl> \ No newline at end of file
diff --git a/app/views/search/module/_infobox_info.php b/app/views/search/module/_infobox_info.php
new file mode 100644
index 0000000..68ce9f3
--- /dev/null
+++ b/app/views/search/module/_infobox_info.php
@@ -0,0 +1,7 @@
+<?= _('Als Suchbegriff sind zugelassen:') ?>
+<ul style="margin: 5px 0 5px 15px; padding:0;">
+ <li><?= _('Modulbezeichnung / Modulcode') ?></li>
+ <li><?= _('Name eines Studiengangs') ?></li>
+ <li><?= _('Name eines Faches') ?></li>
+ <li><?= _('Name einer Einrichtung') ?></li>
+</ul>
diff --git a/app/views/search/module/_modul.php b/app/views/search/module/_modul.php
new file mode 100644
index 0000000..e20a586
--- /dev/null
+++ b/app/views/search/module/_modul.php
@@ -0,0 +1,31 @@
+<tbody class="<?= $modul_id == $modul->id ? 'not-collapsed' : 'collapsed' ?>">
+ <tr class="table-header header-row" id="modul_<?= htmlReady($modul->id) ?>">
+ <td style="vertical-align: middle; text-align: center;">
+ <a data-dialog title="<?= htmlReady($modul->getDisplayName(ModuleManagementModel::DISPLAY_CODE | ModuleManagementModel::DISPLAY_SEMESTER)) . ' (' . _('Vollständige Modulbeschreibung') . ')' ?>" href="<?= $controller->link_for('shared/modul/description/' . $modul->id) ?>">
+ <?= Icon::create('log')->asImg(['title' => _('Vollständige Modulbeschreibung')]) ?>
+ </a>
+ </td>
+ <? if (count($modul->getAssignedCoursesBySemester($selected_semester->id, $GLOBALS['user']->id))) : ?>
+ <td class="toggle-indicator">
+ <a class="mvv-search-modules-row-link mvv-load-in-new-row" href="<?= $controller->link_for("/details/{$modul->id}/#{$modul->id}") ?>">
+ <?= htmlReady($modul->getDisplayName(ModuleManagementModel::DISPLAY_CODE)) ?>
+ </a>
+ </td>
+ <? else : ?>
+ <td class="mvv-search-modules-row">
+ <?= htmlReady($modul->getDisplayName(ModuleManagementModel::DISPLAY_CODE)) ?>
+ </td>
+ <? endif; ?>
+ <td class="dont-hide">
+ <?= htmlReady($modul->getDisplaySemesterValidity()) ?>
+ </td>
+ <td class="dont-hide">
+ <? if ($modul->responsible_institute->institute) : ?>
+ <?= htmlReady($modul->responsible_institute->institute->getDisplayName()); ?>
+ <? endif; ?>
+ </td>
+ </tr>
+<? if ($details_id == $modul->id): ?>
+ <?= $this->render_partial('search/module/details') ?>
+<? endif; ?>
+</tbody>
diff --git a/app/views/search/module/details.php b/app/views/search/module/details.php
new file mode 100644
index 0000000..62f3511
--- /dev/null
+++ b/app/views/search/module/details.php
@@ -0,0 +1,3 @@
+ <td colspan="4">
+ <?= $modul_content ?>
+ </td> \ No newline at end of file
diff --git a/app/views/search/module/index.php b/app/views/search/module/index.php
new file mode 100644
index 0000000..d0b5353
--- /dev/null
+++ b/app/views/search/module/index.php
@@ -0,0 +1,63 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<div style="padding:2em; text-align:center; vertical-align: middle; background-color: #e7ebf1; margin-bottom: 20px;">
+ <form action="<?= $controller->link_for('/index') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="text" style="width:50%;" name="sterm" value="<?= htmlReady($input_search) ?>">
+ <input type="hidden" name="do_search" value="1">
+ <?= Button::create('Suche') ?>
+ <? if ($sterm) : ?>
+ <?= LinkButton::create('Zurücksetzen', $controller->url_for('search/module/reset'), ['title' => _('Suche zurücksetzen')]); ?>
+ <? endif; ?>
+ </form>
+</div>
+<!-- Trefferset -->
+<table class="default collapsable">
+ <caption>
+ <? if ($count) : ?>
+ <?= sprintf(_('Gefundene Module für <i>%s</i>'), htmlReady($sterm)) ?>
+ <span class="actions">
+ <? printf(ngettext('%s Modul', '%s Module', $count), $count); ?>
+ </span>
+ <? endif; ?>
+ </caption>
+ <? if (count($module)) : ?>
+ <colgroup>
+ <col>
+ <col>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th>
+ <abbr title="<?= _('Moduldeskriptor') ?>">
+ <?= Icon::create('log', Icon::ROLE_INFO) ?>
+ </abbr>
+ </th>
+ <th class="mvv-search-modules-row"><?= _('Modultitel') ?></th>
+ <th><?= _('Gültigkeit') ?></th>
+ <th><?= _('Einrichtung') ?></th>
+ </tr>
+ </thead>
+<? foreach ($module as $modul) : ?>
+ <?= $this->render_partial('search/module/_modul', ['modul' => $modul]); ?>
+<? endforeach; ?>
+ <tfoot>
+ <tr>
+ <td colspan="4" style="text-align: right;">
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_module=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render('shared/pagechooser');
+ ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+</table>
diff --git a/app/views/search/module/show.php b/app/views/search/module/show.php
new file mode 100644
index 0000000..04ed30d
--- /dev/null
+++ b/app/views/search/module/show.php
@@ -0,0 +1,158 @@
+<table class="mvv-modul-details">
+ <tr>
+ <th class="mvv-modul-details-head" width="30%"><?= $modul->code ?></td>
+ <th class="mvv-modul-details-head" width="30%"><?= $institut->name ?></td>
+ <th class="mvv-modul-details-head" width="40%"><?= sprintf("%d CP", $modul->kp) ?> </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <?= $modul->getDisplayName() ?><br>
+ <?= _('Lehrveranstaltungen') ?> <?= $semester['name'] ?>
+ </td>
+ <td>
+ <dl>
+ <? foreach ($modulVerantwortung as $gruppe): ?>
+ <dt><?= htmlReady($gruppe['name']) ?></dt>
+ <? foreach ($gruppe['users'] as $user): ?>
+ <dd><?= htmlReady($user['name']) ?></dd>
+ <? endforeach; ?>
+ </dl>
+ <? endforeach; ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" style="padding: 0;">
+ <table style="margin: -1px; padding: 0; border-collapse: collapse;">
+ <? if (mb_strlen($teilnahmeVoraussetzung) > 0): ?>
+ <tr>
+ <th width="20%"><?= _('Teilnahmevoraussetzungen') ?></th>
+ <td ><?= htmlReady($teilnahmeVoraussetzung) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->kommentar)) : ?>
+ <tr>
+ <th><?= _('Hinweise') ?></th>
+ <td><?= formatReady($deskriptor->kommentar) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->ersatztext) > 0): ?>
+ <tr>
+ <th></th>
+ <td><?= formatReady($deskriptor->ersatztext) ?></td>
+ </tr>
+ <? else: ?>
+
+ <? if ($modul->kapazitaet > 0): ?>
+ <tr>
+ <th><?= _('Kapazität Modul') ?></th>
+ <td>
+ <?= $modul->kapazitaet ?>
+ <? if (mb_strlen($deskriptor->kommentar_kapazitaet) > 0): ?>
+ (<?= formatReady($deskriptor->kommentar_kapazitaet) ?>)
+ <? endif; ?>
+
+ </td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($pruef_ebene) > 0): ?>
+ <tr>
+ <th><?= _('Prüfungsebene') ?></th>
+ <td><?= $pruef_ebene ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->pruef_vorleistung)) : ?>
+ <tr>
+ <th><?= _('Prüfungsvorleistung Modul') ?></th>
+ <td><?= formatReady($deskriptor->pruef_vorleistung) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->pruef_leistung)) : ?>
+ <tr>
+ <th><?= _('Prüfungsleistung Modul') ?></th>
+ <td><?= formatReady($deskriptor->pruef_leistung) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->kompetenzziele)): ?>
+ <tr>
+ <th><?= _('Kompetenzziele') ?></th>
+ <td><?= formatReady($deskriptor->kompetenzziele) ?></td>
+ </tr>
+ <? endif; ?>
+
+ <? endif; ?>
+ </table>
+ </td>
+ </tr>
+
+ <? if ($type !== 3): ?>
+ <tr>
+ <? if ($type === 1): ?>
+ <th><?= _('Modulteile') ?></th>
+ <? endif; ?>
+ <th <? if ($type === 2): ?> colspan="3" <? endif; ?> ><?= _('Semesterveranstaltungen') ?></th>
+ <? if ($type === 1): ?>
+ <th><?= _('Prüfungsleistung') ?></th>
+ <? endif; ?>
+ </tr>
+
+ <? foreach ($modulTeile as $lvGruppe): ?>
+ <tr>
+ <? if ($type === 1): ?>
+ <td>
+ <b> <?= $lvGruppe['name'] ?> </b>
+ <? if (mb_strlen($lvGruppe['kommentar']) > 0): ?>
+ (<?= htmlReady($lvGruppe['kommentar']) ?>)
+ <? endif; ?>
+ <? if ($lvGruppe['kapazitaet'] > 0): ?>
+ <br/>
+ <b><?= _('Kapazität') ?>: </b> <?= htmlReady($lvGruppe['kapazitaet']) ?>
+ <? endif; ?>
+ <? if (mb_strlen($lvGruppe['voraussetzung']) > 0): ?>
+ <br/>
+ <b><?= _('Teilnahmevoraussetzungen') ?>:</b> <?= htmlReady($lvGruppe['voraussetzung']) ?>
+ <? endif; ?>
+ </td>
+ <? endif; ?>
+
+ <td <? if ($type === 2): ?> colspan="3" <? endif; ?>>
+ <? foreach ($lvGruppe['lvGruppen'] as $gruppe): ?>
+ <? if (mb_strlen($gruppe['alt_texte']) > 0): ?>
+ <b><?= formatReady($gruppe['alt_texte']) ?></b>
+ <? endif; ?>
+ <ul>
+ <? foreach ($gruppe['courses'] as $seminar_id => $course): ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $seminar_id]) ?>">
+ <?= htmlReady($course['Name']) ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endforeach; ?>
+ </td>
+ <? if ($type === 1): ?>
+ <td width="40%">
+ <? if (mb_strlen($lvGruppe['pruef_vorleistung']) > 0) : ?>
+ <b><?= _('Prüfungsvorleistung') ?>:</b> <?= htmlReady($lvGruppe['pruef_vorleistung']) ?>
+ <? endif; ?>
+ <? if (mb_strlen($lvGruppe['pruef_leistung']) > 0) : ?>
+ <b><?= _('Prüfungsform') ?>:</b> <br/><?= htmlReady($lvGruppe['pruef_leistung']) ?> (<?= htmlReady($lvGruppe['anteil_note']) ?> %)
+ <? endif; ?>
+ </td>
+ <? endif; ?>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+
+ <tr>
+ <td colspan="3">
+ <?
+ if (trim($modul->fassung_nr) != '' && $modul->beschlussdatum) {
+ printf(_('In der Fassung des <b>%d</b>. Beschlusses vom <b>%s</b>. Bitte beachten Sie: Die Modulinformationen stehen an dieser Stelle ohne Gewähr.'), htmlReady($modul->fassung_nr), date('d.m.Y', $modul->beschlussdatum));
+ } else {
+ echo _('Bitte beachten Sie: Die Modulinformationen stehen an dieser Stelle ohne Gewähr.');
+ }
+ ?>
+ </td>
+ </tr>
+</table>
diff --git a/app/views/search/stgtable/index.php b/app/views/search/stgtable/index.php
new file mode 100644
index 0000000..58a7bce
--- /dev/null
+++ b/app/views/search/stgtable/index.php
@@ -0,0 +1,32 @@
+<table class="default">
+ <colgroup>
+ <col>
+ <? for ($i = count($kategorien); $i > 0; $i--) : ?>
+ <col style="text-align: center;">
+ <? endfor; ?>
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Studiengänge') ?></th>
+ <? foreach ($kategorien as $kategorie): ?>
+ <th style="text-align: center;"><?= htmlReady($kategorie->name) ?></th>
+ <? endforeach; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($stgs as $name => $stg): ?>
+ <tr>
+ <td><?= htmlReady($name) ?></td>
+ <? foreach ($kategorien as $kat_id => $kategorie): ?>
+ <? if ($stg[$kat_id]) : ?>
+ <td style="text-align: center;">
+ <a href="<?= $controller->link_for('/studiengang', $stg[$kat_id]) ?>"><?= Icon::create('info-circle-full', 'clickable', ['title' => _('Studiengang anzeigen')])->asImg(); ?></a>
+ </td>
+ <? else : ?>
+ <td></td>
+ <? endif; ?>
+ <? endforeach; ?>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/app/views/search/studiengaenge/_studiengang.php b/app/views/search/studiengaenge/_studiengang.php
new file mode 100644
index 0000000..baa5361
--- /dev/null
+++ b/app/views/search/studiengaenge/_studiengang.php
@@ -0,0 +1,38 @@
+<dt class="<?= $cycle_class ?>" id="<?= $category->getId() ?>">
+ <a href="<?= $controller->url_for('search/studiengang/info/' . $category->getId() . '#' . $modul->getId()) ?>">
+ <?= htmlReady($modul->getDisplayName() . ' (' . $modul->responsible_institute->institute->getDisplayName() . ')'); ?>
+ </a>
+</dt>
+<dd class="odd">
+ <? if ($details_id == $modul->getId()) : ?>
+ <div>
+ <? if ($semester_select) : ?>
+ <div style="width: 50%; float:left;">
+ <form name="semesterSelect" action="<?= $controller->url_for('search/module/overview/' . $modul->getId() . '#' . $modul->getId()) ?>" method="GET">
+ <?= _('Semesterauswahl') ?>:
+ <select name="sem_select" class="submit-upon-select">
+ <? foreach ($semester_select as $sem) : ?>
+ <option value="<?= $sem->getId() ?>"<?= $sem->getId() == $selected_semester ? ' selected' : '' ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <?= Icon::create('accept', 'clickable')->asInput(); ?>
+ </form>
+ </div>
+ <div style="text-align:right;">
+ <a data-dialog href="<?= $controller->url_for('search/module/description/' . $modul->getId()) ?>">
+ <?= _('Vollständige Modulbeschreibung') ?>
+ </a>
+ </div>
+ <? else : ?>
+ <div style="text-align:right;">
+ <a href="<?= $controller->url_for('search/module/overview/' . $modul->getId()) ?>">
+ <?= _('Modulübersicht') ?>
+ </a>
+ </div>
+ <? endif; ?>
+ <?= $modul_content ?>
+ </div>
+ <? endif; ?>
+</dd>
diff --git a/app/views/search/studiengaenge/einfach.php b/app/views/search/studiengaenge/einfach.php
new file mode 100644
index 0000000..9250a7e
--- /dev/null
+++ b/app/views/search/studiengaenge/einfach.php
@@ -0,0 +1,10 @@
+<?= $this->render_partial('search/breadcrumb') ?>
+<h2><?= htmlReady($studiengang->getDisplayName(ModuleManagementModel::DISPLAY_ABSCHLUSS)) ?></h2>
+<h3><?= _('Ausprägungen') ?></h3>
+<ul class="mvv-result-list">
+<? foreach ($data as $fach_id => $fach) : ?>
+ <li>
+ <a href="<?= $controller->link_for($verlauf_url, $fach_id) ?>"><?= htmlReady($fach) ?></a>
+ </li>
+<? endforeach; ?>
+</ul>
diff --git a/app/views/search/studiengaenge/index.php b/app/views/search/studiengaenge/index.php
new file mode 100644
index 0000000..758720e
--- /dev/null
+++ b/app/views/search/studiengaenge/index.php
@@ -0,0 +1,16 @@
+<section class="contentbox">
+ <header>
+ <h1><?= _('Abschluss-Kategorien') ?></h1>
+ </header>
+ <ul class="mvv-result-list">
+ <? foreach ($categories as $category) : ?>
+ <? if ($category->count_studiengaenge) : ?>
+ <li>
+ <a href="<?= $controller->url_for('search/studiengaenge/kategorie', $category->id) ?>">
+ <?= htmlReady($category->getDisplayName()) ?>
+ </a>
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ </ul>
+</section>
diff --git a/app/views/search/studiengaenge/info.php b/app/views/search/studiengaenge/info.php
new file mode 100644
index 0000000..7a5d289
--- /dev/null
+++ b/app/views/search/studiengaenge/info.php
@@ -0,0 +1,205 @@
+<style>
+ /* This should be done by an own class (maybe not table? maybe dd?) */
+ #tablefix {
+ padding: 0;
+ }
+ #tablefix > header {
+ margin: 0px;
+ }
+ #tablefix table {
+ margin-bottom: 0;
+ border-bottom: 0;
+ }
+ #tablefix table tbody tr:last-child td {
+ border-bottom: 0;
+ }
+ input[type=checkbox].mvv-cb-more-items {
+ display: none;
+ }
+ input[type=checkbox].mvv-cb-more-items:checked~ul li:nth-child(n+5) {
+ height: 0;
+ visibility: hidden;
+ }
+ input[type=checkbox].mvv-cb-more-items:not(:checked)~ul li label.cb-more-items {
+ display: none;
+ }
+ input[type=checkbox].mvv-cb-more-items:checked~ul li label.cb-more-items {
+ display: block;
+ }
+</style>
+<div style="width: 100%; text-align: right;">
+ <? foreach (Config::get()->CONTENT_LANGUAGES as $locale => $language) : ?>
+ <a data-dialog="title='<?= htmlReady($studiengang->getDisplayName()) ?>'" href="<?= $controller->url_for('/info/' . $studiengang->id . '/', ['language' => $locale]) ?>">
+ <img src="<?= Assets::image_path('languages/' . $language['picture']) ?>" alt="<?= $language['name'] ?>" title="<?= $language['name'] ?>">
+ </a>
+ <? endforeach; ?>
+</div>
+<article class="studip toggle open" id="tablefix">
+ <header>
+ <h1><a name=""><?= _('Zahlen und Fakten') ?></a></h1>
+ </header>
+ <table class="default">
+ <colgroup>
+ <col>
+ <col style="width: 80%;">
+ </colgroup>
+ <tbody>
+ <tr>
+ <td>
+ <strong><?= _('Studiengangsname') ?>:</strong>
+ </td>
+ <td>
+ <?= htmlReady($studiengang->getDisplayName()) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Dauer') ?>:</strong>
+ </td>
+ <td>
+ <? printf('%s Semester', htmlReady($studiengang->studienzeit)) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Abschlussgrad') ?>:</strong>
+ </td>
+ <td>
+ <?= htmlReady($GLOBALS['MVV_STUDIENGANG']['ABSCHLUSSGRAD']['values'][$studiengang->abschlussgrad]['name']) ?>
+ </td>
+ </tr>
+ <? if (count($studiengang->languages)) : ?>
+ <tr>
+ <td>
+ <strong><?= _('Sprache') ?>:</strong>
+ </td>
+ <td>
+ <?= htmlReady(implode('/', $studiengang->languages->pluck('display_name'))) ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <tr>
+ <td>
+ <strong><?= _('Art der Zulassung') ?>:</strong>
+ </td>
+ <td>
+ <?= htmlReady($GLOBALS['MVV_STUDIENGANG']['ZULASSUNG']['values'][$studiengang->enroll]['name']) ?>
+ </td>
+ </tr>
+ <? foreach ($studiengang->datafields as $df) : ?>
+ <? if (mb_strpos($df->datafield->object_class, 'settings') !== false
+ && !$df->isNew()) : ?>
+ <? $tdf = $df->getTypedDatafield() ?>
+ <? if ($tdf->isVisible() && $tdf->getValue()) : ?>
+ <tr>
+ <td>
+ <strong><?= htmlReady($tdf->getName()) ?></strong>
+ </td>
+ <td>
+ <?= $tdf->getDisplayValue() ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? endif ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+</article>
+<? if (trim($studiengang->beschreibung)) : ?>
+ <article class="studip toggle open">
+ <header>
+ <h1><a name=""><?= _('Beschreibung') ?></a></h1>
+ </header>
+ <section>
+ <?= formatReady($studiengang->beschreibung) ?>
+ </section>
+ </article>
+<? endif ?>
+<? foreach ($studiengang->datafields as $df) : ?>
+ <? if (mb_strpos($df->datafield->object_class, 'info') !== false
+ && !$df->isNew()) : ?>
+ <? $tdf = $df->getTypedDatafield(); ?>
+ <? if ($tdf->isVisible() && trim($tdf->getValue())) : ?>
+ <article class="studip toggle open">
+ <header>
+ <h1><a name=""><?= htmlReady($tdf->getName()) ?></a></h1>
+ </header>
+ <section>
+ <?= $tdf->getDisplayValue() ?>
+ </section>
+ </article>
+ <? endif; ?>
+ <? endif; ?>
+<? endforeach; ?>
+<? if (is_array($all_contacts) && count($all_contacts)) : ?>
+ <article class="studip toggle open">
+ <header>
+ <h1><a name=""><?= _('Ihre AnsprechpartnerInnen') ?></a></h1>
+ </header>
+ <section>
+ <? foreach ($all_contacts as $category => $contacts) : ?>
+ <? if ($GLOBALS['MVV_STUDIENGANG']['PERSONEN_GRUPPEN']['values'][$category]['visible']) : ?>
+ <strong><?= htmlReady($GLOBALS['MVV_STUDIENGANG']['PERSONEN_GRUPPEN']['values'][$category]['name']) ?></strong>
+ <ul>
+ <? foreach ($contacts as $contact) : ?>
+ <li>
+ <?= htmlReady($contact['name']) ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ <? endforeach; ?>
+ </section>
+ </article>
+<? endif ?>
+<? if (is_array($all_documents) && count($all_documents)) : ?>
+ <article class="studip toggle open">
+ <header>
+ <h1><a name=""><?= _('Dokumente: Ordnungen, Formulare, Informationen') ?></a></h1>
+ </header>
+ <section>
+ <? foreach ($all_documents as $category => $files) : ?>
+ <? if ($GLOBALS['MVV_DOCUMENTS']['CATEGORY']['values'][$category]['visible']) : ?>
+ <strong><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['CATEGORY']['values'][$category]['name']) ?></strong>
+ <ul>
+ <? foreach ($files as $file) : ?>
+ <li>
+ <? if ($file['is_link']) : ?>
+ <a href="<?= $file['metadata_url'] ?>" target="_blank"><?= htmlReady($file['name']) ?></a>
+ <? else : ?>
+ <?= htmlReady($file['name']) ?>
+ <a href="<?= $file['url'] ?>"><?= htmlReady($file['extension']) ?></a>
+ <? endif ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ <? endforeach; ?>
+ </section>
+ </article>
+<? endif ?>
+<? if (count($all_aufbaustgs)) : ?>
+ <article class="studip toggle open">
+ <header>
+ <h1><a name=""><?= _('Aufbau-/Kombinationsstudiengänge') ?></a></h1>
+ </header>
+ <section>
+ <? foreach ($all_aufbaustgs as $typ => $aufbaustgs) : ?>
+ <strong><?= htmlReady($GLOBALS['MVV_AUFBAUSTUDIENGANG']['TYP']['values'][$typ]['name']) ?></strong>
+ <? if (count($aufbaustgs) > 4) : ?>
+ <input type="checkbox" class="mvv-cb-more-items" id="cb_more_aufbaustgs" checked>
+ <? endif; ?>
+ <ul>
+ <? foreach ($aufbaustgs as $i => $aufbaustg) : ?>
+ <li>
+ <?= htmlReady($aufbaustg->getDisplayName()) ?>
+ <? if ($i == 3) : ?>
+ <label class="cb-more-items" for="cb_more_aufbaustgs"><?= _('mehr...') ?></label>
+ <? endif; ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? endforeach ?>
+ </section>
+ </article>
+<? endif; ?>
diff --git a/app/views/search/studiengaenge/kategorie.php b/app/views/search/studiengaenge/kategorie.php
new file mode 100644
index 0000000..d5f2ee6
--- /dev/null
+++ b/app/views/search/studiengaenge/kategorie.php
@@ -0,0 +1,21 @@
+<?= $this->render_partial('search/breadcrumb') ?>
+<? foreach ($studiengaenge as $abschluss_id => $studiengaenge_abschluss): ?>
+<article class="studip toggle">
+ <header>
+ <h1>
+ <a name="abschluss-<?= $abschluss_id ?>">
+ <?= htmlReady($abschluesse[$abschluss_id]->getDisplayName()) ?>
+ </a>
+ </h1>
+ </header>
+ <ul class="mvv-result-list">
+ <? foreach ($studiengaenge_abschluss as $id => $s) : ?>
+ <li>
+ <a href="<?= $controller->link_for('search/studiengaenge/studiengang', $id) ?>">
+ <?= htmlReady($s->getDisplayName()); ?>
+ </a>
+ </li>
+ <? endforeach; ?>
+ </ul>
+</article>
+<? endforeach; ?>
diff --git a/app/views/search/studiengaenge/kommentar.php b/app/views/search/studiengaenge/kommentar.php
new file mode 100644
index 0000000..52f11fc
--- /dev/null
+++ b/app/views/search/studiengaenge/kommentar.php
@@ -0,0 +1 @@
+<?= formatReady($abschnitt->kommentar) ?>
diff --git a/app/views/search/studiengaenge/mehrfach.php b/app/views/search/studiengaenge/mehrfach.php
new file mode 100644
index 0000000..c4836f1
--- /dev/null
+++ b/app/views/search/studiengaenge/mehrfach.php
@@ -0,0 +1,37 @@
+<?= $this->render_partial('search/breadcrumb') ?>
+<table class="default nohover">
+ <caption>
+ <?= _('Studiengang') ?>: <?= htmlReady($studiengang->getDisplayName(ModuleManagementModel::DISPLAY_ABSCHLUSS)) ?>
+ <? if (Config::get()->ENABLE_STUDYCOURSE_INFO_PAGE) : ?>
+ <a href="<?= $controller->url_for('search/studiengaenge/info', $studiengang->id)?>" data-dialog>
+ <?= Icon::create('infopage2')->asImg(25) ?>
+ </a>
+ <? endif; ?>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Fächer') ?></th>
+ <? foreach ($studiengangTeilBezeichnungen as $teil_bezeichnung): ?>
+ <th style="text-align: center;"><?= htmlReady($teil_bezeichnung->getDisplayName()) ?></th>
+ <? endforeach; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($data as $fach_id => $fach): ?>
+ <tr>
+ <td>
+ <?= htmlReady($fachNamen[$fach_id]) ?>
+ </td>
+ <? foreach ($studiengangTeilBezeichnungen as $teil_bezeichnung): ?>
+ <td style="text-align: center;">
+ <? if (isset($fach[$teil_bezeichnung->id])) : ?>
+ <a href="<?= $controller->url_for($verlauf_url, $fach[$teil_bezeichnung->id], $teil_bezeichnung->id, $studiengang_id) ?>">
+ <?= Icon::create('info-circle-full', 'clickable', ['title' => _('Studienverlaufsplan anzeigen')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <? endforeach; ?>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/app/views/search/studiengaenge/verlauf.php b/app/views/search/studiengaenge/verlauf.php
new file mode 100644
index 0000000..d3eaf56
--- /dev/null
+++ b/app/views/search/studiengaenge/verlauf.php
@@ -0,0 +1,131 @@
+<div>
+<?= $this->render_partial('search/breadcrumb') ?>
+</div>
+<? if ($studiengangTeilName) : ?>
+ <? $max_fachsemester = count($fachsemesterData) ? max($fachsemesterData) : 0 ?>
+ <table class="mvv-modul-details default nohover">
+ <caption>
+ <?= htmlReady($studiengangTeilName) ?>
+ <? if ($studiengang && $stgTeilBez) : ?>
+ <h3>
+ <?= sprintf(_('%s im Studiengang %s'), htmlReady($stgTeilBez->getDisplayName()), htmlReady($studiengang->getDisplayName(ModuleManagementModel::DISPLAY_ABSCHLUSS))) ?>
+ <? if (Config::get()->ENABLE_STUDYCOURSE_INFO_PAGE) : ?>
+ <a href="<?= $controller->link_for('search/studiengaenge/info', $studiengang->id)?>" data-dialog><?= Icon::create('infopage2', Icon::ROLE_CLICKABLE)->asImg() ?>
+ <? endif ?>
+ </h3>
+ <? endif ?>
+ <? $current_version = $versionen->findOneBy('id', $cur_version_id) ?>
+ <? if ($current_version) : ?>
+ <h4><?= $current_version->getDisplayName() ?></h4>
+ <? else : ?>
+ <h4><?= htmlReady($versionen->first()->getDisplayName()) ?></h4>
+ <? endif ?>
+ </caption>
+ <thead>
+ <tr >
+ <th rowspan="2"><?= _('Name / CP') ?></th>
+ <th rowspan="2"><?= _('Modul') ?></th>
+ <th rowspan="2"><?= _('Modulteil') ?></th>
+ <? if ($max_fachsemester) : ?>
+ <th colspan="<?= $max_fachsemester ?>" style="text-align: center"><?= _('Semester') ?></th>
+ <? endif ?>
+ </tr>
+ <tr>
+ <? for ($i = 1; $i <= $max_fachsemester; $i++) : ?>
+ <th><?= $i ?></th>
+ <? endfor ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($abschnitteData as $abschnitt_id => $abschnitt): ?>
+ <? $displayedAbschnittName = false ?>
+ <? $ueberschrift = (mb_strlen($abschnitt['zwischenUeberschrift'])) ?>
+ <?// if (!$ueberschrift): ?>
+ <? if ($ueberschrift): ?>
+ <tr class="table_header">
+ <td colspan="<?= $max_fachsemester + 3 ?>"><?= htmlReady($abschnitt['zwischenUeberschrift']) ?></td>
+ </tr>
+ <? endif ?>
+
+ <? foreach ($abschnitt['module'] as $modul_id => $modul): ?>
+ <? $displayedModulName = false ?>
+
+ <? foreach ($modul['modulTeile'] as $modulTeil_id => $modulTeil): ?>
+ <? $displayedModulTeilName = false ?>
+ <tr>
+ <? if (!$displayedAbschnittName) : ?>
+ <? $displayedAbschnittName = true ?>
+ <td rowspan="<?= $abschnitt['rowspan'] ?: 1 ?>">
+ <?= htmlReady($abschnitt['name']) ?><br/><?= $abschnitt['creditPoints'] ? $abschnitt['creditPoints'] . ' ' . _('CP') : '' ?>
+ <? if (trim($abschnitt['kommentar'])) : ?>
+ <a data-dialog title="<?= sprintf(_('%s (Kommentar)'), htmlReady($abschnitt['name'])) ?>" href="<?= $controller->link_for('search/studiengaenge/kommentar', $abschnitt_id) ?>">
+ <?= Icon::create('item')->asImg(['title' => _('Zusatzinformationen zum Studiengangsabschnitt')]) ?>
+ </a>
+ <? endif ?>
+ </td>
+ <? endif ?>
+ <? if (!$displayedModulName) : ?>
+ <? $displayedModulName = true ?>
+ <td rowspan="<?= count($modul['modulTeile']) ?>">
+ <? // Anzeige der alternativen Bezeichnung aus mvv_stgteilabschnitt_modul ?>
+ <? $abschnitt_modul = StgteilabschnittModul::findOneBySQL('`abschnitt_id` = ? AND `modul_id` = ?', [$abschnitt_id, $modul_id]) ?>
+ <a data-dialog title="<?= htmlReady($modul['name']) . ' (' . _('Vollständige Modulbeschreibung') . ')' ?>" href="<?= $controller->link_for('shared/modul/description/' . $modul_id, ['display_language' => ModuleManagementModel::getLanguage()]) ?>">
+ <?= Icon::create('log')->asImg(['title' => _('Vollständige Modulbeschreibung')]) ?>
+ </a>
+ <? if($modul['veranstaltungen']):?>
+ <a data-dialog href="<?= $controller->link_for('shared/modul/overview', $modul_id, $active_sem->getId(), ['display_language' => ModuleManagementModel::getLanguage()]) ?>">
+ <?= htmlReady($abschnitt_modul->getDisplayName()) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($abschnitt_modul->getDisplayName()) ?>
+ <? endif ?>
+ </td>
+ <? endif ?>
+ <td><?= htmlReady($modulTeil['name']) ?> </td>
+ <? for ($i = 1; $i <= $max_fachsemester; $i++) : ?>
+ <? $fachsemester_typ = $GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'][$modulTeil['fachsemester'][$fachsemesterData[$i]]] ?>
+ <? if ($fachsemester_typ['visible']) : ?>
+ <td class="mvv-type-<?= $modulTeil['fachsemester'][$fachsemesterData[$i]] ?>"><span title="<? printf(_('%s Semester (%s)'), $i . ModuleManagementModel::getLocaleOrdinalNumberSuffix($i), $fachsemester_typ['name']) ?>"><?= $fachsemester_typ['icon'] ?></span></td>
+ <? else : ?>
+ <td class="mvv-type">&nbsp;</td>
+ <? endif ?>
+ <? endfor ?>
+ </tr>
+ <? endforeach ?>
+
+ <? if (!$displayedModulName): ?>
+ <tr>
+ <? if (!$displayedAbschnittName) : ?>
+ <? $displayedAbschnittName = true ?>
+ <td rowspan="<?= $abschnitt['rowspan'] ?: 1 ?>">
+ <?= htmlReady($abschnitt['name']) ?><br/><?= $abschnitt['creditPoints'] ? $abschnitt['creditPoints'] . ' ' . _('CP') : '' ?>
+ <? if (trim($abschnitt['kommentar'])) : ?>
+ <a data-dialog title="<?= sprintf(_('%s (Kommentar)'), htmlReady($abschnitt['name'])) ?>" href="<?= $controller->link_for('search/studiengaenge/kommentar', $abschnitt_id) ?>">
+ <?= Icon::create('item')->asImg(['title' => _('Zusatzinformationen zum Studiengangsabschnitt')]) ?>
+ </a>
+ <? endif ?>
+ </td>
+ <? endif ?>
+ <td>
+ <a data-dialog title="<?= htmlReady($modul['name']) . ' (' . _('Vollständige Modulbeschreibung') . ')' ?>" href="<?= $controller->link_for('shared/modul/description/' . $modul_id, ['display_language' => ModuleManagementModel::getLanguage()]) ?>">
+ <?= Icon::create('log')->asImg(['title' => _('Vollständige Modulbeschreibung')]) ?>
+ </a>
+ <? if ($modul['veranstaltungen']): ?>
+ <a data-dialog href="<?= $controller->link_for('shared/modul/overview', $modul_id, $active_sem->getId(), ['display_language' => ModuleManagementModel::getLanguage()]) ?>">
+ <?= htmlReady($modul['name']) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($modul['name']) ?>
+ <? endif ?>
+ </td>
+ <td>&ndash;</td>
+ <? for ($i = 1; $i <= $max_fachsemester; $i++) : ?>
+ <td class="mvv-type">&nbsp;</td>
+ <? endfor ?>
+ </tr>
+ <? endif ?>
+ <? endforeach ?>
+ <? endforeach ?>
+ </tbody>
+ </table>
+<? endif ?>
diff --git a/app/views/seminar/details/show_module_pathes.php b/app/views/seminar/details/show_module_pathes.php
new file mode 100644
index 0000000..7ffa38e
--- /dev/null
+++ b/app/views/seminar/details/show_module_pathes.php
@@ -0,0 +1,24 @@
+<?
+if (count($mvv_pathes)) {
+?>
+<font size="-1">
+ <b><?= _('Modulzuordnung:') ?></b><br>
+ <ul style="margin:0; padding-left:2em;">
+ <?
+ foreach ($mvv_pathes as $mvv_path) {
+ $out = [];
+ foreach ($mvv_path as $mvv_object) {
+ if ($mvv_object instanceof StgteilabschnittModul) {
+ $modul_id = $mvv_object->getId();
+ }
+ $out[] = $mvv_object->getDisplayName();
+ }
+ ?>
+ <li><a data-dialog href="<?= $controller->url_for('search/module/show/' . $modul_id . '/1') ?>"><?= htmlReady(implode(' > ', $out)) ?></a></li>
+ <? } ?>
+ </ul>
+ <br>
+</font>
+<? } else { ?>
+<?= _('Keine Modulzuordnungen verfügbar') ?>
+<? } ?>
diff --git a/app/views/settings/account/index.php b/app/views/settings/account/index.php
new file mode 100644
index 0000000..f4d7d56
--- /dev/null
+++ b/app/views/settings/account/index.php
@@ -0,0 +1,160 @@
+<?php
+$genders = [
+ _('unbekannt'),
+ _('männlich'),
+ _('weiblich'),
+ _('divers'),
+];
+?>
+
+<? if ($user->auth_plugin !== 'standard'): ?>
+ <?= MessageBox::info(sprintf(_('Einige Ihrer persönlichen Daten werden nicht in Stud.IP verwaltet '
+ . 'und können daher hier nicht geändert werden.'))) ?>
+<? endif; ?>
+
+<? if ($locked_info): ?>
+ <?= MessageBox::info(formatLinks($locked_info)) ?>
+<? endif; ?>
+
+<form id="edit_userdata" method="post" name="pers" class="default"
+ action="<?= $controller->link_for('settings/account/store') ?>"
+ <? if (!$restricted) echo 'data-validate="true"'; ?>>
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <fieldset>
+ <legend>
+ <?= _('Persönliche Angaben bearbeiten') ?>
+ </legend>
+ <label for="new_username">
+ <span class="required">
+ <?= _('Nutzername') ?>
+ </span>
+ <? if ($restricted) : ?>
+ <?= tooltipIcon('Dieses Feld dürfen Sie nicht ändern, Adminzugriff ist hier nicht erlaubt!') ?>
+ <? endif ?>
+ <input required type="text" name="new_username" id="new_username"
+ pattern="<?= htmlReady(trim($validator->username_regular_expression, '/i^$()')) ?>"
+ data-message="<?= _('Der Benutzername ist unzulässig. Er muss mindestens 4 Zeichen lang sein und darf keine Sonderzeichen oder Leerzeichen enthalten.') ?>"
+ value="<?= $user['username'] ?>"
+ autocorrect="off" autocapitalize="off"
+ <? if ($restricted || !$controller->shallChange('auth_user_md5.username')) echo 'disabled'; ?>>
+ </label>
+ <label class="col-3">
+ <span class="required">
+ <?= _('Vorname') ?>
+ </span>
+ <? if ($restricted) : ?>
+ <?= tooltipIcon('Dieses Feld dürfen Sie nicht ändern, Adminzugriff ist hier nicht erlaubt!') ?>
+ <? endif ?>
+ <input required type="text" name="vorname"
+ pattern="<?= htmlReady(trim($validator->name_regular_expression, '/i^$()')) ?>"
+ value="<?= htmlReady($user['Vorname']) ?>"
+ <? if ($restricted || !$controller->shallChange('auth_user_md5.Vorname', 'name')) echo 'disabled'; ?>>
+ </label>
+ <label class="col-3">
+ <span class="required">
+ <?= _('Nachname') ?>
+ </span>
+ <? if ($restricted) : ?>
+ <?= tooltipIcon('Dieses Feld dürfen Sie nicht ändern, Adminzugriff ist hier nicht erlaubt!') ?>
+ <? endif ?>
+ <input required type="text" name="nachname"
+ pattern="<?= htmlReady(trim($validator->name_regular_expression, '/i^$()')) ?>"
+ data-message="<?= _('Bitte geben Sie Ihren tatsächlichen Nachnamen an.') ?>"
+ value="<?= htmlReady($user['Nachname']) ?>"
+ <? if ($restricted || !$controller->shallChange('auth_user_md5.Nachname', 'name')) echo 'disabled'; ?>>
+ </label>
+ <label class="col-3">
+ <?= _('Titel') ?>
+ <select id="title_front_chooser" name="title_front_chooser"
+ aria-label="<?= _('Titel auswählen') ?>"
+ data-target="#title_front"
+ <? if (!$controller->shallChange('user_info.title_front', 'title')) echo 'disabled'; ?>>
+ <? foreach ($GLOBALS['TITLE_FRONT_TEMPLATE'] as $title): ?>
+ <option <? if ($user['title_front'] == $title) echo 'selected'; ?>>
+ <?= htmlReady($title) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <label class="col-3">
+ <?= _('Titel eingeben') ?>
+ <input type="text" name="title_front" id="title_front"
+ data-target="#title_front_chooser"
+ value="<?= htmlReady($user['title_front']) ?>"
+ <? if (!$controller->shallChange('user_info.title_front', 'title')) echo 'disabled'; ?>>
+ </label>
+ <label class="col-3">
+ <?= _('Titel nachgest.') ?>
+ <select name="title_rear_chooser" id="title_rear_chooser"
+ aria-label="<?= _('Titel nachgestellt auswählen') ?>"
+ data-target="#title_rear"
+ <? if (!$controller->shallChange('user_info.title_rear', 'title')) echo 'disabled'; ?>>
+ <? foreach ($GLOBALS['TITLE_REAR_TEMPLATE'] as $title): ?>
+ <option <? if ($user['title_rear'] == $title) echo 'selected'; ?>>
+ <?= htmlReady($title) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <label class="col-3">
+ <?= _('Titel nachgest. eingeben') ?>
+ <input type="text" name="title_rear" id="title_rear"
+ data-target="#title_rear_chooser"
+ value="<?= htmlReady($user['title_rear']) ?>"
+ <? if (!$controller->shallChange('user_info.title_rear', 'title')) echo 'disabled'; ?>>
+ </label>
+ </fieldset>
+ <fieldset>
+ <legend>
+ <?= _('E-Mail') ?>
+ <? if ($restricted) : ?>
+ <?= tooltipIcon('Dieses Feld dürfen Sie nicht ändern, Adminzugriff ist hier nicht erlaubt!') ?>
+ <? endif ?>
+ </legend>
+ <label class="col-3">
+ <span class="required"><?= _('E-Mail') ?></span>
+ <input required type="email" name="email1" id="email1"
+ value="<?= htmlReady($user['Email']) ?>"
+ <? if ($restricted || !$controller->shallChange('auth_user_md5.Email')) echo 'disabled'; ?>>
+ </label>
+ <label class="col-3">
+ <span class="required"><?= _('E-Mail Wiederholung') ?></span>
+ <input required type="email" name="email2" id="email2"
+ value="<?= htmlReady($user['Email']) ?>"
+ data-must-equal="#email1"
+ <? if ($restricted || !$controller->shallChange('auth_user_md5.Email')) echo 'disabled'; ?>>
+ </label>
+
+ <? if (!$is_sso && !$restricted && $controller->shallChange('auth_user_md5.Email')): ?>
+ <label class="divider email-change-confirm">
+
+ <span id="email-change-confirm">
+ <?= _('Falls Sie Ihre E-Mail-Adresse ändern, muss diese Änderung durch die Eingabe '
+ . 'Ihres Passworts bestätigt werden:') ?>
+ </span>
+ <input type="text" name="disable_autofill" style="display: none;">
+ <input type="password" name="password" aria-labelledby="email-change-confirm">
+ </label>
+ <? endif; ?>
+
+ </fieldset>
+ <fieldset>
+ <legend>
+ <?= _('Geschlecht') ?>
+ </legend>
+
+ <? foreach ($genders as $index => $gender): ?>
+ <label>
+ <input type="radio" name="geschlecht" value="<?= $index ?>"
+ <? if ($user['geschlecht'] == $index) echo 'checked'; ?>
+ <? if (!$controller->shallChange('user_info.geschlecht', 'gender')) echo 'disabled'; ?>>
+ <?= htmlReady($gender) ?>
+ </label>
+ <? endforeach; ?>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+</form>
diff --git a/app/views/settings/account/logout.php b/app/views/settings/account/logout.php
new file mode 100644
index 0000000..ebe089f
--- /dev/null
+++ b/app/views/settings/account/logout.php
@@ -0,0 +1,5 @@
+<h1 class="table_header_bold">
+ <?= _('Daten geändert!') ?>
+</h1>
+
+<?= MessageBox::info(sprintf(_("Um eine korrekte Authentifizierung mit Ihren neuen Daten sicherzustellen, wurden Sie automatisch ausgeloggt.<br>Wenn Sie Ihre E-Mail-Adresse geändert haben, müssen Sie das Ihnen an diese Adresse zugesandte Passwort verwenden!<br><br>Ihr aktueller Benutzername ist: %s"), '<b>'. htmlReady($username). '</b>'). '<br>---&gt; <a href="' . URLHelper::getLink('index.php?again=yes') . '">' . _("Login") . '</a> &lt;---') ?>
diff --git a/app/views/settings/calendar.php b/app/views/settings/calendar.php
new file mode 100644
index 0000000..e218601
--- /dev/null
+++ b/app/views/settings/calendar.php
@@ -0,0 +1,159 @@
+<?
+use Studip\Button, Studip\LinkButton;
+
+$cal_views = [
+ 'day' => _('Tagesansicht'),
+ 'week' => _('Wochenansicht'),
+ 'month' => _('Monatsansicht'),
+ 'year' => _('Jahresansicht'),
+];
+$cal_deletes = [
+ 12 => _('12 Monate nach Ablauf'),
+ 6 => _('6 Monate nach Ablauf'),
+ 3 => _('3 Monate nach Ablauf'),
+ 0 => _('nie'),
+];
+$cal_step_days = [
+ 600 => _('10 Minuten'),
+ 900 => _('15 Minuten'),
+ 1800 => _('30 Minuten'),
+ 3600 => _('1 Stunde'),
+ 7200 => _('2 Stunden'),
+];
+$cal_step_weeks = [
+ 1800 => _('30 Minuten'),
+ 3600 => _('1 Stunde'),
+ 7200 => _('2 Stunden'),
+];
+?>
+
+<form method="post" action="<?= $controller->url_for('settings/calendar/store') ?>" class="default">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Einstellungen des Terminkalenders') ?>
+ </legend>
+
+ <label>
+ <?= _('Startansicht') ?>
+ <select name="cal_view" id="cal_view" size="1">
+ <? foreach ($cal_views as $index => $label): ?>
+ <option value="<?= $index ?>" <? if ($view == $index) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Wochenansicht') ?>
+ <select name="cal_type_week">
+ <option value="LONG"<?= $type_week == 'LONG' ? ' selected' : "" ?>>
+ <?= _('7 Tage-Woche') ?>
+ </option>
+ <option value="SHORT"<?= $type_week == 'SHORT' ? ' selected' : "" ?>>
+ <?= _('5 Tage-Woche') ?>
+ </option>
+ </select>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Einzelterminkalender') ?>
+ </legend>
+
+ <div>
+ <?= _('Zeitraum der Tages- und Wochenansicht') ?>
+ <section class="hgroup">
+ <label>
+ <?= _("Von") ?>
+ <select name="cal_start" aria-label="<?= _('Startzeit der Tages- und Wochenansicht') ?>" class="size-s">
+ <? for ($i = 0; $i < 24; $i += 1): ?>
+ <option value="<?= $i ?>" <? if ($start == $i) echo 'selected'; ?>>
+ <?= sprintf('%02u:00', $i) ?>
+ </option>
+ <? endfor; ?>
+ </select>
+ <?= _("Uhr") ?>
+ </label>
+
+ <label>
+ <?= _("Bis") ?>
+ <select name="cal_end" aria-label="<?= _('Endzeit der Tages- und Wochenansicht') ?>" class="size-s">
+ <? for ($i = 0; $i < 24; $i += 1): ?>
+ <option value="<?= $i ?>" <? if ($end == $i) echo 'selected'; ?>>
+ <?= sprintf('%02u:00', $i) ?>
+ </option>
+ <? endfor; ?>
+ </select>
+ <?= _("Uhr") ?>.
+ </label>
+ </section>
+ </div>
+
+ <label>
+ <?= _('Zeitintervall der Tagesansicht') ?>
+ <select name="cal_step_day" for="cal_step_day">
+ <? foreach ($cal_step_days as $index => $label): ?>
+ <option value="<?= $index ?>" <? if ($step_day == $index) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Zeitintervall der Wochenansicht') ?>
+ <select name="cal_step_week" id="cal_step_week">
+ <? foreach ($cal_step_weeks as $index => $label): ?>
+ <option value="<?= $index ?>" <? if ($step_week == $index) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ </fieldset>
+
+ <? if (Config::get()->CALENDAR_GROUP_ENABLE): ?>
+ <fieldset>
+ <legend>
+ <?= _('Gruppenterminkalender') ?>
+ </legend>
+
+ <label>
+ <?= _("Zeitintervall der Tagesansicht") ?>
+ <select name="cal_step_day_group" id="cal_step_day_group">
+ <? foreach ($cal_step_days as $index => $label): ?>
+ <option value="<?= $index ?>" <? if ($step_day_group == $index) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Zeitintervall der Wochenansicht') ?>
+ <select name="cal_step_week_group" id="cal_step_week_group">
+ <? foreach ($cal_step_weeks as $index => $label): ?>
+ <option value="<?= $index ?>" <? if ($step_week_group == $index) echo 'selected'; ?>>
+ <?= $label ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ </fieldset>
+ <? endif ?>
+
+ <footer>
+ <? if (Request::option('atime')): ?>
+ <input type="hidden" name="atime" value="<?= Request::option('atime') ?>">
+ <? endif ?>
+ <input type="hidden" name="view" value="calendar">
+ <?= Button::createAccept(_('Übernehmen'), ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+</form>
diff --git a/app/views/settings/categories.php b/app/views/settings/categories.php
new file mode 100644
index 0000000..663b54f
--- /dev/null
+++ b/app/views/settings/categories.php
@@ -0,0 +1,80 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<? if (count($categories) === 0): ?>
+<p class="info"><?= _('Es existieren zur Zeit keine eigenen Kategorien.') ?></p>
+<? else: ?>
+<form action="<?= $controller->url_for('settings/categories/store') ?>" method="post" name="main_content" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+
+ <? foreach ($categories as $index => $category): ?>
+ <fieldset>
+ <legend><?= htmlReady($category->name) ?></legend>
+
+ <table style="width: 100%">
+ <colgroup>
+ <col>
+ <col width="100px">
+ </colgroup>
+ <tbody>
+ <tr>
+ <td>
+ <div>
+ (<?= $visibilities[$category->id] ?>)
+ </div>
+
+ <label>
+ <?= _('Name') ?>
+ <input required type="text" name="categories[<?= $category->id ?>][name]" id="name<?= $index ?>"
+ aria-label="<?= _('Name der Kategorie') ?>" style="width: 100%"
+ value="<?= htmlReady($category->name) ?>">
+ </label>
+
+ <label>
+ <?= _('Inhalt') ?>
+
+ <textarea id="content<?= $index ?>" name="categories[<?= $category->id ?>][content]"
+ class="resizable add_toolbar wysiwyg size-l" style="width: 100%; height: 200px;"
+ aria-label="<?= _('Inhalt der Kategorie:') ?>"
+ ><?= wysiwygReady($category->content) ?></textarea>
+ </label>
+ </td>
+ <td style="vertical-align: top">
+ <? if ($index > 0): ?>
+ <a href="<?= $controller->url_for('settings/categories/swap', $category->id, $last->id) ?>">
+ <?= Icon::create('arr_2up', 'sort')->asImg(['class' => 'text-top', 'title' =>_('Kategorie nach oben verschieben')]) ?>
+ </a>
+ <? else: ?>
+ <?= Icon::create('arr_2up', 'inactive')->asImg(['class' => 'text-top']) ?>
+ <? endif; ?>
+
+ <? if ($index < $count - 1): ?>
+ <a href="<?= $controller->url_for('settings/categories/swap', $category->id, $categories[$index + 1]->id) ?>">
+ <?= Icon::create('arr_2down', 'sort')->asImg(['class' => 'text-top', 'title' =>_('Kategorie nach unten verschieben')]) ?>
+ </a>
+ <? else: ?>
+ <?= Icon::create('arr_2down', 'inactive')->asImg(['class' => 'text-top']) ?>
+ <? endif; ?>
+
+ <a href="<?= $controller->url_for('settings/categories/delete', $category->id) ?>">
+ <?= Icon::create('trash')->asImg(['class' => 'text-top', 'title' => _('Kategorie löschen')]) ?>
+ </a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ <? $last = $category;
+ endforeach; ?>
+
+ <? if ($hidden_count > 0): ?>
+ <?= sprintf(ngettext('Es existiert zusätzlich eine Kategorie, die Sie nicht einsehen und bearbeiten können.',
+ 'Es existiereren zusätzlich %s Kategorien, die Sie nicht einsehen und bearbeiten können.',
+ $hidden_count), $hidden_count) ?>
+ <? endif; ?>
+
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store') ?>
+ </footer>
+</form>
+<? endif; ?>
diff --git a/app/views/settings/deputies.php b/app/views/settings/deputies.php
new file mode 100644
index 0000000..606b9fd
--- /dev/null
+++ b/app/views/settings/deputies.php
@@ -0,0 +1,68 @@
+<? if ($deputies && count($deputies)): ?>
+ <form method="post" action="<?= $controller->link_for('settings/deputies/store') ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default no-hover">
+ <colgroup>
+ <col>
+ <? if ($edit_about_enabled): ?>
+ <col style="width: 200px">
+ <? endif ?>
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Nutzer'); ?></th>
+ <? if ($edit_about_enabled): ?>
+ <th><?= _('darf mein Profil bearbeiten'); ?></th>
+ <? endif ?>
+ <th class="actions"><?= _('Aktion'); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($deputies as $deputy): ?>
+ <? $deputy_fullname = $deputy->getDeputyFullname() ?>
+ <tr>
+ <td>
+ <?= Avatar::getAvatar($deputy->user_id)->getImageTag(Avatar::SMALL) ?>
+ <?= htmlReady($deputy_fullname . ' (' . $deputy->username . ', ' . _('Status') . ': ' . $deputy->perms . ')') ?>
+ </td>
+ <? if ($edit_about_enabled): ?>
+ <td style="text-align: center">
+ <div class="hgroup">
+ <label>
+ <input type="radio" name="edit_about[<?= $deputy->user_id ?>]" value="1"
+ <? if ($deputy->edit_about) echo 'checked'; ?>>
+ <?= _('ja') ?>
+ </label>
+
+ <label>
+ <input type="radio" name="edit_about[<?= $deputy->user_id ?>]" value="0"
+ <? if (!$deputy->edit_about) echo 'checked'; ?>>
+ <?= _('nein') ?>
+ </label>
+ </div>
+ </td>
+ <? endif ?>
+ <td class="actions">
+ <?= Icon::create('trash')->asInput(
+ [
+ 'formaction' => $controller->deleteURL($deputy),
+ 'data-confirm' => _('Wollen Sie die Standardvertretung wirklich löschen?')
+ ]
+ ) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="<?= 2 + (int)$edit_about_enabled ?>">
+ <?= Studip\Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen speichern')]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </form>
+<? else: ?>
+ <?= MessageBox::info(_('Sie haben noch niemanden als Ihre Standardvertretung eingetragen. Benutzen Sie die Aktion in der Sidebar, um dies zu tun.')); ?>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/settings/details.php b/app/views/settings/details.php
new file mode 100644
index 0000000..2b5174e
--- /dev/null
+++ b/app/views/settings/details.php
@@ -0,0 +1,109 @@
+<? use Studip\Button; ?>
+
+<? if ($locked_info): ?>
+ <?= MessageBox::info(formatLinks($locked_info)) ?>
+<? endif; ?>
+
+<form id="edit_private" action="<?= $controller->url_for('settings/details/store') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <fieldset>
+ <legend><?= _('Lebenslauf bearbeiten') ?></legend>
+ <label>
+ <?= _('Telefon Festnetz (privat)') ?>
+ <input type="tel" name="telefon" class="size-m"
+ value="<?= htmlReady($user->privatnr) ?>"
+ <? if (!$controller->shallChange('user_info.privatnr')) echo 'disabled'; ?>>
+ </label>
+ <label>
+ <?= _('Mobiltelefon (privat)') ?>
+ <input type="tel" name="cell" class="size-m"
+ value="<?= htmlReady($user->privatcell) ?>"
+ <? if (!$controller->shallChange('user_info.privatcell')) echo 'disabled'; ?>>
+ </label>
+ <label for="private_address">
+ <?= _('Adresse (privat)') ?>
+ <input type="text" name="anschrift" id="private_address"
+ value="<?= htmlReady($user->privadr) ?>"
+ <? if (!$controller->shallChange('user_info.privadr')) echo 'disabled'; ?>>
+ </label>
+ <? if (Config::get()->ENABLE_SKYPE_INFO): ?>
+ <label>
+ <?= _('Skype Name') ?>
+ <input type="text" name="skype_name"
+ value="<?= htmlReady($config->SKYPE_NAME) ?>">
+ </label>
+ <? endif; ?>
+ <label>
+ <?= _('Motto') ?>
+ <input type="text" name="motto" id="motto"
+ value="<?= htmlReady($user->motto) ?>"
+ <? if (!$controller->shallChange('user_info.motto')) echo 'disabled'; ?>>
+ </label>
+ <label>
+ <?= _('Homepage') ?>
+ <input type="url" name="home" id="homepage"
+ value="<?= htmlReady($user->Home) ?>"
+ <? if (!$controller->shallChange('user_info.Home')) echo 'disabled'; ?>>
+ </label>
+ <label>
+ <?= _('Hobbys') ?>
+ <?= I18N::textarea('hobby', $user->hobby, ['class' => 'add_toolbar wysiwyg'] + (!$controller->shallChange('user_info.hobby') ? ['disabled' => true] : [])) ?>
+ </label>
+ <a name="lebenslauf"></a>
+ <label>
+ <?= _('Lebenslauf') ?>
+ <?= I18N::textarea('lebenslauf', $user->lebenslauf, ['class' => 'add_toolbar wysiwyg'] + (!$controller->shallChange('user_info.lebenslauf') ? ['disabled' => true] : [])) ?>
+ </label>
+ <? if ($is_dozent): ?>
+ <a name="schwerpunkte"></a>
+ <label>
+ <?= _('Schwerpunkte') ?>
+ <?= I18N::textarea('schwerp', $user->schwerp, ['class' => 'add_toolbar wysiwyg'] + (!$controller->shallChange('user_info.schwerp') ? ['disabled' => true] : [])) ?>
+ <a name="publikationen"></a>
+ <label>
+ <?= _('Publikationen') ?>
+ <?= I18N::textarea('publi', $user->publi, ['class' => 'add_toolbar wysiwyg'] + (!$controller->shallChange('user_info.publi') ? ['disabled' => true] : [])) ?>
+ </label>
+ <? endif; ?>
+ <? if (Config::get()->OERCAMPUS_ENABLED) : ?>
+ <label>
+ <?= _('Beschreibung auf dem OER Campus') ?>
+ <textarea name="oercampus_description"><?= htmlReady($user->oercampus_description) ?></textarea>
+ </label>
+ <? endif ?>
+ </fieldset>
+
+ <? if (count($user_entries) > 0): ?>
+ <fieldset>
+ <legend> <?= _('Zusätzliche Datenfelder') ?></legend>
+ <? foreach ($user_entries as $id => $entry): ?>
+
+ <? if (isset($invalid_entries[$id])): ?>
+
+ <? $entry = $invalid_entries[$id]; // Exchange entry ?>
+ <? else: ?>
+ <? endif; ?>
+
+ <? if ($entry->isEditable() && !LockRules::check($user->user_id, $entry->getId())): ?>
+ <?= $entry->getHTML('datafields', [
+ 'tooltip' => $entry->isVisible($user->perms) ? '' : _('Systemfeld (für die Person selbst nicht sichtbar)'),
+ 'important' => true
+ ]) ?>
+ <? else: ?>
+ <?= htmlReady($entry->getName()) ?>
+
+ <div>
+ <?= formatReady($entry->getDisplayValue(false)) ?>
+
+ <small> <?= _('(Das Feld ist für die Bearbeitung gesperrt und kann '
+ . 'nur durch einen Administrator verändert werden.)') ?></small>
+ </div>
+ <? endif; ?>
+ <? endforeach; ?>
+ </fieldset>
+ <? endif; ?>
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+</form>
diff --git a/app/views/settings/general.php b/app/views/settings/general.php
new file mode 100644
index 0000000..4bf2fc3
--- /dev/null
+++ b/app/views/settings/general.php
@@ -0,0 +1,148 @@
+<?php
+$start_pages = [
+ '' => _('keine'),
+ 1 => _('Meine Veranstaltungen'),
+ 3 => _('Mein Stundenplan'),
+ 5 => _('Mein Terminkalender'),
+ 4 => _('Mein Adressbuch'),
+ 6 => _('Mein globaler Blubberstream'),
+ 7 => _('Mein Arbeitsplatz'),
+];
+?>
+
+<form method="post" action="<?= $controller->url_for('settings/general/store') ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+
+ <fieldset>
+ <legend><?= _('Allgemeine Einstellungen') ?></legend>
+
+ <label>
+ <?= _('Sprache') ?>
+ <select name="forced_language" class="size-s">
+ <? foreach ($GLOBALS['INSTALLED_LANGUAGES'] as $key => $language): ?>
+ <option value="<?= $key ?>"
+ <? if ($user_language == $key) echo 'selected'; ?>>
+ <?= $language['name'] ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <? if (!$GLOBALS['perm']->have_perm('root')): ?>
+ <label>
+ <?= _('Persönliche Startseite') ?>
+ <?= tooltipHtmlIcon(_('Sie können hier einstellen, welche Seite standardmäßig nach dem Einloggen '
+ .'angezeigt wird. Wenn Sie zum Beispiel regelmäßig die Seite &raquo;Meine '
+ .'Veranstaltungen&laquo; nach dem Login aufrufen, so können Sie dies hier '
+ .'direkt einstellen.')) ?>
+ <select name="personal_startpage">
+ <? foreach ($start_pages as $index => $label): ?>
+ <option value="<?= $index ?>" <? if ($config->PERSONAL_STARTPAGE == $index) echo 'selected'; ?>>
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif ?>
+
+ <label>
+ <input type="checkbox" name="skiplinks_enable"
+ value="1"
+ <? if ($config->SKIPLINKS_ENABLE) echo 'checked'; ?>>
+ <?= _('Skiplinks einblenden') ?>
+ <?= tooltipIcon(_('Mit dieser Einstellung wird nach dem ersten Drücken der Tab-Taste eine '
+ .'Liste mit Skiplinks eingeblendet, mit deren Hilfe Sie mit der Tastatur '
+ .'schneller zu den Hauptinhaltsbereichen der Seite navigieren können. '
+ .'Zusätzlich wird der aktive Bereich einer Seite hervorgehoben.')) ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="accesskey_enable"
+ aria-describedby="accesskey_enable_description" value="1"
+ <? if ($config->ACCESSKEY_ENABLE) echo 'checked'; ?>>
+ <?= _('Tastenkombinationen für Hauptfunktionen') ?>
+ <?= tooltipHtmlIcon(_('Mit dieser Einstellung können Sie für die meisten in der Kopfzeile '
+ .'erreichbaren Hauptfunktionen eine Bedienung über Tastenkombinationen '
+ .'aktivieren. <br>Die Tastenkombination wird im Tooltip des jeweiligen '
+ .'Icons angezeigt.')." "._('Diese kann für jeden Browser und jedes Betriebssystem unterschiedlich '
+ .'sein (siehe <a href="http://en.wikipedia.org/wiki/Accesskey" '
+ .'target="_blank" rel="noopener noreferrer">Wikipedia</a>).')) ?>
+ </label>
+
+ <label>
+ <input type="checkbox"
+ name="showsem_enable"
+ value="1"
+ <? if ($config->SHOWSEM_ENABLE) echo 'checked'; ?>>
+ <?= _('Semesteranzeige auf &raquo;Meine Veranstaltungen&laquo;');?>
+ <?= tooltipHtmlIcon(_('Mit dieser Einstellung können Sie auf der Seite &raquo;Meine '
+ .'Veranstaltungen&laquo; die Einblendung des Start- und Endsemesters '
+ .'hinter jeder Veranstaltung aktivieren.')) ?>
+ </label>
+
+ <? if (Config::get()->TOURS_ENABLE) : ?>
+ <label>
+ <input type="checkbox" name="tour_autostart_disable"
+ aria-describedby="tour_autostart_disable_description" value="1"
+ <? if ($config->TOUR_AUTOSTART_DISABLE) echo 'checked'; ?>>
+ <?= _('Autostart von Touren verhindern');?>
+ <?= tooltipIcon(_('Mit dieser Einstellung können Sie verhindern, dass Touren zu einzelnen '
+ .'Stud.IP-Seiten automatisch starten, wenn Sie die Seite aufrufen. Die Touren '
+ .'können weiterhin über die Hilfe gestartet werden.')) ?>
+ </label>
+ <? endif ?>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Benachrichtigungen') ?></legend>
+
+ <label>
+ <input type="checkbox" name="personal_notifications_activated"
+ aria-describedby="personal_notifications_activated_description" value="1"
+ <? if (PersonalNotifications::isActivated($user->user_id)) echo 'checked'; ?>>
+ <?= _('Benachrichtigungen über Javascript') ?>
+ <?= tooltipIcon(_('Hiermit wird in der Kopfzeile dargestellt, wenn es Benachrichtigungen für '
+ .'Sie gibt. Die Benachrichtigungen werden auch angezeigt, wenn Sie nicht die '
+ .'Seite neuladen.')) ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="personal_notifications_audio_activated"
+ aria-describedby="personal_notifications_audio_activated_description" value="1"
+ <? if (PersonalNotifications::isAudioActivated($user->user_id)) echo 'checked'; ?>>
+ <?= _('Audio-Feedback zu Benachrichtigungen') ?>
+ <?= tooltipIcon(_('Wenn eine neue Benachrichtigung für Sie reinkommt, ' .
+ 'werden Sie mittels eines kleinen Plopps darüber in Kenntnis gesetzt ' .
+ '- auch wenn Sie gerade einen anderen Browsertab anschauen. Der Plopp ist ' .
+ 'nur zu hören, wenn Sie die Benachrichtigungen über Javascript aktiviert haben.')) ?>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Wiki') ?></legend>
+
+ <label>
+ <input type="checkbox" name="wiki_comments_enable" value="1"
+ <? if ($config->WIKI_COMMENTS_ENABLE) echo 'checked'; ?>>
+ <?= _('Wiki-Kommentare einblenden') ?>
+ <?= tooltipIcon(_('Mit dieser Einstellung werden auf Wiki-Seiten die Kommentare eingeblendet'
+ .' und nicht mehr nur als Icon angezeigt.')) ?>
+ </label>
+ </fieldset>
+
+<? if (Config::get()->WYSIWYG): ?>
+ <fieldset>
+ <legend><?= _('WYSIWYG-Editor') ?></legend>
+
+ <label>
+ <input type="checkbox" name="wysiwyg_enabled" value="1"
+ <? if (!$config->WYSIWYG_DISABLED) echo 'checked'; ?>>
+ <?= _('WYSIWYG-Editor aktivieren') ?>
+ </fieldset>
+<? endif; ?>
+
+ <footer>
+ <?= \Studip\Button::create(_("Speichern")) ?>
+ </footer>
+</form>
diff --git a/app/views/settings/messaging.php b/app/views/settings/messaging.php
new file mode 100644
index 0000000..028d9f8
--- /dev/null
+++ b/app/views/settings/messaging.php
@@ -0,0 +1,122 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<?
+ $send_as_email = [
+ 1 => _('nie'),
+ 2 => _('immer'),
+ 3 => _('wenn vom Absender gewünscht'),
+ ];
+ $mail_formats = [
+ 0 => _('Text'),
+ 1 => _('HTML'),
+ ];
+?>
+
+<form action="<?= $controller->url_for('settings/messaging') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+
+ <fieldset>
+ <legend>
+ <?= _('Einstellungen des Nachrichtensystems') ?>
+ </legend>
+
+ <label>
+ <input type="checkbox" value="1" name="save_snd" id="save_snd"
+ <? if ($settings['save_snd'] == 1) echo 'checked'; ?>>
+ <?= _('Gesendete Nachrichten im Postausgang speichern') ?>
+ </label>
+
+ <? if ($GLOBALS['MESSAGING_FORWARD_AS_EMAIL']): ?>
+ <label>
+ <input type="checkbox" value="1" name="request_mail_forward" id="request_mail_forward"
+ <? if ($settings['request_mail_forward'] == 1) echo 'checked'; ?>>
+ <?= _('Gesendete Nachrichten auch als E-Mail verschicken') ?>
+ </label>
+ <? endif ?>
+
+ <? if (Config::get()->SHOW_ADRESSEES_LIMIT): ?>
+ <label>
+ <input type="checkbox" value="1" name="show_adressees" id="show_adressees"
+ <? if ($settings['show_adressees'] == 1) echo 'checked'; ?>>
+ <?= _('Adressaten für die Empfänger sichtbar machen') ?>
+ </label>
+ <? endif ?>
+
+ <label>
+ <input type="checkbox" value="1" name="logout_markreaded" id="logout_markreaded"
+ <? if ($settings['logout_markreaded'] == 1) echo 'checked'; ?>>
+ <?= _('Beim Logout alle Nachrichten als gelesen speichern') ?>
+ </label>
+
+ <? if ($GLOBALS['MESSAGING_FORWARD_AS_EMAIL']): ?>
+ <label>
+ <?= _('Kopie empfangener Nachrichten an eigene E-Mail-Adresse schicken') ?>
+ <select name="send_as_email">
+ <? foreach ($send_as_email as $key => $label): ?>
+ <option value="<?= htmlReady($key) ?>" <? if (($user->email_forward ?: $GLOBALS['MESSAGING_FORWARD_DEFAULT']) == $key) echo 'selected' ?>>
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('E-Mail in folgendem Format versenden') ?>
+ <select name="mail_format">
+ <? foreach ($mail_formats as $key => $label): ?>
+ <option value="<?= htmlReady($key) ?>" <? if ($config->getValue('MAIL_AS_HTML') == $key) echo 'selected' ?>>
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif ?>
+
+ <div>
+ <? if ($user->smsforward_rec): // empfaenger ausgewaehlt ?>
+ <?= _('Empfänger') ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile?username=' . get_username($user->smsforward_rec)) ?>">
+ <?= Avatar::getAvatar($user->smsforward_rec)->getImageTag(Avatar::SMALL) ?>
+ <?= get_fullname($user->smsforward_rec, 'full', true) ?>
+ </a>
+ <a href="<?= $controller->url_for('settings/messaging/verify/forward_receiver') ?>">
+ <?= Icon::create('trash', 'clickable')->asImg() ?>
+ </a>
+ <br>
+ <label>
+ <input type="checkbox" value="1" name="smsforward_copy"
+ <? if ($user->smsforward_copy) echo 'checked'; ?>>
+ <?= _('Kopie im persönlichen Posteingang speichern.') ?>
+ </label>
+ <? else: ?>
+ <label>
+ <?= _('Weiterleitung empfangener Nachrichten') ?>
+ <?= QuickSearch::get('new_smsforward_rec', new StandardSearch('username'))->withButton()->render() ?>
+ </label>
+ <? endif; ?>
+ </div>
+
+ <label style="clear:both;">
+ <?= _('Signatur') ?>
+ <textarea name="sms_sig" aria-label="<?= _('Signatur') ?>"><?= htmlready($settings['sms_sig']) ?></textarea>
+ </label>
+
+ <label>
+ <?= _('Buddies/ Wer ist online?') ?>
+ <select name="online_format">
+ <? foreach ($GLOBALS['NAME_FORMAT_DESC'] as $key => $value): ?>
+ <option value="<?= $key ?>" <? if ($config->getValue('ONLINE_NAME_FORMAT') == $key) echo 'selected '; ?>>
+ <?= htmlReady($value) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+
+ <footer>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <?= LinkButton::create(_('Zurücksetzen'), $controller->url_for('settings/messaging/verify/reset'), ['title' => _('Einstellungen zurücksetzen')]) ?>
+ </footer>
+</form>
diff --git a/app/views/settings/notification.php b/app/views/settings/notification.php
new file mode 100644
index 0000000..8d84579
--- /dev/null
+++ b/app/views/settings/notification.php
@@ -0,0 +1,98 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<form method="post" action="<?= $controller->url_for('settings/notification/store') ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+
+ <table class="default" id="settings-notifications">
+ <colgroup>
+ <col width="7px">
+ <col width="100%">
+ <? for ($i = 0; $i < count($modules); $i += 1): ?>
+ <col width="20px">
+ <? endfor; ?>
+ </colgroup>
+ <thead>
+ <tr>
+ <th colspan="2"><?= _('Veranstaltung') ?></th>
+ <? foreach ($modules as $id => $module): ?>
+ <?php $icon = $module['icon']->copyWithRole(Icon::ROLE_INFO); ?>
+ <th>
+ <?=$icon->asImg(['class' => 'middle', 'title' => $module['name']]) ?>
+ </th>
+ <? endforeach; ?>
+ <th><?= _('Alle') ?></th>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <?= _('Benachrichtigung für unten aufgeführte Veranstaltungen:') ?>
+ </td>
+ <? for ($i = 0; $i < count($modules); $i += 1): ?>
+ <td>
+ <input type="checkbox" name="all[columns][]" value="<?= $i ?>"
+ <? if (!empty($checked) && count(array_filter($checked, function ($item) use ($i) { return $item[$i]; })) == count($checked)) echo 'checked'; ?>>
+ </td>
+ <? endfor; ?>
+ <td>
+ <input type="checkbox" name="all[all]" value="all"
+ <? if (!empty($checked) && count(array_filter($checked, function ($item) { return $item['all']; })) == count($checked)) echo 'checked'; ?>>
+
+ </td>
+ </tr>
+ </thead>
+ <? foreach ($groups as $id => $members): ?>
+ <tbody>
+ <? if ($group_field !== 'not_grouped'): ?>
+ <tr>
+ <th colspan="<?= 3 + count($modules) ?>">
+ <? if (isset($open[$id])): ?>
+ <a class="tree" style="font-weight:bold" name="<?= $id ?>"
+ href="<?= $controller->url_for('settings/notification/close', $id) ?>#<?= $id ?>"
+ <?= tooltip(_('Gruppierung schließen'), true) ?>>
+ <?= Icon::create('arr_1down', 'clickable')->asImg() ?>
+ <? else: ?>
+ <a class="tree" name="<?= $id ?>"
+ href="<?= $controller->url_for('settings/notification/open', $id) ?>#<?= $id ?>"
+ <?= tooltip(_('Gruppierung öffnen'), true) ?>>
+ <?= Icon::create('arr_1right', 'clickable')->asImg() ?>
+ <? endif; ?>
+ <?= htmlReady(my_substr(implode(' &gt; ', (array)$group_names[$id]), 0, 70)) ?>
+ </a>
+ </th>
+ </tr>
+ <? endif; ?>
+ <? if ($id === 'not_grouped' || isset($open[$id])): ?>
+ <? foreach ($members as $member): ?>
+ <tr>
+ <td class="gruppe<?= $seminars[$member['seminar_id']]['gruppe'] ?>">&nbsp;</td>
+ <td>
+ <a href="<?= URLHelper::getLink('seminar_main.php', ['auswahl' => $member['seminar_id']]) ?>">
+ <?= Config::get()->IMPORTANT_SEMNUMBER ? htmlReady($seminars[$member['seminar_id']]['sem_nr']) : '' ?>
+ <?= htmlReady(my_substr($seminars[$member['seminar_id']]['name'], 0, 70)) ?>
+ </a>
+ <? if (!$seminars[$member['seminar_id']]['visible']): ?>
+ <?= _('(versteckt)') ?>
+ <? endif; ?>
+ <input type="hidden" name="m_checked[<?= $member['seminar_id'] ?>][empty]" value="0">
+ </td>
+ <? foreach ($modules as $index => $data): ?>
+ <td>
+ <input type="checkbox" name="m_checked[<?= $member['seminar_id'] ?>][<?= $index ?>]"
+ value="1"
+ <? if ($checked[$member['seminar_id']][$index]) echo 'checked'; ?>>
+ </td>
+ <? endforeach; ?>
+ <td>
+ <input type="checkbox" name="all[rows][]" value="<?= $member['seminar_id'] ?>"
+ <? if (isset($checked[$member['seminar_id']]) && count(array_filter($checked[$member['seminar_id']])) == count($modules) + 1) echo 'checked'; ?>>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+ </table>
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <?= LinkButton::create(_('Abbrechen'), $controller->url_for('settings/notification')) ?>
+ </footer>
+</form>
diff --git a/app/views/settings/password.php b/app/views/settings/password.php
new file mode 100644
index 0000000..ab423f7
--- /dev/null
+++ b/app/views/settings/password.php
@@ -0,0 +1,28 @@
+<? use Studip\Button; ?>
+
+<form id="edit_password" method="post" action="<?= $controller->url_for('settings/password/store') ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <fieldset>
+ <legend>
+ <?= _('Passwort ändern') ?>
+ </legend>
+ <label>
+ <span class="required"><?= _('Aktuelles Passwort') ?></span>
+ <input required type="password" id="password" name="password">
+ </label>
+ <label>
+ <span class="required"><?= _('Neues Passwort') ?></span>
+ <input required type="password" pattern=".{8,}"
+ id="new_password" name="new_password"
+ data-message="<?= _('Das Passwort ist zu kurz. Es sollte mindestens 8 Zeichen lang sein.') ?>">
+ </label>
+ <label>
+ <span class="required"><?= _('Passwort bestätigen') ?></span>
+ <input required type="password" pattern=".{8,}"
+ id="new_password_confirm" name="new_password_confirm"
+ data-must-equal="#new_password">
+ </label>
+ </fieldset>
+ <footer><?= Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?></footer>
+</form>
diff --git a/app/views/settings/privacy.php b/app/views/settings/privacy.php
new file mode 100644
index 0000000..64bf97f
--- /dev/null
+++ b/app/views/settings/privacy.php
@@ -0,0 +1,185 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<form method="post" action="<?= $controller->url_for('settings/privacy/global') ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Privatsphäre') ?>:
+ <?= _('Globale Einstellungen') ?>
+ </legend>
+
+ <label>
+ <?= _('Globale Sichtbarkeit') ?>
+ <?= tooltipIcon(_('Sie können wählen, ob Sie für andere NutzerInnen sichtbar sein '
+ . 'und alle Kommunikationsfunktionen von Stud.IP nutzen können '
+ . 'wollen, oder ob Sie unsichtbar sein möchten und dann nur '
+ . 'eingeschränkte Kommunikationsfunktionen nutzen können.')) ?>
+ <div>
+ <? if (!in_array($global_visibility, ['always', 'never'])
+ && ($user_perm !== 'dozent' || !Config::get()->DOZENT_ALWAYS_VISIBLE)
+ ):
+ // only show selection if visibility can be changed
+ ?>
+ <select name="global_visibility" aria-describedby="global_vis_description" id="global_vis">
+ <?php
+ if (count($user_domains)) {
+ printf("<option %s value=\"global\">" . _('sichtbar für alle Nutzer') . "</option>", $global_visibility === 'global' ? 'selected="selected"' : '');
+ $visible_text = _('sichtbar für eigene Nutzerdomäne');
+ } else {
+ $visible_text = _('sichtbar');
+ }
+ printf("<option %s value=\"yes\">" . $visible_text . "</option>", ($global_visibility == 'yes' || ($global_visibility === 'unknown' && Config::get()->USER_VISIBILITY_UNKNOWN)) ? 'selected' : '');
+ printf("<option %s value=\"no\">" . _("unsichtbar") . "</option>", ($global_visibility == 'no' || ($global_visibility === 'unknown' && !Config::get()->USER_VISIBILITY_UNKNOWN)) ? 'selected' : '');
+ ?>
+ </select>
+ <? else: ?>
+ <? if ($global_visibility === 'never'): ?>
+ <em><?= _('Ihre Kennung wurde von einem Administrator unsichtbar geschaltet.') ?></em>
+ <? elseif ($user_perm == 'dozent' && Config::get()->DOZENT_ALWAYS_VISIBLE): ?>
+ <em><?= _('Sie haben Lehrendenrechte und sind daher immer global sichtbar.') ?></em>
+ <? else: ?>
+ <em><?= _('Sie sind immer global sichtbar.') ?></em>
+ <? endif; ?>
+ <input type="hidden" name="global_visibility" value="<?= $global_visibility ?>">
+ <? endif; ?>
+ </div>
+ </label>
+
+ <? if ((in_array($global_visibility, ['yes', 'global']) ||
+ ($global_visibility === 'unknown' && Config::get()->USER_VISIBILITY_UNKNOWN) ||
+ ($user_perm === 'dozent' && Config::get()->DOZENT_ALWAYS_VISIBLE)) &&
+ (!$NOT_HIDEABLE_FIELDS[$user_perm]['online'] ||
+ !$NOT_HIDEABLE_FIELDS[$user_perm]['search'] ||
+ !$NOT_HIDEABLE_FIELDS[$user_perm]['email'])
+ ) : ?>
+ <div>
+ <?= _('Erweiterte Einstellungen') ?>
+ <?= tooltipIcon(
+ _('Stellen Sie hier ein, in welchen Bereichen des Systems Sie erscheinen wollen.')
+ . (!$NOT_HIDEABLE_FIELDS[$user_perm]['email']
+ ? _('Wenn Sie hier Ihre E-Mail-Adresse verstecken, wird stattdessen die E-Mail-Adresse Ihrer (Standard-)Einrichtung angezeigt.')
+ : '')
+ ) ?>
+
+ <? if (!$NOT_HIDEABLE_FIELDS[$user_perm]['online']): ?>
+ <label>
+ <input type="checkbox" name="online" value="1"
+ <? if ($online_visibility) echo 'checked'; ?>>
+ <?= _('sichtbar in "Wer ist online"') ?>
+ </label>
+ <? endif; ?>
+ <? if (!$NOT_HIDEABLE_FIELDS[$user_perm]['search']): ?>
+ <label>
+ <input type="checkbox" name="search" value="1"
+ <? if ($search_visibility) echo 'checked'; ?>>
+ <?= _('auffindbar über die Personensuche') ?>
+ </label>
+ <? endif; ?>
+ <? if (!$NOT_HIDEABLE_FIELDS[$user_perm]['email']): ?>
+ <label>
+ <input type="checkbox" name="email" value="1"
+ <? if ($email_visibility) echo 'checked'; ?>>
+ <?= _('eigene E-Mail Adresse sichtbar') ?>
+ </label>
+ <? endif; ?>
+ </div>
+ <? endif; ?>
+ </fieldset>
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen speichern')]) ?>
+ </footer>
+</form>
+
+<div style="margin-top: 50px;"></div>
+
+<form method="post" action="<?= $controller->url_for('settings/privacy/homepage') ?>" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studipticket" value="<?= get_ticket() ?>">
+
+ <fieldset>
+ <legend>
+ <?= _('Privatsphäre') ?>:
+ <?= _('Eigenes Profil') ?>
+ </legend>
+
+ <table class="default settings-privacy">
+ <thead>
+ <tr>
+ <th><?= _('Profil-Element'); ?></th>
+ <th class="hidden-tiny-down" style='text-align: center;' colspan="<?= $colCount++ ?>"><?= _('sichtbar für'); ?></th>
+ </tr>
+
+ <tr class="hidden-tiny-down">
+ <th style="background: white; width: 34%;">&nbsp;</th>
+ <? foreach ($visibilities as $visibility): ?>
+ <th style="background: white; width: <?= floor(66 / $colCount) ?>%;"><?= htmlReady($visibility) ?></th>
+ <? endforeach; ?>
+ </tr>
+ </thead>
+ <tbody class="privacy">
+ <? foreach ($homepage_elements['entry'] as $element): ?>
+ <? if ($element['is_header']): ?>
+ <tr class="visibility-homepage-elements-header">
+ <th colspan="<?= 1 + $colCount ?>">
+ <?= htmlReady($element['name']) ?>
+ </th>
+ </tr>
+ <? else: ?>
+ <tr>
+ <td class="visibility-homepage-element" style="padding-left: <?= $element['padding'] ?>">
+ <span class="visibility-homepage-element-name"><?= htmlReady($element['name']) ?></span>
+ <span class="hidden-small-up"><?= _('sichtbar für') ?></span>
+ </td>
+ <? if ($element['is_category']): ?>
+ <td colspan="<?= $colCount ?>"></td>
+ <? else: ?>
+ <? foreach ($homepage_elements['states'] as $index => $state): ?>
+ <td>
+ <label style="white-space: nowrap;">
+ <input type="radio"
+ name="visibility_update[<?= $element['id'] ?>]"
+ value="<?= $state ?>"
+ <? if ($element['state'] == $state) echo 'checked'; ?>>
+ <span class="hidden-small-up"><?= $visibilities[$index + 1] ?></span>
+ </label>
+ </td>
+ <? endforeach; ?>
+ <? endif; ?>
+ </tr>
+ <? endif; ?>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ <label>
+ <?= _('Neue Elemente') ?>
+ <select name="default">
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($visibilities as $visibility => $label): ?>
+ <option value="<?= $visibility ?>" <? if ($default_homepage_visibility == $visibility) echo 'selected'; ?>>
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Jetzt alle Sichtbarkeiten auf') ?>
+ <select name="all">
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($visibilities as $visibility => $label): ?>
+ <option value="<?= $visibility ?>">
+ <?= htmlReady($label) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen speichern')]) ?>
+ </footer>
+</form>
diff --git a/app/views/settings/statusgruppen/_optgroup.php b/app/views/settings/statusgruppen/_optgroup.php
new file mode 100644
index 0000000..2bd3be9
--- /dev/null
+++ b/app/views/settings/statusgruppen/_optgroup.php
@@ -0,0 +1,10 @@
+<? foreach ($data as $row):
+ if (!$row['groups']) continue;
+?>
+ <optgroup label="<?= htmlReady(mb_substr($row['Name'], 0, 70)) ?>">
+ <?= $this->render_partial('settings/statusgruppen/_options', ['data' => $row['groups']]) ?>
+ </optgroup>
+<? if ($row['sub']): ?>
+ <?= $this->render_partial('settings/statusgruppen/_optgroup', ['data' => $row['sub']]) ?>
+<? endif; ?>
+<? endforeach; ?>
diff --git a/app/views/settings/statusgruppen/_options.php b/app/views/settings/statusgruppen/_options.php
new file mode 100644
index 0000000..1115564
--- /dev/null
+++ b/app/views/settings/statusgruppen/_options.php
@@ -0,0 +1,17 @@
+<? if (!$data) return; ?>
+
+<? foreach ($data as $id => $row): ?>
+ <option value="<?= $id ?>" <? if ($row['user_there']) echo 'disabled'; ?>>
+ <? for ($i = 1; $i <= $level; $i++): ?>
+ &nbsp;&nbsp;
+ <? endfor; ?>
+ <?= mb_substr($row['role']->getName(), 0, 70) ?>
+ </option>
+<? if ($row['child']): ?>
+ <?= $this->render_partial('settings/statusgruppen/_options', [
+ 'data' => $row['child'],
+ 'level' => $level + 1,
+ ]) ?>
+<? endif; ?>
+
+<? endforeach; ?>
diff --git a/app/views/settings/statusgruppen/assign.php b/app/views/settings/statusgruppen/assign.php
new file mode 100644
index 0000000..36d52b0
--- /dev/null
+++ b/app/views/settings/statusgruppen/assign.php
@@ -0,0 +1,21 @@
+<form action="<?= $controller->link_for('settings/statusgruppen/assign') ?>" method="post" class="default">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Person einer Gruppe zuordnen') ?></legend>
+
+ <label>
+ <?= _('Einrichtung und Funktion auswählen') ?>:
+ <select required name="role_id" class="role-selector">
+ <option value="">-- <?= _('Bitte auswählen') ?> --</option>
+ <? if ($admin_insts && is_array($admin_insts)): ?>
+ <?= $this->render_partial('settings/statusgruppen/_optgroup', ['data' => $admin_insts]) ?>
+ <? endif; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::create(_('Zuweisen'), 'assign') ?>
+ </footer>
+</form>
diff --git a/app/views/settings/statusgruppen/index.php b/app/views/settings/statusgruppen/index.php
new file mode 100644
index 0000000..708bb89
--- /dev/null
+++ b/app/views/settings/statusgruppen/index.php
@@ -0,0 +1,110 @@
+<? if (count($institutes) === 0): ?>
+ <?= MessageBox::info(_('Sie sind keinem Institut / keiner Einrichtung zugeordnet!')); ?>
+<? else: ?>
+
+ <? $inst_count = 0; ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Zuordnungen zu Einrichtungen') ?></h1>
+ </header>
+ <? foreach ($institutes as $inst_id => $institute): ?>
+ <article class="<?= ContentBoxHelper::classes($inst_id) ?><? if (Request::get('type') == 'institute' && Request::get('open') == $role_id) : ?>open<? endif ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($inst_id) ?>">
+ <?= htmlReady($institute['name']) ?>
+ </a>
+ </h1>
+ <nav>
+ <? if (!$locked && $inst_count > 0) : ?>
+ <a href="<?= $controller->url_for('settings/statusgruppen/move', $inst_id, 'up') ?>">
+ <?= Icon::create('arr_2up', 'sort')->asImg() ?>
+ </a>
+ <? elseif (!$locked && count($institutes) > 1): ?>
+ <?= Icon::create('arr_2up', 'inactive')->asImg() ?>
+ <? endif; ?>
+
+ <? if (!$locked && $inst_count + 1 < count($institutes)): ?>
+ <a href="<?= $controller->url_for('settings/statusgruppen/move', $inst_id, 'down') ?>">
+ <?= Icon::create('arr_2down', 'sort')->asImg() ?>
+ </a>
+ <? elseif (!$locked && count($institutes) > 1): ?>
+ <?= Icon::create('arr_2down', 'inactive')->asImg() ?>
+ <? endif; ?>
+
+ <? if ($GLOBALS['perm']->have_studip_perm('admin', $inst_id)) : ?>
+ <a href="<?= URLHelper::getURL('dispatch.php/institute/members', ['cid' => $inst_id, 'admin_view' => 1]) ?>">
+ <?= Icon::create('link-intern', 'clickable', ['title' => _('Zur Einrichtung')])->asImg() ?>
+ </a>
+ <? else: ?>
+ <a href="<?= URLHelper::getURL('dispatch.php/institute/overview', ['auswahl' => $inst_id]) ?>">
+ <?= Icon::create('link-intern', 'clickable', ['title' => _('Zur Einrichtung')])->asImg() ?>
+ </a>
+ <? endif; ?>
+ </nav>
+ </header>
+ <section>
+ <article>
+ <?= $this->render_partial('settings/statusgruppen/modify_institute', [
+ 'followers' => count($institute['flattened']) > 0,
+ 'inst_id' => $inst_id,
+ 'institute' => $institute,
+ ]) ?>
+ </article>
+ </section>
+ </article>
+
+ <?
+ $inst_count += 1;
+ $role_count = 1;
+ $max_roles = count($institute['flattened']);
+ ?>
+ <? foreach ($institute['flattened'] as $role_id => $role): ?>
+ <article class="indented <?= ContentBoxHelper::classes($role_id) ?> <? if (Request::get('type') === 'role' && Request::get('open') == $role_id) : ?>open<? endif ?>">
+ <header>
+ <h1>
+ <? if (count($institute['datafields'][$role_id]) > 0): ?>
+ <a href="<?= ContentBoxHelper::href($role_id) ?>"
+ name="<?= $role_id ?>"
+ class="link <?= $open === $role_id ? 'open' : 'closed' ?>">
+ <?= htmlReady($role['name_long']) ?>
+ </a>
+ <? else: ?>
+ <a class="link" href="<?= ContentBoxHelper::href($role_id) ?>">
+ <?= htmlReady($role['name_long']) ?>
+ </a>
+ <? endif; ?>
+ </h1>
+ <nav>
+ <? if ($GLOBALS['perm']->have_studip_perm('admin', $inst_id) && !$locked) : ?>
+ <a href="<?= $controller->url_for('settings/statusgruppen/verify/delete/' . $role_id) ?>#<?= $role_id ?>">
+ <?= Icon::create('trash', 'clickable', ['title' => _('Löschen')])->asImg() ?>
+ </a>
+
+ <a href="<?= URLHelper::getURL('dispatch.php/admin/statusgroups', ['cid' => $inst_id]) ?>#group-<?= $role_id ?>">
+ <?= Icon::create('link-intern', 'clickable', ['title' => _('Zur Funktion')])->asImg() ?>
+ </a>
+ <? endif; ?>
+ </nav>
+ </header>
+ <section>
+ <?= $this->render_partial('settings/statusgruppen/modify', [
+ 'followers' => $role_count < $max_roles,
+ 'inst_id' => $inst_id,
+ 'role_id' => $role_id,
+ 'datafields' => $institute['datafields'][$role_id],
+ 'role' => $role['role'],
+ ]) ?>
+ </section>
+ </article>
+
+ <? $role_count += 1; ?>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ </section>
+
+ <? if ($GLOBALS['perm']->have_perm('admin') && !$locked): ?>
+ <?= $this->render_partial('settings/statusgruppen/assign', compact('subview_id', 'admin_insts', 'sub_admin_insts')) ?>
+ <? endif; ?>
+
+<? endif; ?>
diff --git a/app/views/settings/statusgruppen/modify.php b/app/views/settings/statusgruppen/modify.php
new file mode 100644
index 0000000..9c82ac1
--- /dev/null
+++ b/app/views/settings/statusgruppen/modify.php
@@ -0,0 +1,85 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<?
+$default_entries = DataFieldEntry::getDataFieldEntries([$user->user_id, $inst_id]);
+?>
+
+<form action="<?= $controller->url_for('settings/statusgruppen/store/role', $role_id) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <input type="hidden" name="name[<?= $inst_id ?>]" value="<?= htmlReady($institute['Name']) ?>">
+
+ <input type="hidden" name="role_id" value="<?= $role_id ?>">
+ <input type="hidden" name="group_id[]" value="<?= $role_id ?>">
+
+ <table class="default nohover">
+ <thead>
+ <tr>
+ <th colspan="2">
+ <?= _('Daten für diese Funktion') ?>
+ </th>
+ <th>
+ <?= _('Standarddaten') ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($datafields as $id => $entry): ?>
+ <tr>
+ <? if ($entry->isEditable() && ($entry->getValue() != 'default_value') && !$locked): ?>
+ <td>
+ <?= $entry->getHTML('datafields') ?>
+ </td>
+ <td style="text-align: right">
+ <a href="<?= $controller->url_for('settings/statusgruppen/default', $inst_id, $role_id, $id, true) ?>">
+ <?= Icon::create('checkbox-unchecked', 'clickable', ['title' => _('Diese Daten von den Standarddaten übernehmen')])->asImg(16, ["class" => 'text-top']) ?>
+ </a>
+ </td>
+ <? elseif ($entry->getValue() == 'default_value'): ?>
+ <td>
+ <?= $entry->getName() ?><br>
+ <?= $default_entries[$id]->getDisplayValue() ?>
+ </td>
+ <td style="text-align:right">
+ <? if ($entry->isEditable() && !$locked): ?>
+ <a href="<?= $controller->url_for('settings/statusgruppen/default', $inst_id, $role_id, $id, false) ?>"> <?= Icon::create('checkbox-checked', 'clickable', ['title' => _('Diese Daten NICHT von den Standarddaten übernehmen')])->asImg(16, ["class" => 'text-top']) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <? else: ?>
+ <td>
+ <?= $entry->getName() ?><br>
+ <?= $entry->getDisplayValue() ?>
+ </td>
+ <? endif; ?>
+ </td>
+ <td width="30%" class="left bordered"><?= $default_entries[$id]->getDisplayValue() ?></td>
+ </tr>
+ <? endforeach; ?>
+ <? if (!$locked): ?>
+ <tr>
+ <td colspan="2" style="text-align:right">
+ <?= _('Standarddaten übernehmen:') ?>
+ <a href="<?= $controller->url_for('settings/statusgruppen/defaults', $role_id, false) ?>">
+ <?= _('keine') ?>
+ </a>
+ /
+ <a href="<?= $controller->url_for('settings/statusgruppen/defaults', $role_id, true) ?>">
+ <?= _('alle') ?>
+ </a>
+ </td>
+ <td></td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? if (!$locked) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="3">
+ <?= Button::createAccept(_('Änderungen speichern'), 'store') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</form>
diff --git a/app/views/settings/statusgruppen/modify_institute.php b/app/views/settings/statusgruppen/modify_institute.php
new file mode 100644
index 0000000..769f897
--- /dev/null
+++ b/app/views/settings/statusgruppen/modify_institute.php
@@ -0,0 +1,85 @@
+<?
+use Studip\Button, Studip\LinkButton;
+
+// Datenfelder für Rollen in Einrichtungen ausgeben
+// Default-Daten der Einrichtung
+$entries = (array)DataFieldEntry::getDataFieldEntries([$user->user_id, $inst_id], 'userinstrole')
+?>
+
+<form action="<?= $controller->url_for('settings/statusgruppen/store/institute', $inst_id) ?>" method="post"
+ class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="name" value="<?= htmlReady($institute['name']) ?>">
+
+ <label>
+ <?= _('Status') ?>
+ <? if ($GLOBALS['perm']->have_studip_perm('admin', $inst_id) && $institute['inst_perms'] != 'admin' && !$locked): ?>
+ <select name="status">
+ <? foreach ($user->getInstitutePerms() as $cur_status): ?>
+ <option <? if ($cur_status == $institute['inst_perms']) echo 'selected'; ?>><?= $cur_status ?></option>
+ <? endforeach; ?>
+ </select>
+ <? else: ?>
+ <?= ucfirst($institute['inst_perms']) ?>
+ <? endif; ?>
+ </label>
+ <label>
+ <?= _('Raum') ?>
+ <input type="text" name="raum" id="raum"
+ value="<?= htmlReady($institute['raum']) ?>"
+ <? if ($locked) echo 'disabled'; ?>>
+ </label>
+ <label>
+ <?= _('Sprechzeit') ?>
+ <input type="text" name="sprech" id="sprech"
+ value="<?= htmlReady($institute['sprechzeiten']) ?>"
+ <? if ($locked) echo 'disabled'; ?>>
+ </label>
+ <label>
+ <?= _('Telefon') ?>
+ <input type="tel" name="tel"
+ value="<?= htmlReady($institute['telefon']) ?>"
+ <? if ($locked) echo 'disabled'; ?>>
+ </label>
+ <label>
+ <?= _('Fax') ?>
+ <input type="tel" name="fax"
+ value="<?= htmlReady($institute['fax']) ?>"
+ <? if ($locked) echo 'disabled'; ?>>
+ </label>
+
+ <? foreach ($entries as $id => $entry): ?>
+ <? if (!$entry->isEditable() || $locked): ?>
+ <label>
+ <?= $entry->getName() ?>
+ <?= $entry->getDisplayValue() ?>
+ </label>
+ <? else: ?>
+ <?= $entry->getHTML('datafields') ?>
+ <? endif; ?>
+ <? endforeach; ?>
+
+ <label>
+
+ <? if ($institute['externdefault']) : ?>
+ <?= Icon::create('accept', 'inactive')->asImg(['class' => 'text-top']); ?>
+ <input type="hidden" name="default_institute" value="1">
+ <? else : ?>
+ <input type="checkbox" id="default_institute" name="default_institute" value="1"
+ <? if ($institute['externdefault']) echo 'checked'; ?>>
+ <? endif; ?>
+ <?= _('Standard-Adresse') ?>
+ <?= tooltipIcon(_('Angaben, die im Adressbuch und auf den externen '
+ . 'Seiten als Standard benutzt werden.')) ?>
+ </label>
+ <label>
+ <input type="checkbox" name="invisible" id="invisible" value="1"
+ <? if ($institute['visible'] != 1) echo 'checked'; ?>>
+ <?= _('Einrichtung nicht auf der Profilseite'); ?>
+ <?= tooltipIcon(_('Die Angaben zu dieser Einrichtung werden nicht '
+ . 'auf Ihrer Profilseite und in Adressbüchern ausgegeben.')) ?>
+ </label>
+ <footer>
+ <?= Button::createAccept(_('Änderungen speichern'), 'speichern') ?>
+ </footer>
+</form>
diff --git a/app/views/settings/studies/index.php b/app/views/settings/studies/index.php
new file mode 100644
index 0000000..420114f
--- /dev/null
+++ b/app/views/settings/studies/index.php
@@ -0,0 +1,2 @@
+<?= $this->render_partial('settings/studies/studiengang', compact(words('allow_change about'))) ?>
+<?= $this->render_partial('settings/studies/institute', compact(words('allow_change about'))) ?>
diff --git a/app/views/settings/studies/institute.php b/app/views/settings/studies/institute.php
new file mode 100644
index 0000000..1d678ba
--- /dev/null
+++ b/app/views/settings/studies/institute.php
@@ -0,0 +1,108 @@
+<? use Studip\Button; ?>
+
+<h2><?= _('Meine Einrichtungen:') ?></h2>
+
+<form action="<?= $controller->url_for('settings/studies/store_in') ?>" method="post" class="default">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default" id="select_institute">
+ <colgroup>
+ <col>
+ <col width="100px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Einrichtung') ?></th>
+ <th>
+ <? if ($allow_change['in']): ?>
+ <?= _('austragen') ?>
+ <? endif; ?>
+ </th>
+ </thead>
+ <tbody>
+ <? if (count($institutes) === 0 && $allow_change['in']): ?>
+ <tr>
+ <td colspan="2" style="background: inherit;">
+ <strong><?= _('Sie haben sich noch keinen Einrichtungen zugeordnet.') ?></strong><br>
+ <br>
+ <?= _('Wenn Sie auf Ihrem Profil Ihre Einrichtungen '
+ . 'auflisten wollen, können Sie diese Einrichtungen hier eintragen.') ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($institutes as $inst_member): ?>
+ <tr>
+ <td>
+ <label for="inst_delete_<?= $inst_member->institute->id ?>"><?= htmlReady($inst_member->institute->name) ?></label>
+ </td>
+ <td style="text-align:center">
+ <? if ($allow_change['in']): ?>
+ <input type="checkbox" name="inst_delete[]" id="inst_delete_<?= $inst_member->institute->id ?>"
+ value="<?= $inst_member->institute->id ?>">
+ <? else: ?>
+ <?= Icon::create('accept', 'inactive')->asImg(['class' => 'text-top']) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+
+ <? if (count($institutes) !== 0 && $allow_change['in']): ?>
+ <tr>
+ <td colspan="2" style="padding: 0px; text-align: right;">
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store_in', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+</form>
+
+<? if ($allow_change['in']): ?>
+<form action="<?= $controller->url_for('settings/studies/store_in') ?>" method="post" class="default">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Einrichtung hinzufügen') ?></legend>
+
+ <a name="einrichtungen"></a>
+
+ <label for="select_new_inst">
+ <?= _('Um sich einer Einrichtung zuzuordnen, wählen '
+ . 'Sie die entsprechende Einrichtung aus der folgenden Liste aus:') ?>
+
+ <select name="new_inst" id="new_inst" class="nested-select">
+ <option value="" class="is-placeholder">
+ <?= _('-- Bitte Einrichtung auswählen --') ?>
+ </option>
+ <? foreach ($available_institutes as $i) : ?>
+ <? if (InstituteMember::countBySql('user_id = ? AND institut_id = ?', [$user->user_id, $i['Institut_id']]) == 0
+ && (!($i['is_fak'] && $user->perms == 'admin') || $GLOBALS['perm']->have_perm('root'))
+ ): ?>
+ <option class="<?= $i['is_fak'] ? 'nested-item-header' : 'nested-item' ?>"
+ value="<?= htmlReady($i['Institut_id']) ?>">
+ <?= htmlReady(my_substr($i['Name'], 0, 70)) ?>
+ </option>
+ <? else: ?>
+ <option class="<?= $i['is_fak'] ? 'nested-item-header' : 'nested-item' ?>" disabled>
+ <?= htmlReady(my_substr($i['Name'], 0, 70)) ?>
+ </option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store_in', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+</form>
+<? else: ?>
+ <?= _('Die Informationen zu Ihrer Einrichtung werden vom System verwaltet, '
+ . 'und können daher von Ihnen nicht geändert werden.') ?>
+<? endif; ?>
+
+<? if ($allow_change['in']): ?>
+</form>
+<? endif; ?>
diff --git a/app/views/settings/studies/studiengang.php b/app/views/settings/studies/studiengang.php
new file mode 100644
index 0000000..e5ac36b
--- /dev/null
+++ b/app/views/settings/studies/studiengang.php
@@ -0,0 +1,163 @@
+<? use Studip\Button; ?>
+
+<h2><?= _('Ich studiere folgende Fächer und Abschlüsse:') ?></h2>
+
+<form action="<?= $controller->url_for('settings/studies/store_sg') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default" id="select_fach_abschluss">
+ <colgroup>
+ <col>
+ <col>
+ <col>
+ <col width="100px">
+ <col width="100px">
+ </colgroup>
+ <thead class="hidden-tiny-down">
+ <tr>
+ <th><?= _('Fach') ?></th>
+ <th><?= _('Abschluss') ?></th>
+ <th id="version_label"><?= _('Versionen') ?></th>
+ <th id="fachsemester_label"><?= _('Fachsemester') ?></th>
+ <th style="text-align:center;" id="austragen_label">
+ <? if ($allow_change['sg']): ?>
+ <?= _('austragen') ?>
+ <? else: ?>
+ &nbsp;
+ <? endif; ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($user->studycourses) === 0 && $allow_change['sg']): ?>
+ <tr>
+ <td colspan="5" style="background: inherit;">
+ <strong><?= _('Sie haben sich noch keinem Studiengang zugeordnet.') ?></strong><br>
+ <br>
+ <?= _('Tragen Sie bitte hier die Angaben aus Ihrem Studierendenausweis ein!') ?>
+ </td>
+ </tr>
+ <? endif; ?>
+
+
+ <? foreach ($user->studycourses as $usc): ?>
+ <tr>
+ <td data-label="<?= _('Fach') ?>"><?= htmlReady($usc->studycourse->name) ?></td>
+ <td data-label="<?= _('Abschluss') ?>"><?= htmlReady($usc->degree->name) ?></td>
+ <? if ($allow_change['sg']): ?>
+ <td data-label="<?= _('Version') ?>">
+ <? $versionen = StgteilVersion::findByFachAbschluss($usc->fach_id, $usc->abschluss_id); ?>
+ <? $versionen = array_filter($versionen, function ($ver) {
+ return $ver->hasPublicStatus('genehmigt');
+ }); ?>
+ <? if (count($versionen)) : ?>
+ <select name="change_version[<?= $usc->fach_id ?>][<?= $usc->abschluss_id ?>]"
+ aria-labelledby="version_label">
+ <option value=""><?= _('-- Bitte Version auswählen --') ?></option>
+ <? foreach ($versionen as $version) : ?>
+ <option<?= $version->getId() == $usc->version_id ? ' selected' : '' ?>
+ value="<?= htmlReady($version->getId()) ?>">
+ <?= htmlReady($version->getDisplayName()) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <?= tooltipIcon(_('Keine Version in der gewählten Fach-Abschluss-Kombination verfügbar.'), true) ?>
+ <? endif; ?>
+ </td>
+ <? else : ?>
+ <? $version = StgteilVersion::find($usc->version_id); ?>
+ <td>
+ <? if ($version && $version->hasPublicStatus('genehmigt')) : ?>
+ <?= htmlReady($version->getDisplayName()); ?>
+ <? endif; ?>
+ </td>
+ <? endif; ?>
+ <? if ($allow_change['sg']): ?>
+ <td data-label="<?= _('Fachsemester') ?>">
+ <select name="change_fachsem[<?= $usc->fach_id?>][<?= $usc->abschluss_id ?>]"
+ aria-labelledby="fachsemester_label">
+ <? for ($i = 1; $i <= 50; $i += 1): ?>
+ <option <? if ($i == $usc->semester) echo 'selected'; ?>><?= $i ?></option>
+ <? endfor; ?>
+ </select>
+ </td>
+ <td data-label="<?= _('austragen:') ?>">
+ <input type="checkbox" aria-labelledby="austragen_label"
+ name="fach_abschluss_delete[<?= $usc->fach_id ?>]"
+ value="<?= $usc->abschluss_id ?>">
+ </td>
+ <? else: ?>
+ <td data-label="<?= _('Fachsemester:') ?>"><?= htmlReady($usc->semester) ?></td>
+ <td data-label="<?= _('austragen:') ?>" style="text-align: right;">
+ <?= Icon::create('accept', 'inactive')->asImg(['class' => 'text-top']) ?>
+ </td>
+ <? endif; ?>
+ </tr>
+ <? endforeach; ?>
+
+ <? if (count($user->studycourses) !== 0 && $allow_change['sg']): ?>
+ <tr>
+ <td colspan="5" style="padding: 0px; text-align: right;">
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store_in', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+</form>
+
+
+<? if ($allow_change['sg']): ?>
+<form action="<?= $controller->url_for('settings/studies/store_sg') ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Fach / Abschluss hinzufügen') ?>
+ </legend>
+
+
+ <div>
+ <?= _('Wählen Sie die Fächer, Abschlüsse und Fachsemester in der folgenden Liste aus:') ?>
+ </div>
+ <div class="hgroup">
+ <label>
+ <select name="new_studiengang" id="new_studiengang"
+ aria-label="<?= _('-- Bitte Fach auswählen --') ?>">
+ <option selected value="none"><?= _('-- Bitte Fach auswählen --') ?></option>
+ <? foreach ($faecher as $fach) : ?>
+ <?= sprintf('<option value="%s">%s</option>', $fach->id, htmlReady(my_substr($fach->name, 0, 50))); ?>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label>
+ <select name="new_abschluss" id="new_abschluss"
+ aria-label="<?= _('-- Bitte Abschluss auswählen --') ?>">
+ <option selected value="none"><?= _('-- Bitte Abschluss auswählen --') ?></option>
+ <? foreach ($abschluesse as $abschluss) : ?>
+ <?= sprintf('<option value="%s">%s</option>' . "\n", $abschluss->id, htmlReady(my_substr($abschluss->name, 0, 50))); ?>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label>
+ <select name="fachsem" aria-label="<?= _("Bitte Fachsemester wählen") ?>" class="size-s">
+ <? for ($i = 1; $i <= 50; $i += 1): ?>
+ <option><?= $i ?></option>
+ <? endfor; ?>
+ </select>
+ </label>
+ </div>
+ </fieldset>
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store_sg', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+</form>
+<? else: ?>
+ <?= _('Die Informationen zu Ihrem Studiengang werden vom System verwaltet, '
+ . 'und können daher von Ihnen nicht geändert werden.') ?>
+<? endif; ?>
diff --git a/app/views/settings/userdomains.php b/app/views/settings/userdomains.php
new file mode 100644
index 0000000..245d214
--- /dev/null
+++ b/app/views/settings/userdomains.php
@@ -0,0 +1,117 @@
+<? use Studip\Button; ?>
+
+<form action="<?= $controller->url_for('settings/userdomains/store') ?>" method="post" class="default">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <table class="default" id="assigned_userdomains">
+ <caption><?= _('Ich bin folgenden Nutzerdomänen zugeordnet:') ?></caption>
+ <colgroup>
+ <col>
+ <col width="100px">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Nutzerdomäne') ?></th>
+ <th>
+ <? if ($allow_change): ?>
+ <?= _('austragen') ?>
+ <? endif; ?>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($user_domains) === 0): ?>
+ <tr>
+ <td colspan="2" style="text-align: center">
+ <?= _('Sie sind noch keiner Nutzerdomäne zugeordnet.') ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($user_domains as $domain): ?>
+ <tr>
+ <td><?= htmlReady($domain->name) ?></td>
+ <td style="text-align:center">
+ <? if ($allow_change): ?>
+ <input type="checkbox" name="userdomain_delete[]" value="<?= $domain->id ?>">
+ <? else: ?>
+ <?= Icon::create('accept', 'inactive')->asImg(['class' => 'text-top']) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <? if (count($user_domains) > 0 && $allow_change): ?>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store_in', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif ?>
+ </table>
+</form>
+
+<? if ($allow_change): ?>
+<form action="<?= $controller->url_for('settings/userdomains/store') ?>" method="post" class="default">
+ <input type="hidden" name="studipticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Nutzerdomäne hinzufügen') ?></legend>
+</form>
+
+ <a name="userdomains"></a>
+
+ <label>
+ <?= _('Wählen Sie eine Nutzerdomäne aus der folgenden Liste aus:') ?>
+
+ <? if (!empty($domains)) : ?>
+ <select name="new_userdomain" id="new_userdomain">
+ <option selected value="none"><?= _('-- Bitte Nutzerdomäne auswählen --') ?></option>
+ <? foreach ($domains as $domain) : ?>
+ <option value="<?= $domain->getID() ?>"><?= htmlReady(my_substr($domain->name, 0, 50)) ?></option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+<form action="<?= $controller->url_for('settings/userdomains/store') ?>" method="post" class="default">
+ <input type="hidden" name="studipticket" value="<?= get_ticket() ?>">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Nutzerdomäne hinzufügen') ?></legend>
+
+ <a name="userdomains"></a>
+
+ <label>
+ <?= _('Wählen Sie eine Nutzerdomäne aus der folgenden Liste aus:') ?>
+
+ <? if (!empty($domains)) : ?>
+ <select name="new_userdomain" id="new_userdomain">
+ <option selected value="none"><?= _('-- Bitte Nutzerdomäne auswählen --') ?></option>
+ <? foreach ($domains as $domain) : ?>
+ <option value="<?= htmlReady($domain->id) ?>">
+ <?= htmlReady(my_substr($domain->name, 0, 50)) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Button::create(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ </footer>
+</form>
+<? else: ?>
+ <?= _('Die Informationen zu Ihren Nutzerdomänen werden vom System verwaltet und können daher von Ihnen nicht geändert werden.') ?>
+<? endif; ?>
diff --git a/app/views/shared/abschluss_filter.php b/app/views/shared/abschluss_filter.php
new file mode 100644
index 0000000..295e584
--- /dev/null
+++ b/app/views/shared/abschluss_filter.php
@@ -0,0 +1,9 @@
+<strong><?= _('Abschluss') ?></strong><br>
+<form id="abschluss_filter" action="<?= $action ?>" method="post">
+ <select name="abschluss_filter" size="1" style="width: 180px;" class="submit-upon-select">
+ <option value=""><?= _('-- Abschluss wählen --') ?></option>
+ <? foreach ($abschluesse as $abschluss) : ?>
+ <option value="<?= $abschluss->getId() ?>"<?= ($abschluss->getId() == $selected_abschluss ? ' selected' : '') ?>><?= htmlReady($abschluss->name) ?></option>
+ <? endforeach; ?>
+ </select>
+</form>
diff --git a/app/views/shared/chooser.php b/app/views/shared/chooser.php
new file mode 100644
index 0000000..e5e1cae
--- /dev/null
+++ b/app/views/shared/chooser.php
@@ -0,0 +1,14 @@
+<?= $controller->jsUrl() ?>
+<div id="mvv-chooser" style="width:100%;">
+<? foreach ($lists as $name => $list) : ?>
+ <?= $this->render_partial('shared/chooser_form', compact('name', 'list')); ?>
+<? endforeach; ?>
+</div>
+<? if ($last) : ?>
+<script>
+ <? if (sizeof($filter)) : ?>
+ jQuery('#mvv-chooser-toggle').addClass('mvv-chooser-hidden');
+ <? endif; ?>
+ jQuery('#mvv-chooser-toggle').fadeIn();
+</script>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/shared/chooser_form.php b/app/views/shared/chooser_form.php
new file mode 100644
index 0000000..e5e8f92
--- /dev/null
+++ b/app/views/shared/chooser_form.php
@@ -0,0 +1,18 @@
+<form action="<?= $list['stop'] ? $controller->url_for('/index') : $controller->url_for('/chooser'); ?>" style="width: 100%;" id="<?= htmlReady($name) ?>">
+ <? if (is_array($list['elements']) && sizeof($list['elements'])) : ?>
+ <input type="hidden" name="step" value="<?= htmlReady($name) ?>">
+ <? if ($list['stop']) : ?>
+ <input type="hidden" name="stop" value="1">
+ <? endif; ?>
+ <label><?= $list['headline'] ?>
+ <select name="id" style="width: 100%;">
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($list['elements'] as $key => $element) : ?>
+ <option value="<?= htmlReady($key) ?>"<?= $key == $list['selected'] ? ' selected' : '' ?>>
+ <?= htmlReady($element['name']) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+</form>
diff --git a/app/views/shared/contacts/add_ansprechpartner.php b/app/views/shared/contacts/add_ansprechpartner.php
new file mode 100644
index 0000000..f4d40d2
--- /dev/null
+++ b/app/views/shared/contacts/add_ansprechpartner.php
@@ -0,0 +1,135 @@
+<script type="text/javascript">
+jQuery(function ($) {
+ $( document ).ready(function() {
+ preselect('<?= $ansp_status; ?>');
+ });
+
+ $('select[name="ansp_status"]').on('change', function(event) {
+ preselect($(this).val());
+ });
+
+ function preselect(status){
+
+ if (status == 'extern') {
+ $('#contact_intern').hide();
+ $('#contact_inst').hide();
+ $('#contact_extern').show();
+ } else if (status == 'institution') {
+ $('#contact_intern').hide();
+ $('#contact_extern').hide();
+ $('#contact_inst').show();
+ } else {
+ $('#contact_extern').hide();
+ $('#contact_inst').hide();
+ $('#contact_intern').show();
+ }
+ }
+});
+</script>
+
+<form class="default" action="<?= $controller->url_for('/add_ansprechpartner',$origin, $range_type, $range_id, $user_id, $ansp_kat) ?>" method="post" data-dialog="size=auto">
+ <input type="hidden" name="user_id" id="user_id" value="<?= htmlReady($user_id) ?>">
+ <input type="hidden" name="range_id" id="range_id" value="<?= htmlReady($range_id) ?>">
+ <input type="hidden" name="range_type" id="range_type" value="<?= htmlReady($range_type) ?>">
+ <input type="hidden" name="contact_range_id" id="contact_range_id" value="<?= htmlReady($contact_range_id) ?>">
+
+ <label>
+ <?= _('Status') ?>
+ <select style="display: inline-block; max-width: 40em;" name="ansp_status">
+ <? foreach (MvvContact::getStatusNames() as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key == $ansp_status ? ' selected' : '' ?>><?= htmlReady($entry) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <div id="contact_intern">
+ <label>
+ <?= _('Suche') ?>
+ <?= QuickSearch::get(
+ 'ansp_user',
+ new StandardSearch('user_id')
+ )->defaultValue($user_id, $ansp_name)->withButton()->render() ?>
+ </label>
+ </div>
+
+ <div id="contact_inst">
+ <label>
+ <?= _('Suche') ?>
+ <?= QuickSearch::get(
+ 'ansp_inst',
+ new StandardSearch('Institut_id')
+ )->defaultValue($user_id, $ansp_name)->withButton()->render() ?>
+ </label>
+ </div>
+
+ <div id="contact_extern">
+ <label>
+ <?= _('Suche') ?>
+ <?= QuickSearch::get(
+ 'ansp_ext_user',
+ $extcontact_search_obj
+ )->defaultValue($user_id, $ansp_name)->withButton()->render() ?>
+ </label>
+
+ <?= _('oder') ?>
+ <? $perm_extern = MvvPerm::get('MvvExternContact'); ?>
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Neuer externer Ansprechpartner'); ?>
+ </legend>
+ <label>
+ <?= _('Name') ?>
+ <?= MvvI18N::input('exansp_name', $ext_contact->name, ['maxlength' => '255'])->checkPermission($ext_contact) ?>
+ </label>
+ <label>
+ <?= _('Vorname (optional)') ?>
+ <input name="exansp_vorname" type="text" value=""<?= $perm_extern->disable('vorname'); ?>>
+ </label>
+ <label>
+ <?= _('Homepage') ?>
+ <?= MvvI18N::input('exansp_web', $ext_contact->homepage, ['maxlength' => '255'])->checkPermission($ext_contact) ?>
+ </label>
+ <label>
+ <?= _('E-Mail') ?>
+ <input name="exansp_mail" type="text" value=""<?= $perm_extern->disable('mail'); ?>>
+ </label>
+ <label>
+ <?= _('Telefon') ?>
+ <input name="exansp_tel" type="text" value=""<?= $perm_extern->disable('tel'); ?>>
+ </label>
+ </fieldset>
+ </div>
+
+ <label>
+ <?= _('Alternative Kontaktmail (optional)') ?>
+ <input name="ansp_altmail" type="text" value="<?= htmlReady($ansp_altmail) ?>"<?= MvvPerm::get('MvvContact')->disable('alt_mail'); ?>>
+ </label>
+
+ <? if ($range_type !== 'Modul') : ?>
+ <label>
+ <?= _('Ansprechpartnertyp') ?>
+ <select style="display: inline-block; max-width: 40em;" name="ansp_typ">
+ <option value=""<?= empty($ansp_typ) ? ' selected' : '' ?>></option>
+ <? foreach ($GLOBALS['MVV_CONTACTS']['TYPE']['values'] as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key == $ansp_typ ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+
+ <label>
+ <?= _('Kategorie') ?>
+ <select style="display: inline-block; max-width: 40em;" name="ansp_kat">
+ <? foreach (MvvContactRange::getCategoriesByRangetype($range_type) as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key == $ansp_kat ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store_ansprechpartner') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+</form>
diff --git a/app/views/shared/contacts/add_ranges_to_contact.php b/app/views/shared/contacts/add_ranges_to_contact.php
new file mode 100644
index 0000000..f4a428e
--- /dev/null
+++ b/app/views/shared/contacts/add_ranges_to_contact.php
@@ -0,0 +1,44 @@
+<form class="default" action="<?= $controller->url_for('/add_ranges_to_contact', $mvvcontact_id, $range_type) ?>" method="post" data-dialog="size=auto">
+
+ <label>
+ <? if ($range_type == 'Studiengang'): ?>
+ <select id="search-contact-select" data-search_type="studiengang" data-placeholder="<?= _('Studiengang suchen') ?>" class="nested-select" multiple name="ranges[]"></select>
+ <? elseif ($range_type == 'Modul'): ?>
+ <select id="search-contact-select" data-search_type="modul" data-placeholder="<?= _('Modul suchen') ?>" class="nested-select" multiple name="ranges[]"></select>
+ <? elseif ($range_type == 'StudiengangTeil'): ?>
+ <select id="search-contact-select" data-search_type="stgteil" data-placeholder="<?= _('Studiengangteil suchen') ?>" class="nested-select" multiple name="ranges[]"></select>
+ <? endif; ?>
+ </label>
+
+ <? if ($range_type !== 'Modul') : ?>
+ <label>
+ <?= _('Ansprechpartnertyp') ?>
+ <select style="display: inline-block;" name="ansp_typ">
+ <option value=""<?= empty($ansp_typ) ? ' selected' : '' ?>></option>
+ <? foreach ($GLOBALS['MVV_CONTACTS']['TYPE']['values'] as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key == $ansp_typ ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+
+ <label>
+ <?= _('Kategorie') ?>
+ <select style="display: inline-block;" name="ansp_kat">
+ <? foreach (MvvContactRange::getCategoriesByRangetype($range_type) as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key == $ansp_kat ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+</form>
+
+<div id="search-contact-params"
+ data-contact="<?= $mvvcontact_id; ?>"
+></div>
diff --git a/app/views/shared/contacts/details.php b/app/views/shared/contacts/details.php
new file mode 100644
index 0000000..c3f1e44
--- /dev/null
+++ b/app/views/shared/contacts/details.php
@@ -0,0 +1,82 @@
+<td colspan="10">
+ <? if (count($relations) === 0) : ?>
+ <?= _('Diese Person wurde noch nicht referenziert.') ?>
+ <? else : ?>
+ <? $object_types = ['Studiengang', 'StudiengangTeil', 'Modul'] ?>
+ <? foreach ($object_types as $object_type) : ?>
+ <? $object_relations = $relations[$object_type] ?>
+ <? if (!is_array($object_relations) || count($object_relations) === 0) : continue; endif; ?>
+ <table class="default sortable-table" style="margin-top: 10px;" data-sortlist="[[0, 0]]">
+ <colgroup>
+ <? if($object_type === 'Studiengang'): ?>
+ <col width="50%">
+ <col width="20%">
+ <? else: ?>
+ <col width="70%">
+ <? endif; ?>
+ <col width="20%">
+ <col width="5%">
+ </colgroup>
+ <caption>
+ <?= htmlReady($object_type::getClassDisplayName()) ?>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <? if ($object_type === 'Studiengang') : ?>
+ <th data-sorter="text"><?= _('Name'); ?></th>
+ <th data-empty="top" data-sorter="text"><?= _('Ansprechpartnertyp'); ?></th>
+ <? else: ?>
+ <th data-sorter="text"><?= _('Name'); ?></th>
+ <? endif; ?>
+ <th data-sorter="text"><?= _('Kategorie'); ?></th>
+ <th data-sorter="false" style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($object_relations as $range_entries) : ?>
+ <? uasort($range_entries, function ($a, $b) { return strcmp($a->getDisplayName(), $b->getDisplayName()); }) ?>
+ <? foreach ($range_entries as $rel) : ?>
+ <? $object_name = htmlReady($object_type::find($rel['range_id'])->getDisplayName()); ?>
+ <tr>
+ <td data-sort-value="<?= $object_name ?>">
+ <a href="<?= $this->controller->url_for('shared/contacts/dispatch', mb_strtolower($object_type), $rel['range_id']) ?>">
+ <?= $object_name ?>
+ </a>
+ </td>
+ <? if ($object_type === 'Studiengang') : ?>
+ <td>
+ <?= htmlReady($GLOBALS['MVV_CONTACTS']['TYPE']['values'][$rel['type']]['name']); ?>
+ </td>
+ <? endif; ?>
+ <td>
+ <?= htmlReady($rel->getCategoryDisplayname()); ?>
+ </td>
+ <td class="actions">
+ <?
+ $actions = ActionMenu::get();
+ $actions->addLink(
+ $controller->url_for('shared/contacts/add_ansprechpartner', $origin, $rel['range_type'], $rel['range_id'], $rel['contact_id'], $rel['category']),
+ _('Ansprechpartner bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ );
+ $actions->addLink(
+ $controller->url_for('shared/contacts/delete_range', $rel['range_id'], $rel['contact_id'], $rel['category']),
+ _('Ansprechpartner-Zuordnung löschen'),
+ Icon::create('trash'),
+ [
+ 'data-confirm' => _('Wollen Sie die Zuordnung des Ansprechpartners wirklich entfernen?'),
+ 'data-dialog' => 'size=auto'
+ ]
+ );
+ echo $actions;
+ ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ <? endforeach; ?>
+ <? endif; ?>
+</td>
diff --git a/app/views/shared/contacts/index.php b/app/views/shared/contacts/index.php
new file mode 100644
index 0000000..0377a9d
--- /dev/null
+++ b/app/views/shared/contacts/index.php
@@ -0,0 +1,103 @@
+<div id="messagebox-container">
+<? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $messagebox) : ?>
+ <?= $messagebox ?>
+ <? endforeach ?>
+<? endif; ?>
+</div>
+<table id="mvv_contacts" class="default collapsable">
+ <caption>
+ <span class="actions"><? printf('%s Ansprechpartner', $count) ?></span>
+ </caption>
+ <thead>
+ <tr>
+ <?= $controller->renderSortLink('shared/contacts/', _('Name/Institution'), 'name', ['style' => 'width: 40%;']) ?>
+ <?= $controller->renderSortLink('shared/contacts/', _('Alternative Kontaktmail'), 'alt_mail', ['style' => 'width: 20%;']) ?>
+ <?= $controller->renderSortLink('shared/contacts/', _('Status'), 'contact_status', ['style' => 'width: 15%;']) ?>
+ <?= $controller->renderSortLink('shared/contacts/', _('Zuordnungen'), 'count_relations', ['style' => 'width: 20%;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+<? if ($contacts) : ?>
+ <? foreach ($contacts as $mvv_contact) : ?>
+ <? $perm = new MvvPerm($mvv_contact) ?>
+ <tbody class="<?= ($contact_id == $mvv_contact->contact_id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('shared/contacts/details/index', $mvv_contact->contact_id) ?>"><?= htmlReady($mvv_contact->getContactName()) ?></a>
+ </td>
+ <td class="dont-hide"><?= htmlReady($mvv_contact->alt_mail); ?></td>
+ <td class="dont-hide"><?= htmlReady($GLOBALS['MVV_CONTACTS']['STATUS']['values'][$mvv_contact->contact_status]['name']); ?></td>
+ <td class="dont-hide"><?= htmlReady($mvv_contact->count_relations); ?></td>
+ <td class="dont-hide actions">
+ <?
+ $actions = ActionMenu::get();
+ if ($perm->haveFieldPerm('ranges', MvvPerm::PERM_CREATE)) {
+ $actions->addLink(
+ $controller->url_for('shared/contacts/add_ranges_to_contact', $mvv_contact->contact_id),
+ _('Ansprechpartner zuordnen'),
+ Icon::create('person+add'),
+ ['data-dialog' => 'size=auto']
+ );
+ $actions->addLink(
+ $controller->url_for('shared/contacts/delete_all_ranges', $mvv_contact->contact_id),
+ _('Alle Zuordnungen löschen'),
+ Icon::create('trash'),
+ [
+ 'data-confirm' => _('Wollen Sie wirklich alle Zuordnungen entfernen?'),
+ 'data-dialog' => 'size=auto'
+ ]
+ );
+ }
+ if ($mvv_contact->contact_status === 'extern' && $perm->havePerm(MvvPerm::PERM_CREATE)) {
+ $actions->addLink(
+ $controller->url_for('shared/contacts/delete_extern_contact', $mvv_contact->contact_id),
+ _('Externe Person löschen'),
+ Icon::create('trash'),
+ [
+ 'data-confirm' => _('Wollen Sie die externe Person wirklich löschen?'),
+ 'data-dialog' => 'size=auto'
+ ]
+ );
+ }
+ echo $actions;
+ ?>
+ </td>
+ </tr>
+ <? if ($contact_id == $mvv_contact->contact_id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('shared/contacts/details', compact('mvv_contact')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="10" style="text-align: right">
+ <?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_contacts=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render('shared/pagechooser');
+ ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+<? endif; ?>
+</table>
+<script type="text/javascript">
+jQuery(function ($) {
+ $(document).on('dialog-close', function(event) {
+ if ($('div.ui-dialog.studip-confirmation').length) {
+ STUDIP.MVV.Contact.reload_contacttable();
+ }
+ });
+});
+</script>
diff --git a/app/views/shared/contacts/new_ansprechpartner.php b/app/views/shared/contacts/new_ansprechpartner.php
new file mode 100644
index 0000000..0dea8ba
--- /dev/null
+++ b/app/views/shared/contacts/new_ansprechpartner.php
@@ -0,0 +1,17 @@
+<form class="default" action="<?= $controller->url_for('/new_ansprechpartner') ?>" method="post" data-dialog="size=auto">
+
+ <label>
+ <select id="mvv-contacts-range_types" name="range_type">
+ <? foreach ($allowed_object_types as $object_type) : ?>
+ <option value="<?= $object_type ?>"><?= htmlReady($object_type::getClassDisplayName()) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Weiter'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+</form> \ No newline at end of file
diff --git a/app/views/shared/contacts/range.php b/app/views/shared/contacts/range.php
new file mode 100644
index 0000000..1f13bab
--- /dev/null
+++ b/app/views/shared/contacts/range.php
@@ -0,0 +1,83 @@
+<div id="messagebox-container">
+<? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $messagebox) : ?>
+ <?= $messagebox ?>
+ <? endforeach ?>
+<? endif; ?>
+</div>
+<table id="mvv_contacts" class="default sortable-table" data-sortlist="[[0, 0]]">
+ <caption>
+ <span class="actions">
+ <a href="<?= $controller->url_for('shared/contacts/add_ansprechpartner', 'range', $range_type, $range_id);?>" data-dialog="size=auto">
+ <?= Icon::create('headache+add', Icon::ROLE_CLICKABLE, ['title' => _('Ansprechpartner hinzufügen')]); ?>
+ </a>
+ <a href="<?= $controller->url_for('shared/contacts/sort', $range_id);?>" data-dialog="size=auto">
+ <?= Icon::create('arr_2up', Icon::ROLE_CLICKABLE, ['title' => _('Reihenfolge der Ansprechpartner ändern')]); ?>
+ </a>
+ </span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <th data-sorter="digit"><?= _('Pos.'); ?></th>
+ <th data-sorter="text"><?= _('Name/Institution'); ?></th>
+ <? if($range_type !== 'Modul'): ?>
+ <th data-empty="top" data-sorter="text"><?= _('Ansprechpartner-Typ'); ?></th>
+ <? endif; ?>
+ <th data-sorter="text"><?= _('Kategorie'); ?></th>
+ <th data-sorter="digit"><?= _('Zuordnungen'); ?></th>
+ <th data-sorter="false" style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+<? if($contacts): ?>
+ <tbody>
+ <? foreach($contacts as $mvv_contact): ?>
+
+ <tr>
+ <td><?= htmlReady($mvv_contact->position); ?></td>
+ <td><?= htmlReady($mvv_contact->name) ?></td>
+ <? if($range_type !== 'Modul'): ?>
+ <td><?= htmlReady($GLOBALS['MVV_CONTACTS']['TYPE']['values'][$mvv_contact->type]['name']) ?></td>
+ <? endif; ?>
+ <td><?= htmlReady($mvv_contact->getCategoryDisplayname()); ?></td>
+ <td ><?= htmlReady($mvv_contact->count_relations); ?></td>
+ <td class="actions">
+ <?
+ $actions = ActionMenu::get();
+ $actions->addLink(
+ $controller->url_for('shared/contacts/add_ansprechpartner', 'range', $mvv_contact->range_type, $mvv_contact->range_id, $mvv_contact->contact_id, $mvv_contact->category),
+ _('Ansprechpartner bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto']
+ );
+ $actions->addLink(
+ $controller->url_for('shared/contacts/delete_range', $mvv_contact->range_id, $mvv_contact->contact_id, $mvv_contact->category),
+ _('Ansprechpartner-Zuordnung löschen'),
+ Icon::create('trash'),
+ [
+ 'data-confirm' => _('Wollen Sie die Zuordnung des Ansprechpartners wirklich entfernen?'),
+ 'data-dialog' => 'size=auto'
+ ]
+ );
+ echo $actions;
+ ?>
+ </td>
+ </tr>
+ <? if ($range_id == $mvv_contact->range_id && $contact_id == $mvv_contact->contact_id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('shared/contacts/details', compact('mvv_contact')) ?>
+ </tr>
+ <? endif; ?>
+
+ <? endforeach; ?>
+ </tbody>
+<? endif; ?>
+</table>
+<script type="text/javascript">
+jQuery(function ($) {
+ $(document).on('dialog-close', function(event) {
+ if ($('div.ui-dialog.studip-confirmation').length) {
+ STUDIP.MVV.Contact.reload_contacttable('<?= htmlReady($range_id) ?>', '<?= htmlReady($range_type) ?>');
+ }
+ });
+});
+</script>
diff --git a/app/views/shared/contacts/select_range.php b/app/views/shared/contacts/select_range.php
new file mode 100644
index 0000000..3de2e35
--- /dev/null
+++ b/app/views/shared/contacts/select_range.php
@@ -0,0 +1,20 @@
+<form class="default" action="<?= $controller->url_for('/select_range', $range_type) ?>" method="post" data-dialog="size=auto">
+ <?= CSRFProtection::tokenTag(); ?>
+
+ <label>
+ <? if ($range_type == 'Studiengang'): ?>
+ <select id="search-contact-select" data-search_type="studiengang" data-placeholder="<?= _('Studiengang suchen') ?>" class="nested-select" multiple name="range_id[]"></select>
+ <? elseif ($range_type == 'Modul'): ?>
+ <select id="search-contact-select" data-search_type="modul" data-placeholder="<?= _('Modul suchen') ?>" class="nested-select" multiple name="range_id[]"></select>
+ <? else : ?>
+ <select id="search-contact-select" data-search_type="stgteil" data-placeholder="<?= _('Studiengangteil suchen') ?>" class="nested-select" multiple name="range_id[]"></select>
+ <? endif; ?>
+ </label>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Weiter'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </footer>
+
+ <div id="search-contact-params" data-contact=""></div>
+</form>
diff --git a/app/views/shared/contacts/select_range_type.php b/app/views/shared/contacts/select_range_type.php
new file mode 100644
index 0000000..b4ec9a1
--- /dev/null
+++ b/app/views/shared/contacts/select_range_type.php
@@ -0,0 +1,17 @@
+<form class="default" action="<?= $controller->url_for('/select_range_type', $mvvcontact_id) ?>" method="post" data-dialog="size=auto">
+
+ <label>
+ <select id="mvv-contacts-range_types" name="range_type">
+ <? foreach ($allowed_object_types as $object_type) : ?>
+ <option value="<?= $object_type ?>"><?= htmlReady($object_type::getClassDisplayName()) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <?= CSRFProtection::tokenTag(); ?>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Weiter'), 'store') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+
+</form> \ No newline at end of file
diff --git a/app/views/shared/contacts/sort.php b/app/views/shared/contacts/sort.php
new file mode 100644
index 0000000..779cfff
--- /dev/null
+++ b/app/views/shared/contacts/sort.php
@@ -0,0 +1,28 @@
+<script type="text/javascript">
+jQuery(function ($) {
+ $('div.ui-dialog').on('dialogclose', function(event) {
+ STUDIP.MVV.Contact.reload_contacttable('<?= htmlReady($range_id) ?>', '<?= htmlReady($range_type) ?>');
+ });
+});
+</script>
+<? $contact_cat = MvvContactRange::getCategoriesByRangetype($range_type); ?>
+<div class="ordering" title="<?= _('Reihenfolge ändern') ?>">
+ <div class="nestable" data-max-depth="1">
+ <? if ($contacts): ?>
+ <ol class="dd-list">
+ <? foreach ($contacts as $contact): ?>
+ <li class="dd-item" data-id="<?= $contact->contact_id ?>_<?= $contact->category ?>">
+ <div class="dd-handle"><?= formatReady($contact->name) ?> (<?= formatReady($contact_cat[$contact->category]['name']) ?>)</div>
+ </li>
+ <? endforeach; ?>
+ </ol>
+ <? endif; ?>
+ </div>
+</div>
+
+<form class="default" id="order_form" action="<?= $controller->url_for('/sort', $range_id) ?>" method="POST" data-dialog="size=auto">
+ <input type="hidden" name="ordering" id="ordering">
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'order') ?>
+ </footer>
+</form>
diff --git a/app/views/shared/content.php b/app/views/shared/content.php
new file mode 100644
index 0000000..cc97b17
--- /dev/null
+++ b/app/views/shared/content.php
@@ -0,0 +1 @@
+<?= $content ?> \ No newline at end of file
diff --git a/app/views/shared/content_overlay.php b/app/views/shared/content_overlay.php
new file mode 100644
index 0000000..604a75d
--- /dev/null
+++ b/app/views/shared/content_overlay.php
@@ -0,0 +1 @@
+<?= $content_for_layout ?>
diff --git a/app/views/shared/deskriptor_language.php b/app/views/shared/deskriptor_language.php
new file mode 100644
index 0000000..ff2a433
--- /dev/null
+++ b/app/views/shared/deskriptor_language.php
@@ -0,0 +1,11 @@
+<? $table = get_class($modul) == 'Modul' ? 'mvv_modul_deskriptor' : 'mvv_modulteil_deskriptor'; ?>
+<? $languages = $modul->deskriptoren->getAvailableTranslations(); ?>
+<? foreach ($GLOBALS[strtoupper($table)]['SPRACHE']['values'] as $lang => $value) : ?>
+<div style="padding-top:10px;">
+ <a href="<?= URLHelper::getLink($link, ['display_language' => $lang]) ?>">
+ <img src="<?= Assets::image_path('languages/lang_' . mb_strtolower($lang) . '.gif') ?>" alt="<?= $value['name'] ?>">
+ <?= $value['name'] ?> (<?= in_array($lang, $languages) ? 'bearbeiten' : 'neu anlegen' ?>)
+ <?= $lang == $sprache ? Icon::create('accept', 'accept', [])->asImg() : '' ?>
+ </a>
+</div>
+<? endforeach; ?>
diff --git a/app/views/shared/download/mhb.php b/app/views/shared/download/mhb.php
new file mode 100644
index 0000000..59a45f8
--- /dev/null
+++ b/app/views/shared/download/mhb.php
@@ -0,0 +1,85 @@
+<? if (!empty($Stgteile)): ?>
+ <div style="page-break-after:always;">
+ <h1><?= $_('Übersicht') ?> <?= $semName ?></h1>
+ <br>
+ <? foreach ($Stgteile as $abs => $teile) :
+ $abs_kat =AbschlussKategorie::getEnriched($abs);?>
+ <section class="contentbox" style="page-break-after:always;">
+ <header>
+ <h2><?= $abs_kat->getDisplayName() ?></h2>
+ </header>
+ <? foreach ($teile as $id => $content) :
+ $stgtv =StgteilVersion::getEnriched($id); ?>
+ <section class="contentbox">
+ <header>
+ <h2><?= $stgtv->getDisplayName() ?></h2>
+ </header>
+ <? foreach ($content as $id_teil_abschnitt => $modulinfolist) :
+ $teilabschnitt = StgteilAbschnitt::getEnriched($id_teil_abschnitt); ?>
+ <section class="contentbox" style="margin-left: 10pt;">
+ <header><b><?= $teilabschnitt->getDisplayName() ?></b></p></header>
+ <? foreach ($teilabschnitt->getChildren() as $modul) : ?>
+ <? if (empty($module->find($modul->id))): ?>
+ <? $module[] = $modul; ?>
+ <? endif; ?>
+ <p>
+ <a href="#modref_<?= $modul->id; ?>" style="margin-left: 10pt;" >
+ <?= $modul->getDisplayName(); ?>
+ </a>
+ </p>
+ <? endforeach; ?>
+ </section>
+ <? endforeach; ?>
+ </section>
+ <? endforeach; ?>
+ </section>
+ <? endforeach; ?>
+</div>
+<br>
+<? endif; ?>
+<? if ($language == 'DE'): ?>
+ <h3 style="text-align: center">
+ <?= sprintf(_('Modulhandbuch %s'), $StgteilVersion->studiengangteil->getDisplayName())?>
+ </h3>
+ <h5 style="text-align: right"><?= sprintf(_('Datum %s'), strftime('%x', time()))?></h5>
+<? else: ?>
+ <h3>Modules for
+ <? if (!is_null($StgteilVersion->studiengangteil->fach->name)
+ && strlen($StgteilVersion->studiengangteil->fach->name) > 0) : ?>
+ <?= htmlReady($StgteilVersion->studiengangteil->fach->name) ?>
+ <? if (count($StgteilVersion->studiengangteil->studiengang) > 0) : ?>
+ <? if (!is_null($StgteilVersion->studiengangteil->studiengang->zusatz)
+ && strlen($StgteilVersion->studiengangteil->studiengang->zusatz) > 0) : ?>
+ <?= htmlReady($StgteilVersion->studiengangteil->studiengang->zusatz) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <? else : ?>
+ <?= $StgteilVersion->studiengangteil->getDisplayName() ?>
+ <? endif; ?>
+ </h3>
+ <h6 style="text-align: right">Date <?= strftime('%x', time())?></h6>
+<? endif; ?>
+<? foreach($module as $part_id => $values) : ?>
+ <h1><?= $values['part']->getDisplayName() ?></h1>
+ <? foreach($values['modules'] as $mod_id => $modul) : ?>
+ <? $modul_desc = ModulDeskriptor::findOneBySQL('modul_id =?', array($modul->id)); ?>
+ <h3 id="modref_<?= $modul->id ?>"><?= !empty($modul_desc) ? $modul['code'] . ' - ' . $modul_desc['bezeichnung'] : $modul->getDisplayName() ?></h3>
+ <div style="page-break-after:always;">
+ <div>
+ <?= $archiv->getMVVPluginModulDescription($modul, $language); ?>
+ </div>
+ <? if (is_array($modulseminare) && in_array($modul->id, array_keys($modulseminare)) ) : ?>
+ <br>
+ <div><p><b><?= _('dem Modul zugoerdnete Veranstaltungen') ?>:</b></p>
+ <? foreach($modulseminare[$modul->id] as $modulteilName => $modulteil): ?><?= $modulteilName ?>
+ <ul>
+ <? foreach($modulteil as $name => $id): ?>
+ <li><a href="#semref_<?= $id ?>"><?= $name ?></a></li>
+ <? endforeach; ?>
+ </ul>
+ <? endforeach; ?>
+ </div>
+ <? endif; ?>
+ </div>
+ <?endforeach; ?>
+<? endforeach; ?>
diff --git a/app/views/shared/fachbereich_filter.php b/app/views/shared/fachbereich_filter.php
new file mode 100644
index 0000000..6b82ec8
--- /dev/null
+++ b/app/views/shared/fachbereich_filter.php
@@ -0,0 +1,9 @@
+<strong><?= _('Fachbereiche') ?></strong><br>
+<form id="fachbereich_filter" action="<?= $action ?>" method="post">
+ <select name="fachbereich_filter" size="1" style="width: 180px;" class="submit-upon-select">
+ <option value=""><?= _('-- Fachbereich wählen --') ?></option>
+ <? foreach ($fachbereiche as $fachbereich) : ?>
+ <option value="<?= $fachbereich['fachbereich_id'] ?>"<?= ($fachbereich->getId() == $selected_fachbereich ? ' selected' : '') ?>><?= htmlReady($fachbereich->getDisplayName()) ?></option>
+ <? endforeach; ?>
+ </select>
+</form>
diff --git a/app/views/shared/filter.php b/app/views/shared/filter.php
new file mode 100644
index 0000000..e80d3d2
--- /dev/null
+++ b/app/views/shared/filter.php
@@ -0,0 +1,124 @@
+<? if ($selected_status || $selected_kategorie || $selected_abschluss || $selected_fachbereich || $selected_zuordnung || $selected_institut || $selected_name || $selected_semester != $default_semester) : ?>
+<div style="width: 100%; text-align: right;">
+ <a href="<?= $action_reset ?>">
+ <?= Icon::create('refresh', 'clickable', ['title' => _('Filter zurücksetzen')])->asImg(); ?>
+ <?= _('Zurücksetzen') ?>
+ </a>
+</div>
+<? endif; ?>
+<form id="index_filter" action="<?= $action ?>" method="post">
+ <? if ($name_search) : ?>
+ <label class="mvv-name-search">
+ <?= $name_caption ?: _('Name') ?>:
+ <input type="text" name="name_filter" value="<?= htmlReady($selected_name) ?>">
+ <input type="submit" value="<?= _('Suchen') ?>">
+ </label>
+ <? endif ?>
+ <? if (isset($semester)) : ?>
+ <label>
+ <?= $semester_caption ?: _('Semester') . ':' ?><br>
+ <select name="semester_filter" class="sidebar-selectlist submit-upon-select">
+ <option value="all"<?= (!$selected_semester ? ' selected' : '') ?>><?= _('Alle Semester') ?></option>
+ <? foreach ($semester as $sem) : ?>
+ <option value="<?= $sem['semester_id'] ?>"<?= ($sem['semester_id'] == $selected_semester ? ' selected' : '') ?>><?= htmlReady($sem['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+ <? if (isset($zuordnungen)) : ?>
+ <label>
+ <?= _('Zugeordnet zu Objekten') ?>:
+ <select name="zuordnung_filter" class="sidebar-selectlist submit-upon-select">
+ <option value=""><?= _('Alle') ?></option>
+ <? foreach ($zuordnungen as $object_type => $zuordnung) : ?>
+ <option value="<?= $object_type ?>"
+ <?= ($object_type == $selected_zuordnung ? ' selected' : '') ?>><?= htmlReady($object_type::getClassDisplayName()) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+ <? if (isset($status)) : ?>
+ <label>
+ <?= _('Status') ?>:<br>
+ <select name="status_filter" class="sidebar-selectlist submit-upon-select">
+ <option value=""><?= _('Alle') ?></option>
+ <? foreach ($status_array as $key => $stat) : ?>
+ <? if ($status[$key]['count_objects']) : ?>
+ <option value="<?= $key ?>"
+ <?= ($key == $selected_status ? ' selected' : '') ?>><?= htmlReady($stat['name']) . ' (' . ($status[$key] ? $status[$key]['count_objects'] : '0') . ')' ?></option>
+ <? endif; ?>
+ <? endforeach; ?>
+ <? if ($status['__undefined__']) : ?>
+ <option value="__undefined__"<?= $selected_status == '__undefined__' ? ' selected' : '' ?>><?= _('nicht angegeben') . ' (' . ($stat['count_objects'] ?: '0') . ')' ?></option>
+ <? endif; ?>
+ </select>
+ </label>
+ <? endif; ?>
+ <? if (isset($kategorien)) : ?>
+ <label>
+ <?= _('Kategorie') ?>:<br>
+ <select name="kategorie_filter" class="sidebar-selectlist submit-upon-select">
+ <option value=""><?= _('Alle') ?></option>
+ <? foreach ($kategorien as $kategorie) : ?>
+ <option value="<?= $kategorie->id ?>"
+ <? if ($kategorie->id === $selected_kategorie || (isset($abschluesse) && $abschluesse[$selected_abschluss]->kategorie_id == $kategorie->id)) : ?> selected<? endif; ?>>
+ <?= htmlReady($kategorie->name) . ' (' . $kategorie->count_objects . ')' ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+ <? if (isset($abschluesse)) : ?>
+ <label>
+ <?= _('Abschluss') ?>:<br>
+ <select name="abschluss_filter" class="sidebar-selectlist submit-upon-select">
+ <option value=""><?= _('Alle') ?></option>
+ <? foreach ($abschluesse as $abschluss) : ?>
+ <option value="<?= $abschluss->getId() ?>"<?= ($abschluss->getId() == $selected_abschluss ? ' selected' : '') ?>><?= htmlReady($abschluss->name) . ' (' . $abschluss->count_objects . ')' ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+ <? if (isset($institute)) : ?>
+ <? $perm_institutes = MvvPerm::getOwnInstitutes() ?>
+ <? if ($perm_institutes !== false) : ?>
+ <label>
+ <?= _('Verantw. Einrichtung') ?>:<br>
+ <select name="institut_filter" class="sidebar-selectlist nested-select submit-upon-select">
+ <option value=""><?= _('Alle') ?></option>
+ <? foreach ($institute as $institut) : ?>
+ <?
+ if (count($perm_institutes) == 0
+ || in_array($institut->getId(), $perm_institutes)) {
+ echo '<option value="' . $institut->getId()
+ . ($institut->getId() == $selected_institut ?
+ '" selected' : '"')
+ . ' class="nested-item">'
+ . htmlReady($institut->name
+ . ' (' . $institut->count_objects . ')')
+ . '</option>';
+ }
+ ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif ?>
+ <? endif; ?>
+ <? if (isset($fachbereiche)) : ?>
+ <? $perm_institutes = MvvPerm::getOwnInstitutes() ?>
+ <? if ($perm_institutes !== false) : ?>
+ <label>
+ <?= $fachbereich_caption ?: _('Fachbereiche') ?>:<br>
+ <select name="fachbereich_filter" class="sidebar-selectlist nested-select institute-list submit-upon-select">
+ <option value=""><?= _('Alle') ?></option>
+ <? foreach ($fachbereiche as $fachbereich) : ?>
+ <? if (count($perm_institutes) == 0
+ || in_array($fachbereich->getId(), $perm_institutes)) : ?>
+ <option class="nested-item" value="<?= $fachbereich->getId() ?>"<?= ($fachbereich->getId() == $selected_fachbereich ? ' selected' : '') ?>><?= htmlReady($fachbereich->getDisplayName()) . ' (' . $fachbereich->count_objects . ')' ?></option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? endif; ?>
+ <? endif; ?>
+</form>
diff --git a/app/views/shared/form_dokumente.php b/app/views/shared/form_dokumente.php
new file mode 100644
index 0000000..9cbdebe
--- /dev/null
+++ b/app/views/shared/form_dokumente.php
@@ -0,0 +1,103 @@
+<? $perm_dokumente = isset($perm_dokumente) ? $perm_dokumente : true; ?>
+<fieldset>
+ <legend><?= _('Referenzierte Dokumente und Materialien') ?></legend>
+ <? if ($perm_dokumente) : ?>
+ <div class="mvv-item-list-properties" style="display: none;">
+ <div class="mvv-property-de"></div>
+ <div class="mvv-property-en"></div>
+ </div>
+ <div>
+ <?= $search_dokumente['html']->render(); ?>
+ <? if (Request::submitted('search_dokumente')) : ?>
+ <?= Icon::create(
+ 'refresh',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'name' => 'reset_dokumente',
+ 'data-qs_id' => $search_dokumente['id']
+ ]
+ )->asInput(); ?>
+ <? else : ?>
+ <?= Icon::create(
+ 'search',
+ Icon::ROLE_CLICKABLE,
+ [
+ 'name' => 'search_dokumente',
+ 'data-qs_id' => $search_dokumente['id'],
+ 'data-qs_name' => $search_dokumente['html']->getId(),
+ 'class' => 'mvv-qs-button'
+ ]
+ )->asInput(); ?>
+ <? endif; ?>
+ </div>
+ <? endif; ?>
+ <ul id="dokumente_target" class="mvv-assigned-items mvv-with-properties mvv-dokumente sortable">
+ <? if ($perm_dokumente) : ?>
+ <li class="mvv-item-list-placeholder"<?= (empty($dokumente) ? '' : ' style="display: none;"') ?>><?= _('Fügen Sie Dokumente und Materialien hinzu.') ?></li>
+ <? elseif (empty($dokumente)) : ?>
+ <li class="mvv-item-list-placeholder"><?= _('Es wurden keine Dokumente zugeordnet.') ?></li>
+ <? endif; ?>
+ <? foreach ($dokumente as $dokument) : ?>
+ <? if ($perm_dokumente) : ?>
+ <li id="dokumente_<?= $dokument->dokument_id ?>" class="sort_items">
+ <div style="flex: 9;">
+ <?= htmlReady($dokument->document->isI18nField('name')
+ ? $dokument->document->name->original()
+ : $dokument->document->name) ?>
+ </div>
+ <div style="flex: 1; text-align: right;" class="mvv-item-list-buttons">
+ <a href="#" class="mvv-item-remove">
+ <?= Icon::create(
+ 'trash',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Dokument entfernen')]
+ )->asImg(); ?>
+ </a>
+ <a href="#" class="mvv-item-edit-properties">
+ <?= Icon::create(
+ 'edit',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Kommentar bearbeiten')]
+ )->asImg(); ?>
+ </a>
+ </div>
+ <fieldset class="mvv-item-document-comments" style="display: none;">
+ <label><?= _('Anmerkungen/Kommentare') ?>
+ <?= MvvI18N::textarea(
+ 'beschreibung',
+ $dokument->kommentar,
+ ['class' => 'add_toolbar ui-resizable wysiwyg']
+ ) ?>
+ </label>
+ <?= _('Die Änderungen werden erst gespeichert, wenn das Hauptformular gespeichert wurde!') ?>
+ </fieldset>
+ <input type="hidden" name="dokumente_items[]" value="<?= $dokument->dokument_id ?>">
+ </li>
+ <? else : ?>
+ <li id="dokumente_<?= $dokument->dokument_id ?>">
+ <div style="flex: 1;">
+ <?= htmlReady($dokument->document->isI18nField('name')
+ ? $dokument->document->name->original()
+ : $dokument->document->name) ?>
+ </div>
+ <input type="hidden" name="dokumente_items[]" value="<?= $dokument->dokument_id ?>">
+ </li>
+ <? endif; ?>
+ <? endforeach; ?>
+ </ul>
+ <? if ($perm_dokumente) : ?>
+ <div id="dokumente_edit-form-new">
+ <?= _('Neues Dokument anlegen und hinzufügen') ?>
+ <a data-dialog href="<?= URLHelper::getLink($controller->url_for('materialien/dokumente/dokument/')) ?>">
+ <?= Icon::create(
+ 'add',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Neues Dokument anlegen')]
+ )->asImg(); ?>
+ </a>
+ </div>
+ <div style="padding-top: 15px; width: 100%; max-width: 48em;">
+ <?= _('Die Reihenfolge der zugeordneten Dokumente kann durch Anklicken und Ziehen geändert werden. Für die Zuordnung eines Dokumentes kann ein zusätzlicher Text angegeben werden.') ?>
+ </div>
+ <? endif; ?>
+</fieldset>
diff --git a/app/views/shared/include_edit.php b/app/views/shared/include_edit.php
new file mode 100644
index 0000000..f37c760
--- /dev/null
+++ b/app/views/shared/include_edit.php
@@ -0,0 +1,10 @@
+<div id="mvv-include-edit<?= $item_id ?>" class="mvv-include-edit">
+ <a class="mvv-include-close"></a>
+ <div class="mvv-include-background">
+ <div class="mvv-include-content">
+ <h2 class="topic"><?= htmlReady(PageLayout::getTitle()) ?></h2>
+ <?= $content_for_layout ?>
+ </div>
+ </div>
+ <div class="mvv-edit-bottom"></div>
+</div>
diff --git a/app/views/shared/info_search.php b/app/views/shared/info_search.php
new file mode 100644
index 0000000..008d549
--- /dev/null
+++ b/app/views/shared/info_search.php
@@ -0,0 +1,11 @@
+<form id="info_search" action="<?= $action ?>" method="post" role="search">
+ <script>
+ var submitInfoSearch = function () {
+ jQuery('#info_search').submit();
+ };
+ </script>
+ <?= $search ?>
+ <? if ($reset) : ?>
+ <a href="<?= $reset ?>"><?= Icon::create('refresh', 'clickable', ['title' => _('Suche zurücksetzen')])->asImg(); ?></a>
+ <? endif; ?>
+</form>
diff --git a/app/views/shared/inst_chooser.php b/app/views/shared/inst_chooser.php
new file mode 100644
index 0000000..735ed95
--- /dev/null
+++ b/app/views/shared/inst_chooser.php
@@ -0,0 +1,25 @@
+<? require_once dirname(__FILE__) . '/../../controllers/shared/inst_chooser.php'; ?>
+<? if ($chooser_all_institutes) : ?>
+ <? $chooser_institutes = Shared_InstchooserController::get_institutes($parent_id, null, true); ?>
+<? else : ?>
+ <? $chooser_institutes = Shared_InstchooserController::get_institutes($parent_id, $object_roles); ?>
+<? endif; ?>
+<div class="mvv-widget-right">
+ <? if (!Request::isXhr()) : ?>
+ <script>
+ STUDIP.MVV.INST_CHOOSER_URL = "<?= $controller->url_for('shared/inst_chooser', ($chooser_all_institutes ? ['all' => '1'] : [])) ?>/";
+ </script>
+ <? endif; ?>
+ <div class="mvv-inst-chooser">
+ <span class="mvv-inst-add-button"><?= Icon::create('arr_2left', 'sort', ['title' => _('Einrichtung zuordnen')])->asImg(); ?></span>
+ <select name="<?= $chooser_id ?>">
+ <option class="mvv-inst-chooser-empty mvv-inst-chooser-level" value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($chooser_institutes as $institute) : ?>
+ <option class="<?= $institute['kids'] ? '' : 'mvv-inst-chooser-empty' ?><?= $institute['is_object'] ? '' : ' mvv-inst-chooser-level' ?>" value="<?= $institute['object_id']; ?>" data-type="<?= $chooser_id ?>" data-item-id="<?= $institute['item_id'] ?>" data-fb="<?= $institute['fb'] ?>">
+ <?= htmlReady($institute['name']); ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <span class="mvv-inst-next-button"><?= Icon::create('arr_1down', 'clickable', ['title' => _('Ebene anzeigen')])->asImg(); ?></span>
+ </div>
+</div>
diff --git a/app/views/shared/js_url.php b/app/views/shared/js_url.php
new file mode 100644
index 0000000..9f2d8ea
--- /dev/null
+++ b/app/views/shared/js_url.php
@@ -0,0 +1,3 @@
+<script>
+ STUDIP.MVV.CONTROLLER_URL = "<?= $url ?>";
+</script>
diff --git a/app/views/shared/kategorie_filter.php b/app/views/shared/kategorie_filter.php
new file mode 100644
index 0000000..12f36a6
--- /dev/null
+++ b/app/views/shared/kategorie_filter.php
@@ -0,0 +1,9 @@
+<strong><?= _('Kategorie') ?></strong><br>
+<form id="kategorie_filter" action="<?= $action ?>" method="post">
+ <select name="kategorie_filter" size="1" style="width: 180px;" class="submit-upon-select">
+ <option value=""><?= _('-- Kategorie wählen --') ?></option>
+ <? foreach ($kategorien as $kategorie) : ?>
+ <option value="<?= $kategorie->getId() ?>"<?= ($kategorie->getId() == $selected_kategorie ? ' selected' : '') ?>><?= htmlReady($kategorie->name) ?></option>
+ <? endforeach; ?>
+ </select>
+</form>
diff --git a/app/views/shared/language_chooser.php b/app/views/shared/language_chooser.php
new file mode 100644
index 0000000..7777b16
--- /dev/null
+++ b/app/views/shared/language_chooser.php
@@ -0,0 +1,14 @@
+<div class="mvv-widget-right">
+ <div class="mvv-inst-chooser">
+ <select id="mvv-language-chooser-select" style="display: inline;" name="<?= $chooser_id ?>">
+ <option class="mvv-inst-chooser-level" value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($chooser_languages as $key => $language) : ?>
+ <option class="" data-fb="<?= $key ?>" value="<?= $key ?>">
+ <?= htmlReady($language['name']); ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <span class="mvv-inst-add-button"><?= Icon::create('arr_2up', 'clickable', ['title' => _('Sprache zuordnen')])->asImg(); ?></span>
+ </div>
+ <?= $addition ?>
+</div>
diff --git a/app/views/shared/log_event/show.php b/app/views/shared/log_event/show.php
new file mode 100644
index 0000000..ea96f89
--- /dev/null
+++ b/app/views/shared/log_event/show.php
@@ -0,0 +1,68 @@
+<?
+use Studip\Button, Studip\LinkButton;
+?>
+<form action="<?= $controller->url_for('shared/log_event/show', $object_type, $object_id) ?>" method="post">
+ <? if ($object2_type) : ?>
+ <input type="hidden" name="object2_type" value="<?= htmlReady($object2_type) ?>">
+ <input type="hidden" name="object2_id" value="<?= htmlReady($object2_id) ?>">
+ <? endif; ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <span style="float:left;"><h3><?= _('Anzeige der Log-Events') ?></h3></span>
+ <span class="text-bottom" style="float:right; font-size: smaller;">
+ <select name="format">
+ <option value="compact"><?= _('Kompaktdarstellung') ?></option>
+ <option value="detail" <?= ($format == 'detail') ? 'selected="selected"' : ''?>>
+ <?= _('Detaildarstellung') ?>
+ </option>
+ </select>
+ &nbsp;
+ <?= Button::create(_('Anzeigen'),'Anzeigen',['data-dialog' => '']) ?>
+ </span>
+ <? if (isset($error_msg)): ?>
+ <?= MessageBox::error($error_msg) ?>
+ <? endif ?>
+ <? if (isset($log_events)): ?>
+ <table class="default">
+ <tr>
+ <th>
+ <?= _('Zeit') ?>
+ </th>
+ <th>
+ <?= _('Info') ?>
+ </th>
+ </tr>
+ <? foreach ($log_events as $log_event): ?>
+ <tr class="<?= TextHelper::cycle('table_row_even', 'table_row_odd') ?>">
+ <td style="font-size: smaller; white-space: nowrap;">
+ <?= date('d.m.Y H:i:s', $log_event['time']) ?>
+ </td>
+ <td style="font-size: smaller;">
+ <?= $log_event['info'] ?>
+ <? $feld = explode('.', $log_event['detail']); ?>
+ <? $element = count($feld) > 1 ? $feld[1] : $feld[0]; ?>
+ <? if ($format === 'detail' && $element): ?>
+ <br><?= _('Element:').' '. htmlReady($element) ?>
+ <? endif ?>
+ <? if ($format === 'detail' && $log_event['debug']): ?>
+ <br><?= _('Wert:').' '. htmlReady($log_event['debug']) ?>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </table>
+ <p>
+ <? if (count($log_events) > 0): ?>
+ <?= sprintf(_('Eintrag %s - %s von %s'), $start + 1, $start + count($log_events), $num_entries) ?>
+ <input type="hidden" name="start" value="<?= $start ?>">
+ <? if ($start > 0): ?>
+ <?= Button::create('<< '. _("Zurück"), 'back',['data-dialog' => '']) ?>
+ <? endif ?>
+ <? if ($start + count($log_events) < $num_entries): ?>
+ <?= Button::create(_('Weiter') . " >>", 'forward',['data-dialog' => '']) ?>
+ <? endif ?>
+ <? else: ?>
+ <?= _('keine Einträge gefunden') ?>
+ <? endif ?>
+ </p>
+ <? endif ?>
+</form>
diff --git a/app/views/shared/modul/_modul.php b/app/views/shared/modul/_modul.php
new file mode 100644
index 0000000..c953634
--- /dev/null
+++ b/app/views/shared/modul/_modul.php
@@ -0,0 +1,235 @@
+<? $modulDeskriptor = $modul->getDeskriptor($display_language); ?>
+<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modul->getId(); ?>" data-mvv-type="modul">
+ <colgroup>
+ <col width="30%">
+ <col width="70%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th class="mvv-modul-details-head" data-mvv-field="mvv_modul.code"><?= htmlReady($modul->code) ?></th>
+ <th class="mvv-modul-details-head" data-mvv-field="mvv_modul.kp" style="text-align: right;"><?= sprintf("%d CP", $modul->kp) ?></th>
+ </tr>
+ <? if ($show_synopse || $modul->fassung_nr): ?>
+ <tr>
+ <th colspan="2" style="font-weight: normal;">
+ <? if ($show_synopse) : ?>
+ <?=
+ sprintf(_('In der Fassung des <b>%s</b>. Beschlusses vom <b>%s</b> (<b>%s</b>) / Version <b>%s</b>.'),
+ '<span data-mvv-field="mvv_modul.fassung_nr">' . htmlReady($modul->fassung_nr) . '</span>',
+ '<span data-mvv-field="mvv_modul.beschlussdatum">' . date('d.m.Y', $modul->beschlussdatum) . '</span>',
+ '<span data-mvv-field="mvv_modul.fassung_typ">' . htmlReady($GLOBALS['MVV_MODUL']['FASSUNG_TYP'][$modul->fassung_typ]['name']) . '</span>',
+ '<span data-mvv-field="mvv_modul.version">' . htmlReady($modul->version) . '</span>'
+ )
+ ?>
+ <? elseif ($modul->fassung_nr) : ?>
+ <?=
+ sprintf(_('In der Fassung des <b>%s</b>. Beschlusses vom <b>%s</b>.'),
+ '<span data-mvv-field="mvv_modul.fassung_nr">' . htmlReady($modul->fassung_nr) . '</span>',
+ '<span data-mvv-field="mvv_modul.beschlussdatum">' . date('d.m.Y', $modul->beschlussdatum) . '</span>'
+ )
+ ?>
+ <? endif; ?>
+ </th>
+ </tr>
+ <? endif; ?>
+ </thead>
+ <tbody>
+ <tr>
+ <td><strong><?= _('Modulbezeichnung') ?></strong></td>
+ <td data-mvv-field="mvv_modul.bezeichnung"><?= htmlReady($modulDeskriptor->bezeichnung) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Modulcode') ?></strong></td>
+ <td data-mvv-field="mvv_modul.code"><?= htmlReady($modul->code) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Semester der erstmaligen Durchführung') ?></strong></td>
+ <td data-mvv-field="mvv_modul.start"><?= htmlReady($startSemester['name']) ?></td>
+ </tr>
+ <? if ($instituteName) : ?>
+ <tr>
+ <td><strong><?= _('Fachbereich/Institut') ?></strong></td>
+ <td data-mvv-field="mvv_modul_inst"><?= htmlReady($instituteName) ?></td>
+ </tr>
+ <? endif; ?>
+ <tr>
+ <td><strong><?= _('Verwendet in Studiengängen / Semestern') ?></strong></td>
+ <td>
+ <? $trails = $modul->getTrails(['StgteilAbschnitt', 'StgteilVersion', 'Studiengang']); ?>
+ <? $trails = array_filter($trails, function ($trail) {
+ return $trail['Studiengang']->stat !== 'ausgelaufen';
+ }); ?>
+ <? if (count($trails)) : ?>
+ <? $pathes = $modul->getPathes($trails, ' > ') ?>
+ <? if (count($pathes) > 9) : ?>
+ <input type="checkbox" class="mvv-cb-more" id="cb_more_studycourses" checked>
+ <? endif; ?>
+ <ul>
+ <? foreach ($pathes as $i => $path) : ?>
+ <? $version = $trails[$i]['StgteilVersion']['version_id'];?>
+ <? $statement = DBManager::get()->prepare(
+ 'SELECT `mvv_stgteilabschnitt_modul`.`abschnitt_id` '
+ . 'FROM mvv_stgteilabschnitt_modul LEFT JOIN mvv_stgteilabschnitt USING(abschnitt_id) '
+ . 'WHERE modul_id = ? AND version_id = ?');
+ $statement->execute([$modul->getId(), $version]);
+ $res = $statement->fetchOne();
+ $affect_id = $res['abschnitt_id'];
+ ?>
+ <li data-mvv-field="mvv_stgteilabschnitt_modul" data-mvv-id="<?= $affect_id; ?>" data-mvv-cooid="<?= $modul->getId(); ?>">
+ <?= htmlReady($path)?>
+ <? if (!$download && (count($pathes) > 9 && $i == 4)) : ?>
+ <label class="cb-more-label" for="cb_more_studycourses"><?= _('mehr...') ?></label>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Modulverantwortliche/r') ?></strong></td>
+ <td>
+ <?
+ $modulVerantwortung = [];
+ foreach ($modul->contact_assignments->orderBy('position', SORT_NUMERIC) as $contact_assignment) {
+ if ($GLOBALS['MVV_MODUL']['PERSONEN_GRUPPEN']['values'][$contact_assignment->category]['visible']) {
+ if (!isset($modulVerantwortung[$contact_assignment->category])) {
+ $modulVerantwortung[$contact_assignment->category] = [
+ 'name' => $GLOBALS['MVV_MODUL']['PERSONEN_GRUPPEN']['values'][$contact_assignment->category]['name'],
+ 'users' => []
+ ];
+ }
+ $modulVerantwortung[$contact_assignment->category]['contacts'][$contact_assignment->contact_id] = [
+ 'name' => $contact_assignment->contact->getDisplayName(),
+ 'id' => $contact_assignment->contact_id
+ ];
+ }
+ }
+ ?>
+ <? foreach ($modulVerantwortung as $group): ?>
+ <? foreach ($group['contacts'] as $contact): ?>
+ <div data-mvv-field="mvv_modul_user" data-mvv-coid="<?= $contact['id'] ?>">
+ <?= htmlReady($contact['name']) ?> (<?= htmlReady($group['name']) ?>)
+ </div>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ </td>
+ </tr>
+ <? if (trim($modulDeskriptor->verantwortlich)): ?>
+ <tr>
+ <td><strong><?= _('Weitere verantwortliche Personen') ?></strong></td>
+ <td>
+ <?= formatReady($modulDeskriptor->verantwortlich) ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <tr>
+ <td><strong><?= _('Teilnahmevoraussetzungen') ?></strong></td>
+ <td data-mvv-field="mvv_modul_deskriptor.voraussetzung"><?= formatReady($modulDeskriptor->voraussetzung) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Kompetenzziele') ?></strong></td>
+ <td data-mvv-field="mvv_modul_deskriptor.kompetenzziele"><?= formatReady($modulDeskriptor->kompetenzziele) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Modulinhalte') ?></strong></td>
+ <td data-mvv-field="mvv_modul_deskriptor.inhalte"><?= formatReady($modulDeskriptor->inhalte) ?></td>
+ </tr>
+ <? if ($type !== 3) : ?>
+ <tr>
+ <td><strong><?= ngettext('Lehrveranstaltungsform', 'Lehrveranstaltungsformen', count($modul->modulteile)) ?></strong></td>
+ <td data-mvv-field="mvv_modulteil_deskriptor.lernlehrform">
+ <? foreach ($modul->modulteile as $modulteil) : ?>
+ <? if (trim($modulteil->lernlehrform)) : ?>
+ <?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulteil->lernlehrform]['name'] ?>
+ <? if (trim($modulteil->sws) && trim($modulteil->sws) != '0') : ?>
+ (<?= htmlReady($modulteil->sws) . ' ' . _('SWS') ?>)
+ <? endif; ?>
+ <br>
+ <? endif; ?>
+ <? endforeach; ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <tr>
+ <td><strong><?= ngettext('Unterrichtssprache', 'Unterrichtsprachen', sizeof($modul->languages)) ?></strong></td>
+ <td data-mvv-field="mvv_modul_language">
+ <?= htmlReady(implode(', ', $modul->languages->map(function ($m) { return $m->getDisplayName(); }))); ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Dauer in Semestern') ?></strong></td>
+ <td data-mvv-field="mvv_modul.dauer"><?= htmlReady($modul->dauer) ?> <?= _('Semester') ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Angebotsrhythmus Modul') ?></strong></td>
+ <td data-mvv-field="mvv_modul_deskriptor.turnus"><?= htmlReady($modulDeskriptor->turnus) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Aufnahmekapazität Modul') ?></strong></td>
+ <td data-mvv-field="mvv_modul.kapazitaet"><?= htmlReady(trim($modul->kapazitaet)) ?: _('unbegrenzt') ?> <?= MVVController::trim($modulDeskriptor->kommentar_kapazitaet) ? sprintf("(%s)", formatReady($modulDeskriptor->kommentar_kapazitaet)) : '' ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Prüfungsebene') ?></strong></td>
+ <td data-mvv-field="mvv_modul.pruef_ebene"><?= htmlReady($pruefungsEbene) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Credit-Points') ?></strong></td>
+ <td data-mvv-field="mvv_modul.kp"><?= sprintf("%d CP", htmlReady($modul->kp)) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Modulabschlussnote') ?></strong></td>
+ <td>
+ <? if ($type !== 3) : ?>
+ <? $nummer_modulteil = 1; ?>
+ <? $note = []; ?>
+ <? foreach ($modul->modulteile as $modulteil): ?>
+ <? // Für die Kenntlichmachung der Modulteile in Listen die Nummer des
+ // Modulteils und den ausgewählten Namen verwenden.
+ // Ist keine Nummer vorhanden, dann Durchnummerieren und Standard-
+ // Bezeichnung verwenden.
+ if (trim($modulteil->nummer)) {
+ $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulteil->num_bezeichnung]['name'];
+ $note[] = sprintf('%s %s: %s%%',
+ '<span data-mvv-id="'. $modulteil->getId().'" data-mvv-type="modulteil">' .
+ '<span data-mvv-field="mvv_modulteil.num_bezeichnung">' . htmlReady($num_bezeichnung) . '</span>',
+ '<span data-mvv-field="mvv_modulteil.nummer">' . htmlReady($modulteil->nummer) . '</span>',
+ '<span data-mvv-field="mvv_modulteil.anteil_note">' . htmlReady($modulteil->anteil_note) . '</span>' .
+ '</span>'
+ );
+ } else {
+ $num_bezeichnung_default = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['default'];
+ $note[] = sprintf('%s %d: %s%%',
+ htmlReady($GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$num_bezeichnung_default]['name']),
+ htmlReady($nummer_modulteil),
+ htmlReady($modulteil->anteil_note)
+ );
+ $nummer_modulteil++;
+ } ?>
+ <? endforeach; ?>
+ <? if (count($note)) : ?>
+ <?= implode('; ', $note) . '. ' ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= formatReady(trim($modulDeskriptor->kommentar_note)) ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Faktor der Modulnote für die Endnote des Studiengangs') ?></strong></td>
+ <td data-mvv-field="mvv_modul.faktor_note"><?= htmlReady($modul->faktor_note) ?></td>
+ </tr>
+ <? if (trim($modulDeskriptor->kommentar)) : ?>
+ <tr>
+ <td><strong><?= _('Hinweise') ?></strong></td>
+ <td data-mvv-field="mvv_modul_deskriptor.kommentar"><?= formatReady($modulDeskriptor->kommentar) ?></td>
+ </tr>
+ <? endif; ?>
+ <? foreach ($modulDeskriptor->datafields as $entry) : ?>
+ <? $df = $entry->getTypedDatafield(); ?>
+ <tr>
+ <td><strong><?= htmlReady($df->getName()) ?></strong></td>
+ <td><?= $df->getDisplayValue(); ?></td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+</table>
diff --git a/app/views/shared/modul/_modul_ohne_lv.php b/app/views/shared/modul/_modul_ohne_lv.php
new file mode 100644
index 0000000..07e5310
--- /dev/null
+++ b/app/views/shared/modul/_modul_ohne_lv.php
@@ -0,0 +1,37 @@
+<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modul->getId(); ?>" data-mvv-type="modul">
+ <tbody>
+ <? $modulSumme = $modul->wl_selbst + $modul->wl_pruef ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload selbstgestaltete Arbeit') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modul.wl_selbst mvv_modul_deskriptor.kommentar_wl_selbst"><?= htmlReady($modul->wl_selbst) ?> <?= MVVController::trim($modulDeskriptor->kommentar_wl_selbst) ? sprintf(" (%s)", formatReady($modulDeskriptor->kommentar_wl_selbst)) : '' ?></td>
+
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload Prüfung incl. Vorbereitung') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modul.wl_pruef mvv_modul_deskriptor.kommentar_wl_pruef"><?= htmlReady($modul->wl_pruef) ?> <?= MVVController::trim($modulDeskriptor->kommentar_wl_pruef) ? sprintf(" (%s)", formatReady($modulDeskriptor->kommentar_wl_pruef)) : '' ?></td>
+
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload insgesamt') ?></strong></td>
+ <td style="width: 70%;"><?= $modulSumme ?></td>
+ </tr>
+ </tbody>
+</table>
+<table class="mvv-modul-details" data-mvv-id="<?= $modulDeskriptor?$modulDeskriptor->getId():''; ?>" data-mvv-type="moduldeskriptor">
+ <tbody>
+ <? if (trim($modulDeskriptor->pruef_vorleistung)) : ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Prüfungsvorleistung') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_vorleistung" ><?= formatReady($modulDeskriptor->pruef_vorleistung) ?></td>
+ </tr>
+ <? endif; ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Prüfungsform') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_leistung"><?= formatReady($modulDeskriptor->pruef_leistung) ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Wiederholungsprüfung') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_wiederholung"><?= formatReady($modulDeskriptor->pruef_wiederholung) ?></td>
+ </tr>
+ </tbody>
+</table>
diff --git a/app/views/shared/modul/_modullv.php b/app/views/shared/modul/_modullv.php
new file mode 100644
index 0000000..f5df0a6
--- /dev/null
+++ b/app/views/shared/modul/_modullv.php
@@ -0,0 +1,102 @@
+<? $modulTeil = $modul->modulteile->first(); ?>
+<? $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language); ?>
+<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulTeil->id; ?>" data-mvv-type="modulteil">
+ <tbody>
+ <? $modulTeilSumme = $modulTeil->wl_praesenz + $modulTeil->wl_bereitung + $modulTeil->wl_selbst + $modulTeil->wl_pruef ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Lehrveranstaltungsform') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulTeil->lernlehrform]['name'] ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Veranstaltungstitel') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"><?= htmlReady($modulTeilDeskriptor->bezeichnung) ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('SWS') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.sws mvv_modulteil_deskriptor.sws_alternative"><?= $modulTeil->sws ?: '' ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload Präsenz') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"><?= $modulTeil->wl_praesenz ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_praesenz) ? sprintf(" (%s)", formatReady($modulTeilDeskriptor->kommentar_wl_praesenz)) : '' ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload Vor- / Nachbereitung') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"><?= $modulTeil->wl_bereitung ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_bereitung) ? sprintf(" (%s)", formatReady($modulTeilDeskriptor->kommentar_wl_bereitung)) : '' ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload selbstgestaltete Arbeit') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"><?= $modulTeil->wl_selbst ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_selbst) ? sprintf(" (%s)", formatReady($modulTeilDeskriptor->kommentar_wl_selbst)) : '' ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload Prüfung incl. Vorbereitung') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"><?= $modulTeil->wl_pruef ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_pruef) ? sprintf(" (%s)", formatReady($modulTeilDeskriptor->kommentar_wl_pruef)) : '' ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload insgesamt') ?></strong></td>
+ <td style="width: 70%;"><?= $modulTeilSumme ?></td>
+ </tr>
+ <? if ((int) $modul->wl_selbst) : ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload selbstgestaltete Arbeit (modulbezogen') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modul.wl_selbst mvv_modul_deskriptor.kommentar_wl_selbst"><?= $modul->wl_selbst ?> <?= MVVController::trim($modulDeskriptor->kommentar_wl_selbst) ? sprintf(" (%s)", formatReady($modulDeskriptor->kommentar_wl_selbst)) : '' ?></td>
+ </tr>
+ <? endif; ?>
+ <? if ((int) $modul->wl_pruef) : ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload Prüfung incl. Vorbereitung (modulbezogen)') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modul.wl_pruef mvv_modul_deskriptor.kommentar_wl_pruef"><?= $modul->wl_pruef ?> <?= MVVController::trim($modulDeskriptor->kommentar_wl_pruef) ? sprintf(" (%s)", formatReady($modulDeskriptor->kommentar_wl_pruef)) : '' ?></td>
+ </tr>
+ <? endif; ?>
+ <? if ($modul->wl_selbst + $modul->wl_pruef) : ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Workload Modul insgesamt') ?></strong></td>
+ <td style="width: 70%;"><?= $modulTeilSumme + $modul->wl_selbst + $modul->wl_pruef ?></td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+</table>
+<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulTeilDeskriptor->id; ?>" data-mvv-type="modulteil_deskriptor">
+ <tbody>
+ <? if (trim($modulTeilDeskriptor->pruef_vorleistung)) : ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Prüfungsvorleistung') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.pruef_vorleistung"><?= formatReady($modulTeilDeskriptor->pruef_vorleistung) ?></td>
+ </tr>
+ <? endif; ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Prüfungsform') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.pruef_leistung"><?= formatReady($modulTeilDeskriptor->pruef_leistung) ?></td>
+ </tr>
+ </tbody>
+</table>
+<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulTeil->id; ?>" data-mvv-type="modulteil">
+ <tbody>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Angebotsrhythmus') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.semester"><?= $GLOBALS['MVV_NAME_SEMESTER']['values'][$modulTeil->semester]['name'] ?></td>
+ </tr>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Aufnahmekapazität') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.kapazitaet mvv_modulteil_deskriptor.kommentar_kapazitaet"><?= trim($modulTeil->kapazitaet) ?: _('unbegrenzt') ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_kapazitaet) ? sprintf("(%s)", formatReady($modulTeilDeskriptor->kommentar_kapazitaet)) : '' ?></td>
+ </tr>
+ <? if ($modulTeil->pflicht) : ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= _('Anwesenheitspflicht') ?></strong></td>
+ <td style="width: 70%;" data-mvv-field="mvv_modulteil.pflicht mvv_modulteil_deskriptor.kommentar_pflicht"><?= $modulTeil->pflicht ? _('Ja') : _('Nein') ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_pflicht) ? sprintf("(%s)", formatReady($modulTeilDeskriptor->kommentar_pflicht)) : '' ?></td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+</table>
+<? if (count($modulTeilDeskriptor->datafields)) : ?>
+<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulTeilDeskriptor->id; ?>" data-mvv-type="modulteil_deskriptor">
+ <tbody>
+ <? foreach ($modulTeilDeskriptor->datafields as $entry) : ?>
+ <? $df = $entry->getTypedDatafield(); ?>
+ <tr>
+ <td style="width: 30%;"><strong><?= htmlReady($df->getName()) ?></strong></td>
+ <td style="width: 70%;"><?= $df->getDisplayValue(); ?></td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+</table>
+<? endif; ?>
diff --git a/app/views/shared/modul/_modullvs.php b/app/views/shared/modul/_modullvs.php
new file mode 100644
index 0000000..c288d5a
--- /dev/null
+++ b/app/views/shared/modul/_modullvs.php
@@ -0,0 +1,82 @@
+<table class="mvv-modul-details default nohover">
+ <thead>
+ <tr>
+ <th><?= _('Modulveran&shy;staltung') ?></th>
+ <th><?= _('Lehrveranstaltungs&shy;form') ?></th>
+ <th><?= _('Veranstaltungs&shy;titel') ?></th>
+ <th><?= _('SWS') ?></th>
+ <th><?= _('Workload Präsenz') ?></th>
+ <th><?= _('Workload Vor- / Nach&shy;bereitung') ?></th>
+ <th><?= _('Workload selbstge&shy;staltete Arbeit') ?></th>
+ <th><?= _('Workload Prüfung incl. Vorbereitung') ?></th>
+ <th><?= _('Workload Summe') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $wlSelbst = 0; ?>
+ <? $wlPruef = 0; ?>
+ <? $modulSumme = 0; ?>
+ <? $nummer_modulteil = 1; ?>
+ <? foreach ($modul->modulteile as $modulTeil): ?>
+ <? $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language);
+ // Für die Kenntlichmachung der Modulteile in Listen die Nummer des
+ // Modulteils und den ausgewählten Namen verwenden.
+ // Ist keine Nummer vorhanden, dann Durchnummerieren und Standard-
+ // Bezeichnung verwenden.
+ if (trim($modulTeil->nummer)) {
+ $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulTeil->num_bezeichnung]['name'];
+ $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulTeil->nummer);
+ } else {
+ $num_bezeichnung_default = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['default'];
+ $name_kurz = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$num_bezeichnung_default]['name']
+ . ' ' . $nummer_modulteil;
+ $nummer_modulteil++;
+ } ?>
+ <? $wlSelbst += $modulTeil->wl_selbst; ?>
+ <? $wlPruef += $modulTeil->wl_pruef; ?>
+ <? $modulTeilSumme = $modulTeil->wl_praesenz + $modulTeil->wl_bereitung + $modulTeil->wl_selbst + $modulTeil->wl_pruef; ?>
+ <? $modulSumme += $modulTeilSumme; ?>
+ <? if ($show_synopse) : ?>
+ <tr data-mvv-id="<?= $modulTeil->getId(); ?>" data-mvv-type="modulteil">
+ <td data-mvv-field="mvv_modulteil.nummer mvv_modulteil.num_bezeichnung"><strong><?= htmlReady($name_kurz) ?></strong></td>
+ <td data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulTeil->lernlehrform]['name'] ?></td>
+ <td data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"><?= htmlReady($modulTeilDeskriptor->bezeichnung) ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.sws"><?= htmlReady($modulTeil->sws) ?: '' ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"><?= $modulTeil->wl_praesenz ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_praesenz) ? sprintf(' (%s)', formatReady($modulTeilDeskriptor->kommentar_wl_praesenz)) : '' ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"><?= $modulTeil->wl_bereitung ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_bereitung) ? sprintf(' (%s)', formatReady($modulTeilDeskriptor->kommentar_wl_bereitung)) : '' ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"><?= $modulTeil->wl_selbst ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_selbst) ? sprintf(' (%s)', formatReady($modulTeilDeskriptor->kommentar_wl_selbst)) : '' ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"><?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_pruef) ? sprintf(' (%s)',formatReady($modulTeilDeskriptor->kommentar_wl_pruef)) : '' ?><?= $modulTeil->wl_pruef ?></td>
+ <td style="text-align: right;"><?= $modulTeilSumme ?></td>
+ </tr>
+ <? else : ?>
+ <tr data-mvv-id="<?= $modulTeil->getId(); ?>" data-mvv-type="modulteil">
+ <td data-mvv-field="mvv_modulteil.nummer mvv_modulteil.num_bezeichnung"><strong><?= htmlReady($name_kurz) ?></strong></td>
+ <td data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulTeil->lernlehrform]['name'] ?></td>
+ <td data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"><?= htmlReady($modulTeilDeskriptor->bezeichnung) ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.sws"><?= htmlReady($modulTeil->sws) ?: '' ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"><?= $modulTeil->wl_praesenz ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_praesenz) ? tooltipIcon(formatReady($modulTeilDeskriptor->kommentar_wl_praesenz)) : '' ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"><?= $modulTeil->wl_bereitung ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_bereitung) ? tooltipIcon(formatReady($modulTeilDeskriptor->kommentar_wl_bereitung)) : '' ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"><?= $modulTeil->wl_selbst ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_selbst) ? tooltipIcon(formatReady($modulTeilDeskriptor->kommentar_wl_selbst)) : '' ?></td>
+ <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"><?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_pruef) ? tooltipIcon(formatReady($modulTeilDeskriptor->kommentar_wl_pruef)) : '' ?><?= $modulTeil->wl_pruef ?></td>
+ <td style="text-align: right;"><?= $modulTeilSumme ?></td>
+ </tr>
+ <? endif; ?>
+ <? endforeach; ?>
+ <?
+ $modulWLSumme = $modul->wl_selbst + $modul->wl_pruef;
+ $modulSumme += $modulWLSumme;
+ ?>
+ <? if ($modulWLSumme > 0) : ?>
+ <tr>
+ <td colspan="6"><strong><?= _('Workload modulbezogen') ?></strong></td>
+ <td style="text-align: right;"><?= htmlReady($modul->wl_selbst) ?></td>
+ <td style="text-align: right;"><?= htmlReady($modul->wl_pruef) ?></td>
+ <td style="text-align: right;"><?= $modulWLSumme ?></td>
+ </tr>
+ <? endif; ?>
+ <tr>
+ <td colspan="8"><strong><?= _('Workload Modul insgesamt') ?></strong></td>
+ <td style="text-align: right;"><?= $modulSumme ?></td>
+ </tr>
+ </tbody>
+</table>
diff --git a/app/views/shared/modul/_pruefungen.php b/app/views/shared/modul/_pruefungen.php
new file mode 100644
index 0000000..f28657e
--- /dev/null
+++ b/app/views/shared/modul/_pruefungen.php
@@ -0,0 +1,50 @@
+<table class="mvv-modul-details default nohover">
+ <thead>
+ <tr>
+ <th><?= _('Prüfung') ?></th>
+ <th><?= _('Prüfungsvorleistung') ?></th>
+ <th><?= _('Prüfungsform') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($modul->modulteile as $modulTeil): ?>
+ <?
+ $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language);
+ // Für die Kenntlichmachung der Modulteile in Listen die Nummer des
+ // Modulteils und den ausgewählten Namen verwenden.
+ // Ist keine Nummer vorhanden, dann Durchnummerieren und Standard-
+ // Bezeichnung verwenden.
+ if (trim($modulTeil->nummer)) {
+ $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulTeil->num_bezeichnung]['name'];
+ $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulTeil->nummer);
+ } else {
+ $num_bezeichnung_default = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['default'];
+ $name_kurz = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$num_bezeichnung_default]['name']
+ . ' ' . $nummer_modulteil;
+ $nummer_modulteil++;
+ }
+ ?>
+ <tr data-mvv-id="<?= $modulTeil->getId(); ?>" data-mvv-type="modulteil">
+ <td style="vertical-align: top; font-weight: bold;" data-mvv-field="mvv_modulteil.num_bezeichnung mvv_modulteil.nummer"><?= htmlReady($name_kurz) ?></td>
+ <td data-mvv-field="mvv_modulteil_deskriptor.pruef_vorleistung"><?= formatReady($modulTeilDeskriptor->pruef_vorleistung) ?></td>
+ <td data-mvv-field="mvv_modulteil_deskriptor.pruef_leistung"><?= formatReady($modulTeilDeskriptor->pruef_leistung) ?></td>
+ </tr>
+ <? endforeach; ?>
+ <tr data-mvv-id="<?= $modul->getId(); ?>" data-mvv-type="modul">
+ <? $modulDeskriptor = $modul->getDeskriptor($display_language) ?>
+ <td style="vertical-align: top; font-weight: bold;">
+ <?= _('Gesamtmodul') ?>
+ </td>
+ <td data-mvv-field="mvv_modul_deskriptor.pruef_vorleistung"><?= formatReady($modulDeskriptor->pruef_vorleistung) ?></td>
+ <td data-mvv-field="mvv_modul_deskriptor.pruef_leistung"><?= formatReady($modulDeskriptor->pruef_leistung) ?></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top; font-weight: bold;">
+ <?= _('Wiederholungsprüfung') ?>
+ </td>
+ <td colspan="3">
+ <?= formatReady($modulDeskriptor->pruef_wiederholung) ?>
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/app/views/shared/modul/_regularien.php b/app/views/shared/modul/_regularien.php
new file mode 100644
index 0000000..26196b0
--- /dev/null
+++ b/app/views/shared/modul/_regularien.php
@@ -0,0 +1,38 @@
+<table class="mvv-modul-details default nohover">
+ <thead>
+ <tr>
+ <th><?= _('Regularien') ?></th>
+ <th><?= _('Teilnahme&shy;voraussetzungen') ?></th>
+ <th><?= _('Angebots&shy;rhythmus') ?></th>
+ <th><?= _('Anwesenheits&shy;pflicht') ?></th>
+ <th><?= _('Gewicht an Modulnote in %') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($modul->modulteile as $modulTeil): ?>
+ <?
+ $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language);
+ // Für die Kenntlichmachung der Modulteile in Listen die Nummer des
+ // Modulteils und den ausgewählten Namen verwenden.
+ // Ist keine Nummer vorhanden, dann Durchnummerieren und Standard-
+ // Bezeichnung verwenden.
+ if (trim($modulTeil->nummer)) {
+ $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulTeil->num_bezeichnung]['name'];
+ $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulTeil->nummer);
+ } else {
+ $num_bezeichnung_default = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['default'];
+ $name_kurz = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$num_bezeichnung_default]['name']
+ . ' ' . $nummer_modulteil;
+ $nummer_modulteil++;
+ }
+ ?>
+ <tr data-mvv-id="<?= $modulTeil->getId(); ?>" data-mvv-type="modulteil">
+ <td style="vertical-align: top; font-weight: bold;" data-mvv-field="mvv_modulteil.nummer mvv_modulteil.num_bezeichnung"><?= $name_kurz ?></td>
+ <td data-mvv-field="mvv_modulteil_deskriptor.voraussetzung"><?= formatReady($modulTeilDeskriptor->voraussetzung) ?></td>
+ <td data-mvv-field="mvv_modulteil.semester"><?= $GLOBALS['MVV_NAME_SEMESTER']['values'][$modulTeil->semester]['name'] ?></td>
+ <td data-mvv-field="mvv_modulteil.pflicht"><?= ($modulTeil->pflicht ? _('Ja') : _('Nein')) ?> <?= $modulTeilDeskriptor->kommentar_pflicht ? formatReady($modulTeilDeskriptor->kommentar_pflicht) : '' ?></td>
+ <td data-mvv-field="mvv_modulteil.anteil_note"><?= $modulTeil->anteil_note ?>%</td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/app/views/shared/modul/description.php b/app/views/shared/modul/description.php
new file mode 100644
index 0000000..5aac378
--- /dev/null
+++ b/app/views/shared/modul/description.php
@@ -0,0 +1,22 @@
+<? if (count($modul->deskriptoren) > 1): ?>
+<div style="width: 100%; text-align: right;">
+ <? foreach ($modul->deskriptoren->getAvailableTranslations() as $language) : ?>
+ <? $lang = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$language]; ?>
+ <a data-dialog="size=auto;title='<?= htmlReady($modul->getDisplayName()) ?>'" href="<?= $controller->url_for('/description/' . $modul->id . '/', ['display_language' => $language]) ?>">
+ <img src="<?= Assets::image_path('languages/lang_' . mb_strtolower($language) . '.gif') ?>" alt="<?= $lang['name'] ?>" title="<?= $lang['name'] ?>">
+ </a>
+ <? endforeach; ?>
+</div>
+<? endif; ?>
+<?= $this->render_partial('shared/modul/_modul') ?>
+<? if ($type === 1) : ?>
+ <?= $this->render_partial('shared/modul/_modullvs') ?>
+ <?= $this->render_partial('shared/modul/_pruefungen') ?>
+ <?= $this->render_partial('shared/modul/_regularien') ?>
+<? endif;?>
+<? if ($type === 2): ?>
+ <?= $this->render_partial('shared/modul/_modullv') ?>
+<? endif; ?>
+<? if ($type === 3) : ?>
+ <?= $this->render_partial('shared/modul/_modul_ohne_lv') ?>
+<? endif; ?> \ No newline at end of file
diff --git a/app/views/shared/modul/overview.php b/app/views/shared/modul/overview.php
new file mode 100644
index 0000000..0f20791
--- /dev/null
+++ b/app/views/shared/modul/overview.php
@@ -0,0 +1,180 @@
+<table class="default mvv-modul-details nohover">
+ <tr>
+ <th class="mvv-modul-details-head" style="width: 30%"><?= htmlReady($modul->code) ?></th>
+ <th class="mvv-modul-details-head" style="width: 30%"><?= htmlReady($institut->name) ?></th>
+ <th class="mvv-modul-details-head" style="width: 40%"><?= sprintf("%d CP", $modul->kp) ?> </th>
+ <th class="mvv-modul-details-head"></th>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <h3><?= htmlReady($deskriptor->bezeichnung) ?></h3>
+ <?= _('Lehrveranstaltungen') ?> <?= htmlReady($semester['name']) ?>
+ </td>
+ <td>
+ <dl>
+ <? foreach ($GLOBALS['MVV_MODUL']['PERSONEN_GRUPPEN']['values'] as $key => $gruppe) : ?>
+ <? $contacts = $modul->contact_assignments->findBy('category', $key)->orderBy('position', SORT_NUMERIC); ?>
+ <? if ($gruppe['visible'] && count($contacts)) : ?>
+ <dt><?= htmlReady($gruppe['name']) ?></dt>
+ <? foreach ($contacts as $modul_contact): ?>
+ <dd><?= htmlReady($modul_contact->contact->getDisplayName()) ?></dd>
+ <? endforeach; ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </dl>
+ </td>
+ <td>
+ <? if ($GLOBALS['perm']->have_perm('admin')) : ?>
+ <a href="<?= URLHelper::getLink("dispatch.php/shared/modul/mail/{$modul->id}/{$semester['semester_id']}")?>" data-dialog>
+ <?= Icon::create('mail', Icon::ROLE_CLICKABLE, tooltip2(_('Nachricht an alle Veranstaltungteilnehmer die diesem Modul zugeordnet sind.')))?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="4" style="padding: 0;">
+ <table class="default nohover">
+ <? if (mb_strlen($teilnahmeVoraussetzung) > 0): ?>
+ <tr>
+ <td style="width: 20%; font-weight: bold;"><?= _('Teilnahmevoraussetzungen') ?></td>
+ <td ><?= formatReady($teilnahmeVoraussetzung) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->kommentar)) : ?>
+ <tr>
+ <td style="width: 20%; font-weight: bold;"><?= _('Hinweise') ?></td>
+ <td><?= formatReady($deskriptor->kommentar) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->ersatztext) > 0): ?>
+ <tr>
+ <td style="width: 20%; font-weight: bold;"> </td>
+ <td><?= formatReady($deskriptor->ersatztext) ?></td>
+ </tr>
+ <? else: ?>
+
+ <? if ($modul->kapazitaet > 0): ?>
+ <tr>
+ <td style="width: 20%; font-weight: bold;"><?= _('Kapazität Modul') ?></td>
+ <td>
+ <?= htmlReady($modul->kapazitaet) ?>
+ <? if (mb_strlen($deskriptor->kommentar_kapazitaet) > 0): ?>
+ (<?= formatReady($deskriptor->kommentar_kapazitaet) ?>)
+ <? endif; ?>
+
+ </td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($pruef_ebene) > 0): ?>
+ <tr>
+ <td style="width: 20%; font-weight: bold;"><?= _('Prüfungsebene') ?></td>
+ <td><?= htmlReady($pruef_ebene) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->pruef_vorleistung)) : ?>
+ <tr>
+ <td style="width: 20%; font-weight: bold;"><?= _('Prüfungsvorleistung Modul') ?></td>
+ <td><?= formatReady($deskriptor->pruef_vorleistung) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->pruef_leistung)) : ?>
+ <tr>
+ <td style="width: 20%; font-weight: bold;"><?= _('Prüfungsleistung Modul') ?></td>
+ <td><?= formatReady($deskriptor->pruef_leistung) ?></td>
+ </tr>
+ <? endif; ?>
+ <? if (mb_strlen($deskriptor->kompetenzziele)): ?>
+ <tr>
+ <td style="width: 20%; font-weight: bold;"><?= _('Kompetenzziele') ?></td>
+ <td><?= formatReady($deskriptor->kompetenzziele) ?></td>
+ </tr>
+ <? endif; ?>
+
+ <? endif; ?>
+ </table>
+ </td>
+ </tr>
+ <? if ($type !== 3): ?>
+ <tr>
+ <? if ($type === 1): ?>
+ <th><?= _('Modulteile') ?></th>
+ <? endif; ?>
+ <th <? if ($type === 2): ?> colspan="3" <? endif; ?> ><?= _('Semesterveranstaltungen') ?></th>
+ <? if ($type === 1): ?>
+ <th><?= _('Prüfungsleistung') ?></th>
+ <? endif; ?>
+ </tr>
+ <? foreach ($modulTeile as $modul_teil): ?>
+ <tr>
+ <? if ($type === 1): ?>
+ <td>
+ <b> <?= htmlReady($modul_teil['name']) ?> </b>
+ <? if (mb_strlen($modul_teil['kommentar']) > 0): ?>
+ <?= $modul_teil['kommentar'] ? '<br>(' . formatReady($modul_teil['kommentar']) . ')' : '' ?>
+ <? endif; ?>
+ <? if (mb_strlen($modul_teil['voraussetzung']) > 0): ?>
+ <br>
+ <b><?= _('Teilnahmevoraussetzungen') ?>:</b> <?= formatReady($modul_teil['voraussetzung']) ?>
+ <? endif; ?>
+ </td>
+ <? endif; ?>
+ <td <? if ($type === 2): ?> colspan="3" <? endif; ?>>
+ <? foreach ($modul_teil['lvGruppen'] as $gruppe): ?>
+ <? if (mb_strlen($gruppe['alt_texte']) > 0): ?>
+ <?= formatReady($gruppe['alt_texte']) ?>
+ <? endif; ?>
+ <? if (count($gruppe['courses'])) : ?>
+ <ul>
+ <? foreach ($gruppe['courses'] as $course): ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $course->id]) ?>">
+ <?= htmlReady(($course['VeranstaltungsNummer'] ? $course['VeranstaltungsNummer'] . ' - ' : '') . $course['Name']) ?>
+ </a>
+ <? if ($course['visible'] != 1) : ?>
+ <em><?= _('[versteckt]') ?></em>
+ <? endif; ?>
+ <? if (Config::get()->COURSE_SEARCH_SHOW_ADMISSION_STATE) : ?>
+ <? switch (SemBrowse::getStatusCourseAdmission($course->id, $course->admission_prelim)) :
+ case 1:
+ echo Icon::create('span-2quarter', Icon::ROLE_STATUS_YELLOW, [
+ 'alt' => _('Eingeschränkter Zugang'),
+ 'title' => _('Eingeschränkter Zugang'),
+ 'style' => 'vertical-align: text-bottom',
+ ]);
+ break;
+ case 2:
+ echo Icon::create('span-empty', Icon::ROLE_STATUS_RED, [
+ 'alt' => _('Kein Zugang'),
+ 'title' => _('Kein Zugang'),
+ 'style' => 'vertical-align: text-bottom',
+ ]);
+ break;
+ default:
+ echo Icon::create('span-full', Icon::ROLE_STATUS_GREEN, [
+ 'alt' => _('Uneingeschränkter Zugang'),
+ 'title' => _('Uneingeschränkter Zugang'),
+ 'style' => 'vertical-align: text-bottom',
+ ]);
+ endswitch; ?>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ <? endforeach; ?>
+ </td>
+ <? if ($type === 1) : ?>
+ <td>
+ <? if (mb_strlen($modul_teil['pruef_vorleistung']) > 0) : ?>
+ <b><?= _('Prüfungsvorleistung') ?>:</b> <?= htmlReady($modul_teil['pruef_vorleistung']) ?>
+
+ <? endif; ?>
+ <? if (mb_strlen($modul_teil['pruef_leistung']) > 0) : ?>
+ <b><?= _('Prüfungsform') ?>:</b> <br/><?= htmlReady($modul_teil['pruef_leistung']) ?> (<?= ($modul_teil['anteil_note'] ? '(' . htmlReady($modul_teil['anteil_note']) . '%)' : '') ?>
+ <? endif; ?>
+ </td>
+ <? endif; ?>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+</table>
diff --git a/app/views/shared/modul_variants.php b/app/views/shared/modul_variants.php
new file mode 100644
index 0000000..44be825
--- /dev/null
+++ b/app/views/shared/modul_variants.php
@@ -0,0 +1,11 @@
+<?= ngettext('Folgendes Modul ist Variante dieses Moduls:', 'Folgende Module sind Varianten dieses Moduls', sizeof($variants)) ?>
+<br>
+<ul style="margin: 0; padding-left: 15px;">
+<? foreach ($variants as $variant) : ?>
+ <li>
+ <a href="<?= $link . '/' . $variant->getId() ?>">
+ <?= htmlReady($variant->getDisplayName()) ?>
+ </a>
+ </li>
+<? endforeach; ?>
+</ul> \ No newline at end of file
diff --git a/app/views/shared/mvv_tree.php b/app/views/shared/mvv_tree.php
new file mode 100644
index 0000000..c718b9b
--- /dev/null
+++ b/app/views/shared/mvv_tree.php
@@ -0,0 +1,23 @@
+<? foreach ($tree[$node] as $current) : ?>
+<li>
+ <? if ($current['class'] != 'Modulteil' && $current['id'] != 'root') : ?>
+ <input id="<?= htmlReady($current['id'] . $id_sfx->c) ?>" type="checkbox"<?= $current['class'] != 'StgteilabschnittModul' ? 'checked' : ''?>>
+ <? endif; ?>
+ <label for="<?= htmlReady($current['id'] . $id_sfx->c++) ?>"></label>
+ <? if ($current['class'] == 'StgteilabschnittModul') : ?>
+ <a data-dialog title="<?= htmlReady($current['name']) ?>" href="<?= URLHelper::getLink('dispatch.php/shared/modul/overview/' . $current['id'] . '/' . $course->start_semester->id) ?>">
+ <?= htmlReady($current['name']) ?>
+ </a>
+ <a data-dialog title="<?= htmlReady($current['name']) ?>" href="<?= URLHelper::getLink('dispatch.php/shared/modul/description/' . $current['id']) ?>">
+ <?= Icon::create('log', 'clickable', ['title' => _('Modulbeschreibung')]); ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($current['name']) ?>
+ <? endif; ?>
+ <? if ($current['class'] != 'Modulteil') : ?>
+ <ul>
+ <?= $this->render_partial('shared/mvv_tree.php', ['tree' => $tree, 'node' => $current['id']]) ?>
+ </ul>
+ <? endif; ?>
+</li>
+<? endforeach; ?>
diff --git a/app/views/shared/sort_link.php b/app/views/shared/sort_link.php
new file mode 100644
index 0000000..5146468
--- /dev/null
+++ b/app/views/shared/sort_link.php
@@ -0,0 +1,18 @@
+<?php
+$attributes = array_intersect_key($attributes, array_flip(['style', 'colspan']));
+if ($controller->sortby === $field) {
+ $attributes['class'] = 'sort' . mb_strtolower($controller->order);
+}
+
+$parameters = [
+ "sortby{$controller->page_params_suffix}" => $field,
+];
+if ($controller->sortby !== $field || $controller->order === 'DESC') {
+ $parameters["order{$controller->page_params_suffix}"] = 'ASC';
+} else {
+ $parameters["order{$controller->page_params_suffix}"] = 'DESC';
+}
+?>
+<th <?= arrayToHtmlAttributes($attributes) ?>>
+ <a href="<?= $controller->link_for($action, $parameters) ?>"><?= htmlReady($text) ?></a>
+</th>
diff --git a/app/views/shared/studiengang/_stgteilversion.php b/app/views/shared/studiengang/_stgteilversion.php
new file mode 100644
index 0000000..5c0d144
--- /dev/null
+++ b/app/views/shared/studiengang/_stgteilversion.php
@@ -0,0 +1,50 @@
+<h2><?= htmlReady($version->getDisplayName()) ?></h2>
+<table class="default mvv-modul-details" id="<?= $version->id ?>" data-mvv-id="<?= $version->id; ?>" data-mvv-type="stgteilversion">
+ <tbody>
+ <tr>
+ <td><strong><?= _('Gültigkeit') ?></strong></td>
+ <td nowrap data-mvv-field="mvv_stgteilversion.start_sem mvv_stgteilversion.beschlussdatum">
+ <?= _('von Semester:') ?>
+ <? $sem = Semester::find($version->start_sem) ?>
+ <?= htmlReady($sem->name) ?>
+ <br>
+ <?= _('Beschlussdatum:') ?>
+ <?= ($version->beschlussdatum ? strftime('%d.%m.%Y', $version->beschlussdatum) : '') ?>
+ </td>
+ <td nowrap data-mvv-field="mvv_stgteilversion.end_sem mvv_stgteilversion.fassung_typ">
+ <?= _('bis Semester:') ?>
+ <? if ($version->end_sem != "") : ?>
+ <? $sem = Semester::find($version->end_sem) ?>
+ <?= htmlReady($sem->name) ?>
+ <? else : ?>
+ <?= _('unbegrenzt gültig') ?>
+ <? endif; ?>
+ <br>
+ <?= _('Fassung:') ?>
+ <?= htmlReady($version->fassung_nr) ?>.
+ <?= ($version->fassung_typ === '0' ? '--' : $GLOBALS['MVV_STGTEILVERSION']['FASSUNG_TYP'][$version->fassung_typ]['name']) ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Code') ?></strong></td>
+ <td colspan=2 data-mvv-field="mvv_stgteilversion.code">
+ <?= htmlReady($version->code) ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Beschreibung') ?></strong></td>
+ <td data-mvv-field="mvv_stgteilversion.beschreibung">
+ <?= formatReady($version->beschreibung) ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Status der Bearbeitung') ?></strong></td>
+ <td data-mvv-field="mvv_stgteilversion.stat">
+ <?= $GLOBALS['MVV_STGTEILVERSION']['STATUS']['values'][$version->stat]['name'] ?>
+ </td>
+ <td>
+ <?= formatReady($version->kommentar_status) ?>
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/app/views/shared/studiengang/_studiengang.php b/app/views/shared/studiengang/_studiengang.php
new file mode 100644
index 0000000..e5eb417
--- /dev/null
+++ b/app/views/shared/studiengang/_studiengang.php
@@ -0,0 +1,251 @@
+<h1><?= htmlReady($studiengang->getDisplayName()) ?></h1>
+<table class="default mvv-modul-details" id="<?= $studiengang->id ?>" data-mvv-id="<?= $studiengang->id; ?>" data-mvv-type="studiengang">
+ <tbody>
+ <tr>
+ <td>
+ <strong><?= _('Name des Studiengangs') ?></strong>
+ </td>
+ <td data-mvv-field="mvv_studiengang.name">
+ <?= htmlReady($studiengang->name) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Kurzbezeichnung') ?></strong>
+ </td>
+ <td data-mvv-field="mvv_studiengang.name_kurz">
+ <?= htmlReady($studiengang->name_kurz) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Gültigkeit') ?></strong>
+ </td>
+ <td nowrap>
+ <?= _('von Semester:') ?>
+ <? $sem = Semester::find($studiengang->start) ?>
+ <span data-mvv-field="mvv_studiengang.start">
+ <?= htmlReady($sem->name) ?>
+ </span>
+ <br>
+ <?= _('Beschlussdatum:') ?>
+ <span data-mvv-field="mvv_studiengang.beschlussdatum">
+ <?= ($studiengang->beschlussdatum ? strftime('%d.%m.%Y', $studiengang->beschlussdatum) : '') ?>
+ </span>
+ </td>
+ <td nowrap>
+ <?= _('bis Semester:') ?>
+ <? if ($studiengang->end != "") : ?>
+ <? $sem = Semester::find($studiengang->end) ?>
+ <span data-mvv-field="mvv_studiengang.end">
+ <?= htmlReady($sem->name) ?>
+ </span>
+ <? else : ?>
+ <?= _('unbegrenzt gültig') ?>
+ <? endif; ?>
+ <br>
+ <?= _('Fassung:') ?>
+ <span data-mvv-field="mvv_studiengang.fassung_nr">
+ <?= htmlReady($studiengang->fassung_nr) ?>.
+ </span>
+ <span data-mvv-field="mvv_studiengang.fassung_typ">
+ <?= ($studiengang->fassung_typ === '0' ? '--' : htmlReady($GLOBALS['MVV_STUDIENGANG']['FASSUNG_TYP'][$studiengang->fassung_typ]['name'])) ?>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Beschreibung') ?></strong>
+ </td>
+ <td data-mvv-field="mvv_studiengang.beschreibung">
+ <?= formatReady($studiengang->beschreibung) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Studiengangteile') ?></strong>
+ </td>
+ <td colspan="2" data-mvv-field="mvv_studiengang.typ">
+ <? if($studiengang->typ !== 'mehrfach') :?>
+ <?= _('Diesem Studiengang wird ein Fach direkt zugewiesen') ?>
+ <? else: ?>
+ <?= _('Diesem Studiengang können mehrere Studiengangteile zugewiesen werden.') ?>
+ <? endif;?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Abschluss') ?></strong>
+ </td>
+ <td colspan="2" data-mvv-field="mvv_studiengang.abschluss_id">
+ <? $abschluss = Abschluss::find($studiengang->abschluss_id)?>
+ <?= htmlReady($studiengang->abschluss->getDisplayName()) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Verantwortliche Einrichtung') ?></strong>
+ </td>
+ <td colspan="2" data-mvv-field="mvv_studiengang.institut_id">
+ <? if ($studiengang->responsible_institute) : ?>
+ <?= htmlReady($studiengang->responsible_institute->getDisplayName()) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Status der Bearbeitung') ?></strong>
+ </td>
+ <td colspan="2" data-mvv-field="mvv_studiengang.stat">
+ <?= $GLOBALS['MVV_STUDIENGANG']['STATUS']['values'][$studiengang->stat]['name'] ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Kommentar Status') ?></strong>
+ </td>
+ <td colspan="2" data-mvv-field="mvv_studiengang.schlagworte">
+ <?= formatReady($studiengang->kommentar_status) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Schlagworte') ?></strong>
+ </td>
+ <td colspan="2" data-mvv-field="mvv_studiengang.schlagworte">
+ <?= htmlReady($studiengang->schlagworte) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Dauer') ?>:</strong>
+ </td>
+ <td>
+ <? printf('%s Semester', htmlReady($studiengang->studienzeit)) ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Abschlussgrad') ?>:</strong>
+ </td>
+ <td>
+ <?= htmlReady($GLOBALS['MVV_STUDIENGANG']['ABSCHLUSSGRAD']['values'][$studiengang->abschlussgrad]['name']) ?>
+ </td>
+ </tr>
+ <? if (count($studiengang->languages)) : ?>
+ <tr>
+ <td>
+ <strong><?= _('Sprache') ?>:</strong>
+ </td>
+ <td>
+ <?= htmlReady(implode('/', $studiengang->languages->pluck('display_name'))) ?>
+ </td>
+ </tr>
+ <? endif ?>
+
+ <? foreach ($studiengang->datafields as $df) : ?>
+ <? if (mb_strpos($df->datafield->object_class, 'settings') !== false
+ && !$df->isNew()) : ?>
+ <? $tdf = $df->getTypedDatafield(); ?>
+ <? if ($tdf->isVisible() && trim($tdf->getValue())) : ?>
+ <tr>
+ <td>
+ <strong><?= htmlReady($tdf->getName()) ?></strong>
+ </td>
+ <td colspan="2" data-mvv-field="mvv_studiengang.<?= $tdf->id ?>">
+ <?= $tdf->getDisplayValue() ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ <? foreach ($studiengang->datafields as $df) : ?>
+ <? if (mb_strpos($df->datafield->object_class, 'info') !== false
+ && !$df->isNew()) : ?>
+ <? $tdf = $df->getTypedDatafield(); ?>
+ <? if ($tdf->isVisible() && trim($tdf->getValue())) : ?>
+ <tr>
+ <td>
+ <strong><?= htmlReady($tdf->getName()) ?></strong>
+ </td>
+ <td colspan="2" data-mvv-field="mvv_studiengang.<?= $tdf->id ?>">
+ <?= $tdf->getDisplayValue() ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ <? if (is_array($all_contacts) && count($all_contacts)) : ?>
+ <tr>
+ <td>
+ <strong><?= _('Ihre AnsprechpartnerInnen') ?></strong>
+ </td>
+ <td>
+ <? foreach ($all_contacts as $category => $contacts) : ?>
+ <? if ($GLOBALS['MVV_STUDIENGANG']['PERSONEN_GRUPPEN']['values'][$category]['visible']) : ?>
+ <strong><?= htmlReady($GLOBALS['MVV_STUDIENGANG']['PERSONEN_GRUPPEN']['values'][$category]['name']) ?></strong>
+ <ul>
+ <? foreach ($contacts as $contact) : ?>
+ <li>
+ <?= htmlReady($contact['name']) ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ <? endforeach; ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? if (is_array($all_documents) && count($all_documents)) : ?>
+ <tr>
+ <td>
+ <strong><?= _('Dokumente: Ordnungen, Formulare, Informationen') ?></strong>
+ </td>
+ <td>
+ <? foreach ($all_documents as $category => $files) : ?>
+ <? if ($GLOBALS['MVV_DOCUMENTS']['CATEGORY']['values'][$category]['visible']) : ?>
+ <strong><?= htmlReady($GLOBALS['MVV_DOCUMENTS']['CATEGORY']['values'][$category]['name']) ?></strong>
+ <ul>
+ <? foreach ($files as $file) : ?>
+ <li>
+ <? if ($file['is_link']) : ?>
+ <a href="<?= $file['url'] ?>" target="_blank"><?= htmlReady($file['name']) ?></a>
+ <? else : ?>
+ <?= htmlReady($file['name']) ?>
+ <a href="<?= $file['url'] ?>"><?= htmlReady($file['extension']) ?></a>
+ <? endif ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <? endif; ?>
+ <? endforeach; ?>
+ </td>
+ </tr>
+ <? endif ?>
+ <? if (count($all_aufbaustgs)) : ?>
+ <tr>
+ <td>
+ <strong><?= _('Aufbau-/Kombinationsstudiengänge') ?></strong>
+ </td>
+ <td>
+ <? foreach ($all_aufbaustgs as $typ => $aufbaustgs) : ?>
+ <strong><?= htmlReady($GLOBALS['MVV_AUFBAUSTUDIENGANG']['TYP']['values'][$typ]['name']) ?></strong>
+ <? if (count($aufbaustgs) > 4) : ?>
+ <input type="checkbox" class="mvv-cb-more-items" id="cb_more_aufbaustgs" checked>
+ <? endif; ?>
+ <ul>
+ <? foreach ($aufbaustgs as $i => $aufbaustg) : ?>
+ <li>
+ <?= htmlReady($aufbaustg->getDisplayName()) ?>
+ <? if ($i == 3) : ?>
+ <label class="cb-more-items" for="cb_more_aufbaustgs"><?= _('mehr...') ?></label>
+ <? endif; ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? endforeach ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/app/views/shared/studiengang/_studiengang_info.php b/app/views/shared/studiengang/_studiengang_info.php
new file mode 100644
index 0000000..80b496b
--- /dev/null
+++ b/app/views/shared/studiengang/_studiengang_info.php
@@ -0,0 +1,55 @@
+<table class="default nohover">
+ <colgroup>
+ <col width="30%">
+ <col width="70%">
+ </colgroup>
+ <thead>
+ <tr>
+ <? if (trim($stg->name_kurz)) : ?>
+ <th class="mvv-modul-details-head"><?= htmlReady($stg->name_kurz) ?></th>
+ <th class="mvv-modul-details-head"><?= htmlReady($stg->getDisplayName()) ?></th>
+ <? else : ?>
+ <th class="mvv-modul-details-head" colspan="2"><?= htmlReady($stg->getDisplayName()) ?></th>
+ <? endif; ?>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <? printf(_('%s %s vom %s'), ModuleManagementModel::getLocaleOrdinalNumberSuffix($stg->fassung_nr),
+ htmlReady($GLOBALS['MVV_STUDIENGANG']['FASSUNG_TYP']['values'][$stg->fassung_typ]['name']),
+ strftime('%x', $stg->beschlussdatum));
+ ?>
+ </td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><strong><?= _('Name') ?></strong></td>
+ <td><?= htmlReady($stg->getDisplayName()) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Abschluss') ?></strong></td>
+ <td><?= htmlReady($stg->abschluss->getDisplayName()) ?></td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Gültigkeit') ?></strong></td>
+ <td>
+ <? $start_sem = Semester::find($stg->start) ?>
+ <? $end_sem = Semester::find($stg->end) ?>
+ <? if ($stg->start_sem == $stg->end_sem) : ?>
+ <?= htmlReady($start_sem->name) ?>
+ <? elseif (!$stg->end) : ?>
+ <? printf(_('%s bis unbegrenzt'), htmlReady($start_sem->name)) ?>
+ <? else : ?>
+ <? printf(_('%s bis %s'), htmlReady($start_sem->name), htmlReady($end_sem->name)) ?>
+ <? endif; ?>
+ </tr>
+ <tr>
+ <td>
+ <strong><?= _('Beschreibung') ?></strong>
+ </td>
+ <td>
+ <?= formatReady($stg->beschreibung) ?>
+ </td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/app/views/shared/studiengang/_studiengangteil.php b/app/views/shared/studiengang/_studiengangteil.php
new file mode 100644
index 0000000..479e94c
--- /dev/null
+++ b/app/views/shared/studiengang/_studiengangteil.php
@@ -0,0 +1,46 @@
+<h3><?= htmlReady($stgteil->getDisplayName()) ?></h3>
+<table class="default mvv-modul-details" id="<?= $stgteil->getId() ?>" data-mvv-id="<?= $stgteil->getId(); ?>" data-mvv-type="stgteil">
+ <colgroup>
+ <col style="width: 20%;">
+ <col style="width: 10%;">
+ <col style="width: 10%;">
+ <col style="width: 30%;">
+ <col style="width: 10%;">
+ </colgroup>
+ <tr>
+ <th><?= _('Fach') ?></th>
+ <th><?= _('Kredit-Punkte') ?></th>
+ <th><?= _('Semesterzahl') ?></th>
+ <th><?= _('Titelzusatz') ?></th>
+ <th><?= _('Personen/Kontakte') ?></th>
+ </tr>
+ <tr>
+ <td data-mvv-field="mvv_stgteil.fach">
+ <? if ($stgteil->fach) : ?>
+ <?= htmlReady($stgteil->fach->name) ?>
+ <? endif; ?>
+ </td>
+ <td data-mvv-field="mvv_stgteil.kp">
+ <?= htmlReady($stgteil->kp) ?>
+ </td>
+ <td data-mvv-field="mvv_stgteil.semester">
+ <?= htmlReady($stgteil->semester) ?>
+ </td>
+ <td data-mvv-field="mvv_stgteil.zusatz">
+ <?= htmlReady($stgteil->zusatz) ?>
+ </td>
+ <td data-mvv-field="mvv_stgteil.contact_assignments">
+ <? if (empty($stgteil->contact_assignments)): ?>
+ -
+ <? else: ?>
+ <? foreach ($stgteil->contact_assignments as $contact_assignment) : ?>
+ <? if ($GLOBALS['MVV_STGTEIL']['PERSONEN_GRUPPEN']['values'][$contact_assignment->category]['visible']) : ?>
+ <?= htmlReady($contact_assignment->contact->getDisplayName()) ?>
+ (<?= htmlReady($GLOBALS['MVV_STGTEIL']['PERSONEN_GRUPPEN']['values'][$contact_assignment->category]['name']) ?>)
+ <br>
+ <? endif; ?>
+ <? endforeach; ?>
+ <? endif; ?>
+ </td>
+ </tr>
+</table> \ No newline at end of file
diff --git a/app/views/shared/studiengang/description.php b/app/views/shared/studiengang/description.php
new file mode 100644
index 0000000..4bf881a
--- /dev/null
+++ b/app/views/shared/studiengang/description.php
@@ -0,0 +1,12 @@
+<? $languages = Config::get()->INSTALLED_LANGUAGES ?>
+<? if (count($languages) > 1): ?>
+<div style="width: 100%; text-align: right;">
+ <? foreach ($languages as $language) : ?>
+ <a data-dialog="size=auto;title='<?= htmlReady($stg->getDisplayName()) ?>'" href="<?= $controller->url_for('/description/' . $stg->id . '/', array('display_language' => $language)) ?>">
+ <img src="<?= Assets::image_path('languages/' . $language['picture']) ?>" alt="<?= $language['name'] ?>" title="<?= $language['name'] ?>">
+ </a>
+ <? endforeach; ?>
+</div>
+<? endif; ?>
+
+<?= $this->render_partial('shared/studiengang/_studiengang_info') ?> \ No newline at end of file
diff --git a/app/views/shared/trails_table.php b/app/views/shared/trails_table.php
new file mode 100644
index 0000000..98535f7
--- /dev/null
+++ b/app/views/shared/trails_table.php
@@ -0,0 +1,7 @@
+<?
+
+$padded_trails_array = array_map(
+ function($trail_array) {
+ return array_pad($trail_array, -5, null);
+ }, $trails);
+
diff --git a/app/views/shared/version/_version.php b/app/views/shared/version/_version.php
new file mode 100644
index 0000000..71e614f
--- /dev/null
+++ b/app/views/shared/version/_version.php
@@ -0,0 +1,68 @@
+<h1><?= htmlReady($version->getDisplayName()) ?></h1>
+<table class="default nohover" data-mvv-id="<?= $version->getId(); ?>" data-mvv-type="stgteilversion">
+ <tbody>
+ <? if (!empty($version->start_sem)) : ?>
+ <tr>
+ <td colspan="2"><strong><?= _('Gültigkeit') ?></strong>
+ <div style="padding: 10px; float: left;" data-mvv-field="mvv_stgteilversion.start_sem">
+ <?= _('von Semester:') ?>
+ <? $sem = Semester::find($version->start_sem) ?>
+ <?= htmlReady($sem->name) ?>
+ </div>
+ <div style="padding: 10px;" data-mvv-field="mvv_stgteilversion.end_sem">
+ <?= _('bis Semester:') ?>
+ <? if ($version->end_sem != "") : ?>
+ <? $sem = Semester::find($version->end_sem) ?>
+ <?= htmlReady($sem->name) ?>
+ <? else : ?>
+ <?= _('unbegrenzt gültig') ?>
+ <? endif; ?>
+ </div>
+ <div style="padding: 10px; display:inline-block;" data-mvv-field="mvv_stgteilversion.beschlussdatum">
+ <?= _('Beschlussdatum:') ?>
+ <?= ($version->beschlussdatum ? strftime('%d.%m.%Y', $version->beschlussdatum) : '') ?>
+ </div>
+ <div style="padding: 10px; display:inline-block;" data-mvv-field="mvv_stgteilversion.fassung_nr">
+ <?= _('Fassung:') ?>
+ <?= htmlReady($version->fassung_nr) ?>
+ </div>
+ <div style="padding: 10px; display:inline-block;" data-mvv-field="mvv_stgteilversion.fassung_typ">
+ <?= $GLOBALS['MVV_STGTEILVERSION']['FASSUNG_TYP'][$version->fassung_typ]['name'] ?>
+ </div>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? if (!empty($version->code)) : ?>
+ <tr>
+ <td><strong><?= _('Code') ?></strong></td>
+ <td data-mvv-field="mvv_stgteilversion.code">
+ <?= htmlReady($version->code) ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? if (!empty($version->beschreibung)) : ?>
+ <tr>
+ <td><strong><?= _('Beschreibung') ?></strong></td>
+ <td>
+ <div data-mvv-field="mvv_stgteilversion.beschreibung">
+ <div><?= htmlReady($version->beschreibung) ?></div>
+ </div>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? if (!empty($version->status)) : ?>
+ <tr>
+ <td><strong><?= _('Status der Bearbeitung') ?></strong></td>
+ <td data-mvv-field="mvv_stgteilversion.stat">
+ <?= $GLOBALS['MVV_STGTEILVERSION']['STATUS']['values'][$version->stat]['name'] ?>
+ </td>
+ </tr>
+ <tr>
+ <td><strong><?= _('Kommentar Bearbeitungsstatus:') ?></strong></td>
+ <td data-mvv-field="mvv_stgteilversion.kommentar_status">
+ <?= htmlReady($version->kommentar_status) ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/app/views/shared/version/_versionmodule.php b/app/views/shared/version/_versionmodule.php
new file mode 100644
index 0000000..4fbebad
--- /dev/null
+++ b/app/views/shared/version/_versionmodule.php
@@ -0,0 +1,115 @@
+<?
+$abschnitte = StgteilAbschnitt::findByStgteilVersion($version->getId());
+$abschnitteData = [];
+$fachsemesterData = [];
+foreach ($abschnitte as $abschnitt) {
+ $abschnitteData[$abschnitt->getId()] = [
+ 'name' => $abschnitt->getDisplayName(),
+ 'creditPoints' => $abschnitt->kp,
+ 'zwischenUeberschrift' => $abschnitt->ueberschrift,
+ 'kommentar' => $abschnitt->kommentar,
+ 'module' => [],
+ 'rowspan' => 0
+ ];
+ //$module = Modul::findByStgteilAbschnitt($abschnitt->getId());
+ $abschnitt_module = $abschnitt->getModulAssignments();
+ foreach ($abschnitt_module as $abschnitt_modul) {
+
+ $abschnitteData[$abschnitt->getId()]['module'][$abschnitt_modul->modul->getId()] = [
+ 'name' => $abschnitt_modul->getDisplayName(),
+ 'modulTeile' => []
+ ];
+
+ foreach ($abschnitt_modul->modul->modulteile as $teil) {
+ $fachSemester = $abschnitt_modul->getAllFachSemester($teil->getId());
+
+ $abschnitteData[$abschnitt->getId()]['module'][$abschnitt_modul->modul->getId()]['modulTeile'][$teil->getId()] = [
+ 'name' => $teil->getDisplayName(),
+ 'fachsemester' => []
+ ];
+ $abschnitteData[$abschnitt->getId()]['rowspan']++;
+ foreach ($fachSemester as $fachsem) {
+ $fachsemesterData[$fachsem->fachsemester] = $fachsem->fachsemester;
+ $abschnitteData[$abschnitt->getId()]['module'][$abschnitt_modul->modul->getId()]['modulTeile'][$teil->getId()]['fachsemester'][$fachsem->fachsemester] = $fachsem->differenzierung;
+ }
+ }
+ }
+}
+?>
+<h2><?= _('Liste der Studiengangteilabschnitte') ?></h2>
+<dl class="mvv-form" >
+<? foreach ($abschnitteData as $abschnitt_id => $abschnitt): ?>
+ <span data-mvv-id="<?= $abschnitt_id; ?>" data-mvv-type="stgteilabschnitt">
+ <? $displayedAbschnittName = false; ?>
+ <? $ueberschrift = (mb_strlen($abschnitt['zwischenUeberschrift'])) ?>
+ <? if (!$ueberschrift): ?>
+ <dt>
+ <span data-mvv-field="mvv_stgteilabschnitt mvv_stgteilabschnitt.name"><?= $abschnitt['name'] ?></span> <span data-mvv-field="mvv_stgteilabschnitt.kp"><?= $abschnitt['creditPoints'] ? $abschnitt['creditPoints'] . 'CP' : '' ?></span>
+ </dt>
+ <dd>
+ <? if (trim($abschnitt['kommentar'])) : ?>
+ <b><?= _('Kommentar:') ?></b>
+ <span data-mvv-field="mvv_stgteilabschnitt.kommentar"><?= formatReady($abschnitt['kommentar']) ?></span>
+ <? endif; ?>
+ <? if (!empty($abschnitt['module'])) : ?>
+ <table class="mvv-modul-details">
+ <thead>
+ <tr>
+ <th rowspan="2"><?= _('Modul') ?></th>
+ <th rowspan="2"><?= _('Modulteil') ?></th>
+ <th colspan="<?= count($fachsemesterData) ?>" align="center"><?= _('Semester') ?></th>
+ </tr>
+ <tr>
+ <? foreach ($fachsemesterData as $fachsemester) : ?>
+ <th ><?= $fachsemester ?></th>
+ <? endforeach; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($abschnitt['module'] as $modul_id => $modul) : ?>
+ <? $displayedModulName = false; ?>
+ <? foreach ($modul['modulTeile'] as $modulTeil_id => $modulTeil): ?>
+ <tr data-mvv-id="<?= $modulTeil_id; ?>" data-mvv-type="modulteil">
+ <? if (!$displayedModulName) : ?>
+ <? $displayedModulName = true; ?>
+ <td rowspan="<?= count($modul['modulTeile']) ?>" data-mvv-field="mvv_modul_deskriptor.bezeichnung mvv_modul_deskriptor.start mvv_modul_deskriptor.end">
+ <a data-dialog href="<?= URLHelper::getLink('/shared/modul/overview/' . $modul_id) ?>">
+ <? // Anzeige der alternativen Bezeichnung aus mvv_stgteilabschnitt_modul ?>
+ <? $abschnitt_modul = StgteilabschnittModul::findOneBySQL('abschnitt_id = ? AND modul_id = ?', [$abschnitt_id, $modul_id]) ?>
+ <?= htmlReady($abschnitt_modul->getDisplayName()) ?>
+ </a>
+ <a data-dialog title="<?= htmlReady($modul['name']) . ' (' . _('Vollständige Modulbeschreibung') . ')' ?>" href="<?= URLHelper::getLink('shared/modul/description/' . $modul_id) ?>">
+ <?= Icon::create('info-circle', 'clickable', [])->asImg(); ?>
+ </a>
+ </td>
+ <? endif;?>
+ <td><?= htmlReady($modulTeil['name']) ?> </td>
+ <? foreach ($fachsemesterData as $i => $fachsemester) : ?>
+ <? $typ = isset($modulTeil['fachsemester'][$fachsemester]) ? $modulTeil['fachsemester'][$fachsemester] : null; ?>
+ <? if ($typ == 'kann') : ?>
+ <td data-mvv-field="mvv_modulteil_stgteilabschnitt.differenzierung" data-mvv-index="<?= $i; ?>" data-mvv-coid="<?= $abschnitt_id; ?>" class="type kann">o_</td>
+ <? elseif ($typ == 'soll') : ?>
+ <td data-mvv-field="mvv_modulteil_stgteilabschnitt.differenzierung" data-mvv-index="<?= $i; ?>" data-mvv-coid="<?= $abschnitt_id; ?>" class="type soll">+_</td>
+ <? else : ?>
+ <td data-mvv-field="mvv_modulteil_stgteilabschnitt.differenzierung" data-mvv-index="<?= $i; ?>" data-mvv-coid="<?= $abschnitt_id; ?>" class="type">&nbsp;</td>
+ <? endif; ?>
+ <? endforeach; ?>
+ </tr>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+ <? endif; ?>
+ </dd>
+ <? else : ?>
+ <dt><?= htmlReady($abschnitt['zwischenUeberschrift']) ?></dt>
+ <? if (trim($abschnitt['kommentar'])) : ?>
+ <dd data-mvv-field="mvv_stgteilabschnitt.kommentar">
+ <b><?= _('Kommentar:') ?></b>
+ <div><?= formatReady($abschnitt['kommentar']) ?></div>
+ </dd>
+ <? endif; ?>
+ <? endif; ?>
+ </span>
+<? endforeach; ?>
+</dl> \ No newline at end of file
diff --git a/app/views/siteinfo/delete.php b/app/views/siteinfo/delete.php
new file mode 100644
index 0000000..ea8d94c
--- /dev/null
+++ b/app/views/siteinfo/delete.php
@@ -0,0 +1,28 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<div class="white" style="padding: 1ex;">
+ <? if (!$execute): ?>
+ <div style="text-align: center;padding: 10px;">
+ <? if ($detail) :?>
+ <p><?= _("Wollen Sie die Seite wirklich löschen?") ?></p>
+ <? else : ?>
+ <p><?= _("Wollen Sie die Rubrik mit allen Seiten wirklich löschen?") ?></p>
+ <? endif ?>
+ <? $delete_url = 'siteinfo/delete/'.$currentrubric.'/';
+ $delete_url .= $detail ? $currentdetail : "all";
+ $delete_url .= "/execute";
+ $abort_url = 'siteinfo/show/'.$currentrubric;
+ $abort_url .= $detail ? "/".$currentdetail : '';
+ ?>
+ <?= LinkButton::create(_('Löschen'), $controller->url_for($delete_url)) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for($abort_url)) ?>
+ </div>
+ <div>
+ <hr>
+ </div>
+ <? endif ?>
+ <?= $output ?>
+</div>
diff --git a/app/views/siteinfo/edit.php b/app/views/siteinfo/edit.php
new file mode 100644
index 0000000..54bd8d2
--- /dev/null
+++ b/app/views/siteinfo/edit.php
@@ -0,0 +1,58 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+
+?>
+<form action="<?= $controller->url_for('siteinfo/save') ?>" method="POST" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend>
+ <? if ($edit_rubric): ?>
+ <?= _('Rubrik bearbeiten') ?>
+ <? else : ?>
+ <?= _('Seite bearbeiten') ?>
+ <? endif ?>
+ </legend>
+
+ <? if ($edit_rubric): ?>
+ <input type="hidden" name="rubric_id" value="<?= htmlReady($rubric_id) ?>">
+ <label>
+ <?= _('Titel der Rubrik')?>
+ <input type="text" name="rubric_name" id="rubric_name" value="<?= htmlReady($rubric_name) ?>">
+ </label>
+ <? else: ?>
+ <label>
+ <?= _('Rubrik-Zuordnung')?>
+ <select name="rubric_id">
+
+ <? foreach ($rubrics as $option): ?>
+ <option value="<?= htmlReady($option['rubric_id']) ?>" <? if ($currentrubric == $option['rubric_id']) echo 'selected'; ?>>
+ <?= htmlReady(language_filter($option['name'])) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Seitentitel')?>
+ <input type="text" name="detail_name" id="detail_name" value="<?= htmlReady($detail_name) ?>">
+ </label>
+
+ <label>
+ <?= _('Seiteninhalt')?>
+ <textarea style="height: 15em;" name="content" id="content" class="add_toolbar size-l wysiwyg"><?= wysiwygReady($content) ?></textarea>
+ </label>
+
+ <input type="hidden" name="detail_id" value="<?= $currentdetail?>">
+ <? endif; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Abschicken')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('siteinfo/show/'.$currentrubric.'/'.$currentdetail)) ?>
+ </footer>
+</form>
+
+ <? if (!$edit_rubric): ?>
+ <?= $this->render_partial('siteinfo/help.php') ?>
+<? endif; ?>
diff --git a/app/views/siteinfo/help.php b/app/views/siteinfo/help.php
new file mode 100644
index 0000000..54d0d09
--- /dev/null
+++ b/app/views/siteinfo/help.php
@@ -0,0 +1,73 @@
+<?
+# Lifter010: TODO
+?>
+<div style="background-color:#DEE2E8; padding:10px;">
+ <h3><?= _('Verfügbares Markup')?></h3>
+ <p><?= sprintf(_('Zusätzlich zu den üblichen %sSchnellformatierungen%s und dem Wiki-Markup ist folgendes Markup verfügbar:'), '<a href="http://hilfe.studip.de/index.php/Basis/VerschiedenesFormat">', '</a>')?></p>
+ <dl>
+ <dt>[lang=<em>language</em>]<em>...</em>[/lang]</dt>
+ <dd><?= sprintf(_('Nur wenn %s der Nutzersprache entspricht, wird der Text (%s) zwischen den Tags angezeigt'),
+ '<em>language</em>', '<em>...</em>')?></dd>
+ <dt>[style=<em>definition</em>]<em>...</em>[/style]</dt>
+ <dd><?= sprintf(_('Die durch %s angegebenen CSS-Gestaltungsangaben werden dem umschlossenen Bereich (%s) zugewiesen.'),
+ '<em>definition</em>', '<em>...</em>')?></dd>
+ <dt>(:version:)</dt>
+ <dd><?= _('Die Angabe der verwendeten Stud.IP-Version.')?></dd>
+ <dt>(:uniname:)</dt>
+ <dd><?= _('Der Name des Standortes gemäß der Konfiguration.')?></dd>
+ <dt>(:unicontact:)</dt>
+ <dd><?= _('Der administrative Kontakt gemäß der Konfiguration.')?></dd>
+ <dt>(:userinfo <em>user</em>:)</dt>
+ <dd><?= sprintf(_('Ausgabe von Vor- und Nachnamen verlinkt mit dem Profil und der E-Mail-Adresse des mit %s angegebenen Nutzers.'),'<em>user</em>')?></dd>
+ <dt>(:userlink <em>user</em>:)</dt>
+ <dd><?= sprintf(_('Ausgabe von Vor- und Nachnamen verlinkt mit dem Profil des mit %s angegebenen Nutzers.'),'<em>user</em>')?></dd>
+ <dt>(:rootlist:)</dt>
+ <dd><?= _('Ausgabe von Vor- und Nachnamen verlinkt mit dem Profil und der E-Mail-Adresse aller Nutzer mit Root-Status.')?></dd>
+ <dt>(:adminlist:)</dt>
+ <dd><?= _('Ausgabe von Vor- und Nachnamen verlinkt mit dem Profil und der E-Mail-Adresse aller Nutzer mit Admin-Status.')?></dd>
+ <dt>(:coregroup:)</dt>
+ <dd><?= _('Ausgabe des Inhaltes von http://www.studip.de/crew.php.')?></dd>
+ <dt>(:toplist <em>subject</em>:)</dt>
+ <dd><?= sprintf(_('Ausgabe von Ranglisten für die mit %s angegebenen Kriterien, die die Ausprägungen:'),
+ '<em>subject</em>')?>
+ <ul>
+ <li>mostparticipants</li>
+ <li>recentlycreated</li>
+ <li>mostdocuments</li>
+ <li>mostpostings</li>
+ <li>mostvisitedhomepages</li>
+ </ul>
+ haben können.
+ </dd>
+ <dt>(:indicator <em>subject</em>:)</dt>
+ <dd><?= sprintf(_('Ausgabe von mit %s spezifizierten Kennzahlen aus den folgenden Möglichkeiten:'),
+ '<em>subject</em>')?>
+ <ul>
+ <li>seminar_all</li>
+ <li>seminar_archived</li>
+ <li>institute_secondlevel_all</li>
+ <li>institute_firstlevel_all</li>
+ <li>user_admin</li>
+ <li>user_dozent</li>
+ <li>user_tutor</li>
+ <li>user_autor</li>
+ <li>posting</li>
+ <li>document</li>
+ <li>link</li>
+ <li>litlist</li>
+ <li>termin</li>
+ <li>news</li>
+ <li>vote</li>
+ <li>test</li>
+ <li>evaluation</li>
+ <li>wiki_pages</li>
+ <li>lernmodul</li>
+ <li>resource</li>
+ </ul>
+ </dd>
+ <dt>(:history:)</dt>
+ <dd><?= _('Ausgabe der history.txt')?></dd>
+ <dt>(:terms:)</dt>
+ <dd><?= _('Ausgabe der Nutzungsbedingungen')?></dd>
+ </dl>
+</div>
diff --git a/app/views/siteinfo/markup/adminList.php b/app/views/siteinfo/markup/adminList.php
new file mode 100644
index 0000000..1b0cf2c
--- /dev/null
+++ b/app/views/siteinfo/markup/adminList.php
@@ -0,0 +1,31 @@
+<?
+# Lifter010: TODO
+?>
+<? if ($error) : ?>
+ <em><?= _("keine. Na sowas. Das kann ja eigentlich gar nicht sein...") ?></em>
+<? else : ?>
+ <? $current_head = "" ?>
+ <? $switch_column = count($admins)/2 ?>
+ <? $i = 1 ?>
+ <table width="100%">
+ <tr>
+ <td style="vertical-align: top">
+ <? foreach($admins as $admin) : ?>
+ <? if ($current_head != $admin['institute']) :?>
+ <? $current_head = $admin['institute'] ?>
+ <? if ($i>$switch_column) : ?>
+ </td>
+ <td style="vertical-align: top">
+ <? $i = 0 ?>
+ <? endif ?>
+ <h4><?= htmlReady($current_head) ?></h4>
+ <? endif ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile',
+ ['username' => $admin['username']])
+ ?>"><?= htmlReady($admin['fullname'])?></a>, E-Mail:<?= formatLinks($admin['Email']) ?><br>
+ <? $i++ ?>
+ <? endforeach ?>
+ </td>
+ </tr>
+ </table>
+<? endif ?>
diff --git a/app/views/siteinfo/markup/indicator.php b/app/views/siteinfo/markup/indicator.php
new file mode 100644
index 0000000..16e3943
--- /dev/null
+++ b/app/views/siteinfo/markup/indicator.php
@@ -0,0 +1,11 @@
+<?
+# Lifter010: TODO
+?>
+<? if($detail != '') : ?>
+ <span title="<?= $detail ?>">
+<? else : ?>
+ <span>
+<? endif ?>
+<?= $title ?>
+</span>
+: <?= $count ?>
diff --git a/app/views/siteinfo/markup/rootlist.php b/app/views/siteinfo/markup/rootlist.php
new file mode 100644
index 0000000..4f8344a
--- /dev/null
+++ b/app/views/siteinfo/markup/rootlist.php
@@ -0,0 +1,17 @@
+<?
+# Lifter010: TODO
+?>
+<? if ($error) : ?>
+ <em><?= _("keine. Na sowas. Das kann ja eigentlich gar nicht sein...") ?></em>
+<? else : ?>
+ <ul>
+ <? foreach($users as $user) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile',
+ ['username' => $user['username']])
+ ?>"><?= htmlReady($user['fullname']) ?></a>, E-Mail:
+ <?= formatLinks($user['Email']) ?>
+ </li>
+ <? endforeach ?>
+ </ul>
+<? endif ?>
diff --git a/app/views/siteinfo/markup/toplist.php b/app/views/siteinfo/markup/toplist.php
new file mode 100644
index 0000000..499a0b7
--- /dev/null
+++ b/app/views/siteinfo/markup/toplist.php
@@ -0,0 +1,25 @@
+<?
+# Lifter010: TODO
+?>
+<h4><?= $heading ?></h4>
+<ol>
+<? foreach($lines as $line) : ?>
+ <?
+ switch($type){
+ case "seminar":
+ $link = URLHelper::getLink('dispatch.php/course/details/', ['sem_id' => $line["seminar_id"],
+ 'send_from_search' => 'true',
+ 'send_from_search_page' => $view]);
+ break;
+ case "user":
+ $link = URLHelper::getLink('dispatch.php/profile', ['username' => $line["username"]]);
+ break;
+ default:
+ $link = $view;
+ }
+ ?>
+ <li>
+ <a href="<?= $link ?>"><?= htmlReady($line['display']) ?></a> (<?=$line['count']?>)
+ </li>
+<? endforeach ?>
+</ol>
diff --git a/app/views/siteinfo/markup/uniContact.php b/app/views/siteinfo/markup/uniContact.php
new file mode 100644
index 0000000..c622761
--- /dev/null
+++ b/app/views/siteinfo/markup/uniContact.php
@@ -0,0 +1,7 @@
+<?
+# Lifter010: TODO
+?>
+<a href="mailto:<?= $contact ?>">
+ <?= Icon::create('link-extern', 'clickable')->asImg() ?>
+ <?= $contact ?>
+</a>
diff --git a/app/views/siteinfo/markup/userinfo.php b/app/views/siteinfo/markup/userinfo.php
new file mode 100644
index 0000000..54a17a7
--- /dev/null
+++ b/app/views/siteinfo/markup/userinfo.php
@@ -0,0 +1,10 @@
+<?
+# Lifter010: TODO
+?>
+<? if ($error) : ?>
+ <em><?= _("Nutzer nicht gefunden.") ?></em>
+<? else : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile',
+ ['username' => $username])
+ ?>"><?= htmlReady($fullname)?></a>, E-Mail: <?= formatLinks($email)?>
+<? endif ?>
diff --git a/app/views/siteinfo/markup/userlink.php b/app/views/siteinfo/markup/userlink.php
new file mode 100644
index 0000000..29275ed
--- /dev/null
+++ b/app/views/siteinfo/markup/userlink.php
@@ -0,0 +1,10 @@
+<?
+# Lifter010: TODO
+?>
+<? if ($error) : ?>
+ <em><?= _("Nutzer nicht gefunden.") ?></em>
+<? else : ?>
+ <a href="<?= URLHelper::getLink('dispatch.php/profile',
+ ['username' => $username])
+ ?>"><?= htmlReady($fullname)?></a>
+<? endif ?>
diff --git a/app/views/siteinfo/new.php b/app/views/siteinfo/new.php
new file mode 100644
index 0000000..fc59437
--- /dev/null
+++ b/app/views/siteinfo/new.php
@@ -0,0 +1,56 @@
+<?
+# Lifter010: TODO
+use Studip\Button, Studip\LinkButton;
+?>
+<? if (isset($error_msg)): ?>
+ <?= MessageBox::error($error_msg) ?>
+<? endif ?>
+
+<form action="<?= $controller->url_for('siteinfo/save') ?>" method="POST" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <? if($edit_rubric): ?>
+ <?= _('Neue Rubrik anlegen') ?>
+ <? else : ?>
+ <?= _('Neue Seite anlegen') ?>
+ <? endif ?>
+ </legend>
+
+ <? if($edit_rubric): ?>
+ <label>
+ <?= _('Titel der Rubrik') ?>
+ <input type="text" name="rubric_name" id="rubric_name">
+ </label>
+ <? else: ?>
+ <label>
+ <?= _('Rubrik-Zuordnung') ?>
+ <select name="rubric_id">
+ <? foreach ($rubrics as $option) : ?>
+ <option value="<?= $option['rubric_id'] ?>"<? if($currentrubric==$option['rubric_id']){echo " selected";} ?>><?= htmlReady(language_filter($option['name'])) ?></option>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Seitentitel') ?>
+ <input style="width: 90%;" type="text" name="detail_name" id="detail_name">
+ </label>
+
+ <label>
+ <?= _('Seiteninhalt') ?>
+ <textarea style="width: 90%;height: 15em;" name="content" id="content"></textarea><br>
+ </label>
+ <? endif ?>
+ </fieldset>
+
+ <footer>
+ <?= Button::createAccept(_('Abschicken')) ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('siteinfo/show/'.$currentrubric)) ?>
+ </footer>
+</form>
+
+<? if(!$edit_rubric): ?>
+ <?= $this->render_partial('siteinfo/help') ?>
+<? endif ?>
diff --git a/app/views/siteinfo/show.php b/app/views/siteinfo/show.php
new file mode 100644
index 0000000..dc1aa29
--- /dev/null
+++ b/app/views/siteinfo/show.php
@@ -0,0 +1,6 @@
+<?
+# Lifter010: TODO
+?>
+<div class="white" style="padding: 1ex;">
+ <?= $output ?>
+</div>
diff --git a/app/views/sitemap/index.php b/app/views/sitemap/index.php
new file mode 100644
index 0000000..7cb68f0
--- /dev/null
+++ b/app/views/sitemap/index.php
@@ -0,0 +1,9 @@
+<h2><?= _('Hauptnavigation') ?></h2>
+<?= $this->render_partial('sitemap/navigation', ['navigation' => $navigation, 'needs_image' => true, 'style' => 'bold'])
+?>
+<h2><?= _('Zusatznavigation') ?></h2>
+<?= $this->render_partial('sitemap/navigation', ['navigation' => $quicklinks, 'needs_image' => false, 'style' => 'bold'])
+?>
+<h2><?= _('Fußzeile') ?></h2>
+<?= $this->render_partial('sitemap/navigation', ['navigation' => $footer, 'needs_image' => false, 'style' => 'bold'])
+?> \ No newline at end of file
diff --git a/app/views/sitemap/navigation.php b/app/views/sitemap/navigation.php
new file mode 100644
index 0000000..841ed1b
--- /dev/null
+++ b/app/views/sitemap/navigation.php
@@ -0,0 +1,18 @@
+<?
+# Lifter010: TODO
+?>
+<ul>
+ <? foreach ($navigation as $nav) : ?>
+ <? if ($nav->isVisible($needs_image) && $nav->isEnabled()) : ?>
+ <li>
+ <a href="<?= URLHelper::getLink($nav->getURL()) ?>" style="font-weight: <?= $style ?>;">
+ <?= htmlReady($nav->getTitle()) ?>
+ </a>
+ <? if (count($nav->getSubNavigation())) : ?>
+ <?= $this->render_partial('sitemap/navigation',
+ ['navigation' => $nav, 'needs_image' => false, 'style' => 'normal']) ?>
+ <? endif ?>
+ </li>
+ <? endif ?>
+ <? endforeach ?>
+</ul>
diff --git a/app/views/smileys/index.php b/app/views/smileys/index.php
new file mode 100644
index 0000000..5860b95
--- /dev/null
+++ b/app/views/smileys/index.php
@@ -0,0 +1,117 @@
+<?php
+use Studip\Button;
+
+// divide smiley array in equal chunks, spillover from left to right
+$count = count($smileys);
+$columns = min(3, ceil($count / 5));
+
+$max = $columns ? floor($count / $columns) : 0;
+$spillover = $columns ? $count % $columns : 0;
+
+$data = [];
+for ($i = 0; $i < $columns; $i++) {
+ $num = $max + (int)($spillover > 0);
+
+ $data[] = array_splice($smileys, 0, $num);
+
+ $spillover -= 1;
+}
+$data = array_filter($data);
+?>
+
+<ul class="smiley-tabs" role="navigation">
+<? if ($favorites_activated): ?>
+ <li class="favorites <? if ($view === 'favorites') echo 'current'; ?>">
+ <a href="<?= $controller->url_for('smileys/index/favorites') ?>" data-dialog>
+ <?= _('Favoriten') ?>
+ </a>
+ </li>
+<? endif; ?>
+<? if (Smiley::getShort()): ?>
+ <li <? if ($view === 'short') echo 'class="current"'; ?>>
+ <a href="<?= $controller->url_for('smileys/index/short') ?>" data-dialog>
+ <?= _('Kürzel') ?>
+ </a>
+ </li>
+<? endif; ?>
+ <li <? if ($view === 'all') echo 'class="current"'; ?>>
+ <a href="<?= $controller->url_for('smileys/index/all') ?>" data-dialog>
+ <?= _('Alle') ?>
+ </a>
+ </li>
+<? foreach (array_keys($characters) as $char): ?>
+ <li <? if ($view === $char) echo 'class="current"'; ?>>
+ <a href="<?= $controller->url_for('smileys/index', $char) ?>" data-dialog>
+ <?= mb_strtoupper($char) ?>
+ </a>
+ </li>
+<? endforeach; ?>
+</ul>
+
+<div class="clear"></div>
+
+<? if (!$count): ?>
+ <?= MessageBox::info($view === 'favorites'
+ ? _('Keine Favoriten vorhanden.')
+ : _('Keine Smileys vorhanden.')) ?>
+<? else: ?>
+ <table class="smiley-container">
+ <tr>
+ <? foreach ($data as $smileys): ?>
+ <td valign="top" align="center">
+
+ <table class="smiley-column default">
+ <colgroup>
+ <col>
+ <col width="25%">
+ <col width="25%">
+ <? if ($favorites_activated): ?>
+ <col width="32px">
+ <? endif; ?>
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Bild') ?></th>
+ <th><?= _('Code') ?></th>
+ <th><?= _('Kürzel') ?></th>
+ <? if ($favorites_activated): ?>
+ <th class="actions">
+ <abbr title="<?= _('Favorit') ?>">
+ <?= Icon::create('star', 'info')->asImg() ?>
+ </abbr>
+ </th>
+ <? endif; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($smileys as $smiley): ?>
+ <tr id="smiley<?= $smiley->id ?>">
+ <td class="smiley-icon">
+ <a name="smiley<?= $smiley->id ?>"></a>
+ <?= $smiley->getImageTag() ?>
+ </td>
+ <td><?= sprintf(':%s:', $smiley->name) ?></td>
+ <td><?= htmlReady($smiley->short) ?></td>
+ <? if ($favorites_activated): ?>
+ <td class="actions">
+ <a href="<?= $controller->url_for('smileys/favor', $smiley->id, $view) ?>"
+ class="smiley-toggle <?= $favorites->contain($smiley->id) ? 'favorite' : '' ?>">
+ <? if ($favorites->contain($smiley->id)): ?>
+ <?= _('Als Favorit entfernen') ?>
+ <? else: ?>
+ <?= _('Als Favorit markieren') ?>
+ <? endif; ?>
+ </a>
+ </td>
+ <? endif; ?>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+
+ </td>
+ <? endforeach; ?>
+ </tr>
+ </table>
+<? endif; ?>
+
diff --git a/app/views/smileys/picker.php b/app/views/smileys/picker.php
new file mode 100644
index 0000000..8093fb5
--- /dev/null
+++ b/app/views/smileys/picker.php
@@ -0,0 +1,77 @@
+<div class="smiley-picker">
+ <table class="navigation top">
+ <tr>
+ <? if ($favorites_activated && count($favorites->get()) > 0): ?>
+ <td>
+ <a href="<?= $controller->url_for('smileys/picker/favorites') ?>">
+ <?= Icon::create('star', $view === 'favorites' ? 'attention' : 'clickable', ['title' => _('Favoriten')]) ?>
+ </a>
+ </td>
+ <? endif; ?>
+ <td style="text-align: right;">
+ <a href="<?= $controller->url_for('smileys/picker/all') ?>">
+ <?= Icon::create('smiley', $view === 'all' ? 'attention' : 'clickable', ['title' => _('alle')]) ?>
+ </a>
+ </td>
+ <? for ($i = 0; $i < 26; $i++):
+ $char = chr(ord('a') + $i);
+ ?>
+ <td <? if ($view === $char) echo 'class="active"'; ?>>
+ <? if (isset($characters[$char])): ?>
+ <a href="<?= $controller->url_for('smileys/picker/'. $char) ?>">
+ <?= mb_strtoupper($char) ?>
+ </a>
+ <? else: ?>
+ <?= $char ?>
+ <? endif; ?>
+ </td>
+ <? endfor; ?>
+ </tr>
+ </table>
+
+ <div class="smileys">
+<? foreach (array_pad($smileys, $controller::GRID_WIDTH * $controller::GRID_HEIGHT, null) as $smiley): ?>
+ <? if ($smiley === null): ?>
+ <span class="empty"></span>
+ <? else: ?>
+ <a class="smiley" href="#" data-code="<?= $smiley->short ?: (':' . $smiley->name . ':') ?>">
+ <?= $smiley->html ?>
+ </a>
+ <? endif; ?>
+<? endforeach; ?>
+ </div>
+
+ <table class="navigation bottom">
+ <tr>
+ <td>
+ <? if ($page > 0): ?>
+ <a href="<?= $controller->url_for('smileys/picker/' . $view . '/0') ?>">
+ <?= Icon::create('arr_eol-left', 'clickable')->asImg() ?>
+ </a>
+ <a href="<?= $controller->url_for('smileys/picker/' . $view . '/' . ($page - 1)) ?>">
+ <?= Icon::create('arr_1left', 'clickable')->asImg() ?>
+ </a>
+ <? else: ?>
+ <?= Icon::create('arr_eol-left', 'inactive')->asImg() ?>
+ <?= Icon::create('arr_1left', 'inactive')->asImg() ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center;">
+ <?= sprintf('Seite %u von %u', $page + 1, $pages + 1) ?>
+ </td>
+ <td style="text-align: right;">
+ <? if ($page < $pages): ?>
+ <a href="<?= $controller->url_for('smileys/picker/' . $view . '/' . ($page + 1)) ?>">
+ <?= Icon::create('arr_1right', 'clickable')->asImg() ?>
+ </a>
+ <a href="<?= $controller->url_for('smileys/picker/' . $view . '/' . $pages) ?>">
+ <?= Icon::create('arr_eol-right', 'clickable')->asImg() ?>
+ </a>
+ <? else: ?>
+ <?= Icon::create('arr_1right', 'inactive')->asImg() ?>
+ <?= Icon::create('arr_eol-right', 'inactive')->asImg() ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ </table>
+</div> \ No newline at end of file
diff --git a/app/views/start/_widget.php b/app/views/start/_widget.php
new file mode 100644
index 0000000..13a365c
--- /dev/null
+++ b/app/views/start/_widget.php
@@ -0,0 +1,35 @@
+<div class="ui-widget_head widget-header" id="widget-<?= $widget->widget_id ?>">
+ <span class="header-options">
+ <? if (isset($icons)): ?>
+ <? foreach ($icons as $nav): ?>
+ <? if ($nav->isVisible(true)): ?>
+ <? $attr = $nav->getLinkAttributes() ?>
+ <a href="<?= URLHelper::getLink($nav->getURL()) ?>"
+ <? foreach ($attr as $key => $value): ?>
+ <? if ($key !== 'src'): ?>
+ <?= $key ?>="<?= htmlReady($value) ?>"
+ <? endif ?>
+ <? endforeach ?>>
+ <?= $nav->getImage() ?>
+ </a>
+ <? endif ?>
+ <?endforeach ?>
+ <? endif ?>
+
+ <? if (isset($admin_url)): ?>
+ <a href="<?= URLHelper::getLink($admin_url) ?>">
+ <?= Icon::create('admin', 'clickable', ['title' => $admin_title])->asImg() ?>
+ </a>
+ <? endif ?>
+
+ <a href="<?= $controller->url_for('start/delete/' . $widget->widget_id) ?>">
+ <?= Icon::create('decline', 'clickable', ['title' => _('Entfernen')])->asImg() ?>
+ </a>
+ </span>
+ <span id="widgetName<?= $widget->widget_id ?>" class="widget-title">
+ <?= htmlReady(isset($title) ? $title : $widget->getPluginName()) ?>
+ </span>
+</div>
+<div id="wid<?=$widget->widget_id?>">
+ <?= $content_for_layout ?>
+</div>
diff --git a/app/views/start/add.php b/app/views/start/add.php
new file mode 100644
index 0000000..f53607a
--- /dev/null
+++ b/app/views/start/add.php
@@ -0,0 +1,30 @@
+<form action="<?= $controller->url_for('start/add') ?>" method="post" class="default">
+ <input type="hidden" name="studip_ticket" value="<?= get_ticket() ?>">
+ <input type="hidden" name="position" value="0">
+
+ <fieldset>
+ <legend>
+ <?= _('Neues Widget zur Startseite hinzufügen') ?>
+ </legend>
+
+ <ul class="addclip-widgets">
+ <? foreach ($widgets as $widget): ?>
+ <? $metadata = $widget->getMetadata(); ?>
+ <li>
+ <label>
+ <input type="checkbox" name="widget_id[]" value="<?= $widget->getPluginId() ?>">
+ <?= htmlReady($widget->getPluginName()) ?>
+ </label>
+ <? if ($metadata['description']): ?>
+ <p><?= formatReady($metadata['description']) ?></p>
+ <? endif; ?>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Hinzufügen')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('start')) ?>
+ </footer>
+</form>
diff --git a/app/views/start/edit_defaults.php b/app/views/start/edit_defaults.php
new file mode 100644
index 0000000..1ea3e4b
--- /dev/null
+++ b/app/views/start/edit_defaults.php
@@ -0,0 +1,58 @@
+<div class="edit-widgetcontainer">
+ <div class="start-widgetcontainer">
+ <ul class="portal-widget-list">
+ <? foreach ($initial_widgets[0] as $widget_id) : ?>
+ <? $widget = $widgets[$widget_id]; unset($widgets[$widget_id]) ?>
+ <li class="studip-widget-wrapper" id="<?= $widget->getPluginId() ?>">
+ <div class="ui-widget-content studip-widget">
+ <div class="ui-widget_head widget-header">
+ <span>
+ <?= htmlReady($widget->getPluginName()) ?>
+ </span>
+ </div>
+ </div>
+ </li>
+ <? endforeach; ?>
+ </ul>
+
+ <ul class="portal-widget-list">
+ <? foreach ($initial_widgets[1] as $widget_id) : ?>
+ <? $widget = $widgets[$widget_id]; unset($widgets[$widget_id]) ?>
+ <li class="studip-widget-wrapper" id="<?= $widget->getPluginId() ?>">
+ <div class="ui-widget-content studip-widget">
+ <div class="ui-widget_head widget-header">
+ <span>
+ <?= htmlReady($widget->getPluginName()) ?>
+ </span>
+ </div>
+ </div>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+
+ <h2><?= _('Nicht standardmäßig aktivierte Widgets') ?></h2>
+ <div class="available-widgets">
+ <ul class="portal-widget-list" style="clear: both;">
+ <? foreach ($widgets as $widget) : ?>
+ <li class="studip-widget-wrapper" id="<?= $widget->getPluginId() ?>">
+ <div class="ui-widget-content studip-widget">
+ <div class="ui-widget_head widget-header">
+ <span>
+ <?= htmlReady($widget->getPluginName()) ?>
+ </span>
+ </div>
+ </div>
+ </li>
+ <? endforeach; ?>
+ </ul>
+ </div>
+</div>
+
+<script>
+(function($) {
+ $(document).ready(function() {
+ STUDIP.startpage.init_edit('<?= $permission ?>');
+ })
+}(jQuery));
+</script> \ No newline at end of file
diff --git a/app/views/start/edit_mail_address.php b/app/views/start/edit_mail_address.php
new file mode 100644
index 0000000..00ff0b7
--- /dev/null
+++ b/app/views/start/edit_mail_address.php
@@ -0,0 +1,25 @@
+<form method="post" class="default" action="<?=$controller->url_for('start/change_mail_address')?>" data-dialog="size=auto">
+ <?= CSRFProtection::tokenTag()?>
+ <fieldset>
+ <legend>
+ <?= _('E-Mail-Adresse ändern') ?>
+ </legend>
+
+ <label>
+ <span class="required"><?= _('E-Mail') ?></span>
+ <input required type="email" name="email1" id="email1"
+ value="<?= htmlReady($email) ?>"
+ <? if ($restricted) echo 'disabled'; ?>>
+ </label>
+ <label>
+ <span class="required"><?= _('E-Mail Wiederholung') ?></span>
+ <input required type="email" name="email2" id="email2"
+ value=""
+ data-must-equal="#email1"
+ <? if ($restricted) echo 'disabled'; ?>>
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'))?>
+ </footer>
+</form>
diff --git a/app/views/start/index.php b/app/views/start/index.php
new file mode 100644
index 0000000..8ec9ea0
--- /dev/null
+++ b/app/views/start/index.php
@@ -0,0 +1,37 @@
+<h1 class="sr-only">
+ <? if ($GLOBALS['perm']->have_perm('root')) :?>
+ <?= _("Startseite für Root bei Stud.IP")?>
+ <? elseif ($GLOBALS['perm']->have_perm('admin')) : ?>
+ <?= _("Startseite für Admins")?>
+ <? elseif ($GLOBALS['perm']->have_perm('dozent')) :?>
+ <?= _("Startseite für Lehrende")?>
+ <? else : ?>
+ <?= _("Ihre persönliche Startseite")?>
+ <? endif ?>
+</h1>
+
+<?php
+// display a random banner if the module is enabled
+if (Config::get()->BANNER_ADS_ENABLE) {
+ echo Banner::getRandomBanner()->toHTML();
+}
+?>
+
+<div class="start-widgetcontainer">
+ <? foreach ([$left, $right] as $column): ?>
+ <ul class="portal-widget-list">
+ <? foreach ($column as $widget): ?>
+ <li class="studip-widget-wrapper" id="<?= $widget->widget_id ?>">
+ <div class="ui-widget-content studip-widget">
+ <? if ($template = $widget->getPortalTemplate()): ?>
+ <? $template->set_layout($this->_factory->open('start/_widget')) ?>
+ <?= $this->render_partial($template, compact('widget')) ?>
+ <? else: ?>
+ <?= $this->render_partial('start/_widget', compact('widget')) ?>
+ <? endif ?>
+ </div>
+ </li>
+ <? endforeach ?>
+ </ul>
+ <? endforeach ?>
+</div>
diff --git a/app/views/studiengaenge/abschluesse/index.php b/app/views/studiengaenge/abschluesse/index.php
new file mode 100644
index 0000000..59610f8
--- /dev/null
+++ b/app/views/studiengaenge/abschluesse/index.php
@@ -0,0 +1,44 @@
+<table class="default collapsable"">
+<thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('/index', _('Abschluss'), 'name') ?>
+ <?= $controller->renderSortLink('/index', _('Studiengänge'), 'count_studiengaenge', ['style' => 'text-align: center; width: 10%;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+</thead>
+<? foreach ($abschluesse as $abschluss) : ?>
+ <?php
+ // skip unknown Abschluesse
+ if (is_null($abschluss->name)) {
+ continue;
+ }
+ ?>
+ <tbody class="<?= ($abschluss->count_studiengaenge ? '' : 'empty') ?> <?= ($abschluss_id === $abschluss->id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row" id="abschluss_<?= $abschluss->id ?>">
+ <td class="toggle-indicator">
+ <? if (is_null($abschluss->name) && $abschluss->count_studiengaenge) : ?>
+ <a class="mvv-load-in-new-row" href="<?= $controller->link_for('/details/' . $abschluss->id) ?>">
+ <?= _('Keinem Abschluss zugeordnet') ?>
+ </a>
+ <? else : ?>
+ <? if ($abschluss->count_studiengaenge) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->link_for('/details/' . $abschluss->id) ?>">
+ <?= htmlReady($abschluss->getDisplayName()) ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($abschluss->getDisplayName()) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center;" class="dont-hide"><?= $abschluss->count_studiengaenge ?></td>
+ <td></td>
+ </tr>
+ <? if ($abschluss_id === $abschluss->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengaenge/details') ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+<? endforeach; ?>
+</table>
diff --git a/app/views/studiengaenge/abschnitte/index.php b/app/views/studiengaenge/abschnitte/index.php
new file mode 100644
index 0000000..31404ce
--- /dev/null
+++ b/app/views/studiengaenge/abschnitte/index.php
@@ -0,0 +1,3 @@
+<div id="main">
+ <h3><? _('Studiengänge Studiengangabschnitte'); ?></h3>
+</div> \ No newline at end of file
diff --git a/app/views/studiengaenge/fachbereiche/index.php b/app/views/studiengaenge/fachbereiche/index.php
new file mode 100644
index 0000000..d666e89
--- /dev/null
+++ b/app/views/studiengaenge/fachbereiche/index.php
@@ -0,0 +1,45 @@
+<table class="default collapsable" style="width: 100%;">
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('/index', _('Fachbereich'), 'name') ?>
+ <?= $controller->renderSortLink('/index', _('Studiengänge'), 'count_objects', ['style' => 'text-align: center; width: 10%;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($fachbereiche as $fachbereich) : ?>
+ <?php
+ // skip unknown Fachbereiche
+ if (is_null($fachbereich->name)) {
+ continue;
+ }
+ ?>
+ <tbody class="<?= ($fachbereich->count_objects ? '' : 'empty') ?> <?= ($fachbereich_id === $fachbereich->id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row" id="fachbereich_<?= $fachbereich->id ?>">
+ <td class="toggle-indicator">
+ <? if (is_null($fachbereich->name) && $fachbereich->count_objects) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details/' . $fachbereich->id) ?>">
+ <?= _('Keinem Fachbereich zugeordnet') ?>
+ </a>
+ <? else : ?>
+ <? if ($fachbereich->count_objects) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details/' . $fachbereich->id) ?>">
+ <?= htmlReady($fachbereich->getDisplayName()) ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($fachbereich->getDisplayName()) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center;" class="dont-hide"><?= $fachbereich->count_objects ?></td>
+ <td></td>
+ </tr>
+ <? if ($fachbereich_id === $fachbereich->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengaenge/details') ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+</table>
diff --git a/app/views/studiengaenge/fachbereichestgteile/index.php b/app/views/studiengaenge/fachbereichestgteile/index.php
new file mode 100644
index 0000000..6ae4dab
--- /dev/null
+++ b/app/views/studiengaenge/fachbereichestgteile/index.php
@@ -0,0 +1,39 @@
+<form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default collapsable">
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('studiengaenge/fachbereichestgteile/', _('Fachbereich'), 'fachbereich') ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($fachbereiche as $fachbereich) : ?>
+ <tbody class="<?= $fachbereich['stgteile'] ? '' : 'empty' ?> <?= ((count($stgteil_ids) || $details_id === $fachbereich['institut_id']) ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <? if ($fachbereich['stgteile']) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details_fachbereich/' . $fachbereich['institut_id']) ?>">
+ <?= htmlReady($fachbereich['name']) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($fachbereich['name']) ?>
+ <? endif; ?>
+ </td>
+ <td class="actions dont-hide" style="white-space: nowrap;">
+ <? if (MvvPerm::havePermCreate('StudiengangTeil')) : ?>
+ <a href="<?= $controller->url_for('/stgteil_fachbereich/' . $fachbereich['institut_id']) ?>">
+ <?= Icon::create('file+add', Icon::ROLE_CLICKABLE , ['title' => _('Neuen Studiengangteil in diesem Fachbereich anlegen')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <? if ($details_id === $fachbereich['institut_id'] || count($stgteil_ids)) : ?>
+ <? $stgteile = StudiengangTeil::findByFachbereich($fachbereich['institut_id'], ['mvv_stgteil.stgteil_id' => $stgteil_ids], 'fach_name,zusatz,kp', 'ASC'); ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengangteile/details_grouped', compact('stgteile')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach ?>
+ </table>
+</form> \ No newline at end of file
diff --git a/app/views/studiengaenge/faecher/index.php b/app/views/studiengaenge/faecher/index.php
new file mode 100644
index 0000000..188e23b
--- /dev/null
+++ b/app/views/studiengaenge/faecher/index.php
@@ -0,0 +1,63 @@
+<form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default collapsable">
+ <caption>
+ <?= _('Studiengangteile nach Fächern gruppiert') ?>
+ <span class="actions"><? printf(_('%s Fächer'), $count) ?></span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('/index', _('Fach'), 'name') ?>
+ <?= $controller->renderSortLink('/index', _('Studiengangteile'), 'count_stgteile', ['style' => 'width: 5%; text-align: center;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($faecher as $fach): ?>
+ <tbody class="<?= $fach->count_stgteile ? '' : 'empty' ?> <?= (($details_id === $fach->id || (isset($stgteil_ids) && count($stgteil_ids))) ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <? if ($fach->count_stgteile) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details_fach/' . $fach->id) ?>">
+ <?= htmlReady($fach->name) ?>
+ </a>
+ <? else: ?>
+ <?= htmlReady($fach->name) ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center;" class="dont-hide"><?= $fach->count_stgteile ?> </td>
+ <td class="dont-hide actions">
+ <? if (MvvPerm::havePermCreate('StudiengangTeil')) : ?>
+ <a href="<?= $controller->url_for('/stgteil_fach/' . $fach->id) ?>">
+ <?= Icon::create('file+add', Icon::ROLE_CLICKABLE ,['title' => _('Neuen Studiengangteil für gewähltes Fach anlegen')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? if ($details_id === $fach->getId() || (isset($stgteil_ids) && count($stgteil_ids))) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengangteile/details_grouped', compact('stgteile')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach ?>
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="5" style="text-align: right;">
+ <?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_faecher=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render("shared/pagechooser");
+ ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</form> \ No newline at end of file
diff --git a/app/views/studiengaenge/informationen/degree.php b/app/views/studiengaenge/informationen/degree.php
new file mode 100644
index 0000000..206a0a9
--- /dev/null
+++ b/app/views/studiengaenge/informationen/degree.php
@@ -0,0 +1,45 @@
+<table class="default nohover collapsable">
+ <colgroup>
+ <col width="70%">
+ <col width="29%">
+ <col width="1%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Abschluss') ?></th>
+ <th><?= _('Studierende') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($degree as $key => $deg) : ?>
+ <? if (($studycount = Studiengaenge_InformationenController::getStudyCount($deg->abschluss_id)) > 0 ) : ?>
+ <tbody class="collapsed">
+ <tr class="table-header header-row">
+ <td class="toggle-indicator">
+ <a id="<?= $deg->abschluss_id?>" class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/showstudycourse', $deg->abschluss_id, $key+1)?>"
+ onclick="icon_toggle(this)">
+
+ <?= htmlReady($deg->name) ?>
+ </a>
+ </td>
+ <td>
+ <?= $studycount ?>
+ </td>
+ <td class="dont-hide actions">
+ <? if ($GLOBALS['perm']->have_perm("root", $GLOBALS['user']->id)) : ?>
+
+ <a href="<?= $controller->url_for('/messagehelper',
+ ['abschluss_id' => $deg->abschluss_id]) ?>" data-dialog >
+
+ <?= Icon::create('mail', Icon::ROLE_CLICKABLE,
+ ['title' => htmlReady(sprintf(_('Alle Studierenden mit dem Studienabschluss %s benachrichtigen.'),
+ $deg->name))]) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif; ?>
+ <? endforeach; ?>
+</table>
diff --git a/app/views/studiengaenge/informationen/index.php b/app/views/studiengaenge/informationen/index.php
new file mode 100644
index 0000000..5895f05
--- /dev/null
+++ b/app/views/studiengaenge/informationen/index.php
@@ -0,0 +1,39 @@
+<table class="default nohover collapsable">
+ <colgroup>
+ <col width="70%">
+ <col width="29%">
+ <col width="1%">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Fach') ?></th>
+ <th><?= _('Studierende') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($studycourses as $key => $studycourse) : ?>
+ <? $count = UserStudyCourse::countBySql('fach_id = ?', [$studycourse->fach_id]); ?>
+ <? if ($count > 0) : ?>
+ <tbody class="collapsed">
+ <tr class="table-header header-row">
+ <td class="toggle-indicator">
+ <a id="<?= $studycourse->fach_id?>" class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/showdegree', $studycourse->fach_id, $key+1)?>">
+ <?= htmlReady($studycourse->name) ?>
+ </a>
+ </td>
+ <td>
+ <?= $count ?>
+ </td>
+ <td class="dont-hide actions">
+ <a href="<?= $controller->url_for('/messagehelper', ['fach_id' => $studycourse->fach_id]) ?>" data-dialog >
+ <?= Icon::create('mail', Icon::ROLE_CLICKABLE,
+ ['title' => htmlReady(sprintf(_('Alle Studierenden des Faches %s benachrichtigen.'),
+ $studycourse->name))]) ?>
+ </a>
+ </td>
+ </tr>
+ </tbody>
+ <? endif; ?>
+ <? endforeach; ?>
+</table>
diff --git a/app/views/studiengaenge/informationen/showdegree.php b/app/views/studiengaenge/informationen/showdegree.php
new file mode 100644
index 0000000..dc2c043
--- /dev/null
+++ b/app/views/studiengaenge/informationen/showdegree.php
@@ -0,0 +1,31 @@
+<td colspan="3">
+ <table class="default">
+ <colgroup>
+ <col width="70%">
+ <col width="29%">
+ <col width="1%">
+ </colgroup>
+ <? foreach ($degree as $key => $deg) : ?>
+ <tbody>
+ <tr>
+ <td><?= htmlReady($deg->name) ?></td>
+ <td>
+ <?= UserStudyCourse::countBySql('fach_id = :fach_id AND abschluss_id = :abschluss_id',
+ [':fach_id' => $studycourse->fach_id, ':abschluss_id' => $deg->abschluss_id])?>
+ </td>
+ <td class="actions">
+ <? $action =ActionMenu::get()
+ ->addLink($controller->url_for('/messagehelper',
+ ['fach_id' => $studycourse->fach_id, 'abschluss_id' => $deg->abschluss_id]),
+ _('Nachricht an Studierende schreiben'),
+ Icon::create('mail', Icon::ROLE_CLICKABLE,
+ ['title' => htmlReady(sprintf(_('Nachricht an alle Studierende mit dem Studiengang %s mit dem Abschluss %s'),
+ $studycourse->name, $deg->name))]),
+ ['data-dialog' => '']) ?>
+ <?= $action ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endforeach; ?>
+ </table>
+</td> \ No newline at end of file
diff --git a/app/views/studiengaenge/informationen/showstudycourse.php b/app/views/studiengaenge/informationen/showstudycourse.php
new file mode 100644
index 0000000..c1c57bf
--- /dev/null
+++ b/app/views/studiengaenge/informationen/showstudycourse.php
@@ -0,0 +1,32 @@
+<td colspan="3">
+ <table class="default">
+ <colgroup>
+ <col width="70%">
+ <col width="29%">
+ <col width="1%">
+ </colgroup>
+ <? foreach ($studycourses as $key => $course) : ?>
+ <? if (($count = UserStudyCourse::countBySql('fach_id = :fach_id AND abschluss_id = :abschluss_id',
+ [':fach_id' => $course->fach_id, ':abschluss_id' => $degree->abschluss_id])) > 0) : ?>
+
+ <tr>
+ <td><?= htmlReady($course->name) ?></td>
+ <td>
+ <?= $count ?>
+ </td>
+ <td class="actions">
+ <? $action =ActionMenu::get()
+ ->addLink($controller->url_for('/messagehelper',
+ ['fach_id' => $course->fach_id, 'abschluss_id' => $degree->abschluss_id]),
+ _('Nachricht an Studierende schreiben'),
+ Icon::create('mail', Icon::ROLE_CLICKABLE,
+ ['title' => htmlReady(sprintf(_('Nachricht an alle Studierende mit dem Studiengang %s mit dem Abschluss %s'),
+ $course->name, $degree->name))]),
+ ['data-dialog' => '']) ?>
+ <?= $action ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <? endforeach; ?>
+ </table>
+</td>
diff --git a/app/views/studiengaenge/kategorien/index.php b/app/views/studiengaenge/kategorien/index.php
new file mode 100644
index 0000000..7bd291d
--- /dev/null
+++ b/app/views/studiengaenge/kategorien/index.php
@@ -0,0 +1,45 @@
+<table class="default collapsable">
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('/index', _('Abschluss-Kategorie'), 'name') ?>
+ <?= $controller->renderSortLink('/index', _('Studiengänge'), 'count_studiengaenge', ['style' => 'text-align: center; width: 10%;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? foreach ($kategorien as $kategorie) : ?>
+ <?php
+ // skip unknown Abschluesse
+ if (is_null($kategorie->name)) {
+ continue;
+ }
+ ?>
+ <tbody class="<?= ($kategorie->count_studiengaenge ? '' : 'empty') ?> <?= ($kategorie_id === $kategorie->id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row" id="kategorie_<?= $kategorie->id ?>">
+ <td class="toggle-indicator">
+ <? if (is_null($kategorie->name) && $kategorie->count_studiengaenge) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details/' . $kategorie->id) ?>">
+ <?= _('Keiner Abschluss-Kategorie zugeordnet') ?>
+ </a>
+ <? else : ?>
+ <? if ($kategorie->count_studiengaenge) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details/' . $kategorie->id) ?>">
+ <?= htmlReady($kategorie->getDisplayName()) ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($kategorie->getDisplayName()) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ <td style="text-align: center;" class="dont-hide"><?= $kategorie->count_studiengaenge ?></td>
+ <td></td>
+ </tr>
+ <? if ($kategorie_id == $kategorie->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengaenge/details') ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+</table>
diff --git a/app/views/studiengaenge/stgteilbezeichnungen/details.php b/app/views/studiengaenge/stgteilbezeichnungen/details.php
new file mode 100644
index 0000000..7b49ab7
--- /dev/null
+++ b/app/views/studiengaenge/stgteilbezeichnungen/details.php
@@ -0,0 +1,67 @@
+<? $languages = Config::get()->CONTENT_LANGUAGES; ?>
+<? $def_lang = reset(array_keys($languages)); ?>
+<td colspan="4">
+ <table class="default nohover">
+ <tbody>
+ <tr>
+ <th><?= _('Name') ?></th>
+ </tr>
+ <tr>
+ <td>
+ <img src="<?= Assets::image_path('languages/' . $languages[$def_lang]['picture']) ?>"
+ alt="<?= $languages[$def_lang]['name'] ?>">
+ <?= htmlReady($stgteilbezeichnung->isI18nField('name')
+ ? $stgteilbezeichnung->name->original()
+ : $stgteilbezeichnung->name) ?>
+ </td>
+ </tr>
+ <? if ($stgteilbezeichnung->isI18nField('name')) : ?>
+ <?php $stgteilbezeichnung_arr = $stgteilbezeichnung->name->toArray();?>
+ <? foreach ($stgteilbezeichnung_arr as $locale => $localized) : ?>
+ <tr>
+ <td>
+ <img src="<?= Assets::image_path('languages/' . $languages[$locale]['picture']) ?>"
+ alt="<?= $languages[$locale]['name'] ?>">
+ <?= htmlReady($localized) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+ <? if ($stgteilbezeichnung->isI18nField('name_kurz')) : ?>
+ <? if ($stgteilbezeichnung->name_kurz->original() || count($stgteilbezeichnung->name_kurz->toArray())) : ?>
+ <tr>
+ <th><strong><?= _('Kurzname:') ?></strong></th>
+ </tr>
+ <? if ($stgteilbezeichnung->name_kurz->original()) : ?>
+ <tr>
+ <td>
+ <img src="<?= Assets::image_path('languages/' . $languages[$def_lang]['picture']) ?>"
+ alt="<?= $languages[$def_lang]['name'] ?>">
+ <?= htmlReady($stgteilbezeichnung->name_kurz->original()) ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ <?php $stgteilbezeichnung_arr = $stgteilbezeichnung->name_kurz->toArray() ?>
+ <? foreach ($stgteilbezeichnung_arr as $locale => $localized) : ?>
+ <tr>
+ <td>
+ <img src="<?= Assets::image_path('languages/' . $languages[$locale]['picture']) ?>"
+ alt="<?= $languages[$locale]['name'] ?>">
+ <?= htmlReady($localized) ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? endif; ?>
+ <? else : ?>
+ <tr>
+ <th><strong><?= _('Kurzname:') ?></strong></th>
+ </tr>
+ <tr>
+ <td>
+ <?= htmlReady($stgteilbezeichnung->name_kurz) ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ </table>
+</td> \ No newline at end of file
diff --git a/app/views/studiengaenge/stgteilbezeichnungen/index.php b/app/views/studiengaenge/stgteilbezeichnungen/index.php
new file mode 100644
index 0000000..27cb570
--- /dev/null
+++ b/app/views/studiengaenge/stgteilbezeichnungen/index.php
@@ -0,0 +1,68 @@
+<?= $controller->jsUrl() ?>
+<form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table id="stgteilbezeichnungen" class="default sortable collapsable">
+ <caption>
+ <?= _('Studiengangteil-Bezeichnungen') ?>
+ <span class="actions"><? printf(_('%s Bezeichnungen'), count($stgteilbezeichnungen)) ?></span>
+ </caption>
+ <thead>
+ <tr>
+ <th><?= _('Name') ?></th>
+ <th style="width: 15%;"><?= _('Kurzname') ?></th>
+ <th style="text-align: center; width: 5%;"><?= _('Studiengänge') ?></th>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? if (count($stgteilbezeichnungen)) : ?>
+ <? foreach ($stgteilbezeichnungen as $stgteilbezeichnung) : ?>
+ <? $perm = MvvPerm::get($stgteilbezeichnung) ?>
+ <tbody id="<?= $stgteilbezeichnung->id ?>"
+ class="collapsed <?php if ($perm->haveFieldPerm('position')) echo 'sort_items'; ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details/' . $stgteilbezeichnung->id) ?>">
+ <?= htmlReady($stgteilbezeichnung->name) ?>
+ </a>
+ </td>
+ <td class="dont-hide">
+ <?= htmlReady($stgteilbezeichnung->name_kurz) ?>
+ </td>
+ <td style="text-align: center;" class="dont-hide">
+ <?= $stgteilbezeichnung->count_studiengaenge ?>
+ </td>
+ <td class="dont-hide actions">
+ <? if ($perm->havePermWrite()) : ?>
+ <a data-dialog
+ href="<?= $controller->url_for('/stgteilbezeichnung/' . $stgteilbezeichnung->id) ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE ,['title' => _('Studiengangteil-Bezeichnung bearbeiten')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ <? if ($perm->havePermCreate() && $stgteilbezeichnung->count_stgteile < 1) : ?>
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE , ['title' => _('Studiengangteil-Bezeichnung löschen')])
+ ->asInput([
+ 'formaction' => $controller->url_for('/delete/' . $stgteilbezeichnung->id),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich die Studiengangteil-Bezeichnung "%s" löschen?'), htmlReady($stgteilbezeichnung->name)),]) ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? if ($bezeichnung_id == $stgteilbezeichnung->getId()) : ?>
+ <?= $this->render_partial(
+ 'studiengaenge/stgteilbezeichnungen/details',
+ compact('stgteilbezeichnung')
+ ) ?>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+ <? else : ?>
+ <tbody>
+ <tr>
+ <td colspan="4" style="text-align: center">
+ <?= _('Es sind keine Studiengangteil-Bezeichnungen vorhanden') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif ?>
+ </table>
+</form>
diff --git a/app/views/studiengaenge/stgteilbezeichnungen/stgteilbezeichnung.php b/app/views/studiengaenge/stgteilbezeichnungen/stgteilbezeichnung.php
new file mode 100644
index 0000000..68a4d81
--- /dev/null
+++ b/app/views/studiengaenge/stgteilbezeichnungen/stgteilbezeichnung.php
@@ -0,0 +1,44 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? $perm = MvvPerm::get($stgteilbezeichnung) ?>
+<form class="mvv-form default"
+ action="<?= $controller->url_for('studiengaenge/stgteilbezeichnungen/store' . ($stgteilbezeichnung->getId() ? '/' . $stgteilbezeichnung->getId() : '')) ?>"
+ method="post"<?= Request::isXhr() ? ' data-dialog' : '' ?>>
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label><?= _('Studiengangteil-Bezeichnung') ?>
+ <?= MvvI18N::input(
+ 'name',
+ $stgteilbezeichnung->name,
+ ['maxlength' => '100', 'required' => '']
+ )->checkPermission($stgteilbezeichnung) ?>
+ </label>
+ <label><?= _('Kurzname') ?>
+ <?= MvvI18N::input(
+ 'name_kurz',
+ $stgteilbezeichnung->name_kurz,
+ ['maxlength' => '20']
+ )->checkPermission($stgteilbezeichnung) ?>
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <? if ($stgteilbezeichnung->isNew()) : ?>
+ <?= Button::createAccept(
+ _('Anlegen'),
+ 'store',
+ ['title' => _('Studiengangteil-Bezeichnung anlegen')]
+ ) ?>
+ <? else : ?>
+ <?= Button::createAccept(
+ _('Übernehmen'),
+ 'store',
+ ['title' => _('Änderungen übernehmen')]
+ ) ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('studiengaenge/stgteilbezeichnungen/index'),
+ ['title' => _('zurück zur Übersicht')]
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/studiengaenge/studiengaenge/approve.php b/app/views/studiengaenge/studiengaenge/approve.php
new file mode 100644
index 0000000..c8b8af0
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/approve.php
@@ -0,0 +1,35 @@
+<form data-dialog="reload-on-close" name="approve" action="<?= $controller->url_for('/approve', $studiengang_id) ?>"
+ method="post" style="margin-left: auto; margin-right: auto;">
+ <?= $this->render_partial('shared/studiengang/_studiengang', ['studiengang' => $studiengang, 'institut' => $institut]); ?>
+ <? if (count($studiengang->stgteil_assignments)) : ?>
+ <h2><?= _('Studiengangteile') ?></h2>
+ <? if (count($studiengang->stgteil_bezeichnungen)) : ?>
+ <? foreach ($studiengang->stgteil_bezeichnungen as $stgteilbez) : ?>
+ <h2><?= $stgteilbez->name; ?></h2>
+ <div style="margin-left: 3em;">
+ <? foreach (StudiengangStgteil::findByStudiengangStgteilBez($studiengang->getId(), $stgteilbez->getId()) as $stgstgteil) : ?>
+ <? $stgteilbez_ids = $stgstgteil->getId(); ?>
+ <? $stgteil = StudiengangTeil::find($stgteilbez_ids[1]); ?>
+ <? if ($stgteil) : ?>
+ <?= $this->render_partial('shared/studiengang/_studiengangteil', ['stgteil' => $stgteil]); ?>
+ <? foreach (StgteilVersion::findByStgteil($stgteil->getId()) as $version) : ?>
+ <? if ($version->stat == 'genehmigt') : ?>
+ <?= $this->render_partial('shared/studiengang/_stgteilversion', ['version' => $version]) ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </div>
+ <? endforeach; ?>
+ <? else : ?>
+ <? foreach ($studiengang->studiengangteile as $stgteil) : ?>
+ <?= $this->render_partial('shared/studiengang/_studiengangteil', ['stgteil' => StudiengangTeil::find($stgteil->stgteil_id)]); ?>
+ <? endforeach; ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= CSRFProtection::tokenTag(); ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Genehmigen'), 'approval', []) ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), ['data-dialog' => 'close']) ?>
+ </footer>
+</form> \ No newline at end of file
diff --git a/app/views/studiengaenge/studiengaenge/aufbaustg_edit.php b/app/views/studiengaenge/studiengaenge/aufbaustg_edit.php
new file mode 100644
index 0000000..0d430f6
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/aufbaustg_edit.php
@@ -0,0 +1,23 @@
+<? $perm = MvvPerm::get($aufbaustg); ?>
+<form data-dialog action="<?= $controller->url_for('studiengaenge/studiengaenge/aufbaustg_store') ?>" class="default" id="mvv-aufbaustg-new" method="post">
+ <input type="hidden" name="aufbaustg_id" value="<?= $aufbaustg->id ?>">
+ <label>
+ <?= _('Typ des Aufbaustudiengangs') ?>
+ <select name="aufbaustg_typ" class="nested-select"<?= $perm->haveFieldPerm('typ', MvvPerm::PERM_WRITE) ? '' : ' disabled' ?>>
+ <option class="is-placeholder"><?= _('Typ auswählen') ?></option>
+ <? foreach ($GLOBALS['MVV_AUFBAUSTUDIENGANG']['TYP']['values'] as $key => $aufbaustg_typ) : ?>
+ <? if ($aufbaustg_typ['visible']) : ?>
+ <option value="<?= $key ?>"<?= $key == $aufbaustg->typ ? ' selected' : '' ?>><?= htmlReady($aufbaustg_typ['name']) ?></option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <label>
+ <?= _('Bemerkung') ?>
+ <?= MvvI18N::textarea('aufbaustg_kommentar', $aufbaustg->kommentar, ['class' => 'wysiwyg'])->checkPermission($aufbaustg) ?>
+ </label>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store_aufbaustg') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+</form>
diff --git a/app/views/studiengaenge/studiengaenge/aufbaustg_edit__.php b/app/views/studiengaenge/studiengaenge/aufbaustg_edit__.php
new file mode 100644
index 0000000..36dcb01
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/aufbaustg_edit__.php
@@ -0,0 +1,12 @@
+<? $perm = MvvPerm::get($aufbau_stg); ?>
+<form data-dialog action="<?= $controller->url_for('studiengaenge/studiengaenge/aufbaustg_store') ?>" class="default" id="mvv-aufbaustg-new" method="post">
+ <input type="hidden" name="aufbaustg_id" value="<? $aufbaustg->id ?>">
+ <label for="mvv-aufbaustg-select">
+ <?= _('Studiengang') ?>
+ </label>
+
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store_aufbaustg') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+</form>
diff --git a/app/views/studiengaenge/studiengaenge/aufbaustg_info.php b/app/views/studiengaenge/studiengaenge/aufbaustg_info.php
new file mode 100644
index 0000000..e30c085
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/aufbaustg_info.php
@@ -0,0 +1,10 @@
+<article class="studip">
+ <header>
+ <h1>
+ <? printf(_('Bemerkungen zum Aufbaustudiengang %s (%s)'), $aufbaustg->getDisplayName(), $GLOBALS['MVV_AUFBAUSTUDIENGANG']['TYP']['values'][$aufbaustg->typ]['name']) ?>
+ </h1>
+ </header>
+ <section>
+ <?= formatReady($aufbaustg->kommentar) ?>
+ </section>
+</article> \ No newline at end of file
diff --git a/app/views/studiengaenge/studiengaenge/aufbaustg_select.php b/app/views/studiengaenge/studiengaenge/aufbaustg_select.php
new file mode 100644
index 0000000..199baf3
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/aufbaustg_select.php
@@ -0,0 +1,19 @@
+<form data-dialog action="<?= $controller->url_for('studiengaenge/studiengaenge/aufbaustg_assign') ?>" class="default" id="mvv-aufbaustg-new" method="post">
+ <input type="hidden" name="grundstg_id" value="<?= htmlReady($grundstg->id) ?>">
+
+ <label for="mvv-aufbaustg-select">
+ <?= _('Aufbaustudiengang auswählen') ?>
+ </label>
+ <select multiple id="mvv-aufbaustg-select" name="aufbaustg_ids[]" class="nested-select">
+ <option class="is-placeholder"><?= _('Aufbaustudiengang auswählen') ?></option>
+ <? foreach ($aufbaustgs as $stg) : ?>
+ <option value="<?= htmlReady($stg->id) ?>"<?= in_array($stg->id, $aufbaustg_assigmnents) ? ' disabled' : '' ?>>
+ <?= htmlReady($stg->getDisplayName()) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <div data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'store_aufbaustg') ?>
+ <?= Studip\LinkButton::createCancel(); ?>
+ </div>
+</form>
diff --git a/app/views/studiengaenge/studiengaenge/aufbaustg_table.php b/app/views/studiengaenge/studiengaenge/aufbaustg_table.php
new file mode 100644
index 0000000..09fa8eb
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/aufbaustg_table.php
@@ -0,0 +1,86 @@
+<? $perm = MvvPerm::get($grund_stg) ?>
+<div id="mvv-aufbaustg-table">
+ <table class="default sortable-table" data-sortlist="[[0, 1]]">
+ <colgroup>
+ <col width="45%">
+ <col width="15%">
+ <col>
+ <col width="5%">
+ </colgroup>
+ <caption>
+ <?= _('Aufbaustudiengänge im Master') ?>
+ <span class="actions">
+ <? if (!$perm->haveFieldPerm('aufbaustg_assignments', MvvPerm::PERM_CREATE) || $grund_stg->isNew()) : ?>
+ <?= Icon::create('add', Icon::ROLE_INACTIVE) ?>
+ <? else : ?>
+ <a href="<?= $controller->url_for('studiengaenge/studiengaenge/aufbaustg_select', $grund_stg->id) ?>" data-dialog="size=auto">
+ <?= Icon::create('add', Icon::ROLE_CLICKABLE) ?>
+ </a>
+ <? endif; ?>
+ </span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <th data-sort="text"><?= _('Aufbaustudiengang'); ?></th>
+ <th data-sort="htmldata"><?= _('Typ'); ?></th>
+ <th data-sort="false"><?= _('Bemerkung'); ?></th>
+ <th data-sort="false"></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($grund_stg->aufbaustg_assignments as $aufbau_stg) : ?>
+ <tr>
+ <td><?= htmlReady($aufbau_stg->getDisplayName()) ?></td>
+ <td data-sort-value="<?= htmlReady($GLOBALS['MVV_AUFBAUSTUDIENGANG']['TYP']['values'][$aufbau_stg->typ]['name']) ?>">
+ <select name="aufbaustg_typ[<?= $aufbau_stg->id ?>]">
+ <? foreach ($GLOBALS['MVV_AUFBAUSTUDIENGANG']['TYP']['values'] as $typ_key => $typ_value) : ?>
+ <? if ($GLOBALS['MVV_AUFBAUSTUDIENGANG']['TYP']['values'][$typ_key]['visible']) : ?>
+ <option value="<?= htmlReady($typ_key) ?>"<?= $typ_key == $aufbau_stg->typ ? ' selected' : '' ?>>
+ <?= htmlReady($typ_value['name']) ?>
+ </option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </td>
+ <td>
+ <div style="display: inline-block; overflow: hidden; vertical-align: bottom; white-space: nowrap; text-overflow: ellipsis; max-width: 250px;">
+ <?= formatReady($aufbau_stg->kommentar) ?>
+ </div>
+ <? if (trim($aufbau_stg->kommentar)) : ?>
+ <a data-dialog="size=auto" href="<?= $controller->link_for('studiengaenge/studiengaenge/aufbaustg_info', $aufbau_stg->id) ?>">
+ <?= Icon::create('info')->asImg(12, tooltip2(_('Bemerkung anzeigen'))) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <td class="actions">
+ <? if ($perm->haveFieldPerm('aufbaustg_assignments', MvvPerm::PERM_WRITE)) : ?>
+ <a data-dialog="" href="<?= $controller->link_for('studiengaenge/studiengaenge/aufbaustg_edit', $aufbau_stg->id) ?>">
+ <?= Icon::create('edit') ?>
+ </a>
+ <? endif; ?>
+ <? if ($perm->haveFieldPerm('aufbaustg_assignments', MvvPerm::PERM_CREATE)) : ?>
+ <a data-dialog href="<?= $controller->url_for('studiengaenge/studiengaenge/aufbaustg_delete', $aufbau_stg->id) ?>">
+ <?= Icon::create('trash')->asInput([
+ 'formaction' => $controller->url_for('studiengaenge/studiengaenge/aufbaustg_delete', $aufbau_stg->id),
+ 'title' => _('Zuordnung als Aufbaustudiengang löschen'),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich die Zuordnung von "%s" als "%s" löschen?'), htmlReady($aufbau_stg->getDisplayName()), htmlReady($aufbau_stg->typ))
+ ]) ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ <? if (count($grund_stg->aufbaustg_assignments) === 0): ?>
+ <tr>
+ <td colspan="4">
+ <? if ($grund_stg->isNew()) : ?>
+ <?= _('Der neue Studiengang muss erst gespeichert werden, um Aufbaustudiengänge zuordnen zu können.') ?>
+ <? else : ?>
+ <?= _('Es wurden noch keine Aufbaustudiengänge angelegt.') ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ </table>
+</div>
diff --git a/app/views/studiengaenge/studiengaenge/details.php b/app/views/studiengaenge/studiengaenge/details.php
new file mode 100644
index 0000000..ef92bc1
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/details.php
@@ -0,0 +1,11 @@
+<td colspan="3">
+ <table class="default collapsable">
+ <colgroup>
+ <col>
+ <col style="width: 15%;">
+ <col style="width: 15%;">
+ <col style="width: 8%; white-space: nowrap;">
+ </colgroup>
+ <?= $this->render_partial('studiengaenge/studiengaenge/studiengaenge') ?>
+ </table>
+</td> \ No newline at end of file
diff --git a/app/views/studiengaenge/studiengaenge/export.php b/app/views/studiengaenge/studiengaenge/export.php
new file mode 100644
index 0000000..72ed610
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/export.php
@@ -0,0 +1,57 @@
+<html lang="de" xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'>
+ <head>
+ <meta charset="UTF-8">
+ <title><?= htmlReady($studiengang->getDisplayName()) ?></title>
+
+ <!--[if gte mso 9]>
+ <xml>
+ <w:WordDocument>
+ <w:View>Print</w:View>
+ <w:Zoom>90</w:Zoom>
+ <w:DoNotOptimizeForBrowser/>
+ </w:WordDocument>
+ </xml>
+ <![endif]-->
+
+ <style>
+ table.mvv-modul-details {
+ border: 1px solid black;
+ border-collapse: collapse;
+ font: 8pt arial, sans-serif;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ }
+ table.mvv-modul-details td, table.mvv-modul-details th {
+ border: 1px solid black;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ }
+ table.mvv-modul-details tbody th {
+ text-align: left;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ }
+ </style>
+ </head>
+ <body>
+ <div>
+ <?= $this->render_partial('shared/studiengang/_studiengang', array('studiengang' => $studiengang)); ?>
+ <? if (count($studiengang->studiengangteile)) : ?>
+ <h1><?= _('Studiengangteile') ?></h1>
+ <? if (count($studiengang->stgteil_bezeichnungen)) : ?>
+ <? foreach ($studiengang->stgteil_bezeichnungen as $stgteilbez) : ?>
+ <h2><?= $stgteilbez->name; ?></h2>
+ <? $stg_stgteile = $studiengang->stgteil_assignments->findBy('stgteil_bez_id', $stgteilbez->id); ?>
+ <? foreach ($stg_stgteile as $stg_stgteil) : ?>
+ <?= $this->render_partial('shared/studiengang/_studiengangteil', ['stgteil' => $stg_stgteil->studiengangteil]); ?>
+ <? endforeach; ?>
+ <? endforeach; ?>
+ <? else : ?>
+ <? foreach($studiengang->studiengangteile as $stgteil) :?>
+ <? echo $this->render_partial('shared/studiengang/_studiengangteil', ['stgteil' => $stgteil]); ?>
+ <? endforeach; ?>
+ <? endif; ?>
+ <? endif; ?>
+ </div>
+ </body>
+</html>
diff --git a/app/views/studiengaenge/studiengaenge/index.php b/app/views/studiengaenge/studiengaenge/index.php
new file mode 100644
index 0000000..8919c62
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/index.php
@@ -0,0 +1,52 @@
+<?= $controller->jsUrl() ?>
+<table class="default collapsable">
+ <caption>
+ <?= _('Liste der Studiengänge')?>
+ <span class="actions"><? printf(_('%s Studiengänge'), $count) ?></span>
+ </caption>
+ <colgroup>
+ <col>
+ <col style="width: 15%;">
+ <col style="width: 15%;">
+ <col style="width: 8%; white-space: nowrap;">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('studiengaenge/studiengaenge/index/', _('Studiengang'), 'name') ?>
+ <?= $controller->renderSortLink('studiengaenge/studiengaenge/index/', _('Einrichtung'), 'institut_name', ['style' => 'width: 15%;']) ?>
+ <?= $controller->renderSortLink('studiengaenge/studiengaenge/index/', _('Kategorie'), 'kategorie_name', ['style' => 'width: 15%;']) ?>
+ <th style="width: 8%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? if ($count) : ?>
+ <?= $this->render_partial('studiengaenge/studiengaenge/studiengaenge') ?>
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="5" style="text-align: right;">
+
+ <?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_studiengaenge=%s';
+ $pagination->set_attribute('pagelink', $page_link);
+ echo $pagination->render('shared/pagechooser');
+ ?>
+
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ <? else : ?>
+ <tbody>
+ <tr>
+ <td colspan="5" style="text-align: center">
+ <?= $msg ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif ?>
+</table>
diff --git a/app/views/studiengaenge/studiengaenge/stgteil_bezeichnungen.php b/app/views/studiengaenge/studiengaenge/stgteil_bezeichnungen.php
new file mode 100644
index 0000000..fe943d6
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/stgteil_bezeichnungen.php
@@ -0,0 +1,69 @@
+<td colspan="5">
+ <table class="default collapsable">
+ <colgroup>
+ <col>
+ <col style="width: 1%">
+ </colgroup>
+ <? $stgteile_bez = StgteilBezeichnung::findByStudiengang($studiengang->id) ?>
+ <? foreach ($stgteile_bez as $bez_stgteil) : ?>
+ <tbody class="<?= ($bez_stgteil->count_stgteile ? '' : 'empty') ?> <?= (($stg_stgbez_id === $studiengang->id . '_' . $bez_stgteil->id) ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row" id="stgteil_<?= $bez_stgteil->id ?>">
+ <td class="toggle-indicator">
+ <? if ($bez_stgteil->count_stgteile) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details_studiengang', $studiengang->id, $bez_stgteil->id) ?>">
+ <?= htmlReady($bez_stgteil->name) ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($bez_stgteil->name) ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide actions"></td>
+ </tr>
+ <? if ($stg_stgbez_id === $studiengang->id . '_' . $bez_stgteil->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengaenge/studiengangteile', compact('studiengang', 'stg_stgbez_id', 'search')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; ?>
+ <? if ($studiengang->typ === 'mehrfach' && MvvPerm::haveFieldPermStudiengangteil($studiengang, MVVPerm::PERM_CREATE)) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="3">
+ <form style="width: 100%;"
+ action="<?= $controller->url_for('/add_stgteil/' . $studiengang->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <div style="float: left; padding-right: 10px;"><?= _('Studiengangteil hinzufügen') ?></div>
+ <div style="float: left; padding-right: 10px;">
+ <?= $search_stgteil->render() ?>
+ <?= Icon::create(
+ 'search',
+ Icon::ROLE_CLICKABLE ,
+ [
+ 'title' => _('Studiengangteil zuordnen'),
+ 'name' => 'search_stgteil', 'data-qs_name' => $search_stgteil->getId(),
+ 'data-qs_id' => $qs_search_stgteil_id,
+ 'data-qs_submit' => 'no',
+ 'class' => 'mvv-qs-button'
+ ])->asInput(); ?>
+ </div>
+ <label><?= _('als') ?>
+ <select name="stgteil_bez_id" size="1">
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach (StgteilBezeichnung::getAllEnriched() as $stgteil_bez) : ?>
+ <option value="<?= $stgteil_bez->getId() ?>"><?= htmlReady($stgteil_bez->name) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <input type="hidden" name="level" value="stg">
+ <input name="add_stgteil" class="text-top mvv-submit" type="image"
+ title="<?= _('Studiengangteil hinzufügen') ?>"
+ src="<?= Icon::create('accept')->asImagePath(); ?>">
+ </form>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</td>
diff --git a/app/views/studiengaenge/studiengaenge/studiengaenge.php b/app/views/studiengaenge/studiengaenge/studiengaenge.php
new file mode 100644
index 0000000..54f2766
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/studiengaenge.php
@@ -0,0 +1,86 @@
+<? foreach ($studiengaenge as $studiengang) : ?>
+ <? $perm = new MvvPerm($studiengang) ?>
+ <tbody class="<?= ($studiengang_id === $studiengang->id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="table-header header-row" id="studiengang_<?= $studiengang->id ?>">
+ <td class="toggle-indicator">
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details_studiengang/' . $studiengang->id) ?>">
+ <? $ampel_icon = $GLOBALS['MVV_STUDIENGANG']['STATUS']['values'][$studiengang->stat]['icon'] ?>
+ <? $ampelstatus = $GLOBALS['MVV_STUDIENGANG']['STATUS']['values'][$studiengang->stat]['name'] ?>
+ <? if ($ampel_icon) : ?>
+ <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?>
+ <? endif; ?>
+ <?= htmlReady($studiengang->name) ?> <?= (mb_strlen($studiengang->name_kurz) ? '(' . htmlReady($studiengang->name_kurz) . ')' : '') ?>
+ <? if ($studiengang->count_dokumente) : ?>
+ <?= Icon::create(
+ 'staple',
+ Icon::ROLE_INFO,
+ [
+ 'title' => sprintf(
+ ngettext('%s Dokument zugeordnet', '%s Dokumente zugeordnet', $studiengang->count_dokumente),
+ $studiengang->count_dokumente
+ ),
+ 'style' => 'vertical-align: text-top;'
+ ]) ?>
+ <? endif; ?>
+ </a>
+ </td>
+ <td class="dont-hide">
+ <? if ($studiengang->responsible_institute) : ?>
+ <?= htmlReady($studiengang->responsible_institute->getDisplayName()) ?>
+ <? else : ?>
+ <?= _('Unbekannte Einrichtung') ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide">
+ <?= htmlReady($studiengang->abschluss->category->getDisplayName()) ?>
+ </td>
+ <td class="actions dont-hide">
+ <form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($studiengang->stat === 'planung' && MvvPerm::haveFieldPermStat($studiengang)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/approve/' . $studiengang->id),
+ _('Studiengang genehmigen'),
+ Icon::create('accept', Icon::ROLE_CLICKABLE , ['title' => _('Studiengang genehmigen')]),
+ ['data-dialog' => 'buttons=false'])
+ ?>
+ <? endif; ?>
+ <? if ($perm->havePerm(MvvPerm::PERM_WRITE)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/studiengang/' . $studiengang->id),
+ _('Studiengang bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE , ['title' => _('Studiengang bearbeiten')]))
+ ?>
+ <? endif; ?>
+ <? if ($perm->havePerm(MvvPerm::PERM_CREATE)) : ?>
+ <? if (!$studiengang->count_faecher) : ?>
+ <? $actionMenu->addButton(
+ 'delete',
+ _('Studiengang löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE ,tooltip2(_('Studiengang löschen'))),
+ [
+ 'formaction' => $controller->url_for('/delete/' . $studiengang->id),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich den Studiengang "%s" löschen?'), htmlReady($studiengang->name))
+ ]
+ ) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </form>
+ </td>
+ </tr>
+ <? if ($studiengang_id === $studiengang->id) : ?>
+ <? if ($studiengang->typ == 'mehrfach') : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengaenge/stgteil_bezeichnungen', compact('studiengang_id', 'studiengang', 'bez_stgteile', 'stgteile', 'stg_stgbez_id', 'search_stgteil', 'search')) ?>
+ </tr>
+ <? else : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengaenge/studiengangteile', compact('studiengang', 'stgteile', 'search_stgteil', 'search')) ?>
+ </tr>
+ <? endif; ?>
+ <? endif; ?>
+ </tbody>
+<? endforeach; ?>
diff --git a/app/views/studiengaenge/studiengaenge/studiengang.php b/app/views/studiengaenge/studiengaenge/studiengang.php
new file mode 100644
index 0000000..bb507ed
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/studiengang.php
@@ -0,0 +1,359 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+<? $perm = MvvPerm::get($studiengang) ?>
+<form class="default" action="<?= $controller->link_for('/studiengang', $studiengang->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset class="collapsable">
+ <legend>
+ <?= _('Fach-Abschluss-Bezeichnung'); ?>
+ </legend>
+
+ <? if ($perm->haveFieldPerm('name', MvvPerm::PERM_WRITE)) : ?>
+ <label>
+ <?= _('Fachsuche:') ?>
+ <?= tooltipHtmlIcon(_('Soll der Name des Studiengangs mit dem eines Fachs übereinstimmen, geben Sie den Namen des Fachs ein, und wählen Sie das Fach aus der Liste. Es werden dann automatisch die weiteren Bezeichnungen aus den Daten des Fachs übernommen.')) ?>
+ <?= $search ?>
+ </label>
+ <? endif; ?>
+ <label>
+ <?= _('Name:') ?>
+ <?= MvvI18N::input('name', $studiengang->name, ['maxlength' => '255'])->checkPermission($studiengang) ?>
+ </label>
+ <label><?= _('Kurzbezeichnung:') ?>
+ <?= MvvI18N::input('name_kurz', $studiengang->name_kurz, ['maxlength' => '50'])->checkPermission($studiengang) ?>
+ </label>
+ <label><?= _('Abschlusszuordnung:') ?>
+ <? if ($perm->haveFieldPerm('abschluss_id')) : ?>
+ <select id="abschluss_id" name="abschluss_id" size="1">
+ <option value=""><?= _('-- bitte wählen --') ?></option>
+ <? foreach ($abschluesse as $abschluss) : ?>
+ <option <?= ($abschluss['abschluss_id'] == $studiengang->abschluss_id ? 'selected ' : '') ?>value="<?= $abschluss['abschluss_id'] ?>"><?= htmlReady($abschluss['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ <? else: ?>
+ <? $abschluss = Abschluss::find($studiengang->abschluss_id)?>
+ <?= htmlReady($abschluss['name']) ?>
+ <input type="hidden" name="abschluss_id" value="<?= $studiengang->abschluss_id ?>">
+ <? endif; ?>
+ </label>
+ <label for="mvv-abschlussgrad"><?= _('Angestrebter Abschlussgrad') ?>
+ <input type ="hidden" name="abschlussgrad" value="<?= $studiengang->abschlussgrad ?>">
+ <select id="mvv-abschlussgrad" name="abschlussgrad"<?= $perm->haveFieldPerm('abschlussgrad', MvvPerm::PERM_WRITE) ? '' : ' disabled' ?>>
+ <? foreach ($GLOBALS['MVV_STUDIENGANG']['ABSCHLUSSGRAD']['values'] as $key => $entry) : ?>
+ <? if ($entry['visible']) : ?>
+ <option value="<?= htmlReady($key) ?>"<?= $key == $studiengang->abschlussgrad ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Gültigkeit'); ?>
+ </legend>
+
+ <label>
+ <?= _('von Semester:') ?>
+ <? if ($perm->haveFieldPerm('start')) : ?>
+ <select name="start" size="1">
+ <option value=""><?= _('-- Semester wählen --') ?></option>
+ <? foreach ($semester as $sem) : ?>
+ <option value="<?= $sem->semester_id ?>"<?= ($sem->semester_id === $studiengang->start ? ' selected' : '') ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <? $sem = Semester::find($studiengang->start) ?>
+ <?= htmlReady($sem->name) ?>
+ <input type="hidden" name="start" value="<?= $studiengang->start ?>">
+ <? endif; ?>
+ </label>
+ <label>
+ <?= _('bis Semester:') ?>
+ <? if ($perm->haveFieldPerm('end')) : ?>
+ <select name="end" size="1">
+ <option value=""><?= _('unbegrenzt gültig') ?></option>
+ <? foreach ($semester as $sem) : ?>
+ <option value="<?= $sem->semester_id ?>"<?= ($sem->semester_id === $studiengang->end ? ' selected' : '') ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <? if ($studiengang->end !== '') : ?>
+ <? $sem = Semester::find($studiengang->end) ?>
+ <?= htmlReady($sem->name) ?>
+ <? else : ?>
+ <?= _('unbegrenzt gültig') ?>
+ <? endif; ?>
+ <input type="hidden" name="end" value="<?= $studiengang->end ?>">
+ <? endif; ?>
+ </label>
+ <div><?= _('Das Endsemester wird nur angegeben, wenn der Studiengang abgeschlossen ist.') ?></div>
+ <label>
+ <?= _('Beschlussdatum:') ?>
+ <? if ($perm->haveFieldPerm('beschlussdatum')) : ?>
+ <input type="text" name="beschlussdatum"
+ value="<?= ($studiengang->beschlussdatum ? strftime('%d.%m.%Y', $studiengang->beschlussdatum) : '') ?>"
+ placeholder="<?= _('TT.MM.JJJJ') ?>" size="15" class="with-datepicker">
+ <? else : ?>
+ <?= ($studiengang->beschlussdatum ? strftime('%d.%m.%Y', $studiengang->beschlussdatum) : '') ?>
+ <input type="hidden" name="beschlussdatum"
+ value="<?= ($studiengang->beschlussdatum ? strftime('%d.%m.%Y', $studiengang->beschlussdatum) : '') ?>">
+ <? endif; ?>
+ </label>
+ <label>
+ <?= _('Fassung:') ?>
+ <select <?= $perm->disable('fassung_nr') ?> name="fassung_nr" style="display: inline-block; width: 5em;">
+ <option value="">--</option>
+ <? foreach (range(1, 30) as $nr) : ?>
+ <option<?= $nr === (int)$studiengang->fassung_nr ? ' selected' : '' ?> value="<?= $nr ?>"><?= $nr ?>.</option>
+ <? endforeach; ?>
+ </select>
+ <? if ($perm->haveFieldPerm('fassung_typ')): ?>
+ <select style="display: inline-block; max-width: 40em;" name="fassung_typ">
+ <option value="0">--</option>
+ <? foreach ($GLOBALS['MVV_STUDIENGANG']['FASSUNG_TYP'] as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key === $studiengang->fassung_typ ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ <? else: ?>
+ <?= ($studiengang->fassung_typ === '0' ? '--' : $GLOBALS['MVV_STUDIENGANG']['FASSUNG_TYP'][$studiengang->fassung_typ]['name']) ?>
+ <input type="hidden" name="fassung_typ" value="<?= $studiengang->fassung_typ ?>">
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Einstellungen'); ?>
+ </legend>
+
+ <label>
+ <?= _('Verantwortliche Einrichtung') ?>
+ <? if ($perm->haveFieldPerm('institut_id', MvvPerm::PERM_WRITE)): ?>
+ <div>
+ <div style="display: inline-block;width: 100%;max-width: 48em;">
+ <?= $search_institutes->render() ?>
+ </div>
+ <? if (Request::submitted('search_institutes')) : ?>
+ <?= Icon::create('decline')->asInput(['name' => 'reset_institutes', 'data-qs_id' => $search_institutes_id, 'class' => 'text-bottom']) ?>
+ <? else : ?>
+ <?= Icon::create('search')->asInput(['name' => 'search_institutes', 'data-qs_id' => $search_institutes_id, 'data-qs_name' => $search_institutes->getId(), 'class' => 'mvv-qs-button text-bottom']) ?>
+ <? endif; ?>
+ </div>
+ <? endif; ?>
+ <ul id="institut_target" class="mvv-assigned-items mvv-assign-single mvv-institute">
+ <li class="mvv-item-list-placeholder"<?= ($studiengang->institut_id ? ' style="display: none;"' : '') ?>><?= _('Bitte eine Einrichtung suchen und zuordnen.') ?></li>
+ <? if ($studiengang->institut_id) : ?>
+ <li id="institut_<?= $studiengang->institut_id ?>">
+ <div class="mvv-item-list-text">
+ <? if ($institut) : ?>
+ <?= htmlReady($institut->getDisplayName()) ?>
+ <? else: ?>
+ <?= _('Unbekannte Einrichtung') ?>
+ <? endif; ?>
+ </div>
+ <? if ($perm->haveFieldPerm('institut_id', MvvPerm::PERM_WRITE)): ?>
+ <div class="mvv-item-list-buttons">
+ <a href="#"
+ class="mvv-item-remove"><?= Icon::create('trash', Icon::ROLE_CLICKABLE , ['title' => _('Einrichtung entfernen')])->asImg(); ?></a>
+ </div>
+ <? endif; ?>
+ <input type="hidden" name="institut_item" value="<?= $studiengang->institut_id ?>">
+ </li>
+ <? endif; ?>
+ </ul>
+ </label>
+
+
+ <label><?= _('Status der Bearbeitung') ?></label>
+ <? if ($perm->haveFieldPerm('stat', MvvPerm::PERM_WRITE) && $studiengang->stat !== 'planung'): ?>
+ <? foreach ($GLOBALS['MVV_STUDIENGANG']['STATUS']['values'] as $key => $status_bearbeitung) : ?>
+ <label>
+ <input <?= ($studiengang->stat === 'ausgelaufen' && $key === 'genehmigt') ? 'disabled' : '' ?>
+ type="radio" name="status"
+ value="<?= $key ?>"<?= $studiengang->stat === $key ? ' checked' : '' ?>>
+ <?= $status_bearbeitung['name'] ?>
+ </label>
+ <? endforeach; ?>
+ <? else : ?>
+ <label>
+ <?= $GLOBALS['MVV_STUDIENGANG']['STATUS']['values'][$studiengang->stat]['name'] ?>
+ <input type="hidden" name="status" value="<?= $studiengang->stat ?>">
+ </label>
+ <? endif; ?>
+
+ <label for="kommentar_status" style="vertical-align: top;"><?= _('Kommentar Bearbeitungsstatus') ?>
+ <? if ($perm->haveFieldPerm('kommentar_status', MvvPerm::PERM_WRITE)): ?>
+ <textarea cols="60" rows="5" name="kommentar_status" id="kommentar_status"
+ class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($studiengang->kommentar_status) ?></textarea>
+ <? else: ?>
+ <textarea readonly cols="60" rows="5" name="kommentar_status" id="kommentar_status"
+ class="ui-resizable"><?= htmlReady($studiengang->kommentar_status) ?></textarea>
+ <? endif; ?>
+ </label>
+
+ <input type="hidden" name="stg_typ" value="<?= htmlReady($studiengang->typ) ?>">
+ <label><?= _('Studiengangteile') ?></label>
+ <label>
+ <input id="stg_typ" type="radio" name="stg_typ"<?= ($studiengang->typ != 'mehrfach' ? ' checked' : '') ?> value="einfach"<?= $perm->disable('typ', MvvPerm::PERM_WRITE) ?>>
+ <?= _('Einfach-Studiengang (Diesem Studiengang wird ein oder mehrere Studiengangteil(e) direkt zugewiesen)') ?>
+ </label>
+ <label>
+ <input type="radio" name="stg_typ"<?= ($studiengang->typ == 'mehrfach' ? ' checked' : '') ?> value="mehrfach"<?= $perm->disable('typ', MvvPerm::PERM_WRITE) ?>>
+ <?= _('Mehrfach-Studiengang (Diesem Studiengang können mehrere Studiengangteile in Abschnitten zugewiesen werden)') ?>
+ </label>
+
+ <label><?= _('Regelstudienzeit') ?>
+ <input type="number" name="studienzeit" value="<?= htmlReady($studiengang->studienzeit) ?>"<?= $perm->disable('studienzeit', MvvPerm::PERM_WRITE) ?>>
+ </label>
+
+ <label><?= _('Studienplätze') ?>
+ <input type="number" name="studienplaetze" value="<?= htmlReady($studiengang->studienplaetze) ?>"<?= $perm->disable('studienplaetze', MvvPerm::PERM_WRITE) ?>>
+ </label>
+
+ <label for="mvv-language-chooser-select"><?= _('Lehrsprachen') ?>
+ <? if ($perm->haveFieldPerm('languages', MvvPerm::PERM_CREATE)) : ?>
+ <ul id="language_target" class="mvv-assigned-items sortable mvv-languages">
+ <li class="mvv-item-list-placeholder"<?= (count($studiengang->languages) ? ' style="display:none;"' : '') ?>>
+ <?= _('Geben Sie die Lehrsprachen an.') ?>
+ </li>
+ <? foreach ($studiengang->languages as $assigned_language) : ?>
+ <li id="language_<?= $assigned_language->lang ?>" class="sort_items">
+ <div class="mvv-item-list-text"><?= htmlReady($assigned_language->getDisplayName()) ?></div>
+ <div class="mvv-item-list-buttons">
+ <a href="#" class="mvv-item-remove"><?= Icon::create('trash', 'clickable', array('title' => _('Sprache entfernen')))->asImg(); ?></a>
+ </div>
+ <input type="hidden" name="language_items[]" value="<?= htmlReady($assigned_language->lang) ?>">
+ </li>
+ <? endforeach; ?>
+ </ul>
+ <?= $this->render_partial('shared/language_chooser', ['chooser_id' => 'language', 'chooser_languages' => $GLOBALS['MVV_STUDIENGANG']['SPRACHE']['values'], 'addition' => _('Die Reihenfolge der Sprachen kann durch Anklicken und Ziehen geändert werden.')]); ?>
+ <? else : ?>
+ <ul id="languages_target" class="mvv-assigned-items mvv-languages">
+ <? if (count($studiengang->languages)) : ?>
+ <? foreach ($studiengang->languages as $assigned_language) : ?>
+ <li id="institut_<?= $assigned_language->lang ?>">
+ <div class="mvv-item-list-text"><?= htmlReady($assigned_language->getDisplayName()) ?></div>
+ <input type="hidden" name="language_items[]" value="<?= htmlReady($assigned_language->lang) ?>">
+ </li>
+ <? endforeach; ?>
+ <? else : ?>
+ <li class="mvv-item-list-placeholder">
+ <?= _('Es wurden noch keine Sprachen angegeben.') ?>
+ </li>
+ <? endif; ?>
+ </ul>
+ <? endif; ?>
+ </label>
+ <label for="mvv-studycourse-types" style="margin-bottom: 0ex;"><?= _('Typ des Studiengangs') ?></label>
+ <? if ($perm->haveFieldPerm('studycourse_types', MvvPerm::PERM_CREATE)) : ?>
+ <select id="mvv-studycourse-types" name="studycourse_types[]" class="nested_select" multiple>
+ <? else : ?>
+ <? foreach ($studiengang->studycourse_types as $stc_type) : ?>
+ <input type="hidden" name="studycourse_types[]" value="<?= $stc_type->type ?>">
+ <? endforeach; ?>
+ <select id="mvv-studycourse-types" name="studycourse_types[]" class="nested_select" disabled multiple>
+ <? endif; ?>
+ <? foreach ($GLOBALS['MVV_STUDIENGANG']['STUDYCOURSE_TYPE']['values'] as $key => $entry) : ?>
+ <? if ($entry['visible']) : ?>
+ <option value="<?= $key ?>"<?= in_array($key, $studiengang->studycourse_types->pluck('type')) ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+ <label style="margin-top: 1.5ex;">
+ <input type="checkbox" name="enroll[]" value="wise"<?= strpos($studiengang->enroll, 'wise') !== false ? ' checked' : '' ?><?= $perm->disable('enroll', MvvPerm::PERM_WRITE) ?>>
+ <?= _('Bewerbung/Einschreibung im Wintersemester möglich') ?>
+ </label>
+ <label>
+ <input type="checkbox" name="enroll[]" value="sose"<?= strpos($studiengang->enroll, 'sose') !== false ? ' checked' : '' ?><?= $perm->disable('enroll', MvvPerm::PERM_WRITE) ?>>
+ <?= _('Bewerbung/Einschreibung im Sommersemester möglich') ?>
+ </label>
+
+ <div id="mvv-aufbaustg-table"></div>
+
+ <? $datafields = DataFieldEntry::getDataFieldEntries($studiengang->id, 'studycourse'); ?>
+ <? foreach ($datafields as $df) : ?>
+ <? if (mb_strpos($df->model->object_class, 'settings') !== false) : ?>
+ <? if ($perm->haveDfEntryPerm($df->model->id, MvvPerm::PERM_WRITE)) : ?>
+ <?= $df->getHTML('datafields'); ?>
+ <? else : ?>
+ <em><?= htmlReady($df->getName()) ?>:</em><br>
+ <?= $df->getDisplayValue() ?>
+ <? endif; ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Inhalte und Informationen'); ?>
+ </legend>
+ <label>
+ <?= _('Beschreibung') ?>
+ <?= MvvI18N::textarea('beschreibung', $studiengang->beschreibung, ['class' => 'add_toolbar ui-resizable wysiwyg'])->checkPermission($studiengang) ?>
+ </label>
+ <? foreach ($datafields as $df) : ?>
+ <? if (mb_strpos($df->model->object_class, 'info') !== false) : ?>
+ <? if ($perm->haveDfEntryPerm($df->model->id, MvvPerm::PERM_WRITE)) : ?>
+ <?= $df->getHTML('datafields'); ?>
+ <? else : ?>
+ <em><?= htmlReady($df->getName()) ?>:</em><br>
+ <?= $df->getDisplayValue() ?>
+ <? endif; ?>
+ <? endif; ?>
+ <? endforeach; ?>
+ <label><?= _('Schlagwörter') ?>
+ <textarea <?= $perm->disable('schlagworte') ?> cols="60" rows="5" name="schlagworte" id="schlagworte" class="ui-resizable"><?= htmlReady($studiengang->schlagworte) ?></textarea>
+ <div><?= _('Hier können zusätzlich Schlagwörter angegeben werden, die in der Suche berücksichtigt werden.') ?></div>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Dokumente'); ?>
+ </legend>
+ <?= $this->render_partial('materialien/files/range', ['perm_dokumente' => $perm->haveFieldPerm('document_assignments', MvvPerm::PERM_CREATE), 'range_type' => 'Studiengang', 'range_id' => $studiengang->id]) ?>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Ansprechpartner'); ?>
+ </legend>
+ <?= $this->render_partial('shared/contacts/range', ['perm_contacts' => $perm->haveFieldPerm('contact_assignments', MvvPerm::PERM_CREATE), 'range_type' => 'Studiengang', 'range_id' => $studiengang->id]) ?>
+ </fieldset>
+
+ <?= $plugin_hook_content ?>
+
+ <footer>
+ <? if ($studiengang->isNew()) : ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Studiengang anlegen')]) ?>
+ <?= Button::createAccept(_('Anlegen und abbrechen'), 'store_cancel', ['title' => _('Studiengang anlegen und abbrechen')]) ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store',
+ [
+ 'title' => _('Änderungen übernehmen'),
+ 'formaction' => $controller->url_for('/studiengang', $studiengang->id),
+ 'formmethod' => 'post'
+ ]) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
+
+<script>
+ $(document).ready(function() {
+ $('#mvv-studycourse-types').select2({
+ placeholder: '<?= _('Typ wählen') ?>'
+ });
+ STUDIP.MVV.Aufbaustg.loadTable('<?= $studiengang->id ?>');
+ });
+</script>
diff --git a/app/views/studiengaenge/studiengaenge/studiengangteile.php b/app/views/studiengaenge/studiengaenge/studiengangteile.php
new file mode 100644
index 0000000..ed0aa05
--- /dev/null
+++ b/app/views/studiengaenge/studiengaenge/studiengangteile.php
@@ -0,0 +1,87 @@
+<td colspan="5">
+ <table id="stgteilbez_<?= $stg_stgbez_id ?>" class="default sortable">
+ <colgroup>
+ <col>
+ <col width="1%">
+ </colgroup>
+ <? foreach ($stgteile as $stgteil) : ?>
+ <tbody id="<?= $stg_stgbez_id . '_' . $stgteil->id ?>"<?= MvvPerm::haveFieldPermStudiengangteil($studiengang, MVVPerm::PERM_WRITE) ? 'class="sort_items"' : '' ?>>
+ <tr class="header-row">
+ <td width="90%"><?= htmlReady($stgteil->getDisplayName()) ?></td>
+ <td class="actions">
+ <? if (MvvPerm::haveFieldPermStudiengangteil($studiengang, MVVPerm::PERM_CREATE)) : ?>
+ <? if ($stg_bez) : ?>
+ <? $msg = sprintf(
+ _('Wollen Sie die Zuordnung des Studiengangteils "%s" als "%s" zum Studiengang "%s" wirklich löschen?'),
+ htmlReady($stgteil->getDisplayName()),
+ htmlReady($stg_bez->getDisplayName()),
+ htmlReady($studiengang->getDisplayName())
+ ) ?>
+ <form action="<?= $controller->url_for('/delete_stgteilmf/' . $studiengang->id, $stgteil->id, $stg_bez->id) ?>"
+ method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <?= Icon::create(
+ 'trash',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Zuordnung des Studiengangteils löschen')]
+ )->asInput(['data-confirm' => htmlReady($msg)]); ?>
+ </form>
+ <? else : ?>
+ <? $msg = sprintf(
+ _('Wollen Sie die Zuordnung des Studiengangteils "%s" zum Studiengang "%s" wirklich löschen?'),
+ htmlReady($stgteil->getDisplayName()),
+ htmlReady($studiengang->getDisplayName())
+ ) ?>
+ <form action="<?= $controller->url_for('/delete_stgteil/' . $studiengang->id, $stgteil->id) ?>"
+ method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <?= Icon::create(
+ 'trash',
+ Icon::ROLE_CLICKABLE ,
+ ['title' => _('Zuordnung des Studiengangteils löschen')]
+ )->asInput(['data-confirm' => htmlReady($msg)]); ?>
+ </form>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endforeach; ?>
+ <? if (MvvPerm::haveFieldPermStudiengangteil($studiengang, MVVPerm::PERM_CREATE)) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <form style="width: 100%;"
+ action="<?= $controller->url_for('/add_stgteil/' . $studiengang->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <?= _('Studiengangteil hinzufügen') ?></div>
+ <?= $search->render() ?>
+ <?= Icon::create(
+ 'search',
+ Icon::ROLE_CLICKABLE ,
+ [
+ 'title' => _('Studiengangteil suchen'),
+ 'name' => 'search_stgteil',
+ 'data-qs_name' => $search->getId(),
+ 'data-qs_id' => $qs_search_id,
+ 'data-qs_submit' => '1',
+ 'class' => 'mvv-qs-button'
+ ])->asInput(); ?>
+ <?= Icon::create(
+ 'accept',
+ Icon::ROLE_CLICKABLE ,
+ [
+ 'title' => _('Studiengangteil zuordnen')
+ ])->asInput(['class' => 'mvv-submit', 'name' => 'add_stgteil']); ?>
+ <? if ($stg_bez) : ?>
+ <input type="hidden" name="stgteil_bez_id" value="<?= $stg_bez->id ?>">
+ <? endif; ?>
+ <input type="hidden" name="level" value="stgteilbez">
+ </form>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</td>
+
diff --git a/app/views/studiengaenge/studiengangteile/approve.php b/app/views/studiengaenge/studiengangteile/approve.php
new file mode 100644
index 0000000..1b1afdf
--- /dev/null
+++ b/app/views/studiengaenge/studiengangteile/approve.php
@@ -0,0 +1,10 @@
+<form name="approve"
+ action="<?= $controller->url_for('studiengaenge/studiengangteile/approve/' . $stgteil_id . '/' . $version_id) ?>"
+ method="post" style="margin-left: auto; margin-right: auto;">
+ <? echo $this->render_partial('shared/studiengang/_stgteilversion', ['version' => $version]); ?>
+ <? echo $this->render_partial('shared/version/_versionmodule', ['version' => $version]); ?>
+ <div style="text-align: center;" data-dialog-button>
+ <?= Studip\Button::createAccept(_('Genehmigen'), 'approval') ?>
+ <?= Studip\Button::createCancel(_('Abbrechen'), ['data-dialog' => 'close']) ?>
+ </div>
+</form> \ No newline at end of file
diff --git a/app/views/studiengaenge/studiengangteile/details.php b/app/views/studiengaenge/studiengangteile/details.php
new file mode 100644
index 0000000..724021a
--- /dev/null
+++ b/app/views/studiengaenge/studiengangteile/details.php
@@ -0,0 +1,10 @@
+<td colspan="6">
+ <table class="default collapsable">
+ <colgroup>
+ <col>
+ <col style="width: 5%;">
+ <col style="width: 1%;">
+ </colgroup>
+ <?= $this->render_partial('studiengaenge/versionen/versionen'); ?>
+ </table>
+</td>
diff --git a/app/views/studiengaenge/studiengangteile/details_grouped.php b/app/views/studiengaenge/studiengangteile/details_grouped.php
new file mode 100644
index 0000000..9659624
--- /dev/null
+++ b/app/views/studiengaenge/studiengangteile/details_grouped.php
@@ -0,0 +1,47 @@
+<td colspan="3">
+ <table class="default">
+ <tbody>
+ <? foreach ($stgteile as $stgteil) : ?>
+ <tr>
+ <td>
+ <? if ($ampel_icon) : ?>
+ <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?>
+ <? endif; ?>
+ <?= htmlReady($stgteil->getDisplayName()) ?>
+ </td>
+ <td class="actions" style="white-space: nowrap; width: 1%;">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (MvvPerm::havePermWrite($stgteil)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/stgteil/' . $stgteil->id),
+ _('Studiengangteil bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE , ['title' => _('Studiengangteil bearbeiten')]))
+ ?>
+ <? endif; ?>
+ <? if (MvvPerm::havePermCreate($stgteil)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/copy/' . $stgteil->id),
+ _('Studiengangteil kopieren'),
+ Icon::create('files', Icon::ROLE_CLICKABLE , ['title' => _('Studiengangteil kopieren')]))
+ ?>
+ <? endif; ?>
+ <? if (MvvPerm::havePermCreate($stgteil)) : ?>
+ <? $actionMenu->addButton(
+ 'delete_part',
+ _('Studiengangteil löschen'),
+ Icon::create(
+ 'trash',
+ Icon::ROLE_CLICKABLE ,
+ ['title' => _('Studiengangteil löschen'),
+ 'formaction' => $controller->url_for('/delete/' . $stgteil->getId()),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich den Studiengangteil "%s" löschen?'), htmlReady($stgteil->getDisplayName()))]
+ ))
+ ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ </table>
+</td>
diff --git a/app/views/studiengaenge/studiengangteile/index.php b/app/views/studiengaenge/studiengangteile/index.php
new file mode 100644
index 0000000..bbffead
--- /dev/null
+++ b/app/views/studiengaenge/studiengangteile/index.php
@@ -0,0 +1,115 @@
+<?= $controller->jsUrl() ?>
+<form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default collapsable">
+ <caption>
+ <?= _('Liste der Studiengangteile') ?>
+ <span class="actions"><? printf(_('%s Studiengangteile'), $count) ?></span>
+ </caption>
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('/index', _('Fach'), 'fach_name,zusatz,kp') ?>
+ <?= $controller->renderSortLink('/index', _('Zweck'), 'zusatz,fach_name,kp', ['style' => 'width: 40%;']) ?>
+ <?= $controller->renderSortLink('/index', _('CP'), 'kp,fach_name,zusatz', ['style' => 'text-align: center; width: 2%;']) ?>
+ <?= $controller->renderSortLink('/index', _('Versionen'), 'count_versionen,fach_name,kp', ['style' => 'text-align: center; width: 2%;']) ?>
+ <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? if ($count) : ?>
+ <? foreach ($stgteile as $stgteil): ?>
+ <tbody class="<?php if (!$stgteil->count_versionen) echo 'empty' ?> <?= $stgteil_id === $stgteil->getId() ? 'not-collapsed' : 'collapsed' ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <? if ($stgteil->count_versionen) : ?>
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details/' . $stgteil->getId()) ?>">
+ <?= htmlReady($stgteil->fach_name) ?>
+ <? if ($stgteil->count_contacts) : ?>
+ <?= Icon::create('community', Icon::ROLE_INFO, ['title' => sprintf(ngettext('%s Kontakt zugeordnet', '%s Kontakte zugeordnet', $stgteil->count_contacts), $stgteil->count_contacts)]) ?>
+ <? endif; ?>
+ </a>
+ <? else : ?>
+ <?= htmlReady($stgteil->fach_name) ?>
+ <? if ($stgteil->count_contacts) : ?>
+ <?= Icon::create('community', Icon::ROLE_INFO, ['title' => sprintf(ngettext('%s Kontakt zugeordnet', '%s Kontakte zugeordnet', $stgteil->count_contacts), $stgteil->count_contacts)]) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide"><?= htmlReady($stgteil->zusatz) ?> </td>
+ <td class="dont-hide" style="text-align: center;"><?= htmlReady($stgteil->kp) ?> </td>
+ <td class="dont-hide" style="text-align: center;"><?= $stgteil->count_versionen ?> </td>
+ <td class="dont-hide actions" style="white-space: nowrap;">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (MvvPerm::havePermCreate('StgteilVersion')) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/version/' . $stgteil->getId()),
+ _('Neue Version anlegen'),
+ Icon::create('file+add', Icon::ROLE_CLICKABLE, ['title' => _('Neue Version anlegen')])
+ ) ?>
+ <? endif; ?>
+ <? if (MvvPerm::havePermWrite($stgteil)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/stgteil/' . $stgteil->getId()),
+ _('Studiengangteil bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE, ['title' => _('Studiengangteil bearbeiten')])
+ ) ?>
+ <? endif; ?>
+ <? if (MvvPerm::havePermCreate('StudiengangTeil')) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/copy/' . $stgteil->getId()),
+ _('Studiengangteil kopieren'),
+ Icon::create('files', Icon::ROLE_CLICKABLE, ['title' => _('Studiengangteil kopieren')])
+ ) ?>
+ <? endif; ?>
+ <? if (MvvPerm::havePermCreate($stgteil)) : ?>
+ <? $actionMenu->addButton(
+ 'delete_part',
+ _('Studiengangteil löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, [
+ 'title' => _('Studiengangteil löschen'),
+ 'formaction' => $controller->url_for('/delete/' . $stgteil->getId()),
+ 'data-confirm' => sprintf(_('Wollen Sie wirklich den Studiengangteil "%s" löschen?'), htmlReady($stgteil->getDisplayName())),
+ ])
+ ) ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? if ($stgteil_id == $stgteil->getId()) : ?>
+ <? $versionen = StgteilVersion::findByStgteil($stgteil->getId()); ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/studiengangteile/details', compact('stgteil_id', 'versionen')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach ?>
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="5" style="text-align: right;">
+ <?
+ $page_link = reset(explode('?', $controller->url_for('/index'))) . '?page_studiengangteile=%s';
+
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->perPage = MVVController::$items_per_page;
+ $pagination->num_postings = $count;
+ $pagination->page = $page;
+ $pagination->pagelink = $page_link;
+ echo $pagination->render();
+ ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ <? else : ?>
+ <tbody>
+ <tr>
+ <td style="text-align: center" colspan="5">
+ <?= _('Es wurden noch keine Studiengangteile angelegt.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif ?>
+ </table>
+</form>
diff --git a/app/views/studiengaenge/studiengangteile/stgteil.php b/app/views/studiengaenge/studiengangteile/stgteil.php
new file mode 100644
index 0000000..7579579
--- /dev/null
+++ b/app/views/studiengaenge/studiengangteile/stgteil.php
@@ -0,0 +1,105 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+<? $perm = MvvPerm::get($stgteil) ?>
+
+<form class="default" action="<?= $controller->url_for('/stgteil/' . $stgteil->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset class="collapsable">
+ <legend>
+ <?= _('Fach') ?>
+ </legend>
+ <? if (is_array($faecher)) : ?>
+ <label>
+ <?= sprintf(_('Mögliche Fächer im gewählten Fachbereich %s:'), '<strong>' . htmlReady($fachbereich->name) . '</strong>') ?>
+ <select name="fach_item">
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($faecher as $fach) : ?>
+ <option value="<?= $fach->id ?>"><?= htmlReady($fach->name) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <? else : ?>
+ <? if ($perm->haveFieldPerm('fach', MvvPerm::PERM_WRITE)) : ?>
+ <?= $search_fach->render() ?>
+ <? if (Request::submitted('search_fach')) : ?>
+ <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['name' => 'reset_fach', 'data-qs_id' => $search_fach_id])->asInput(); ?>
+ <? else : ?>
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE, ['name' => 'search_fach', 'data-qs_id' => $search_fach_id, 'data-qs_name' => $search_fach->getId(), 'class' => 'mvv-qs-button'])->asInput(); ?>
+ <? endif; ?>
+ <? endif; ?>
+ <ul id="fach_target" class="mvv-assigned-items mvv-assign-single mvv-faecher">
+ <li class="mvv-item-list-placeholder"<?= ($stgteil->fach ? ' style="display: none;"' : '') ?>>
+ <?= _('Bitte ein Fach suchen und zuordnen.') ?>
+ </li>
+ <? if ($stgteil->fach) : ?>
+ <li id="fach_<?= $stgteil->fach->id ?>">
+ <div class="mvv-item-list-text">
+ <?= htmlReady($stgteil->fach->name) ?>
+ </div>
+ <? if ($perm->haveFieldPerm('fach', MvvPerm::PERM_WRITE)) : ?>
+ <div class="mvv-item-list-buttons">
+ <a href="#" class="mvv-item-remove">
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE, ['title' => _('Fach entfernen')])->asImg(); ?>
+ </a>
+ </div>
+ <? endif; ?>
+ <input type="hidden" name="fach_item" value="<?= $stgteil->fach->id ?>">
+ </li>
+ <? endif; ?>
+ </ul>
+ <? endif; ?>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Ausprägung') ?>
+ </legend>
+ <label><?= _('Kredit-Punkte') ?>
+ <input <?= $perm->disable('kp') ?>
+ type="text" name="kp" id="stgteil_kp" size="10" maxlength="50"
+ value="<?= htmlReady($stgteil->kp) ?>">
+ </label>
+ <label>
+ <?= _('Semesterzahl') ?>
+ <? if ($perm->haveFieldPerm('semester')) : ?>
+ <select name="semester" id="stgteil_semester">
+ <option value="">--</option>
+ <? for ($sem = 1; $sem < 21; $sem++) : ?>
+ <option value="<?= $sem ?>"<?= ((int) $stgteil->semester === $sem ? ' selected' : '') ?>><?= $sem ?></option>
+ <? endfor; ?>
+ </select>
+ <? else : ?>
+ <?= htmlReady($stgteil->semester) ?>
+ <input type="hidden" name="semester" value="<?= $stgteil->semester ?>">
+ <? endif; ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Titelzusatz') ?>
+ </legend>
+ <?= MvvI18N::input('zusatz', $stgteil->zusatz, ['id' => 'stgteil_zusatz', 'maxlength' => '200'])->checkPermission($stgteil) ?>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Ansprechpartner'); ?>
+ </legend>
+ <?= $this->render_partial('shared/contacts/range', ['perm_contacts' => $perm->haveFieldPerm('contact_assignments', MvvPerm::PERM_CREATE), 'range_type' => 'StudiengangTeil', 'range_id' => $stgteil->id]) ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if ($stgteil->isNew()) : ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Abschluss anlegen')]) ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/studiengaenge/versionen/abschnitt.php b/app/views/studiengaenge/versionen/abschnitt.php
new file mode 100644
index 0000000..dccc3e0
--- /dev/null
+++ b/app/views/studiengaenge/versionen/abschnitt.php
@@ -0,0 +1,32 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? $perm = MvvPerm::get($abschnitt) ?>
+
+<form class="default" action="<?= $controller->url_for('/abschnitt/' . $abschnitt->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label><?= _('Name') ?>
+ <?= MvvI18N::input('name', $abschnitt->name, ['maxlength' => '254'])->checkPermission($abschnitt) ?>
+ </label>
+ <label>
+ <?= _('Kommentar') ?>
+ <?= MvvI18N::textarea('kommentar', $abschnitt->kommentar, ['class' => 'add_toolbar resizable ui-resizable'])->checkPermission($abschnitt) ?>
+ <label><?= _('Kreditpunkte') ?>
+ <input <?= $perm->disable('kp') ?>
+ type="text" name="kp" id="kp"
+ value="<?= htmlReady($abschnitt->kp) ?>" size="5" maxlength="10">
+ </label>
+ <label><?= _('Zwischenüberschrift') ?>
+ <?= MvvI18N::input('ueberschrift', $abschnitt->ueberschrift, ['maxlength' => '254'])->checkPermission($abschnitt) ?>
+ </label>
+ </fieldset>
+ <input type="hidden" name="version_id" value="<?= $this->version->id ?>">
+ <footer data-dialog-button>
+ <? if ($abschnitt->isNew()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Abschnitt anlegen')]) ?>
+ <? else : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/studiengaenge/versionen/abschnitte.php b/app/views/studiengaenge/versionen/abschnitte.php
new file mode 100644
index 0000000..7a71067
--- /dev/null
+++ b/app/views/studiengaenge/versionen/abschnitte.php
@@ -0,0 +1,89 @@
+<td colspan="3">
+ <table id="abschnitte_<?= $version->id ?>" class="default collapsable sortable">
+ <colgroup>
+ <col>
+ <col style="width: 1%;">
+ </colgroup>
+ <? foreach ($abschnitte as $abschnitt) : ?>
+ <tbody id="<?= $abschnitt->id ?>"
+ class="<?= ($abschnitt_id === $abschnitt->id ? 'not-collapsed' : 'collapsed') ?><?= MvvPerm::haveFieldPermPosition($abschnitt, MvvPerm::PERM_WRITE) ? ' sort_items' : '' ?>">
+ <tr class="header-row" id="abschnittt_<?= $abschnitt->id ?>">
+ <td class="toggle-indicator">
+ <a class="mvv-load-in-new-row"
+ href="<?= $controller->url_for('/details_abschnitt/' . $abschnitt->id) ?>">
+ <?= htmlReady($abschnitt->name) ?>
+ </a>
+ </td>
+ <td class="dont-hide actions" style="white-space: nowrap;">
+ <form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if (MvvPerm::havePermWrite($version)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/abschnitt/' . $abschnitt->id),
+ _('Studiengangteil-Abschnitt bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE, tooltip2(_('Studiengangteil-Abschnitt bearbeiten'))),
+ ['data-dialog' => true])
+ ?>
+ <? endif; ?>
+ <? if (MvvPerm::haveFieldPermAbschnitte($version, MvvPerm::PERM_CREATE)) : ?>
+ <? if (!$abschnitt->count_module) : ?>
+ <? $actionMenu->addButton(
+ 'delete',
+ _('Studiengangteil-Abschnitt löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE, tooltip2(_('Studiengangteil-Abschnitt löschen'))),
+ [
+ 'formaction' => $controller->url_for('/delete_abschnitt/' . $abschnitt->id),
+ 'data-confirm' => sprintf(_('Wollen Sie den Studiengangteil-Abschnitt "%s" wirklich löschen?'), htmlReady($abschnitt->getDisplayName()))
+ ]
+ ) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </form>
+ </td>
+ </tr>
+ <? if ($abschnitt_id === $abschnitt->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/versionen/details_abschnitt', compact('abschnitt')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach;
+ TextHelper::reset_cycle(); ?>
+ <? if (count($version->abschnitte) > 0 && MvvPerm::haveFieldPermModul_zuordnungen('StgteilAbschnitt', MvvPerm::PERM_CREATE)
+ ) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="3">
+ <form class="mvv-qsform" action="<?= $controller->link_for('/add_modul/' . $version->id) ?>"
+ method="post">
+ <?= _('Modul hinzufügen') ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $search_modul_version->render(); ?>
+ <?= Icon::create('search')->asInput([
+ 'title' => _('Modul suchen'),
+ 'name' => 'search_stgteil',
+ 'data-qs_name' => $search_modul_version->getId(),
+ 'data-qs_id' => $qs_search_modul_version_id,
+ 'data-qs_submit' => 'no',
+ 'class' => 'mvv-qs-button'
+ ]) ?>
+ <label>
+ <?= _('zu Abschnitt') ?>
+ <select name="abschnitt_id">
+ <? foreach ($abschnitte as $abschnitt) : ?>
+ <option value="<?= $abschnitt->id; ?>"><?= htmlReady($abschnitt->getDisplayName()) ?></option>
+ <? endforeach; ?>
+ </select>
+ </label>
+ <input name="add_modul" class="text-top mvv-submit" type="image"
+ title="<?= _('Studiengangteil-Abschnitt hinzufügen') ?>"
+ src="<?= Icon::create('accept')->asImagePath(); ?>">
+ </form>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+</td>
diff --git a/app/views/studiengaenge/versionen/approve.php b/app/views/studiengaenge/versionen/approve.php
new file mode 100644
index 0000000..57b61ec
--- /dev/null
+++ b/app/views/studiengaenge/versionen/approve.php
@@ -0,0 +1,10 @@
+<form name="approve" action="<?= $controller->url_for('/approve/' . $version_id) ?>" method="post"
+ style="margin-left: auto; margin-right: auto;">
+ <? echo $this->render_partial('shared/studiengang/_stgteilversion', ['version' => $version]); ?>
+ <? echo $this->render_partial('shared/version/_versionmodule', ['version' => $version]); ?>
+ <div style="text-align: center;" data-dialog-button>
+ <?= CSRFProtection::tokenTag(); ?>
+ <?= Studip\ Button::createAccept(_('Genehmigen'), 'approval', []) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen')) ?>
+ </div>
+</form> \ No newline at end of file
diff --git a/app/views/studiengaenge/versionen/details_abschnitt.php b/app/views/studiengaenge/versionen/details_abschnitt.php
new file mode 100644
index 0000000..539a74e
--- /dev/null
+++ b/app/views/studiengaenge/versionen/details_abschnitt.php
@@ -0,0 +1,75 @@
+<td colspan="2">
+ <form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <table id="module_<?= $abschnitt->id ?>" class="default collapsable sortable">
+ <colgroup>
+ <col>
+ <col style="width: 1%">
+ </colgroup>
+ <? foreach ($assignments as $assignment) : ?>
+ <tbody class="<?= count($assignment->modul->modulteile) ? '' : 'empty' ?> <?= ($modul_id == $assignment->modul->id ? 'not-collapsed' : 'collapsed') ?><?= MvvPerm::haveFieldPermPosition($assignment, MvvPerm::PERM_WRITE) ? ' sort_items' : '' ?>" id="<?= $assignment->id ?>">
+ <tr id="modul_<?= $assignment->modul->id ?>" class="header-row">
+ <td class="toggle-indicator">
+ <? if (count($assignment->modul->modulteile)) : ?>
+ <a class="mvv-load-in-new-row" href="<?= $controller->url_for('/modulteile', $assignment->id) ?>"><?= htmlReady($assignment->getDisplayName()) ?></a>
+ <? else : ?>
+ <?= htmlReady($assignment->getDisplayName()) ?>
+ <? endif; ?>
+ <? if (trim($assignment->modulcode) || trim($assignment->bezeichnung)) : ?>
+ <span style="color: #636a71; font-size: smaller;">
+ <? printf(_('Orig.: %s - %s'),
+ htmlReady(trim($assignment->modul->code) ?: trim($assignment->modulcode)),
+ htmlReady(trim($assignment->modul->getDeskriptor()->bezeichnung) ?: trim($assignment->bezeichnung))) ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide actions" style="white-space: nowrap;">
+ <? if (MvvPerm::haveFieldPermModul_zuordnungen($abschnitt, MvvPerm::PERM_WRITE)) : ?>
+ <a data-dialog="" href="<?= $controller->link_for('/modul_zuordnung', $assignment->id) ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE , tooltip2(_('Modulzuordnung bearbeiten')))->asImg(); ?>
+ </a>
+ <? endif; ?>
+ <? if (MvvPerm::havePermCreate($assignment)) : ?>
+ <?= Icon::create('trash', Icon::ROLE_CLICKABLE , tooltip2(_('Modulzuordnung löschen')))
+ ->asInput([
+ 'name' => 'delete',
+ 'formaction' => $controller->url_for('/delete_modul', $assignment->abschnitt_id, $assignment->modul_id),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie die Zuordnung des Moduls "%s" zum Studiengangteil-Abschnitt "%s" wirklich löschen?'),
+ htmlReady($assignment->modul->getDisplayName()),
+ htmlReady($abschnitt->getDisplayName())
+ )
+ ]); ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? if ($modul_id == $assignment->modul->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/versionen/modulteile', ['modul' => $assignment->modul, 'abschnitt_id' => $assignment->abschnitt_id, 'assignment' => $assignment]) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+ <? endforeach; TextHelper::reset_cycle(); ?>
+ <? if (MvvPerm::haveFieldPermModul_zuordnungen($abschnitt, MvvPerm::PERM_CREATE)) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="2">
+ <?= _('Modul hinzufügen') ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= $search_modul_abschnitt->render(); ?>
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE, ['title' => _('Modul suchen'), 'name' => 'search_stgteil', 'data-qs_name' => $search_modul_abschnitt->getId(), 'data-qs_id' => $qs_search_modul_abschnitt_id, 'data-qs_submit' => 'no', 'class' => 'mvv-qs-button'])->asInput(); ?>
+ <input type="hidden" name="abschnitt_id" value="<?= $abschnitt->id ?>">
+ <?= Icon::create('accept', Icon::ROLE_CLICKABLE , tooltip2(_('Modul hinzufügen')))
+ ->asInput(
+ [
+ 'formaction' => $controller->url_for('/add_modul', $version->id),
+ 'name' => 'add_modul',
+ 'class' => 'text-top mvv-submit'
+ ]
+ ); ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+ </form>
+</td>
diff --git a/app/views/studiengaenge/versionen/diff.php b/app/views/studiengaenge/versionen/diff.php
new file mode 100644
index 0000000..8daa267
--- /dev/null
+++ b/app/views/studiengaenge/versionen/diff.php
@@ -0,0 +1,70 @@
+<style>
+ del.diffmod {
+ color: red;
+ }
+ del.diffdel {
+ color: red;
+ }
+ ins.diffmod {
+ color: green;
+ }
+ ins.diffins {
+ color: green;
+ }
+ .mvv-diff {
+ margin: 0;
+ padding: 0;
+ width: 95%;
+ }
+ .mvv-modul-details
+ {
+ margin: 10px;
+ border-collapse: collapse;
+ font-size: 5pt;
+ width: 100%;
+ }
+ .mvv-modul-details td
+ {
+ padding: 3px;
+ vertical-align: top;
+ border: 1px solid black;
+ }
+ .mvv-modul-details th
+ {
+ border: 1px solid black;
+ }
+ .mvv-diff-deleted .mvv-modul-details {
+ color: red;
+ }
+ .mvv-diff-deleted .mvv-modul-details td,
+ .mvv-diff-deleted .mvv-modul-details th {
+ border: solid 1px red;
+ }
+ .mvv-diff-added .mvv-modul-details {
+ color: green;
+ }
+ .mvv-diff-added .mvv-modul-details td,
+ .mvv-diff-added .mvv-modul-details th {
+ border: solid 1px green;
+ }
+</style>
+<h2>
+ <? printf(_('Vergleich von %s mit %s'), '<span style="font-style: italic">'
+ . htmlReady($old_version->getDisplayName()) . '</span>',
+ '<span style="font-style: italic;">' . htmlReady($new_version->getDisplayName()) . '</span>'); ?>
+</h2>
+<div class="mvv-diff">
+<?
+$old = $this->render_partial('shared/version/_version', ['version' => $old_version]);
+$new = $this->render_partial('shared/version/_version', ['version' => $new_version]);
+$diff = new Caxy\HtmlDiff\HtmlDiff($old, $new);
+$diff->build();
+echo $diff->getDifference();
+
+$old = $this->render_partial('shared/version/_versionmodule', ['version' => $old_version]);
+$new = $this->render_partial('shared/version/_versionmodule', ['version' => $new_version]);
+$diff = new Caxy\HtmlDiff\HtmlDiff($old, $new);
+$diff->build();
+echo $diff->getDifference();
+?>
+</div>
diff --git a/app/views/studiengaenge/versionen/diff_select.php b/app/views/studiengaenge/versionen/diff_select.php
new file mode 100644
index 0000000..45a59f1
--- /dev/null
+++ b/app/views/studiengaenge/versionen/diff_select.php
@@ -0,0 +1,18 @@
+<h1><?= htmlReady($version->getDisplayName()) ?></h1>
+<div>
+ <h4><?= _('Vergleich mit folgender Version:') ?></h4>
+ <form data-dialog="size=auto" class="mvv-new-tab" action="<?= $controller->link_for('/diff') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <div>
+ <?= $search_version->render(); ?>
+ <? if (Request::submitted('search_vesrsion')) : ?>
+ <?= Icon::create('refresh', Icon::ROLE_CLICKABLE , ['name' => 'reset_version', 'data-qs_id' => $qs_id_version])->asInput(); ?>
+ <? else : ?>
+ <?= Icon::create('search', Icon::ROLE_CLICKABLE , ['name' => 'search_version', 'data-qs_id' => $qs_id_version, 'data-qs_name' => $search_version->getId(), 'class' => 'mvv-qs-button', 'data-qs_submit' => ''])->asInput(); ?>
+ <? endif; ?>
+ <input type="hidden" name="new_id" value="<?= $version->id ?>">
+ <input name="version_diff" class="mvv-submit" type="image" title="<?= _('Version suchen') ?>"
+ src="<?= Icon::create('accept')->asImagePath(); ?>">
+ </div>
+ </form>
+</div>
diff --git a/app/views/studiengaenge/versionen/export.php b/app/views/studiengaenge/versionen/export.php
new file mode 100644
index 0000000..2b0ac5b
--- /dev/null
+++ b/app/views/studiengaenge/versionen/export.php
@@ -0,0 +1,56 @@
+<html lang="de" xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'>
+ <head>
+ <meta charset="UTF-8">
+ <title><?= htmlReady($stgversion->getDisplayName()) ?></title>
+
+ <!--[if gte mso 9]>
+ <xml>
+ <w:WordDocument>
+ <w:View>Print</w:View>
+ <w:Zoom>90</w:Zoom>
+ <w:DoNotOptimizeForBrowser/>
+ </w:WordDocument>
+ </xml>
+ <![endif]-->
+
+ <style>
+ body {
+ font-size: 10pt;
+ }
+ body, h1, h2, h3, h4, h5 {
+ font-family: Arial, Sans Serif;
+ }
+ div.Section1 {
+ page: Section1;
+ font: italic 10pt arial, sans-serif;
+ }
+ table.mvv-modul-details {
+ border: 1px solid black;
+ border-collapse: collapse;
+ font: 8pt arial, sans-serif;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ width: 100%;
+ }
+ table.mvv-modul-details td, table.mvv-modul-details th {
+ border: 1px solid black;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ }
+ table.mvv-modul-details tbody th {
+ text-align: left;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+ }
+ </style>
+ <?= Assets::stylesheet('print') ?>
+ </head>
+ <body>
+ <div>
+ <?
+ echo $this->render_partial('shared/version/_version', ['version' => $stgversion]);
+ echo $this->render_partial('shared/version/_versionmodule', ['version' => $stgversion]);
+ ?>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/app/views/studiengaenge/versionen/index.php b/app/views/studiengaenge/versionen/index.php
new file mode 100644
index 0000000..e069024
--- /dev/null
+++ b/app/views/studiengaenge/versionen/index.php
@@ -0,0 +1,43 @@
+ <? $count = isset($versionen) ? count($versionen) : 0; ?>
+<div class="mvv-version-content">
+ <table class="default collapsable">
+ <thead>
+ <tr class="sortable">
+ <?= $controller->renderSortLink('studiengaenge/versionen/', _('Studiengangteil-Version'), 'start_sem') ?>
+ <th colspan="2" style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <? if ($count) : ?>
+ <?= $this->render_partial('studiengaenge/versionen/versionen') ?>
+ <? endif; ?>
+ <? if ($count > MVVController::$items_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="3" style="text-align: right;">
+ <?
+ $pagination = $GLOBALS['template_factory']->open('shared/pagechooser');
+ $pagination->clear_attributes();
+ $pagination->set_attribute('perPage', MVVController::$items_per_page);
+ $pagination->set_attribute('num_postings', $count);
+ $pagination->set_attribute('page', $page);
+ $pagination->set_attribute('pagelink', '?page=%s');
+ echo $pagination->render('shared/pagechooser');
+ ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+ <? if ($stgteil && !$count) : ?>
+ <div>
+ <?= sprintf(_('Für den Studiengangteil <strong>%s</strong> wurden noch keine Versionen angelegt. '), htmlReady($stgteil->getDisplayName())) ?>
+ </div>
+ <a href="<?= $controller->url_for('studiengaenge/versionen/version') ?>">
+ <?= Studip\LinkButton::create(
+ _('Eine neue Version anlegen.'),
+ $controller->url_for('/version/' . $stgteil->id),
+ ['title' => _('Eine neue Version anlegen')]
+ ) ?>
+ </a>
+ <? endif; ?>
+</div>
diff --git a/app/views/studiengaenge/versionen/modul_zuordnung.php b/app/views/studiengaenge/versionen/modul_zuordnung.php
new file mode 100644
index 0000000..ce68a7d
--- /dev/null
+++ b/app/views/studiengaenge/versionen/modul_zuordnung.php
@@ -0,0 +1,41 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? $perm = new MvvPerm($zuordnung) ?>
+<form class="default" action="<?= $controller->url_for('/modul_zuordnung/' . $zuordnung->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+ <label><?= _('Bezeichnung der Modulzuordnung') ?>
+ <?= MvvI18N::input(
+ 'bezeichnung',
+ $zuordnung->bezeichnung,
+ ['maxlength' => '250']
+ )->checkPermission($zuordnung) ?>
+ </label>
+ </fieldset>
+ <fieldset>
+ <legend><?= _('Weitere Angaben') ?></legend>
+ <label for="zuordnung_flexnow_modul"><?= _('ID der Zuordnung aus Fremdsystem') ?>
+ <input <?= $perm->disable('flexnow_modul') ?>
+ type="text" name="flexnow_modul" id="zuordnung_flexnow_modul"
+ maxlength="250"
+ value="<?= htmlReady($zuordnung->flexnow_modul) ?>">
+ </label>
+ <label for="zuordnung_modulcode"><?= _('Spezifischer Modulcode') ?>
+ <input <?= $perm->disable('modulcode') ?>
+ type="text" name="modulcode" id="zuordnung_modulcode"
+ maxlength="250" value="<?= htmlReady($zuordnung->modulcode) ?>">
+ </label>
+ </fieldset>
+ <footer data-dialog-button>
+ <?= Button::createAccept(
+ _('Übernehmen'),
+ 'store',
+ ['title' => _('Änderungen übernehmen')]
+ ) ?>
+ <?= LinkButton::createCancel(
+ _('Abbrechen'),
+ $controller->url_for('/'),
+ ['title' => _('zurück zur Übersicht')]
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/studiengaenge/versionen/modulteil_semester.php b/app/views/studiengaenge/versionen/modulteil_semester.php
new file mode 100644
index 0000000..3252876
--- /dev/null
+++ b/app/views/studiengaenge/versionen/modulteil_semester.php
@@ -0,0 +1,61 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<? $perm_abschnitt = MvvPerm::getFieldPermModulteil_abschnitte($abschnitt_modul->abschnitt); ?>
+<h3>
+ <?= _('Zuordnung der Modulteile zu Fachsemestern') ?>
+</h3>
+<form class="default" data-dialog="" action="<?= $controller->url_for('/modulteil_semester', $abschnitt_modul->id, $modulteil->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <fieldset>
+ <legend><?= _('Belegung in folgenden Fachsemestern') ?></legend>
+ <? for ($i = 1; $i <= $GLOBALS['MVV_MODULTEIL_FACHSEMESTER']; $i++) : ?>
+ <? $fachsemester = $abschnitt_modul->getFachsemester($modulteil->id, $i) ?>
+ <? $perm = $fachsemester ? MvvPerm::get($fachsemester) : null ?>
+ <div class="mvv-fachsemester" style="flex:1;">
+ <label>
+ <? if ($fachsemester) : ?>
+ <? if ($perm->haveFieldPerm('fachsemester')): ?>
+ <input type="checkbox" name="fachsemester[<?= $i ?>]" value="1"<?= ($fachsemester ? ' checked' : '') ?> style="vertical-align: middle;">
+ <? else : ?>
+ <input type="hidden" name="fachsemester[<?= $i ?>]" value="1">
+ <? endif; ?>
+ <? printf(_('%s. Fachsemester'), $i) ?>
+ <? else : ?>
+ <? if ($perm_abschnitt > MvvPerm::PERM_WRITE): ?>
+ <input type="checkbox" name="fachsemester[<?= $i ?>]" value="1"<?= ($fachsemester ? ' checked' : '') ?> style="vertical-align: middle;">
+ <? printf(_('%s. Fachsemester'), $i) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </label>
+ <label style="<?= (($fachsemester || !Request::isXhr()) ? 'display: inline;' : 'display: none;') ?>">
+ <?= _('Status:') ?>
+ <? if ($fachsemester && !$perm->haveFieldPerm('differenzierung')): ?>
+ <?= $GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'][$fachsemester->differenzierung]['name'] ?>
+ <input type="hidden" name="status[<?= $i ?>]" value="<?= $fachsemester->differenzierung ?>">
+ <? else: ?>
+ <select name="status[<?= $i ?>]">
+ <option value="">-- <?= _('Bitte wählen') ?> --</option>
+ <? foreach ($GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'] as $status_key => $status) : ?>
+ <? if ($status['visible']) : ?>
+ <option value="<?= $status_key ?>"<?= ($fachsemester && $fachsemester->differenzierung == $status_key ? ' selected' : '') ?>><?= $status['name'] ?></option>
+ <? endif; ?>
+ <? endforeach; ?>
+ </select>
+
+
+ <? endif; ?>
+ </label>
+ </div>
+ <? endfor; ?>
+ </fieldset>
+ <div data-dialog-button >
+ <? if ($perm_abschnitt >= MvvPerm::PERM_WRITE) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('/modulteile', $abschnitt_modul->abschnitt->id), ['title' => _('zurück zur Übersicht')]) ?>
+ </div>
+</form>
+<script>
+ jQuery('.mvv-fachsemester input').on('change', function() {
+ jQuery(this).closest('label').next('label').fadeToggle();
+ });
+</script>
diff --git a/app/views/studiengaenge/versionen/modulteile.php b/app/views/studiengaenge/versionen/modulteile.php
new file mode 100644
index 0000000..7fac584
--- /dev/null
+++ b/app/views/studiengaenge/versionen/modulteile.php
@@ -0,0 +1,23 @@
+<td colspan="2">
+ <table id="modulteile_<?= $modul->id ?>" class="default">
+ <colgroup>
+ <col>
+ <col style="width: 1%;">
+ </colgroup>
+ <? foreach ($modul->modulteile as $modulteil) : ?>
+ <tbody id="<?= $modulteil->id ?>">
+ <tr id="modulteil_<?= $modulteil->id ?>">
+ <td><?= htmlReady($modulteil->getDisplayName()) ?></td>
+ <td class="actions">
+ <? $perm = MvvPerm::get($assignment->abschnitt) ?>
+ <? if ($perm->haveFieldPerm('modulteil_abschnitte')) : ?>
+ <a data-dialog="" href="<?= $controller->url_for('/modulteil_semester', $assignment->id, $modulteil->id) ?>">
+ <?= Icon::create('edit', Icon::ROLE_CLICKABLE , ['title' => _('Semesterzuordnung bearbeiten')])->asImg(); ?>
+ </a>
+ <? endif; ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endforeach; ?>
+ </table>
+</td> \ No newline at end of file
diff --git a/app/views/studiengaenge/versionen/version.php b/app/views/studiengaenge/versionen/version.php
new file mode 100644
index 0000000..674c23a
--- /dev/null
+++ b/app/views/studiengaenge/versionen/version.php
@@ -0,0 +1,146 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $controller->jsUrl() ?>
+<? $perm = MvvPerm::get($version) ?>
+
+<form class="default" action="<?= $controller->url_for('/version', $stgteil->id, $version->id) ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset class="collapsable">
+ <legend>
+ <?= _('Gültigkeit') ?>
+ </legend>
+ <label>
+ <?= _('von Semester:') ?>
+ <? if ($perm->haveFieldPerm('start_sem')) : ?>
+ <select name="start_sem" size="1">
+ <option value=""><?= _('-- Semester wählen --') ?></option>
+ <? foreach ($semester as $sem) : ?>
+ <option value="<?= $sem->semester_id ?>"<?= ($sem->semester_id == $version->start_sem ? ' selected' : '') ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <? $sem = Semester::find($version->start_sem) ?>
+ <?= htmlReady($sem->name) ?>
+ <input type="hidden" name="start_sem" value="<?= $version->start_sem ?>">
+ <? endif; ?>
+ </label>
+ <label>
+ <?= _('bis Semester:') ?>
+ <? if ($perm->haveFieldPerm('end_sem')) : ?>
+ <select name="end_sem" size="1">
+ <option value=""><?= _('unbegrenzt gültig') ?></option>
+ <? foreach ($semester as $sem) : ?>
+ <option value="<?= $sem->semester_id ?>"<?= ($sem->semester_id == $version->end_sem ? ' selected' : '') ?>>
+ <?= htmlReady($sem->name) ?>
+ </option>
+ <? endforeach; ?>
+ </select>
+ <? else : ?>
+ <? if ($version->end_sem != "") : ?>
+ <? $sem = Semester::find($version->end_sem) ?>
+ <?= htmlReady($sem->name) ?>
+ <? else : ?>
+ <?= _('unbegrenzt gültig') ?>
+ <? endif; ?>
+ <input type="hidden" name="end_sem" value="<?= $version->end_sem ?>">
+ <? endif; ?>
+ </label>
+ <div><?= _('Das Endsemester wird nur angegeben, wenn die Version abgeschlossen ist.') ?></div>
+ <label>
+ <?= _('Beschlussdatum:') ?>
+ <? if ($perm->haveFieldPerm('beschlussdatum')) : ?>
+ <input type="text" name="beschlussdatum" value="<?= ($version->beschlussdatum ? strftime('%d.%m.%Y', $version->beschlussdatum) : '') ?>" placeholder="<?= _('TT.MM.JJJJ') ?>" class="with-datepicker">
+ <? else : ?>
+ <?= ($version->beschlussdatum ? strftime('%d.%m.%Y', $version->beschlussdatum) : '') ?>
+ <input type="hidden" name="beschlussdatum" value="<?= ($version->beschlussdatum ? strftime('%d.%m.%Y', $version->beschlussdatum) : '') ?>">
+ <? endif; ?>
+ </label>
+ <label for="fassung_nr"><?= _('Fassung:') ?></label>
+ <section class="hgroup">
+ <select<?= $perm->haveFieldPerm('fassung_nr') ? '' : ' disabled' ?> name="fassung_nr" id="fassung_nr" class="size-s">
+ <option value="">--</option>
+ <? foreach (range(1, 30) as $nr) : ?>
+ <option<?= $nr === (int)$version->fassung_nr ? ' selected' : '' ?> value="<?= $nr ?>"><?= $nr ?>.</option>
+ <? endforeach; ?>
+ </select>
+ <? if (!$perm->haveFieldPerm('fassung_nr')) : ?>
+ <input type="hidden" name="fassung_nr" value="<?= htmlReady($version->fassung_nr) ?>">
+ <? endif; ?>
+ <select<?= $perm->haveFieldPerm('fassung_typ') ? '' : ' disabled' ?> name="fassung_typ">
+ <option value="0">--</option>
+ <? foreach ($GLOBALS['MVV_STGTEILVERSION']['FASSUNG_TYP'] as $key => $entry) : ?>
+ <option value="<?= $key ?>"<?= $key === $version->fassung_typ ? ' selected' : '' ?>><?= htmlReady($entry['name']) ?></option>
+ <? endforeach; ?>
+ </select>
+ <? if (!$perm->haveFieldPerm('fassung_typ')) : ?>
+ <input type="hidden" name="fassung_typ" value="<?= $version->fassung_typ ?>">
+ <? endif; ?>
+ </section>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Code') ?>
+ </legend>
+ <input <?= $perm->disable('code') ?> type="text" name="code" id="code" value="<?= htmlReady($version->code) ?>" maxlength="100">
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Beschreibung') ?>
+ </legend>
+ <?= MvvI18N::textarea('beschreibung', $version->beschreibung, ['class' => 'add_toolbar ui-resizable wysiwyg', 'id' => 'beschreibung'])->checkPermission($version) ?>
+ </fieldset>
+
+ <? $url = $controller->url_for('/dokumente_properties'); ?>
+ <? $perm_dokumente = $perm->haveFieldPerm('document_assignments', MvvPerm::PERM_CREATE) ?>
+ <?//= $this->render_partial('shared/form_dokumente', compact('search_dokumente', 'dokumente', 'url', 'perm_dokumente')) ?>
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Dokumente'); ?>
+ </legend>
+ <?= $this->render_partial('materialien/files/range', array('perm_dokumente' => $perm->haveFieldPerm('document_assignments', MvvPerm::PERM_CREATE))) ?>
+ </fieldset>
+
+ <fieldset class="collapsable collapsed">
+ <legend>
+ <?= _('Status der Bearbeitung') ?>
+ </legend>
+ <input type="hidden" name="status" value="<?= $version->stat ?>">
+ <? foreach ($GLOBALS['MVV_STGTEILVERSION']['STATUS']['values'] as $key => $status_bearbeitung) : ?>
+ <? // The MVVAdmin have always PERM_CREATE for all fields ?>
+ <label>
+ <? if ($perm->haveFieldPerm('stat', MvvPerm::PERM_CREATE) && $version->stat != 'planung') : ?>
+ <input type="radio" name="status" value="<?= $key ?>"<?= ($version->stat == $key ? ' checked' : '') ?>>
+ <?= $status_bearbeitung['name'] ?>
+ <? elseif ($perm->haveFieldPerm('stat', MvvPerm::PERM_WRITE) && $version->stat != 'planung') : ?>
+ <input <?= ($version->stat == 'ausgelaufen' && $key == 'genehmigt') ? 'disabled' :'' ?> type="radio" name="status" value="<?= $key ?>"<?= ($version->stat == $key ? ' checked' : '') ?>>
+ <?= $status_bearbeitung['name'] ?>
+ <? elseif($version->stat == $key) : ?>
+ <?= $status_bearbeitung['name'] ?>
+ <? endif; ?>
+ </label>
+ <? endforeach; ?>
+ <label for="kommentar_status" style="vertical-align: top;"><?= _('Kommentar:') ?></label>
+ <? if($perm->haveFieldPerm('kommentar_status', MvvPerm::PERM_WRITE)) : ?>
+ <textarea cols="60" rows="5" name="kommentar_status" id="kommentar_status" class="add_toolbar ui-resizable wysiwyg"><?= htmlReady($version->kommentar_status) ?></textarea>
+ <? else : ?>
+ <textarea disabled cols="60" rows="5" name="kommentar_status" id="kommentar_status" class="ui-resizable"><?= htmlReady($version->kommentar_status) ?></textarea>
+ <? endif; ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if ($version->isNew()) : ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <?= Button::createAccept(_('Anlegen'), 'store', ['title' => _('Version anlegen')]) ?>
+ <? endif; ?>
+ <? else : ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?>
+ <? endif; ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?>
+ </footer>
+</form>
diff --git a/app/views/studiengaenge/versionen/versionen.php b/app/views/studiengaenge/versionen/versionen.php
new file mode 100644
index 0000000..f73790c
--- /dev/null
+++ b/app/views/studiengaenge/versionen/versionen.php
@@ -0,0 +1,91 @@
+<? foreach ($versionen as $version) : ?>
+ <? $perm = MvvPerm::get($version); ?>
+ <tbody class="<?= ($version->count_abschnitte ? '' : 'empty') ?> <?= ($version_id === $version->id ? 'not-collapsed' : 'collapsed') ?>">
+ <tr class="header-row">
+ <td class="toggle-indicator">
+ <? if ($version->count_abschnitte) : ?>
+ <a class="mvv-load-in-new-row" href="<?= $controller->url_for('/abschnitte/' . $version->id) ?>">
+ <? endif; ?>
+ <? $ampel_icon = $GLOBALS['MVV_STGTEILVERSION']['STATUS']['values'][$version->stat]['icon'] ?>
+ <? $ampelstatus = $GLOBALS['MVV_STGTEILVERSION']['STATUS']['values'][$version->stat]['name'] ?>
+ <? if ($ampel_icon) : ?>
+ <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?>
+ <? endif; ?>
+ <?= htmlReady($version->getDisplayName()) ?>
+ <? if ($version->count_abschnitte) : ?>
+ </a>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide" style="text-align: center;">
+ <? if ($version->count_dokumente) : ?>
+ <?= Icon::create('staple', Icon::ROLE_INFO, ['title' => sprintf(ngettext('%s Dokument zugeordnet', '%s Dokumente zugeordnet', $version->count_dokumente), $version->count_dokumente)])->asImg(); ?>
+ <? endif; ?>
+ </td>
+ <td class="dont-hide" style="white-space: nowrap; text-align: right;">
+ <form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <? $actionMenu = ActionMenu::get() ?>
+ <? if ($version->stat === 'planung' && MvvPerm::haveFieldPermStat($version)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/approve/' . $version->id),
+ _('Version genehmigen'),
+ Icon::create('accept', Icon::ROLE_CLICKABLE, ['title' => _('Version genehmigen')]),
+ ['data-dialog' => 'title=' . htmlReady($version->getDisplayName()) . ''])
+ ?>
+ <? endif; ?>
+ <? if ($perm->haveFieldPerm('abschnitte', MvvPerm::PERM_CREATE)) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/abschnitt', ['version_id' => $version->id]),
+ _('Studiengangteil-Abschnitt anlegen'),
+ Icon::create('file+add', Icon::ROLE_CLICKABLE, ['title' => _('Studiengangteil-Abschnitt anlegen')]),
+ ['data-dialog' => true])
+ ?>
+ <? endif; ?>
+ <? if ($perm->havePermWrite()) : ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('/version/' . $version->stgteil_id . '/' . $version->id),
+ _('Version bearbeiten'),
+ Icon::create('edit', Icon::ROLE_CLICKABLE, ['title' => _('Version bearbeiten')]))
+ ?>
+ <? endif; ?>
+ <? if (MvvPerm::havePermCreate('StgteilVersion')) : ?>
+ <? $actionMenu->addButton(
+ 'copy',
+ _('Version kopieren'),
+ Icon::create(
+ 'files',
+ Icon::ROLE_CLICKABLE,
+ ['title' => _('Version kopieren'),
+ 'formaction' => $controller->url_for('/copy_version/' . $version->id),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie wirklich die Version "%s" des Studiengangteils kopieren?'),
+ htmlReady($version->getDisplayName()))
+ ]
+ ))
+ ?>
+ <? endif; ?>
+ <? if ($perm->havePermCreate()) : ?>
+ <? $actionMenu->addButton(
+ 'delete',
+ _('Version löschen'),
+ Icon::create('trash', Icon::ROLE_CLICKABLE,
+ ['title' => _('Version löschen'),
+ 'formaction' => $controller->url_for('/delete_version/' . $version->id),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie wirklich die Version "%s" des Studiengangteils löschen?'),
+ htmlReady($version->getDisplayName()))
+ ]
+ ))
+ ?>
+ <? endif; ?>
+ <?= $actionMenu->render() ?>
+ </form>
+ </td>
+ </tr>
+ <? if ($version_id === $version->id) : ?>
+ <tr class="loaded-details nohover">
+ <?= $this->render_partial('studiengaenge/versionen/abschnitte', compact('version', 'abschnitte')) ?>
+ </tr>
+ <? endif; ?>
+ </tbody>
+<? endforeach; ?> \ No newline at end of file
diff --git a/app/views/study_area/tree.php b/app/views/study_area/tree.php
new file mode 100644
index 0000000..e1f2557
--- /dev/null
+++ b/app/views/study_area/tree.php
@@ -0,0 +1,22 @@
+<li>
+<? if ($node->id !== 'root' && $node->required_children): ?>
+ <input id='<?= htmlReady($node->id) ?>' type='checkbox' <?= $open && !in_array($layer, $dont_open) ? 'checked' : ''?>>
+<? endif; ?>
+ <label for='<?= htmlReady($node->id) ?>'></label>
+
+<? if ($node->id !== 'root'): ?>
+ <a href="<?= URLHelper::getLink('show_bereich.php?level=sbb&id=' . $node->id) ?>">
+ <?= htmlReady($node->name) ?>
+ </a>
+<? else: ?>
+ <?= htmlReady($node->name) ?>
+<? endif; ?>
+
+<? if ($node->required_children): ?>
+ <ul>
+ <? foreach ($node->required_children as $child): ?>
+ <?= $this->render_partial('study_area/tree.php', ['node' => $child, 'open' => $open, 'layer' => $layer + 1]) ?>
+ <? endforeach; ?>
+ </ul>
+<? endif; ?>
+</li> \ No newline at end of file
diff --git a/app/views/studygroup/browse.php b/app/views/studygroup/browse.php
new file mode 100644
index 0000000..93ec047
--- /dev/null
+++ b/app/views/studygroup/browse.php
@@ -0,0 +1,105 @@
+<?= $this->render_partial("course/studygroup/_feedback") ?>
+
+<?php
+$headers = [
+ 'name' => _('Name'),
+ 'founded' => _('gegründet'),
+ 'member' => _('Mitglieder'),
+ 'founder' => _('GründerIn'),
+ 'ismember' => _('Mitglied'),
+];
+?>
+
+<? if ($anzahl > 0): ?>
+ <table class="default studygroup-browse">
+ <caption>
+ <?= sprintf(ngettext('%u Studiengruppe', '%u Studiengruppen', $anzahl), $anzahl)?>
+ </caption>
+ <colgroup>
+ <col style="width: 32px">
+ <col>
+ <col style="width: 10%">
+ <col style="width: 10%">
+ <col style="width: 20%">
+ <col style="width: 10%">
+ </colgroup>
+ <thead>
+ <tr class="sortable" title="<?= _('Klicken, um die Sortierung zu ändern') ?>">
+ <th class="nosort hidden-small-down"></th>
+ <? foreach ($headers as $key => $label): ?>
+ <th <? if ($sort_type === $key) echo 'class="sort' . $sort_order . '"'; ?>>
+ <a href="<?= $controller->link_for("studygroup/browse/1/{$key}_" . ($sort_order === 'asc' ? 'desc' : 'asc'), compact('q', 'closed')) ?>">
+ <?= htmlReady($label) ?>
+ </a>
+ </th>
+ <? endforeach; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($groups as $group): ?>
+ <? $is_member = $user->course_memberships->findBy('seminar_id', $group['Seminar_id'])->count(); ?>
+ <tr>
+ <td class="hidden-small-down">
+ <?= StudygroupAvatar::getAvatar($group['Seminar_id'])->getImageTag(Avatar::SMALL, ['title' => $group['Name']]) ?>
+ </td>
+ <td class="studygroup-title">
+ <? if ($is_member): ?>
+ <a href="<?= URLHelper::getlink("seminar_main.php?auswahl=" . $group['Seminar_id']) ?>">
+ <? else: ?>
+ <a href="<?= URLHelper::getlink("dispatch.php/course/studygroup/details/" . $group['Seminar_id'], ['cid' => null]) ?>">
+ <? endif; ?>
+ <?= htmlready($group['Name']) ?>
+ <?= $group['visible'] ? '' : "[" . _('versteckt') . "]" ?>
+ <? if ($group['admission_prelim'] == 1) { ?>
+ <?= Icon::create('lock-locked', 'inactive', ['title' => _('Mitgliedschaft muss beantragt werden')]) ?>
+ <? } ?>
+ </a>
+ </td>
+ <td><?= strftime('%x', $group['mkdate']) ?>
+ </td>
+ <td align="center">
+ <?= StudygroupModel::countMembers($group['Seminar_id']) ?>
+ </td>
+ <td style="white-space:nowrap;">
+ <? $founders = StudygroupModel::getFounder($group['Seminar_id']);
+ foreach ($founders as $founder) : ?>
+ <?= Avatar::getAvatar($founder['user_id'])->getImageTag(Avatar::SMALL, [
+ 'class' => 'hidden-small-down',
+ ]) ?>
+ <a href="<?= URLHelper::getlink('dispatch.php/profile', ['username' => $founder['uname']]) ?>">
+ <?= htmlready($founder['fullname']) ?>
+ </a>
+ <br>
+ <? endforeach; ?>
+ </td>
+ <td align="center">
+ <? if ($is_member) : ?>
+ <?= Icon::create('person', 'inactive', ['title' => _('Sie sind Mitglied in dieser Gruppe')])->asImg() ?>
+ <? endif; ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <? if ($anzahl > $entries_per_page) : ?>
+ <tfoot>
+ <tr>
+ <td colspan="6" class="actions">
+ <?= $GLOBALS['template_factory']->render('shared/pagechooser', [
+ 'perPage' => $entries_per_page,
+ 'num_postings' => $anzahl,
+ 'page' => $page,
+ 'pagelink' => "dispatch.php/studygroup/browse/%s/{$sort}",
+ 'pageparams' => compact('q', 'closed'),
+ ]) ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+<? endif; ?>
+
+<?= \Studip\LinkButton::createAdd(
+ _('Neue Studiengruppe anlegen'),
+ URLHelper::getURL('dispatch.php/course/wizard', ['studygroup' => 1]),
+ ['class' => 'hidden-medium-up']
+) ?>
diff --git a/app/views/terms/index.php b/app/views/terms/index.php
new file mode 100644
index 0000000..03ebf09
--- /dev/null
+++ b/app/views/terms/index.php
@@ -0,0 +1,32 @@
+<form action="<?= $controller->link_for('terms', compact('return_to', 'redirect_token')) ?>" method="post">
+ <?= CSRFProtection::tokenTag()?>
+ <? if ($denial_message): ?>
+ <section class="contentbox">
+ <header>
+ <h1><?= _('Was können Sie tun?') ?></h1>
+ </header>
+ <section>
+ <?= $denial_message ?>
+ </section>
+ </section>
+ <? else: ?>
+ <?= $GLOBALS['template_factory']->render('terms.php') ?>
+ <? endif; ?>
+ <footer style="text-align: center">
+ <? if ($denial_message): ?>
+ <?= Studip\LinkButton::createAccept(
+ _('Verstanden'),
+ URLHelper::getURL('logout.php')
+ ) ?>
+ <? else: ?>
+ <?= Studip\Button::createAccept(_('Ich erkenne die Nutzungsbedingungen an'), 'accept') ?>
+
+ <? if (!$compulsory): ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Ich stimme den Nutzungsbedingungen nicht zu'),
+ $controller->url_for('terms', ['action' => 'denied'])
+ ) ?>
+ <? endif; ?>
+ <? endif; ?>
+ </footer>
+</form>
diff --git a/app/views/tfa/index.php b/app/views/tfa/index.php
new file mode 100644
index 0000000..7905347
--- /dev/null
+++ b/app/views/tfa/index.php
@@ -0,0 +1,7 @@
+<p>
+ <?= _('Zwei-Faktor-Authentifizierung ist aktiviert') ?>:
+ <?= $secret->type == 'app' ? _('Authenticator-App') : _('E-Mail') ?>
+</p>
+<form action="<?= $controller->revoke() ?>" method="post">
+ <?= Studip\Button::createAccept(_('Aufheben')) ?>
+</form>
diff --git a/app/views/tfa/setup.php b/app/views/tfa/setup.php
new file mode 100644
index 0000000..6522bd0
--- /dev/null
+++ b/app/views/tfa/setup.php
@@ -0,0 +1,28 @@
+<form class="default" action="<?= $controller->create() ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend><?= _('Zwei-Faktor-Authentifizierung einrichten') ?></legend>
+
+ <p>
+ <?= _('Mittels Zwei-Faktor-Authentifizierung können Sie Ihr Konto schützen, '
+ . 'indem bei jedem Login ein Token von Ihnen eingegeben werden muss.') ?>
+ <?= _('Dieses Token erhalten Sie entweder per E-Mail oder können es über '
+ . 'eine geeignete Authenticator-App erzeugen lassen.') ?>
+ </p>
+
+ <label>
+ <input required type="radio" name="type" value="email">
+ <?= _('E-Mail') ?>
+ </label>
+
+ <label>
+ <input required type="radio" name="type" value="app">
+ <?= _('Authenticator-App') ?>
+ </label>
+ </fieldset>
+
+ <footer>
+ <?= Studip\Button::createAccept(_('Aktivieren')) ?>
+ </footer>
+</form>
diff --git a/app/views/tour/admin_conflicts.php b/app/views/tour/admin_conflicts.php
new file mode 100644
index 0000000..129ef66
--- /dev/null
+++ b/app/views/tour/admin_conflicts.php
@@ -0,0 +1,63 @@
+<? use Studip\LinkButton; ?>
+
+<h1><?= _('Versions-Konflikte der Touren') ?></h1>
+<form action="<?= $controller->url_for('tour/admin_conflicts') ?>" id="admin_tour_form" method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+<? if (count($conflicts) > 0) : ?>
+ <? foreach ($conflicts as $conflict) : ?>
+ <table class="default">
+ <? $keys = array_keys($conflict); ?>
+ <colgroup>
+ <col width="20%">
+ <col width="40%">
+ <col width="40%">
+ </colgroup>
+ <tbody>
+ <tr>
+ <th><?= _('Feld') ?></th>
+ <th><?= sprintf(_('Lokale Version (%s)'), $conflict[$keys[0]]->studip_version) ?></th>
+ <th><?= sprintf(_('Offizielle Version (%s)'), $conflict[$keys[1]]->studip_version) ?></th>
+ </tr>
+ <tr>
+ <td><?= _('Titel') ?></td>
+ <td><?= htmlReady($conflict[$keys[0]]->name) ?></td>
+ <td><?= htmlReady($conflict[$keys[1]]->name) ?></td>
+ </tr>
+ <? foreach ($diff_fields as $field => $title) : ?>
+ <? if ($conflict[$keys[0]]->$field !== $conflict[$keys[1]]->$field) : ?>
+ <tr>
+ <td><?= htmlReady($title) ?></td>
+ <td><?= htmlReady($conflict[$keys[0]]->$field) ?></td>
+ <td><?= htmlReady($conflict[$keys[1]]->$field) ?></td>
+ </tr>
+ <? endif ?>
+ <? endforeach ?>
+ <? $max_steps = max(
+ count($conflict[$keys[0]]->steps),
+ count($conflict[$keys[1]]->steps)
+ ); ?>
+ <? for ($nr = 1; $nr <= $max_steps; $nr++) : ?>
+ <? foreach ($diff_step_fields as $field => $title) : ?>
+ <? if ($conflict[$keys[0]]->steps[$nr]->$field != $conflict[$keys[1]]->steps[$nr]->$field) : ?>
+ <tr>
+ <td><?= htmlReady($title) ?> <?= sprintf(_('(Schritt %s)'), $nr) ?></td>
+ <td><?= htmlReady($conflict[$keys[0]]->steps[$nr]->$field) ?></td>
+ <td><?= htmlReady($conflict[$keys[1]]->steps[$nr]->$field) ?></td>
+ </tr>
+ <? endif ?>
+ <? endforeach ?>
+ <? endfor ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td></td>
+ <td><?= LinkButton::create(_('Übernehmen'), $controller->url_for('tour/resolve_conflict/' . $conflict[$keys[0]]->getId() . '/accept')) ?></td>
+ <td><?= LinkButton::create(_('Löschen'), $controller->url_for('tour/resolve_conflict/' . $conflict[$keys[0]]->getId() . '/delete')) ?></td>
+ </tr>
+ </tfoot>
+ </table>
+ <? endforeach ?>
+<? else : ?>
+ <?= MessageBox::info(_('Keine Konflikte vorhanden.')) ?>
+<? endif ?>
+</form>
diff --git a/app/views/tour/admin_details.php b/app/views/tour/admin_details.php
new file mode 100644
index 0000000..cf018b0
--- /dev/null
+++ b/app/views/tour/admin_details.php
@@ -0,0 +1,192 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $delete_question ?>
+
+<form class="default" action="<?= $controller->url_for('tour/save/' . $tour->tour_id) ?>" method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <fieldset>
+ <legend><?= _('Grunddaten') ?></legend>
+
+ <? if (!count($tour->steps)) : ?>
+ <label>
+ <span class="required">
+ <?= _('Sprache der Tour:') ?>
+ </span>
+ <select name="tour_language">
+ <? foreach ($GLOBALS['INSTALLED_LANGUAGES'] as $key => $language) : ?>
+ <option value="<?= mb_substr($key, 0, 2) ?>" <? if ($tour->language === mb_substr($key, 0, 2)) echo 'selected'; ?>>
+ <?= htmlReady($language['name']) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ </label>
+ <? endif ?>
+
+ <label>
+ <span class="required"><?= _('Name der Tour:') ?></span>
+ <input type="text" size="60" maxlength="255" name="tour_name"
+ value="<?= $tour ? htmlReady($tour->name) : '' ?>"
+ required="required" aria-required="true"
+ placeholder="<?= _('Bitte geben Sie einen Namen für die Tour an') ?>">
+ </label>
+
+ <label>
+ <span class="required"> <?= _('Beschreibung:') ?></span>
+ <textarea cols="60" rows="5" name="tour_description"
+ required="required" aria-required="true"
+ placeholder="<?= _('Bitte geben an, welchen Inhalt die Tour hat') ?>"><?= $tour ? htmlReady($tour->description) : '' ?></textarea>
+ </label>
+
+ <label>
+ <?= _('Art der Tour:') ?>
+ <select name="tour_type">
+ <option value="tour" <? if ($tour->type === 'tour') echo 'selected'; ?>>
+ <?= _('Tour (passiv)') ?>
+ </option>
+ <option value="wizard" <? if ($tour->type === 'wizard') echo 'selected'; ?>>
+ <?= _('Wizard (interaktiv)') ?>
+ </option>
+ </select>
+ </label>
+
+ <label>
+ <?= _('Zugang zur Tour:') ?>
+ <select name="tour_access">
+ <option value="link" <? if ($tour->settings->access === 'link') echo 'selected'; ?>>
+ <?= _('unsichtbar') ?>
+ </option>
+ <option value="standard" <? if ($tour->settings->access === 'standard') echo 'selected'; ?>>
+ <?= _('Anzeige im Hilfecenter') ?>
+ </option>
+ <option value="autostart" <? if ($tour->settings->access === 'autostart') echo 'selected'; ?>>
+ <?= _('Startet bei jedem Aufruf der Seite, bis die Tour abgeschlossen wurde') ?>
+ </option>
+ <option value="autostart_once" <? if ($tour->settings->access === 'autostart_once') echo 'selected'; ?>>
+ <?= _('Startet nur beim ersten Aufruf der Seite') ?>
+ </option>
+ </select>
+ </label>
+
+ <? if (!count($tour->steps)) : ?>
+ <label>
+ <span class="required"><?= _('Startseite der Tour:') ?></span>
+ <input type="text" size="60" maxlength="255" name="tour_startpage"
+ value="<?= $tour_startpage ? htmlReady($tour_startpage) : '' ?>"
+ required="required" aria-required="true"
+ placeholder="<?= _('Bitte geben Sie eine Startseite für die Tour an') ?>"/>
+ </label>
+
+ <? endif ?>
+
+ <section>
+ <?= _('Geltungsbereich (Nutzendenstatus):') ?>
+ <? foreach (['autor', 'tutor', 'dozent', 'admin', 'root'] as $role) : ?>
+ <label>
+ <input type="checkbox" name="tour_roles[]" value="<?= $role ?>"
+ <? if (mb_strpos($tour->roles, $role) !== false) echo 'checked'; ?>>
+ <?=$role ?>
+ </label>
+ <? endforeach ?>
+ </section>
+
+ <!--label for="tour_audience" class="caption">
+ <?= _('Bedingung') ?>
+ </label>
+ <select name="tour_audience_type">
+ <option value=""></option>
+ <option value="sem"<?= ($audience->type == 'sem') ? ' selected' : '' ?>><?= _('Teilnehmende der Veranstaltung') ?></option>
+ <option value="inst"<?= ($audience->type == 'inst') ? ' selected' : '' ?>><?= _('Mitglied der Einrichtung') ?></option>
+ <option value="studiengang"<?= ($audience->type == 'studiengang') ? ' selected' : '' ?>><?= _('Eingeschrieben in Studiengang') ?></option>
+ <option value="abschluss"<?= ($audience->type == 'abschluss') ? ' selected' : '' ?>><?= _('Angestrebter Abschluss') ?></option>
+ <option value="userdomain"<?= ($audience->type == 'userdomain') ? ' selected' : '' ?>><?= _('Zugeordnet zur Nutzerdomäne') ?></option>
+ </select>
+ <input type="text" size="60" maxlength="255" name="tour_audience_range_id"
+ value="<?= $audience ? htmlReady($audience->range_id) : '' ?>"
+ placeholder="<?= _('interne ID des Objekts') ?>"/-->
+
+ </fieldset>
+ <footer>
+ <?= CSRFProtection::tokenTag() ?>
+ <?= Button::createAccept(_('Speichern'), 'save_tour_details') ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('tour/admin_overview')) ?>
+ </footer>
+</form>
+
+<? if (!$tour->isNew()) : ?>
+ <form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption>
+ <div class="step_list_title"><?= _('Schritte') ?></div>
+ </caption>
+ <colgroup>
+ <col width="2%">
+ <col width="25%">
+ <col>
+ <col width="15%">
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Nr.') ?></th>
+ <th><?= _('Überschrift') ?></th>
+ <th><?= _('Inhalt') ?></th>
+ <th><?= _('Seite') ?></th>
+ <th><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($tour->steps)) : ?>
+ <? foreach ($tour->steps as $step) : ?>
+ <tr id="<?= $tour_id . '_' . $step->step ?>">
+ <td><?= $step->step ?></td>
+ <td><?= htmlReady($step->title) ?></td>
+ <td><?= htmlReady($step->tip) ?></td>
+ <td><?= htmlReady($step->route) ?></td>
+ <td class="actions">
+ <? $actionMenu = ActionMenu::get() ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('tour/edit_step/' . $tour->tour_id . '/' . $step->step),
+ _('Schritt bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=auto;reload-on-close']
+ ) ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('tour/admin_details/' . $tour->tour_id, ['delete_tour_step' => $step->step]),
+ _('Schritt löschen'),
+ Icon::create('trash')
+ ) ?>
+ <? $actionMenu->addLink(
+ $controller->url_for('tour/edit_step/' . $tour->tour_id . '/' . ($step->step + 1) . '/new'),
+ _('Neuen Schritt hinzufügen'),
+ Icon::create('add'),
+ ['data-dialog' => 'size=auto;reload-on-close']
+ ) ?>
+ <?= $actionMenu->render() ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? else : ?>
+ <tr>
+ <td colspan="6">
+ <?= _('In dieser Tour sind bisher keine Schritte vorhanden.') ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+ </table>
+ </form>
+<? endif ?>
+
+<?
+if (count($tour->steps)) {
+ $sidebar = Sidebar::get();
+
+ $widget = new ActionsWidget();
+ $widget->addLink(
+ _('Schritt hinzufügen'),
+ $controller->url_for('tour/edit_step/' . $tour->tour_id . '/' . (count($tour->steps) + 1) . '/new'),
+ Icon::create('add', 'clickable'),
+ ['data-dialog' => 'size=auto;reload-on-close']
+ );
+ $sidebar->addWidget($widget);
+}
diff --git a/app/views/tour/admin_overview.php b/app/views/tour/admin_overview.php
new file mode 100644
index 0000000..a6710fc
--- /dev/null
+++ b/app/views/tour/admin_overview.php
@@ -0,0 +1,105 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<?= $delete_question ?>
+
+<form action="<?= $controller->url_for('tour/admin_overview') ?>" id="admin_tour_form" method="post" class="default">
+ <input type="hidden" name="tour_filter" value="set">
+ <input type="hidden" name="tour_filter_term" value="<?= htmlReady($tour_searchterm) ?>">
+ <?= CSRFProtection::tokenTag(); ?>
+<? if ($filter_text) : ?>
+ <table class="default">
+ <tr>
+ <td><?= htmlReady($filter_text) ?></td>
+ <td>
+ <div class="tour_reset_filter">
+ <?= Button::create(_('Auswahl aufheben'), 'reset_filter') ?>
+ </div>
+ </td>
+ </tr>
+ </table>
+<? endif ?>
+
+ <table class="default">
+ <caption>
+ <div class="tour_list_title"><?= _('Touren') ?></div>
+ </caption>
+ <colgroup>
+ <col width="20">
+ <col>
+ <col width="10%">
+ <col width="10%">
+ <col width="10%">
+ <col width="20%">
+ <col width="10%">
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr>
+ <th><?= _('Aktiv') ?></th>
+ <th><?= _('Überschrift') ?></th>
+ <th><?= _('Sprache') ?></th>
+ <th><?= _('Typ') ?></th>
+ <th><?= _('Zugang') ?></th>
+ <th><?= _('Startseite') ?></th>
+ <th><?= _('Anzahl der Schritte') ?></th>
+ <th><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <? if (count($tours)) : ?>
+ <tbody>
+ <? foreach ($tours as $tour_id => $tour) : ?>
+ <tr>
+ <td>
+ <input type="checkbox" name="tour_status_<?= $tour_id ?>" value="1"
+ aria-label="<?= _('Status der Tour (aktiv oder inaktiv)') ?>" <?= tooltip(_("Status der Tour (aktiv oder inaktiv)"), false) ?><?= ($tour->settings->active) ? ' checked' : '' ?>>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for('tour/admin_details/' . $tour_id) ?>">
+ <?= htmlReady($tour->name) ?>
+ </a>
+ </td>
+ <td><?= $tour->language ?></td>
+ <td><?= $tour->type ?></td>
+ <td><?= $tour->settings->access ?></td>
+ <td>
+ <? if (count($tour->steps)): ?>
+ <?= htmlReady($tour->steps[0]->route) ?>
+ <? endif; ?>
+ </td>
+ <td><?= count($tour->steps) ?></td>
+ <td class="actions">
+ <?= ActionMenu::get()->addLink(
+ $controller->url_for('tour/admin_details/' . $tour_id),
+ _('Tour bearbeiten'),
+ Icon::create('edit')
+ )->addLink(
+ $controller->url_for('tour/export/' . $tour_id),
+ _('Tour exportieren'),
+ Icon::create('export'),
+ ['disabled' => count($tour->steps) === 0]
+ )->addButton(
+ 'tour_remove_' . $tour_id,
+ _('Tour löschen'),
+ Icon::create('trash')
+ ) ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="8">
+ <?= Button::createAccept(_('Speichern'), 'save_tour_settings') ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? else : ?>
+ <tbody>
+ <tr>
+ <td colspan="8" style="text-align: center">
+ <?= _('Keine Touren vorhanden.') ?>
+ </td>
+ </tr>
+ </tbody>
+ <? endif ?>
+ </table>
+</form>
diff --git a/app/views/tour/edit_step.php b/app/views/tour/edit_step.php
new file mode 100644
index 0000000..4c0cfb8
--- /dev/null
+++ b/app/views/tour/edit_step.php
@@ -0,0 +1,196 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+
+<div id="edit_tour_step" class="edit_tour_step">
+ <? if (Request::isXhr()) : ?>
+ <? foreach (PageLayout::getMessages() as $msg) : ?>
+ <?= $msg ?>
+ <? endforeach ?>
+ <? endif ?>
+ <form id="edit_tour_form" class="default"
+ action="<?= $controller->url_for('tour/edit_step/' . $tour_id . '/' . $step->step . '/save') ?>"
+ method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+ <fieldset>
+ <input type="hidden" name="tour_step_nr" value="<?= $step->step ?>">
+ <input type="hidden" name="tour_step_editmode" value="<?= $mode ?>">
+ <legend><?= sprintf(_('Schritt %s'), $step->step) ?></legend>
+ <label>
+ <?= _('Titel') ?>
+ <input type="text" size="60" maxlength="255" name="step_title"
+ value="<?= $step ? htmlReady($step->title) : '' ?>"
+ placeholder="<?= _('Bitte geben Sie einen Titel für den Schritt an') ?>">
+ </label>
+
+ <label>
+ <?= _('Inhalt') ?>
+ <textarea cols="60" rows="5" name="step_tip"
+ placeholder="<?= _('Bitte geben Sie den Text für diesen Schritt ein') ?>"><?= $step ? htmlReady($step->tip) : '' ?></textarea>
+ </label>
+
+ <label>
+ <span class="required"><?= _('Art') ?></span>
+ <select name="step_interactive">
+ <option value="0" <? if (!$step->interactive) echo 'selected'; ?>>
+ <?= _('Geführt') ?>
+ </option>
+ <option value="1" <? if ($step->interactive) echo ' selected'; ?>>
+ <?= _('Interaktiv') ?>
+ </option>
+ </select>
+ </label>
+
+ <? if ($force_route) : ?>
+ <input type="hidden" name="step_route" value="<?= $force_route ?>">
+ <input type="hidden" name="step_css" value="<?= $step->css_selector ?>">
+ <? else : ?>
+ <label for="step_route" class="caption">
+ <span class="required"><?= _('Seite') ?></span>
+ <input type="text" size="60" maxlength="255" name="step_route"
+ value="<?= $step ? htmlReady($step->route) : '' ?>"
+ placeholder="<?= _('Route für den Schritt (z.B. "dispatch.php/profile")') ?>">
+ </label>
+ <label>
+ <?= _('CSS-Selektor') ?>
+ <input type="text" size="60" maxlength="255" name="step_css"
+ value="<?= $step ? htmlReady($step->css_selector) : '' ?>"
+ placeholder="<?= _('Selektor, an dem der Schritt angezeigt wird') ?>"/>
+ </label>
+
+ <? endif ?>
+ </fieldset>
+ <? if ($step->css_selector) : ?>
+ <fieldset>
+ <legend><?= _('Orientierung') ?></legend>
+ <div class="tour_step_orientation">
+ <table>
+ <tr>
+ <td></td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="TL" <? if ($step->orientation === 'TL') echo 'checked'; ?>>
+ <?= _('oben (links)') ?>
+ </label>
+ </td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="T" <? if ($step->orientation === 'T') echo 'checked'; ?>>
+ <?= _('oben') ?>
+ </label>
+ </td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="TR" <? if ($step->orientation === 'TR') echo 'checked'; ?>>
+ <?= _('oben (rechts)') ?>
+ </label>
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="LT" <? if ($step->orientation === 'LT') echo 'checked'; ?>>
+ <?= _('links (oben)') ?>
+ </label>
+ </td>
+ <td colspan="3"></td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="RT" <? if ($step->orientation === 'RT') echo 'checked'; ?>>
+ <?= _('rechts (oben)') ?>
+ </label>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="L" <? if ($step->orientation === 'L') echo 'checked'; ?>>
+ <?= _('links') ?>
+ </label>
+ </td>
+ <td colspan="3" style="text-align: center"><?= _('Selektiertes Element') ?></td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="R" <? if ($step->orientation === 'R') echo 'checked'; ?>>
+ <?= _('rechts') ?>
+ </label>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="RB" <? if ($step->orientation === 'RB') echo 'checked'; ?>>
+ <?= _('links (unten)') ?>
+ </label>
+ </td>
+ <td colspan="3"></td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="LB" <? if ($step->orientation === 'LB') echo 'checked'; ?>>
+ <?= _('rechts (unten)') ?>
+ </label>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="BL" <? if ($step->orientation === 'BL') echo 'checked'; ?>>
+ <?= _('unten (links)') ?>
+ </label>
+ </td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="B" <? if ($step->orientation === 'B') echo 'checked'; ?>>
+ <?= _('unten') ?>
+ </label>
+ </td>
+ <td>
+ <label>
+ <input type="radio" name="step_orientation"
+ value="BR" <? if ($step->orientation === 'BR') echo 'checked'; ?>>
+ <?= _('unten (rechts)') ?>
+ </label>
+ </td>
+ <td></td>
+ </tr>
+ </table>
+ </div>
+ </fieldset>
+ <? endif ?>
+
+ <footer data-dialog-button>
+ <? if ($via_ajax): ?>
+ <?= Button::createAccept(_('Speichern'), 'confirm', ['data-dialog' => '']) ?>
+ <? else: ?>
+ <?= Button::createAccept(_('Speichern'), 'submit') ?>
+ <? endif; ?>
+ <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('tour/admin_overview'), []) ?>
+ </footer>
+ </form>
+</div>
+
+<script>
+jQuery(function ($) {
+ $('input[name=step_css]').change(function () {
+ if ($('input[name=step_css]').val()) {
+ $('.tour_step_orientation').show();
+ } else {
+ $('.tour_step_orientation').hide();
+ }
+ });
+ if (STUDIP.Tour.started) {
+ $('#tour_controls, #tour_tip, #selector_overlay').hide();
+ }
+});
+</script>
diff --git a/app/views/tour/import.php b/app/views/tour/import.php
new file mode 100644
index 0000000..57681a1
--- /dev/null
+++ b/app/views/tour/import.php
@@ -0,0 +1,49 @@
+<? use Studip\Button, Studip\LinkButton; ?>
+<form class="default" enctype="multipart/form-data" action="<?= $controller->link_for('tour/import') ?>" method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+
+ <fieldset>
+ <legend><?= _('Importieren') ?></legend>
+
+ <? if (!$tourdata) : ?>
+ <label>
+ <span class="required"><?= _('Datei:') ?></span>
+ <input type="file" size="60" name="tour_file"
+ required aria-required="true"
+ accept="application/json"
+ placeholder="<?= _('Bitte wählen Sie eine Quelldatei mit der Tour aus') ?>">
+ </label>
+ <? else : ?>
+ <label>
+ <span class="required"><?= _('Datei:') ?></span>
+ </label>
+ <div>
+ <table class="default">
+ <tr>
+ <td><?= _('Stud.IP Version') ?></td>
+ <td><?= htmlReady($metadata['version']) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Institution')?></td>
+ <td><?= htmlReady($metadata['source'] . ' (' . $metadata['url'] . ')')?></td>
+ </tr>
+ <tr>
+ <td><?= _('Sprache')?></td>
+ <td><?= htmlReady($tourdata['language']) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Startseite')?></td>
+ <td><?= htmlReady($tourdata['steps'][0]['route']) ?></td>
+ </tr>
+ </table>
+ </div>
+ <? endif ?>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <? if (!$tourdata) : ?>
+ <?= Studip\Button::create(_('Importieren'), 'import_file', ['data-dialog' => 'size=auto;reload-on-close'])?>
+ <? endif ?>
+ <?= Studip\LinkButton::createCancel(_('Schließen'), $controller->url_for('tour/admin_overview')) ?>
+ </footer>
+</form>
diff --git a/app/views/userfilter/field/configure.php b/app/views/userfilter/field/configure.php
new file mode 100644
index 0000000..e41c782
--- /dev/null
+++ b/app/views/userfilter/field/configure.php
@@ -0,0 +1,35 @@
+<?php if ($className) { ?>
+ <? if (count($field->getValidCompareOperators()) > 1) : ?>
+ <select name="compare_operator[]" size="1" class="conditionfield_compare_op">
+ <?php foreach ($field->getValidCompareOperators() as $op => $text) { ?>
+ <option value="<?= $op ?>"><?= htmlReady($text) ?></option>
+ <?php } ?>
+ </select>
+ <? else : ?>
+ <input type="hidden" class="conditionfield_compare_op" name="compare_operator[]" value="<?=key($field->getValidCompareOperators())?>">
+ <? endif ?>
+ <? if (count($field->getValidValues()) > 1) : ?>
+ <select name="value[]" class="conditionfield_value">
+ <?php foreach ($field->getValidValues() as $id => $name) { ?>
+ <option value="<?= $id ?>"><?= htmlReady($name) ?></option>
+ <?php } ?>
+ </select>
+ <? elseif (count($field->getValidValues()) == 1) : ?>
+ <input type="hidden" name="value[]" class="conditionfield_value" value="<?=key($field->getValidValues())?>">
+ <? else : ?>
+ <input type="text" name="value[]" class="conditionfield_value" value="">
+ <? endif ?>
+<?php } else { ?>
+ <?= (!$is_first ? '<strong>' . _("und") . '</strong>' : '')?>
+ <div class="conditionfield">
+ <select name="field[]" class="conditionfield_class" size="1" onchange="STUDIP.UserFilter.getConditionFieldConfiguration(this, '<?= $controller->url_for('userfilter/field/configure') ?>')">
+ <option value="">-- <?= _('bitte auswählen') ?> --</option>
+ <?php foreach ($conditionFields as $className => $displayName) { ?>
+ <option value="<?= $className ?>"><?= htmlReady($displayName) ?></option>
+ <?php } ?>
+ </select>
+ <a href="#" onclick="return STUDIP.UserFilter.removeConditionField($(this).parent())"
+ class="conditionfield_delete">
+ <?= Icon::create('trash', 'clickable')->asImg(); ?></a>
+</div>
+<?php } ?> \ No newline at end of file
diff --git a/app/views/userfilter/filter/add.php b/app/views/userfilter/filter/add.php
new file mode 100644
index 0000000..fc84444
--- /dev/null
+++ b/app/views/userfilter/filter/add.php
@@ -0,0 +1,9 @@
+<div class="condition" id="<?= $condition->getId() ?>">
+ <input type="checkbox" name="conditions_checkbox[]"/>
+ <?= $condition->toString() ?>
+ <input type="hidden" name="conditions[]" value="<?= htmlReady(ObjectBuilder::exportAsJson($condition)) ?>"/>
+ <input type="hidden" name="conditiongroup_<?=$condition->getId()?>" value=""/>
+ <a href="#" onclick="return STUDIP.UserFilter.removeConditionField($(this).parent())"
+ class="conditionfield_delete">
+ <?= Icon::create('trash', 'clickable')->asImg(); ?></a>
+</div> \ No newline at end of file
diff --git a/app/views/userfilter/filter/configure.php b/app/views/userfilter/filter/configure.php
new file mode 100644
index 0000000..59155c0
--- /dev/null
+++ b/app/views/userfilter/filter/configure.php
@@ -0,0 +1,19 @@
+<?php
+use Studip\Button, Studip\LinkButton;
+?>
+<div id="conditionfields">
+ <?= $this->render_partial('userfilter/field/configure.php', ['is_first' => true]); ?>
+</div>
+<br/>
+<a href="#" onclick="return STUDIP.UserFilter.addConditionField('conditionfields', '<?= $controller->url_for('userfilter/field/configure') ?>')">
+ <?= Icon::create('add', 'clickable')->asImg(16, ["alt" => _('Auswahlfeld hinzufügen')]) ?>
+ <?php
+ $text = _('Auswahlfeld hinzufügen');
+ echo $text;
+ ?>
+</a>
+<br/><br/>
+<div class="submit_wrapper" data-dialog-button>
+ <?= Button::createAccept(_('Speichern'), 'submit', ['onclick' => "STUDIP.UserFilter.addCondition('".$containerId."', '".$controller->url_for('userfilter/filter/add')."');"]) ?>
+ <?= Button::createCancel(_('Abbrechen')) ?>
+</div>
diff --git a/app/views/web_migrate/history.php b/app/views/web_migrate/history.php
new file mode 100644
index 0000000..ed8b853
--- /dev/null
+++ b/app/views/web_migrate/history.php
@@ -0,0 +1,83 @@
+<? if (STUDIP\ENV === 'development'): ?>
+<form method="post" action="<?= $controller->link_for('revert') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+<? endif; ?>
+ <table class="default" id="migration-list">
+ <caption>
+ <? if (STUDIP\ENV === 'development'): ?>
+ <?= _('Die markierten Anpassungen werden beim Klick auf "Starten" zurückgesetzt:') ?>
+ <? else: ?>
+ <?= _('Diese Anpassungen wurden im System bereits ausgeführt.') ?>
+ <? endif; ?>
+ </caption>
+ <colgroup>
+ <? if (STUDIP\ENV === 'development' && !$lock->isLocked($lock_data)): ?>
+ <col style="width: 24px">
+ <? endif; ?>
+ <col style="width: 120px">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <? if (STUDIP\ENV === 'development' && !$lock->isLocked($lock_data)): ?>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="#migration-list tbody :checkbox"
+ data-activates="#migration-list tfoot .button">
+ </th>
+ <? endif; ?>
+ <th><?= _('Nr.') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($history as $number => $migration): ?>
+ <tr>
+ <? if (STUDIP\ENV === 'development' && !$lock->isLocked($lock_data)): ?>
+ <td>
+ <input type="checkbox"
+ name="versions[]" value="<?= htmlReady($number) ?>">
+ </td>
+ <? endif; ?>
+ <td>
+ <?= htmlReady($number) ?>
+ </td>
+ <td>
+ <? if ($migration->description()): ?>
+ <?= htmlReady($migration->description()) ?>
+ <? else: ?>
+ <em><?= _('keine Beschreibung vorhanden') ?></em>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <? if (STUDIP\ENV === 'development'): ?>
+ <tfoot>
+ <tr>
+ <td colspan="3">
+ <? if ($lock->isLocked($lock_data)): ?>
+ <?= MessageBox::info(sprintf(
+ _('Die Migration wurde %s von %s bereits angestossen und läuft noch.'),
+ reltime($lock_data['timestamp']),
+ htmlReady(User::find($lock_data['user_id'])->getFullName()
+ )), [
+ sprintf(
+ _('Sollte während der Migration ein Fehler aufgetreten sein, so können Sie '
+ . 'diese Sperre durch den unten stehenden Link oder das Löschen der Datei '
+ . '<em>%s</em> auflösen.'),
+ $lock->getFilename()
+ )
+ ]) ?>
+ <?= Studip\LinkButton::create(_('Sperre aufheben'), $controller->link_for('release', $target)) ?>
+ <? else: ?>
+ <?= Studip\Button::createAccept(_('Starten'), 'start')?>
+ <? endif; ?>
+ </td>
+ </tr>
+ </tfoot>
+ <? endif; ?>
+ </table>
+<? if (STUDIP\ENV === 'development'): ?>
+</form>
+<? endif; ?>
diff --git a/app/views/web_migrate/index.php b/app/views/web_migrate/index.php
new file mode 100644
index 0000000..c9b9725
--- /dev/null
+++ b/app/views/web_migrate/index.php
@@ -0,0 +1,91 @@
+<? if (count($migrations) === 0): ?>
+ <?= MessageBox::info(_('Ihr System befindet sich auf dem aktuellen Stand.'))->hideClose() ?>
+<? else: ?>
+<form method="post" action="<?= $controller->link_for('migrate') ?>">
+ <?= CSRFProtection::tokenTag() ?>
+<? if (isset($target)): ?>
+ <input type="hidden" name="target" value="<?= htmlReady($target) ?>">
+<? endif ?>
+<? if (STUDIP\ENV !== 'development'): ?>
+ <?= addHiddenFields('versions', array_keys($migrations)) ?>
+<? endif; ?>
+
+
+ <table class="default" id="migration-list">
+ <caption>
+ <? if (STUDIP\ENV === 'development'): ?>
+ <?= _('Die markierten Anpassungen werden beim Klick auf "Starten" ausgeführt:') ?>
+ <? else: ?>
+ <?= _('Die hier aufgeführten Anpassungen werden beim Klick auf "Starten" ausgeführt:') ?>
+ <? endif; ?>
+ </caption>
+ <colgroup>
+ <? if (STUDIP\ENV === 'development' && !$lock->isLocked($lock_data)): ?>
+ <col style="width: 24px">
+ <? endif; ?>
+ <col style="width: 120px">
+ <col>
+ </colgroup>
+ <thead>
+ <tr>
+ <? if (STUDIP\ENV === 'development' && !$lock->isLocked($lock_data)): ?>
+ <th>
+ <input type="checkbox"
+ data-proxyfor="#migration-list tbody :checkbox"
+ data-activates="#migration-list tfoot .button">
+ </th>
+ <? endif; ?>
+ <th><?= _('Nr.') ?></th>
+ <th><?= _('Beschreibung') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($migrations as $number => $migration): ?>
+ <tr>
+ <? if (STUDIP\ENV === 'development' && !$lock->isLocked($lock_data)): ?>
+ <td>
+ <input type="checkbox" checked
+ name="versions[]" value="<?= htmlReady($number) ?>">
+ </td>
+ <? endif; ?>
+ <td>
+ <?= htmlReady($number) ?>
+ </td>
+ <td>
+ <? if ($migration->description()): ?>
+ <?= htmlReady($migration->description()) ?>
+ <? else: ?>
+ <em><?= _('keine Beschreibung vorhanden') ?></em>
+ <? endif ?>
+ </td>
+ </tr>
+ <? endforeach; ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td colspan="<?= 2 + (int) (STUDIP\ENV === 'development') ?>">
+ <? if ($lock->isLocked($lock_data)):
+ $user = User::find($lock_data['user_id']);
+ ?>
+ <?= MessageBox::info(sprintf(
+ _('Die Migration wurde %s von %s bereits angestossen und läuft noch.'),
+ reltime($lock_data['timestamp']),
+ htmlReady($user ? $user->getFullName() : _('unbekannt'))
+ ), [
+ sprintf(
+ _('Sollte während der Migration ein Fehler aufgetreten sein, so können Sie '
+ . 'diese Sperre durch den unten stehenden Link oder das Löschen der Datei '
+ . '<em>%s</em> auflösen.'),
+ $lock->getFilename()
+ )
+ ]) ?>
+ <?= Studip\LinkButton::create(_('Sperre aufheben'), $controller->url_for('release', $target)) ?>
+ <? else: ?>
+ <?= Studip\Button::createAccept(_('Starten'), 'start')?>
+ <? endif; ?>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
+<? endif ?>
diff --git a/app/views/wiki/change_courseperms.php b/app/views/wiki/change_courseperms.php
new file mode 100644
index 0000000..4f59fe6
--- /dev/null
+++ b/app/views/wiki/change_courseperms.php
@@ -0,0 +1,26 @@
+<form action="<?= $controller->link_for('wiki/store_courseperms', compact('keyword')) ?>" method="post" class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <label><?= _('Editierberechtigung') ?></label>
+
+ <label>
+ <input type="radio" name="courseperms" value="0"
+ <? if (!$restricted) echo 'checked'; ?>>
+ <?= _('Alle in der Veranstaltung') ?>
+ </label>
+ <label>
+ <input type="radio" name="courseperms" value="1"
+ <? if ($restricted) echo 'checked'; ?>>
+ <?= _('Lehrende und Tutor/innen') ?>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ URLHelper::getURL('wiki.php', compact('keyword'))
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/wiki/change_page_config.php b/app/views/wiki/change_page_config.php
new file mode 100644
index 0000000..84b99f1
--- /dev/null
+++ b/app/views/wiki/change_page_config.php
@@ -0,0 +1,74 @@
+<form action="<?= $controller->link_for('wiki/store_page_config', compact('keyword')) ?>" method="post" class="default" id="wiki-config">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset class="global-permissions">
+ <label>
+ <input type="checkbox" name="page_global_perms" value="1"
+ data-deactivates=".read-permissions :radio, .edit-permissions :radio"
+ <? if ($config->isDefault()) echo 'checked'; ?>>
+ <?= _('Standard Wiki-Einstellungen verwenden') ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="read-permissions">
+ <legend><?= _('Leseberechtigung') ?></legend>
+
+ <label>
+ <input type="radio" name="page_read_perms" id="autor_read" value="0"
+ <? if (!$config->read_restricted) echo 'checked'; ?>
+ title="<?= _('Wiki-Seite für alle Teilnehmenden lesbar') ?>"
+ data-activates=".edit-permissions :radio">
+ <?= _('Alle in der Veranstaltung') ?>
+ </label>
+ <label>
+ <input type="radio" name="page_read_perms" id="tutor_read" value="1"
+ <? if ($config->read_restricted) echo 'checked'; ?>
+ title="<?= _('Wiki-Seite nur eingeschränkt lesbar') ?>"
+ data-deactivates="#autor_edit" data-activates="#tutor_edit">
+ <?= _('Lehrende und Tutor/innen') ?>
+ </label>
+ </fieldset>
+
+ <fieldset class="edit-permissions">
+ <legend><?= _('Editierberechtigung') ?></legend>
+
+ <label>
+ <input type="radio" name="page_edit_perms" id="autor_edit" value="0"
+ <? if (!$config->edit_restricted) echo 'checked'; ?>
+ title="<?= _('Nur editierbar, wenn für alle Teilnehmenden lesbar') ?>">
+ <?= _('Alle in der Veranstaltung') ?>
+ </label>
+ <label>
+ <input type="radio" name="page_edit_perms" id="tutor_edit" value="1"
+ <? if ($config->edit_restricted) echo 'checked'; ?>
+ title="<?= _('Nur editierbar, wenn für diesen Personenkreis lesbar') ?>">
+ <?= _('Lehrende und Tutor/innen') ?>
+ </label>
+ </fieldset>
+
+ <fieldset>
+ <legend><?= _('Vorgängerseite') ?></legend>
+ <label>
+ <? if ($keyword === "WikiWikiWeb") : ?>
+ <p><?= _("Diese Wikiseite darf keine Vorgängerseite haben.") ?></p>
+ <? else : ?>
+ <select name="ancestor_select" id="ancestor_select">
+ <option value=""> <?= _('keine Vorgängerseite') ?> </option>
+ <? foreach ($validKeywords as $validKeyword) : ?>
+ <option value="<?= htmlReady($validKeyword) ?>" <?= $page->ancestor === $validKeyword ? 'selected="selected"' : '' ?> >
+ <?= $validKeyword === 'WikiWikiWeb' ? _('Wiki-Startseite') : htmlReady($validKeyword) ?>
+ </option>
+ <? endforeach ?>
+ </select>
+ <? endif ?>
+ </label>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern')) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ URLHelper::getURL('wiki.php', compact('keyword'))
+ ) ?>
+ </footer>
+</form>
diff --git a/app/views/wiki/create.php b/app/views/wiki/create.php
new file mode 100644
index 0000000..927d1f9
--- /dev/null
+++ b/app/views/wiki/create.php
@@ -0,0 +1,30 @@
+<p>
+ <?= _('Hier können Sie eine neue Wiki-Seite erstellen.') ?>
+ <br />
+ <?= _('Bitte beachten Sie:') ?>
+ <?= _('Eckige Klammern und das Zeichen | sind im Titel nicht erlaubt.') ?>
+</p>
+
+<form action="<?= URLHelper::getLink('wiki.php', ['view' => 'editnew', 'lastpage' => $keyword]) ?>" method="post" class="default">
+ <label>
+ <span class="required"><?= _('Titel') ?></span>
+ <input required type="text" name="keyword" pattern="[^\][|]+"
+ placeholder="<?= _('Name der Wiki-Seite') ?>">
+ </label>
+
+ <label>
+ <span class="required"><?= _('Vorgängerseite') ?></span>
+ <select name="ancestor_select" id="ancestor_select">
+ <option value=""> <?= _('keine Vorgängerseite') ?> </option>
+ <?php foreach ($wiki_page_names as $keyword) : ?>
+ <option value="<?= htmlReady($keyword) ?>" <?= $this->keyword == $keyword ? 'selected="selected"' : '' ?> >
+ <?= $keyword === 'WikiWikiWeb' ? _('Wiki-Startseite') : htmlReady($keyword) ?>
+ <? endforeach ?>
+ </select>
+ </label>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Anlegen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), URLHelper::getURL('wiki.php', compact('keyword'))) ?>
+ </footer>
+</form>
diff --git a/app/views/wiki/import.php b/app/views/wiki/import.php
new file mode 100644
index 0000000..b95f876
--- /dev/null
+++ b/app/views/wiki/import.php
@@ -0,0 +1,141 @@
+<form class="default" method="post"
+ name="wiki_import_form"
+ data-dialog="size=auto;<?= $show_wiki_page_form ? 'reload-on-close' : '' ?>"
+ action="<?= $controller->link_for("wiki/import/{$course->id}") ?>">
+ <?= CSRFProtection::tokenTag() ?>
+
+<? if (!$show_wiki_page_form && !$success): ?>
+ <fieldset>
+ <legend><?= _('Suche nach Veranstaltungen') ?></legend>
+ <label class="with-action">
+ <? if ($bad_course_search): ?>
+ <?= _('Meinten Sie eine der folgenden Veranstaltungen?') ?>
+ <? else: ?>
+ <?= _('Sie können hier eine Veranstaltung mit zu importierenden Wikiseiten suchen.') ?>
+ <? endif ?>
+ <?= $course_search->render() ?>
+ <?= Icon::create('search')->asImg([
+ 'class' => 'text-bottom',
+ 'title' => _('Suche starten'),
+ 'onclick' => "jQuery(this).closest('form').submit();"
+ ]) ?>
+ <? if ($bad_course_search): ?>
+ <a href="<?= $controller->link_for("wiki/import/{$course->id}") ?>"
+ data-dialog="1">
+ <?= Icon::create('decline')->asImg([
+ 'class' => 'text-bottom',
+ 'title' => _('Suche zurücksetzen'),
+ 'onclick' => "STUDIP.QuickSearch.reset('wiki_import_form', 'selected_course_id');"
+ ]) ?>
+ </a>
+ <? else: ?>
+ <?= Icon::create('decline')->asImg([
+ 'class' => 'text-bottom',
+ 'title' => _('Suche zurücksetzen'),
+ 'onclick' => "STUDIP.QuickSearch.reset('wiki_import_form', 'selected_course_id');"
+ ]) ?>
+ <? endif ?>
+ </label>
+ <div data-dialog-button>
+ <? if ($bad_course_search): ?>
+ <?= Studip\LinkButton::create(
+ _('Neue Suche'),
+ $controller->url_for("wiki/import/{$course->id}"),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <? endif ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ URLHelper::getURL(
+ 'wiki.php',
+ [
+ 'cid' => Context::getId(),
+ 'view' => 'show'
+ ]
+ )
+ ) ?>
+ </div>
+ </fieldset>
+<? endif ?>
+
+<? if ($show_wiki_page_form): ?>
+ <input type="hidden" name="selected_course_id"
+ value="<?= htmlReady($selected_course->id) ?>">
+ <? if ($wiki_pages): ?>
+ <table class="default">
+ <colgroup>
+ <col width="20px">
+ <col>
+ </colgroup>
+ <caption>
+ <?= sprintf(
+ _('%s: Importierbare Wikiseiten'),
+ htmlReady($selected_course->getFullName())
+ ) ?>
+ </caption>
+ <thead>
+ <tr>
+ <th>
+ <input type="checkbox"
+ data-proxyfor=":checkbox[name='selected_wiki_page_ids[]']">
+ </th>
+ <th><?= _('Seitenname') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? foreach ($wiki_pages as $wiki_page): ?>
+ <tr>
+ <td>
+ <input type="checkbox"
+ name="selected_wiki_page_ids[]"
+ value="<?= htmlReady(json_encode($wiki_page->getId())) ?>">
+ </td>
+ <td><?= htmlReady($wiki_page->keyword) ?></td>
+ </tr>
+ <? endforeach ?>
+ </tbody>
+ </table>
+ <div data-dialog-button>
+ <?= Studip\Button::create(_('Importieren'), 'import') ?>
+ <?= Studip\LinkButton::create(
+ _('Neue Suche'),
+ $controller->url_for("wiki/import/{$course->id}"),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Abbrechen'),
+ URLHelper::getURL(
+ 'wiki.php',
+ [
+ 'cid' => Context::getId(),
+ 'view' => 'show'
+ ]
+ )
+ ) ?>
+ </div>
+ <? else: ?>
+ <?= MessageBox::info(
+ _('Die gewählte Veranstaltung besitzt keine Wikiseiten!')
+ ) ?>
+ <? endif ?>
+<? endif ?>
+<? if ($success): ?>
+ <div data-dialog-button>
+ <?= Studip\LinkButton::create(
+ _('Import neu starten'),
+ $controller->url_for("wiki/import/{$course->id}"),
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ <?= Studip\LinkButton::createCancel(
+ _('Zurück zum Wiki'),
+ URLHelper::getURL(
+ 'wiki.php',
+ [
+ 'cid' => Context::getId(),
+ 'view' => 'show'
+ ]
+ )
+ ) ?>
+ </div>
+<? endif ?>
+</form>
diff --git a/app/views/wiki/info.php b/app/views/wiki/info.php
new file mode 100644
index 0000000..54f9e86
--- /dev/null
+++ b/app/views/wiki/info.php
@@ -0,0 +1,84 @@
+<h1>
+ <?= $keyword === 'WikiWikiWeb' ? _("Wiki-Startseite") : htmlReady($keyword) ?>
+</h1>
+
+<aside class="wiki-info-aside">
+ <table class="default nohover">
+ <caption>
+ <?= _('Details') ?>
+ </caption>
+
+ <tbody>
+ <tr>
+ <td><?= _('Version') ?></td>
+ <td><?= $last_page['version'] ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Erstellt') ?></td>
+ <td><?= date('d.m.Y, H:i', $first_page['chdate']) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Erstellt von') ?></td>
+ <td><?= htmlReady($first_user->username) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Zuletzt geändert') ?></td>
+ <td><?= date('d.m.Y, H:i', $last_page['chdate']) ?></td>
+ </tr>
+ <tr>
+ <td><?= _('Geändert von') ?></td>
+ <td><?= htmlReady($last_user->username) ?></td>
+ </tr>
+ </tbody>
+ </table>
+</aside>
+
+<table class="default nohover wiki-backlinks">
+ <caption>
+ <?=_('Verweise auf diese Seite') ?>
+ </caption>
+
+ <tbody>
+ <? if ($backlinks): ?>
+ <? foreach (getBacklinks($keyword) as $backlink) : ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('wiki.php', ['keyword' => $backlink]) ?>">
+ <?= Icon::create('link-extern') ?>
+ <?= $backlink === 'WikiWikiWeb' ? _('Wiki-Startseite') : htmlReady($backlink) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? else: ?>
+ <tr>
+ <td><?= _('keine') ?></td>
+ </tr>
+ <? endif ?>
+ </tbody>
+</table>
+
+<table class="default nohover wiki-backlinks">
+ <caption>
+ <?=_('Untergeordnete Seiten') ?>
+ </caption>
+
+ <tbody>
+ <? if ($descendants): ?>
+ <? foreach ($descendants as $descendant) : ?>
+ <tr>
+ <td>
+ <a href="<?= URLHelper::getLink('wiki.php', ['keyword' => $descendant->keyword]) ?>">
+ <?= Icon::create('wiki') ?>
+ <?= htmlReady($descendant->keyword) ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? else: ?>
+ <tr>
+ <td><?= _('keine') ?></td>
+ </tr>
+ <? endif ?>
+ </tbody>
+</table>