diff --git a/app/controllers/institute/basicdata.php b/app/controllers/institute/basicdata.php index 2f13d9b15acaa6fcd0299e6cbcd25d4942615e0b..04764ec9b9e49b26b70cb5be9dd2736fe901f3e1 100644 --- a/app/controllers/institute/basicdata.php +++ b/app/controllers/institute/basicdata.php @@ -76,7 +76,7 @@ class Institute_BasicdataController extends AuthenticatedController $this->question = (string) QuestionBox::create( $message, $this->url_for('institute/basicdata/delete/' . $i_view, $post), - $this->url_for('institute/basicdata/delete/' . $i_view, []) + $this->url_for('institute/basicdata/index/' . $i_view) ); } diff --git a/app/views/institute/basicdata/index.php b/app/views/institute/basicdata/index.php index 8e697c1e01143bbeec67e9f6273c702a3a2e7020..f896634da8f500c22163121a3bf51d0cddb8f647 100644 --- a/app/views/institute/basicdata/index.php +++ b/app/views/institute/basicdata/index.php @@ -119,8 +119,8 @@ <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' => ''] : []) ?> + $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; ?> diff --git a/lib/classes/ActionMenu.php b/lib/classes/ActionMenu.php index c72b757a20ae8fa1d107d86a8eac9c10e014fcb1..935cc2a5caffc601710bf5f6b910eb9a28a65213 100644 --- a/lib/classes/ActionMenu.php +++ b/lib/classes/ActionMenu.php @@ -129,6 +129,7 @@ class ActionMenu 'attributes' => $attributes, ]; } + $index = $index ?: md5($action['link'] . json_encode($action['attributes'])); $action['index'] = $index; //now insert it possibly at the desired position: @@ -258,10 +259,10 @@ class ActionMenu : self::TEMPLATE_FILE_MULTIPLE; ; $template = $GLOBALS['template_factory']->open($template_file); - $template->actions = array_map(function ($action) { - $disabled = isset($action['attributes']['disabled']) + $template->actions = array_map(function ($action): array { + $action['disabled'] = isset($action['attributes']['disabled']) && $action['attributes']['disabled'] !== false; - if ($disabled && $action['icon']) { + if ($action['disabled'] && $action['icon']) { $action['icon'] = $action['icon']->copyWithRole(Icon::ROLE_INACTIVE); } return $action; diff --git a/lib/classes/LinkButton.class.php b/lib/classes/LinkButton.class.php index 848d2e6aea2b0df1ee7288d01be6c06970cc3c78..40044b60da31058cf5372ab7a952cfd2b5542237 100644 --- a/lib/classes/LinkButton.class.php +++ b/lib/classes/LinkButton.class.php @@ -35,6 +35,13 @@ class LinkButton extends Interactable */ public function __toString() { + if ( + isset($this->attributes['disabled']) + && $this->attributes['disabled'] !== false + ) { + return (string) Button::create($this->label, 'none', $this->attributes); + } + // add "button" to attribute @class if (empty($this->attributes['class'])) { $this->attributes['class'] = ''; diff --git a/resources/assets/stylesheets/scss/actionmenu.scss b/resources/assets/stylesheets/scss/actionmenu.scss index 588f50c039132c21bbda0d1f2dedbd018da3c936..9d82982cf809936cd3c9caa2790827255b6ca993 100644 --- a/resources/assets/stylesheets/scss/actionmenu.scss +++ b/resources/assets/stylesheets/scss/actionmenu.scss @@ -102,21 +102,7 @@ $action-menu-shadow: 1px 1px 1px $dark-gray-color-60; display: block; } - &.action-menu-item-disabled { - > a, - > label { - &, - &:hover { - color: $dark-gray-color-80; - cursor: default; - } - } - } - - a img, - a svg, - .action-menu-no-icon, - input[type="image"] { + .action-menu-item-icon { display: inline-block; margin: 0 0.25em; vertical-align: middle; @@ -141,6 +127,18 @@ $action-menu-shadow: 1px 1px 1px $dark-gray-color-60; color: $active-color; } } + + &.action-menu-item-disabled { + > label, + > button { + color: $dark-gray-color-80; + cursor: default; + + &:hover { + color: $dark-gray-color-80; + } + } + } } &.is-open { diff --git a/resources/vue/components/StudipActionMenu.vue b/resources/vue/components/StudipActionMenu.vue index d67f6a230f47e9076dd3a1f0d69569140fdcc77f..ab07e545c82fb4150523a8f432d5040398a719ea 100644 --- a/resources/vue/components/StudipActionMenu.vue +++ b/resources/vue/components/StudipActionMenu.vue @@ -10,20 +10,40 @@ {{ $gettext('Aktionen') }} </div> <ul class="action-menu-list"> - <li v-for="item in navigationItems" :key="item.id" class="action-menu-item"> - <a v-if="item.type === 'link'" v-bind="linkAttributes(item)" v-on="linkEvents(item)"> - <studip-icon v-if="item.icon !== false" :shape="item.icon.shape" :role="item.icon.role"></studip-icon> + <li v-for="item in navigationItems" :key="item.id" + class="action-menu-item" + :class="{'action-menu-item-disabled': item.disabled}" + > + <label v-if="item.disabled" aria-disabled="true" v-bind="item.attributes"> + <studip-icon v-if="item.icon" + :shape="item.icon" + role="inactive" + class="action-menu-item-icon" + /> + <span v-else class="action-menu-no-icon"></span> + + {{ item.label }} + </label> + <a v-else-if="item.type === 'link'" v-bind="item.attributes" v-on="linkEvents(item)"> + <studip-icon v-if="item.icon" + :shape="item.icon" + class="action-menu-item-icon" + /> <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.icon" class="undecorated" v-on="linkEvents(item)"> + <studip-icon :shape="item.icon" + :name="item.name" + class="action-menu-item-icon" + v-bind="item.attributes" + /> {{ 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="item.attributes" v-on="linkEvents(item)"> {{ item.label }} </button> </template> @@ -32,9 +52,21 @@ </div> </div> <div v-else> - <a v-for="item in navigationItems" :key="item.id" v-bind="linkAttributes(item)" v-on="linkEvents(item)"> - <studip-icon :title="item.label" :shape="item.icon.shape" :role="item.icon.role" :size="20"></studip-icon> - </a> + <template v-for="item in navigationItems"> + <label v-if="item.disabled" :key="item.id" aria-disabled="true" v-bind="item.attributes"> + <studip-icon :shape="item.icon" + :title="item.label" + role="inactive" + class="action-menu-item-icon" + /> + </label> + <a v-else :key="item.id" v-bind="item.attributes" v-on="linkEvents(item)"> + <studip-icon :shape="item.icon" + :title="item.label" + class="action-menu-item-icon" + ></studip-icon> + </a> + </template> </div> </template> @@ -57,26 +89,12 @@ export default { }; }, methods: { - linkAttributes (item) { - let attributes = item.attributes; - attributes.class = item.classes; - - if (item.disabled) { - attributes.disabled = true; - } - - if (item.url) { - attributes.href = item.url; - } - - return attributes; - }, linkEvents (item) { let events = {}; if (item.emit) { events.click = (e) => { e.preventDefault(); - this.$emit.apply(this, [item.emit].concat(item.emitArguments)); + this.$emit.apply(this, [item.emit].concat(item.emitArguments ?? [])); this.close(); }; } @@ -89,25 +107,14 @@ export default { computed: { navigationItems () { return this.items.map((item) => { - let classes = item.classes ?? ''; - if (item.disabled) { - classes += " action-menu-item-disabled"; + item.type = item.type ?? 'link'; + item.attributes = item.attributes ?? {}; + + if (item.type === 'link') { + item.attributes.href = item.url ?? '#'; } - return { - label: item.label, - url: item.url || '#', - emit: item.emit || false, - emitArguments: item.emitArguments || [], - icon: item.icon ? { - shape: item.icon, - role: item.disabled ? 'inactive' : 'clickable' - } : false, - type: item.type || 'link', - name: item.name ?? null, - classes: classes.trim(), - attributes: item.attributes || {}, - disabled: item.disabled, - }; + + return item; }); }, shouldCollapse () { diff --git a/resources/vue/mixins/MyCoursesMixin.js b/resources/vue/mixins/MyCoursesMixin.js index 39e11e739d02b73d9ffbca84d1cb6d3c3011fce7..dcf73a6ec86fb0a82ca987ec9a5b8f8e163bb5dd 100644 --- a/resources/vue/mixins/MyCoursesMixin.js +++ b/resources/vue/mixins/MyCoursesMixin.js @@ -77,7 +77,7 @@ export default { label: this.$gettext('Veranstaltungsdetails'), icon: 'info-circle', attributes: { - 'data-dialog': '' + 'data-dialog': '', }, }); } diff --git a/templates/shared/action-menu-single.php b/templates/shared/action-menu-single.php index a34a01e69dcefe5643f96cc8037a88c10a8e26a5..d504248adb28b27774b7f349aa7d0c4b305160d5 100644 --- a/templates/shared/action-menu-single.php +++ b/templates/shared/action-menu-single.php @@ -12,17 +12,29 @@ */ ?> <? foreach ($actions as $action): ?> - <? if ($action['type'] === 'link'): ?> + <? if ($action['disabled']): ?> + <label class="undecorated action-menu-item-disabled" aria-disabled="true" <?= arrayToHtmlAttributes($action['attributes'] + ['title' => $action['label']]) ?>> + <? if ($action['icon']): ?> + <?= $action['icon']->asImg(['class' => 'action-menu-item-icon']) ?> + <? else: ?> + <?= htmlReady($action['label']) ?> + <? endif ?> + </label> + <? elseif ($action['type'] === 'link'): ?> <a href="<?= htmlReady($action['link']) ?>" <?= arrayToHtmlAttributes($action['attributes'] + ['title' => $action['label']]) ?>> <? if ($action['icon']): ?> - <?= $action['icon']->asImg() ?> + <?= $action['icon']->asImg(['class' => 'action-menu-item-icon']) ?> <? else: ?> <?= htmlReady($action['label']) ?> <? endif ?> </a> <? elseif ($action['type'] === 'button'): ?> <? if ($action['icon']): ?> - <?= $action['icon']->asInput($action['attributes'] + ['name' => $action['name'], 'title' => $action['label']]) ?> + <?= $action['icon']->asInput($action['attributes'] + [ + 'class' => 'action-menu-item-icon', + 'name' => $action['name'], + 'title' => $action['label'], + ]) ?> <? else: ?> <button name="<?= htmlReady($action['name']) ?>" <?= arrayToHtmlAttributes($action['attributes']) ?>> <?= htmlReady($action['label']) ?> diff --git a/templates/shared/action-menu.php b/templates/shared/action-menu.php index c781f3338596474fd14a50b270f4ec188954b235..302194bc094ae51c98419fc9406fa372616949f6 100644 --- a/templates/shared/action-menu.php +++ b/templates/shared/action-menu.php @@ -9,6 +9,9 @@ * icon: Icon, * attributes: array * }> $actions + * @var string $title + * @var string $action_menu_title + * @var array $attributes */ ?> <? // class "action-menu" will be set from API ?> @@ -24,11 +27,21 @@ </div> <ul class="action-menu-list" aria-label="<?= _('Aktionen') ?>"> <? foreach ($actions as $action): ?> - <li class="action-menu-item <? if (isset($action['attributes']['disabled'])) echo 'action-menu-item-disabled'; ?>"> - <? if ($action['type'] === 'link'): ?> + <li class="action-menu-item <? if ($action['disabled']) echo 'action-menu-item-disabled'; ?>"> + <? if ($action['disabled']): ?> + <label class="undecorated" aria-disabled="true" <?= arrayToHtmlAttributes($action['attributes']) ?>> + <? if ($action['icon']): ?> + <?= $action['icon']->asImg(false, ['class' => 'action-menu-item-icon']) ?> + <? else: ?> + <span class="action-menu-no-icon"></span> + <? endif ?> + + <?= htmlReady($action['label']) ?> + </label> + <? elseif ($action['type'] === 'link'): ?> <a href="<?= htmlReady($action['link']) ?>" <?= arrayToHtmlAttributes($action['attributes']) ?>> <? if ($action['icon']): ?> - <?= $action['icon']->asImg(false) ?> + <?= $action['icon']->asImg(false, ['class' => 'action-menu-item-icon']) ?> <? else: ?> <span class="action-menu-no-icon"></span> <? endif ?> @@ -37,7 +50,11 @@ <? elseif ($action['type'] === 'button'): ?> <? if ($action['icon']): ?> <label class="undecorated"> - <?= $action['icon']->asInput(false, $action['attributes'] + ['name' => $action['name'], 'title' => $action['label']]) ?> + <?= $action['icon']->asInput(false, $action['attributes'] + [ + 'class' => 'action-menu-item-icon', + 'name' => $action['name'], + 'title' => $action['label'], + ]) ?> <?= htmlReady($action['label']) ?> </label> <? else: ?>