From 860bdce14bfb70344eea1c7d5a6b020743b22dd6 Mon Sep 17 00:00:00 2001
From: Dominik George <dominik.george@teckids.org>
Date: Mon, 18 Jul 2022 16:46:43 +0200
Subject: [PATCH] Rewrite notifications page in Vue components

---
 .eslintrc.js                                  |  4 +-
 .../core/templates/core/notifications.html    | 38 +------------------
 assets/app.js                                 |  2 +
 .../notifications/NotificationItem.vue        | 34 +++++++++++++++++
 .../notifications/NotificationList.vue        | 38 +++++++++++++++++++
 webpack.config.js                             | 11 +++++-
 6 files changed, 87 insertions(+), 40 deletions(-)
 create mode 100644 assets/components/notifications/NotificationItem.vue
 create mode 100644 assets/components/notifications/NotificationList.vue

diff --git a/.eslintrc.js b/.eslintrc.js
index ff2ba5584..15b0fbe28 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -3,7 +3,7 @@ module.exports = {
     'plugin:vue/strongly-recommended',
   ],
   rules: {
-    // override/add rules settings here, such as:
-    // 'vue/no-unused-vars': 'error'
+    'vue/no-unused-vars': 'off',
+    'vue/multi-word-component-names': 'off'
   }
 }
diff --git a/aleksis/core/templates/core/notifications.html b/aleksis/core/templates/core/notifications.html
index dee85ebb3..d72018673 100644
--- a/aleksis/core/templates/core/notifications.html
+++ b/aleksis/core/templates/core/notifications.html
@@ -4,42 +4,6 @@
 {% block browser_title %}{% blocktrans %}Notifications{% endblocktrans %}{% endblock %}
 {% block page_title %}{% blocktrans %}Notifications{% endblocktrans %}{% endblock %}
 
-
 {% block content %}
-  {% if object_list %}
-    <v-list two-line>
-      {% for notification in object_list %}
-        <v-list-item>
-          <v-list-item-content>
-            <v-list-item-title>{{ notification.title }}</v-list-item-title>
-
-            <v-list-item-subtitle>
-              <v-icon>mdi-clock-outline</v-icon>
-              {{ notification.created }}
-            </v-list-item-subtitle>
-
-            <v-list-item-subtitle>
-              {{ notification.description|linebreaks }}
-            </v-list-item-subtitle>
-          </v-list-item-content>
-
-          {% if notification.link %}
-            <v-list-item-action>
-              <v-btn text href="{{ notification.link }}">
-                {% blocktrans %}More information →{% endblocktrans %}
-              </v-btn>
-            </v-list-item-action>
-          {% endif %}
-
-          <v-list-item-icon>
-            <v-chip color="primary">{{ notification.sender }}</v-chip>
-          </v-list-item-icon>
-
-        </v-list-item>
-        <v-divider inset></v-divider>
-      {% endfor %}
-    </v-list>
-  {% else %}
-    <p>{% blocktrans %}No notifications available yet.{% endblocktrans %}</p>
-  {% endif %}
+  <notification-list/>
 {% endblock %}
diff --git a/assets/app.js b/assets/app.js
index 1b3595b5c..733a93201 100644
--- a/assets/app.js
+++ b/assets/app.js
@@ -55,6 +55,7 @@ const apolloClient = new ApolloClient({
 import CacheNotification from "./components/CacheNotification.vue";
 import LanguageForm from "./components/LanguageForm.vue";
 import MessageBox from "./components/MessageBox.vue";
+import NotificationList from "./components/notifications/NotificationList.vue";
 import SidenavSearch from "./components/SidenavSearch.vue";
 
 Vue.component(MessageBox.name, MessageBox); // Load MessageBox globally as other components depend on it
@@ -82,6 +83,7 @@ const app = new Vue({
     components: {
         "cache-notification": CacheNotification,
         "language-form": LanguageForm,
+        "notification-list": NotificationList,
         "sidenav-search": SidenavSearch,
     },
 })
diff --git a/assets/components/notifications/NotificationItem.vue b/assets/components/notifications/NotificationItem.vue
new file mode 100644
index 000000000..01e52aa9b
--- /dev/null
+++ b/assets/components/notifications/NotificationItem.vue
@@ -0,0 +1,34 @@
+<template>
+  <v-list-item>
+    <v-list-item-content>
+      <v-list-item-title>{{ notification.title }}</v-list-item-title>
+
+      <v-list-item-subtitle>
+        <v-icon>mdi-clock-outline</v-icon>
+        {{ notification.created }}
+      </v-list-item-subtitle>
+
+      <v-list-item-subtitle>
+        {{ notification.description }}
+      </v-list-item-subtitle>
+    </v-list-item-content>
+
+    <v-list-item-action v-if="notification.link">
+      <v-btn text :href="notification.link">
+        {{ this.$root.django.gettext('More information →') }}
+      </v-btn>
+    </v-list-item-action>
+
+    <v-list-item-icon>
+      <v-chip color="primary">{{ notification.sender }}</v-chip>
+    </v-list-item-icon>
+  </v-list-item>
+</template>
+
+<script>
+  export default {
+    props: {
+      notification: Object,
+    },
+  }
+</script>
diff --git a/assets/components/notifications/NotificationList.vue b/assets/components/notifications/NotificationList.vue
new file mode 100644
index 000000000..815d66aef
--- /dev/null
+++ b/assets/components/notifications/NotificationList.vue
@@ -0,0 +1,38 @@
+<template>
+  <ApolloQuery
+    :query="gql => gql`{
+      myNotifications: whoAmI {
+        notifications {
+          id
+          title
+          description
+          link
+          created
+          sender
+        }
+      }
+    }`"
+    :pollInterval="1000"
+  >
+    <template v-slot="{ result: { error, data }, isLoading }">
+      <v-list two-line v-if="data && data.myNotifications.notifications">
+        <NotificationItem
+          v-for="notification in data.myNotifications.notifications"
+          :key="notification.id"
+          :notification="notification"
+        />
+      </v-list>
+      <p v-else>{{ this.$root.django.gettext('No notifications available yet.') }}</p>
+    </template>
+  </ApolloQuery>
+</template>
+
+<script>
+  import NotificationItem from "./NotificationItem.vue";
+
+  export default {
+    components: {
+      NotificationItem,
+    },
+  }
+</script>
diff --git a/webpack.config.js b/webpack.config.js
index b15388b8b..f6c1da761 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -32,7 +32,16 @@ module.exports = {
     rules: [
       {
         test: /\.vue$/,
-        loader: 'vue-loader'
+        use: {
+          loader: 'vue-loader',
+          options: {
+            transpileOptions: {
+              transforms: {
+                dangerousTaggedTemplateString: true
+              }
+            }
+          }
+        },
       },
       {
         test: /\.(css)$/,
-- 
GitLab