From beacf24a89f937db757cade801d545ce94360bc5 Mon Sep 17 00:00:00 2001 From: Elmar Ludwig <elmar.ludwig@uni-osnabrueck.de> Date: Tue, 21 Nov 2023 15:16:53 +0000 Subject: [PATCH] add API for checkboxes/radio buttons in action menus, fixes #3482 Closes #3482 Merge request studip/studip!2388 --- lib/classes/ActionMenu.php | 38 +++++++++++++++++++ resources/vue/components/AdminCourses.vue | 5 ++- resources/vue/components/StudipActionMenu.vue | 15 ++++++-- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/lib/classes/ActionMenu.php b/lib/classes/ActionMenu.php index cf4fb80cd4f..929c485189e 100644 --- a/lib/classes/ActionMenu.php +++ b/lib/classes/ActionMenu.php @@ -207,6 +207,44 @@ class ActionMenu return $this; } + /** + * Adds a checkbox to the list of actions. + * + * @param String $name Input name + * @param String $label Label displayed in the menu + * @param bool $checked Checked state of the action + * @param array $attributes Optional attributes to add to the button + * @return ActionMenu instance to allow chaining + */ + public function addCheckbox($name, $label, bool $checked, array $attributes = []) + { + return $this->addButton( + $name, + $label, + Icon::create($checked ? 'checkbox-checked' : 'checkbox-unchecked'), + $attributes + ['role' => 'checkbox', 'aria-checked' => $checked ? 'true' : 'false'] + ); + } + + /** + * Adds a radio button to the list of actions. + * + * @param String $name Input name + * @param String $label Label displayed in the menu + * @param bool $checked Checked state of the action + * @param array $attributes Optional attributes to add to the button + * @return ActionMenu instance to allow chaining + */ + public function addRadioButton($name, $label, bool $checked, array $attributes = []) + { + return $this->addButton( + $name, + $label, + Icon::create($checked ? 'radiobutton-checked' : 'radiobutton-unchecked'), + $attributes + ['role' => 'radio', 'aria-checked' => $checked ? 'true' : 'false'] + ); + } + /** * Adds a MultiPersonSearch object to the list of actions. * diff --git a/resources/vue/components/AdminCourses.vue b/resources/vue/components/AdminCourses.vue index b27e6f6c6e6..425447b03d6 100644 --- a/resources/vue/components/AdminCourses.vue +++ b/resources/vue/components/AdminCourses.vue @@ -179,10 +179,11 @@ export default { }, availableFields() { return Object.keys(this.fields).map(f => { - let state = this.activatedFields.includes(f); return { + type: 'checkbox', label: this.fields[f], - icon: state ? 'checkbox-checked' : 'checkbox-unchecked', + checked: this.activatedFields.includes(f), + name: 'activatedFields', emit: 'toggleActiveField', emitArguments: f, } diff --git a/resources/vue/components/StudipActionMenu.vue b/resources/vue/components/StudipActionMenu.vue index c70d8edd55e..434336fbf8a 100644 --- a/resources/vue/components/StudipActionMenu.vue +++ b/resources/vue/components/StudipActionMenu.vue @@ -17,13 +17,21 @@ <span v-else class="action-menu-no-icon"></span> {{ item.label }} </a> - <label v-else-if="item.icon" class="undecorated" v-bind="linkAttributes(item)" v-on="linkEvents(item)"> - <studip-icon :shape="item.icon.shape" :role="item.icon.role" :name="item.name" :title="item.label" v-bind="item.attributes ?? {}"></studip-icon> + <label v-else-if="item.type === 'checkbox'" class="undecorated" v-on="linkEvents(item)"> + <studip-icon :shape="item.checked ? 'checkbox-checked' : 'checkbox-unchecked'" :role="item.icon.role" :name="item.name" :title="item.label" aria-role="checkbox" :aria-checked="item.checked.toString()" v-bind="linkAttributes(item)"></studip-icon> + {{ item.label }} + </label> + <label v-else-if="item.type === 'radio'" class="undecorated" v-on="linkEvents(item)"> + <studip-icon :shape="item.checked ? 'radiobutton-checked' : 'radiobutton-unchecked'" :role="item.icon.role" :name="item.name" :title="item.label" aria-role="radio" :aria-checked="item.checked.toString()" v-bind="linkAttributes(item)"></studip-icon> + {{ item.label }} + </label> + <label v-else-if="item.icon" class="undecorated" v-on="linkEvents(item)"> + <studip-icon :shape="item.icon.shape" :role="item.icon.role" :name="item.name" :title="item.label" v-bind="linkAttributes(item)"></studip-icon> {{ item.label }} </label> <template v-else> <span class="action-menu-no-icon"></span> - <button :name="item.name" v-bind="Object.assign(item.attributes ?? {}, linkAttributes(item))" v-on="linkEvents(item)"> + <button :name="item.name" v-bind="linkAttributes(item)" v-on="linkEvents(item)"> {{ item.label }} </button> </template> @@ -114,6 +122,7 @@ export default { classes: classes.trim(), attributes: item.attributes || {}, disabled: item.disabled, + checked: item.checked, }; }); }, -- GitLab