From bcfc77c260ddc12e2f1b0aec005060943a6bb246 Mon Sep 17 00:00:00 2001
From: tgloeggl <tgloeggl@uos.de>
Date: Fri, 4 Aug 2023 14:08:20 +0200
Subject: [PATCH 1/3] working on action menu

---
 assets/css/opencast.scss                      | 59 +++++++++++++++
 vueapp/components/Studip/StudipActionMenu.vue | 73 ++++++++++---------
 2 files changed, 99 insertions(+), 33 deletions(-)

diff --git a/assets/css/opencast.scss b/assets/css/opencast.scss
index ed81908fa..81119aee0 100644
--- a/assets/css/opencast.scss
+++ b/assets/css/opencast.scss
@@ -6,6 +6,7 @@ $item-width : 20em;
 $item-height-small: auto;
 $item-width-small : 16em;
 $episode-background: $light-gray-color-20;
+$action-menu-icon-size: 20px;
 
 /* * * * * * * * * * * * * * * * * */
 /*   G L O B A L E   K L A S S E N */
@@ -473,6 +474,64 @@ h2.oc--loadingbar, .oc--loadingbar-title {
     display: flex;
     justify-content: center;
     align-items: center;
+
+    .action-menu-icon {
+        background: transparent;
+        border: 0;
+
+        // Create animated icon that changes to close icon on activation/hover
+        span {
+            width: 5px;
+            height: 5px;
+            transform: translate(-2.5px);
+            transition: all .25s ease-in-out;
+
+            display: block;
+            position: absolute;
+            background:  $base-color;
+            border-radius: 50%;
+            opacity: 1;
+            left: 50%;
+
+            &:nth-child(1) {
+                top: 0px;
+            }
+
+            &:nth-child(2) {
+                top: 10px;
+                transform: translate(-2.5px, -2.5px);
+            }
+
+            &:nth-child(3) {
+                bottom: 0;
+            }
+        }
+    }
+
+    .is-open {
+        z-index: 3;
+        .action-menu-icon {
+            span {
+                border-radius: 0;
+
+                &:nth-child(1) {
+                    left: 0;
+                    transform: rotate(45deg) translate(calc(($action-menu-icon-size / 4) + 0.5px), calc(($action-menu-icon-size / 4) + 0.5px));
+                    width: 100%;
+                }
+
+                &:nth-child(2) {
+                    opacity: 0;
+                }
+
+                &:nth-child(3) {
+                    left: 0;
+                    transform: rotate(-45deg) translate(calc($action-menu-icon-size / 4), calc(-1 * ($action-menu-icon-size / 4)));
+                    width: 100%;
+                }
+            }
+        }
+    }
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * */
diff --git a/vueapp/components/Studip/StudipActionMenu.vue b/vueapp/components/Studip/StudipActionMenu.vue
index f3b6bb390..9111fb090 100644
--- a/vueapp/components/Studip/StudipActionMenu.vue
+++ b/vueapp/components/Studip/StudipActionMenu.vue
@@ -1,18 +1,13 @@
 <template>
     <nav v-if="shouldCollapse" class="action-menu">
-        <button v-if="render_button_icon" class="action-menu-icon" :title="$gettext('Aktionen')" aria-expanded="false">
+        <button class="action-menu-icon" :title="title" aria-expanded="false">
             <span></span>
             <span></span>
             <span></span>
         </button>
-        <a v-else class="action-menu-icon" :title="$gettext('Aktionen')" aria-expanded="false" :aria-label="$gettext('Aktionsmenü')" href="#">
-            <div></div>
-            <div></div>
-            <div></div>
-        </a>
         <div class="action-menu-content">
             <div class="action-menu-title">
-                {{ 'Aktionen' }}
+                {{ $gettext('Aktionen') }}
             </div>
             <ul class="action-menu-list">
                 <li v-for="item in navigationItems" :key="item.id" class="action-menu-item">
@@ -22,30 +17,45 @@
 
                         {{ 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>
+                        {{ 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)">
+                            {{ item.label }}
+                        </button>
+                    </template>
                 </li>
             </ul>
         </div>
     </nav>
-    <nav v-else class="action-menu">
-        <ul class="action-menu-list">
-            <li v-for="item in navigationItems" :key="item.id" class="action-menu-item">
-                <a 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>
-            </li>
-        </ul>
+    <nav 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>
     </nav>
 </template>
 
 <script>
-import StudipIcon from '@studip/StudipIcon.vue';
+import StudipIcon from '@studip/StudipIcon.vue'
+
 export default {
-  components: { StudipIcon },
     name: 'studip-action-menu',
+
+    components: {
+        StudipIcon
+    },
+
     props: {
         items: Array,
         collapseAt: {
-            default: true,
+            default: null,
+        },
+        context: {
+            type: String,
+            default: ''
         }
     },
     data () {
@@ -71,7 +81,8 @@ export default {
         linkEvents (item) {
             let events = {};
             if (item.emit) {
-                events.click = () => {
+                events.click = (e) => {
+                    e.preventDefault();
                     this.$emit.apply(this, [item.emit].concat(item.emitArguments));
                     this.close();
                 };
@@ -85,13 +96,13 @@ export default {
     computed: {
         navigationItems () {
             return this.items.map((item) => {
-                let classes = item.classes || '';
+                let classes = item.classes ?? '';
                 if (item.disabled) {
                     classes += " action-menu-item-disabled";
                 }
                 return {
                     label: item.label,
-                    url: item.url || false,
+                    url: item.url || '#',
                     emit: item.emit || false,
                     emitArguments: item.emitArguments || [],
                     icon: item.icon ? {
@@ -99,6 +110,7 @@ export default {
                         role: item.disabled ? 'inactive' : 'clickable'
                     } : false,
                     type: item.type || 'link',
+                    name: item.name ?? null,
                     classes: classes.trim(),
                     attributes: item.attributes || {},
                     disabled: item.disabled,
@@ -106,24 +118,19 @@ export default {
             });
         },
         shouldCollapse () {
-            if (this.collapseAt === false) {
+            const collapseAt = this.collapseAt ?? this.getStudipConfig('ACTIONMENU_THRESHOLD');
+
+            if (collapseAt === false) {
                 return false;
             }
-            if (this.collapseAt === true) {
+            if (collapseAt === true) {
                 return true;
             }
-            return Number.parseInt(this.collapseAt) <= this.items.length;
+            return Number.parseInt(collapseAt) <= this.items.length;
         },
-
-        render_button_icon() {
-            return (window.OpencastPlugin?.STUDIP_VERSION && window.OpencastPlugin.STUDIP_VERSION >= 5.2) ? true : false;
+        title () {
+            return this.context ? this.$gettextInterpolate(this.$gettext('Aktionsmenü für %{context}'), {context: this.context}) : this.$gettext('Aktionsmenü');
         }
     }
 }
 </script>
-
-<style lang="scss">
-.action-menu-list .action-menu-item a {
-    cursor: pointer;
-}
-</style>

From 5a475614e60e23d7f3e5a90597188187900a771d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Till=20Gl=C3=B6ggler?= <till@gundk.it>
Date: Fri, 4 Aug 2023 14:42:53 +0200
Subject: [PATCH 2/3] fix typo

---
 migrations/053_add_default_config_option.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/migrations/053_add_default_config_option.php b/migrations/053_add_default_config_option.php
index 948ca19f4..7a68f6fce 100644
--- a/migrations/053_add_default_config_option.php
+++ b/migrations/053_add_default_config_option.php
@@ -18,7 +18,7 @@ public function up()
         $stmt->execute([
             'name'        => 'OPENCAST_DEFAULT_SERVER',
             'section'     => 'opencast',
-            'description' => 'Das ist der standaramäßig verwendete Opencast-Server.',
+            'description' => 'Das ist der standardmäßig verwendete Opencast-Server.',
             'range'       => 'global',
             'type'        => 'integer',
             'value'       => $config_id

From 91fbeda5868aae59c83c2be5f58f48f13a37a8d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Till=20Gl=C3=B6ggler?= <till@gundk.it>
Date: Sat, 5 Aug 2023 09:24:39 +0200
Subject: [PATCH 3/3] fix action menu for 4.6-5.3

---
 assets/css/opencast.scss | 91 +++++++++++++++++++++-------------------
 1 file changed, 48 insertions(+), 43 deletions(-)

diff --git a/assets/css/opencast.scss b/assets/css/opencast.scss
index 81119aee0..10ab9c31d 100644
--- a/assets/css/opencast.scss
+++ b/assets/css/opencast.scss
@@ -466,6 +466,10 @@ h2.oc--loadingbar, .oc--loadingbar-title {
     }
 }
 
+/* * * * * * * * * * * * * * */
+/*   A C T I O N   M E N U   */
+/* * * * * * * * * * * * * * */
+
 .oc--actions-container {
     min-width: 2em;
     border-left: 1px solid $light-gray-color-40;
@@ -474,66 +478,67 @@ h2.oc--loadingbar, .oc--loadingbar-title {
     display: flex;
     justify-content: center;
     align-items: center;
+}
 
-    .action-menu-icon {
-        background: transparent;
-        border: 0;
+.action-menu-icon {
+    background: transparent;
+    border: 0;
 
-        // Create animated icon that changes to close icon on activation/hover
-        span {
-            width: 5px;
-            height: 5px;
-            transform: translate(-2.5px);
-            transition: all .25s ease-in-out;
+    // Create animated icon that changes to close icon on activation/hover
+    span {
+        width: 5px;
+        height: 5px;
+        transform: translate(-2.5px);
+        transition: all .25s ease-in-out;
 
-            display: block;
-            position: absolute;
-            background:  $base-color;
-            border-radius: 50%;
-            opacity: 1;
-            left: 50%;
+        display: block;
+        position: absolute;
+        background:  $base-color;
+        border-radius: 50%;
+        opacity: 1;
+        left: 50%;
 
-            &:nth-child(1) {
-                top: 0px;
-            }
+        &:nth-child(1) {
+            top: 0px;
+        }
 
-            &:nth-child(2) {
-                top: 10px;
-                transform: translate(-2.5px, -2.5px);
-            }
+        &:nth-child(2) {
+            top: 10px;
+            transform: translate(-2.5px, -2.5px);
+        }
 
-            &:nth-child(3) {
-                bottom: 0;
-            }
+        &:nth-child(3) {
+            bottom: 0;
         }
     }
+}
 
-    .is-open {
-        z-index: 3;
-        .action-menu-icon {
-            span {
-                border-radius: 0;
+.action-menu-wrapper.is-open {
+    z-index: 3;
+    .action-menu-icon {
+        span {
+            border-radius: 0;
 
-                &:nth-child(1) {
-                    left: 0;
-                    transform: rotate(45deg) translate(calc(($action-menu-icon-size / 4) + 0.5px), calc(($action-menu-icon-size / 4) + 0.5px));
-                    width: 100%;
-                }
+            &:nth-child(1) {
+                left: 0;
+                transform: rotate(45deg) translate(5.5px, 5.5px);
+                width: 100%;
+            }
 
-                &:nth-child(2) {
-                    opacity: 0;
-                }
+            &:nth-child(2) {
+                opacity: 0;
+            }
 
-                &:nth-child(3) {
-                    left: 0;
-                    transform: rotate(-45deg) translate(calc($action-menu-icon-size / 4), calc(-1 * ($action-menu-icon-size / 4)));
-                    width: 100%;
-                }
+            &:nth-child(3) {
+                left: 0;
+                transform: rotate(-45deg) translate(5px, -5px);;
+                width: 100%;
             }
         }
     }
 }
 
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * */
 /*   M U L T I   P U R P O S E   S E A R C H B A R   */
 /* * * * * * * * * * * * * * * * * * * * * * * * * * */