Ver código fonte

اضافه کردن ویجت

AlertMe.vue
hgh 1 ano atrás
pai
commit
230bbd4cdb

+ 2 - 0
src/api/APIGateway.js

@@ -57,11 +57,13 @@ import ContentTopicCategoryAPI from 'src/api/models/ContentTopicCategory.js'
 import ClassroomRegistrationAPI from 'src/api/models/ClassroomRegistration.js'
 import ProjectAttendanceSheetsAPI from 'src/api/models/ProjectAttendanceSheets.js'
 import SessionAttendanceSheetsAPI from 'src/api/models/SessionAttendanceSheets.js'
+import AlertAPI from 'src/api/models/Alert'
 
 /* Exporting the APIGateway object. */
 export const APIGateway = {
   seo: new SeoAPI(),
   auth: new AuthAPI(),
+  alert: new AlertAPI(),
   user: new UserAPI(),
   unit: new UnitAPI(),
   post: new PostAPI(),

+ 104 - 0
src/api/models/Alert.js

@@ -0,0 +1,104 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+import { Alert, AlertList } from 'src/models/Alert.js'
+
+export default class AlertAPI extends APIRepository {
+  constructor() {
+    super('alert', appApi)
+    this.APIAdresses = {
+      base: '/mma/alerts',
+      byId: (id) => '/mma/alerts/' + id,
+      myCorrespondingAlert: '/mma/alerts/my_corresponding_alert'
+    }
+    this.restUrl = (id) => this.url + '/' + id
+    /* Setting the callback functions for the CRUD operations. */
+    this.setCrudCallbacks({
+      get: (response) => { return new Alert(response.data) },
+      post: (response) => { return new Alert(response.data) },
+      put: (response) => { return new Alert(response.data) },
+      delete: (response) => { return response.data }
+    })
+  }
+
+  index(data) {
+    return this.sendRequest({
+      apiMethod: 'get',
+      api: this.api,
+      request: this.APIAdresses.base,
+      data: this.getNormalizedSendData({
+        page: 1 // Number
+      }, data),
+      resolveCallback: (response) => {
+        const paginate = response.data
+        const results = response.data.results
+        delete paginate.results
+        return {
+          list: new AlertList(results),
+          paginate
+          // {
+          //   "count": 1,
+          //   "num_pages": 1,
+          //   "per_page": 10,
+          //   "current": 1,
+          //   "next": null,
+          //   "previous": null,
+          // }
+        }
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
+  getMyCorrespondingAlert(data) {
+    return this.sendRequest({
+      apiMethod: 'get',
+      api: this.api,
+      request: this.APIAdresses.myCorrespondingAlert,
+      data: this.getNormalizedSendData({
+        source_type: 'UNIT' //
+      }, data),
+      resolveCallback: (response) => {
+        return new Alert(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
+  submit (data) {
+    return this.sendRequest({
+      apiMethod: 'post',
+      api: this.api,
+      request: this.APIAdresses.base,
+      data: this.getNormalizedSendData({
+        source_type: 'UNIT'
+      }, data),
+      resolveCallback: (response) => {
+        return new Alert(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
+  seen(id) {
+    return this.sendRequest({
+      apiMethod: 'put',
+      api: this.api,
+      request: this.APIAdresses.byId(id),
+      data: {
+        state: 'READ'
+      },
+      resolveCallback: (response) => {
+        return new Alert(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+}

+ 121 - 0
src/components/Widgets/AlertMe/AlertMe.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="notification-toggle-wrapper">
+    <q-toggle v-model="is_enabled"
+              class="large-toggle"
+              checked-icon="notifications"
+              unchecked-icon="notifications_off"
+              color="primary"
+              :label="`اطلاع‌رسانی درس سطح یک`"
+              left-label
+              :disable="loading"
+              @update:model-value="onToggle">
+      <q-tooltip anchor="top middle"
+                 self="bottom middle"
+                 :offset="[10, 10]">
+        {{ is_enabled ? 'غیرفعال کردن اطلاع‌رسانی' : 'فعال‌سازی اطلاع‌رسانی' }}
+      </q-tooltip>
+
+      <template v-slot:loading>
+        <q-spinner color="primary" />
+      </template>
+    </q-toggle>
+
+    <!-- دیالوگ لاگین -->
+    <q-dialog v-model="showLoginDialog">
+      <login-component @login-success="onLoginSuccess" />
+    </q-dialog>
+  </div>
+</template>
+
+<script>
+import LoginComponent from 'src/components/Auth/LoginComponent.vue'
+import { APIGateway } from 'src/api/APIGateway'
+
+export default {
+  name: 'NotificationToggle',
+  components: { LoginComponent },
+  props: {
+    initialState: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data () {
+    return {
+      sourceType: 'UNIT',
+      sourceId: 1,
+      // is_enabled: this.initialState,
+      is_enabled: false,
+      loading: false,
+      showLoginDialog: false,
+      isUserLogin: false
+    }
+  },
+  mounted () {
+    this.loadAuthData()
+    if (this.isUserLogin) {
+      this.fetchNotificationStatus()
+    }
+  },
+  methods: {
+    loadAuthData () { // prevent Hydration node mismatch
+      this.user = this.$store.getters['Auth/user']
+      this.isUserLogin = this.$store.getters['Auth/isUserLogin']
+    },
+    fetchNotificationStatus () {
+      this.loading = true
+      APIGateway.alert.getMyCorrespondingAlert(
+        {
+          source_id: this.sourceId,
+          source_type: this.sourceType
+        }).then((alert) => {
+        this.is_enabled = alert?.is_enabled
+      }).catch(() => {
+        this.is_enabled = false
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+    onToggle (val) {
+      if (!this.isUserLogin) {
+        this.showLoginDialog = true
+        // برگردوندن toggle به حالت قبلی تا لاگین انجام بشه
+        this.is_enabled = !val
+        return
+      }
+      this.toggleNotification(val)
+    },
+
+    toggleNotification (val) {
+      this.loading = true
+      APIGateway.alert.submit({
+        source_id: this.sourceId,
+        source_type: this.sourceType,
+        is_enabled: val,
+        owner: this.user.id
+      }).then((data) => {
+        this.is_enabled = data.is_enabled
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+    onLoginSuccess () {
+      this.showLoginDialog = false
+      this.fetchNotificationStatus()
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.notification-toggle-wrapper {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 16px;
+  font-size: 18px;
+}
+:deep(.q-toggle__inner) {
+  font-size: 64px;
+}
+</style>

+ 53 - 0
src/components/Widgets/AlertMe/OptionPanel.vue

@@ -0,0 +1,53 @@
+<template>
+  <option-panel-tabs v-model:options="localOptions">
+    <template #main-tab>
+      <div class="q-mt-md">
+        عنوان
+      </div>
+      <div class="row">
+        <div class="col-md-8 col-12">
+          <q-input v-model="localOptions.sourceTitle" />
+        </div>
+      </div>
+      <div class="q-mt-md">
+        نوع منبع
+      </div>
+      <div class="row">
+        <div class="col-md-8 col-12">
+          <q-input v-model="localOptions.sourceType" />
+        </div>
+      </div>
+      <div class="q-mt-md">
+        شناسه منبع
+      </div>
+      <div class="row">
+        <div class="col-md-8 col-12">
+          <q-input v-model="localOptions.sourceId" />
+        </div>
+      </div>
+    </template>
+  </option-panel-tabs>
+</template>
+
+<script>
+import { defineComponent } from 'vue'
+import { mixinOptionPanel } from 'quasar-ui-q-page-builder'
+import OptionPanelTabs from 'quasar-ui-q-page-builder/src/components/OptionPanelComponents/OptionPanelTabs.vue'
+
+export default defineComponent({
+  name: 'OptionPanel',
+  components: {
+    OptionPanelTabs
+  },
+  mixins: [mixinOptionPanel],
+  data () {
+    return {
+      defaultOptions: {
+        sourceTitle: 'عنوان دلخواه',
+        sourceType: null,
+        sourceId: null
+      }
+    }
+  }
+})
+</script>

+ 38 - 0
src/models/Alert.js

@@ -0,0 +1,38 @@
+import { User } from 'src/models/User.js'
+import { Collection, Model } from 'js-abstract-model'
+
+class Alert extends Model {
+  constructor (data) {
+    super(data, [
+      { key: 'id' },
+      { key: 'source_type' },
+      { key: 'source_id' },
+      { key: 'creation_time' },
+      { key: 'owner' },
+      { key: 'is_enabled' },
+      {
+        key: 'owner_info',
+        relatedModel: User
+      }
+    ], {
+      source_type: {
+        infoKey: 'source_type',
+        enumListKey: 'sourceTypeEnums',
+        enums: [
+          {
+            label: 'درس',
+            value: 'UNIT'
+          }
+        ]
+      }
+    })
+  }
+}
+
+class AlertList extends Collection {
+  model () {
+    return Alert
+  }
+}
+
+export { Alert, AlertList }