ali 3 лет назад
Родитель
Сommit
b2afdfd40a

+ 12 - 2
src/components/Menu/SideMenu/MenuItem.vue

@@ -2,7 +2,7 @@
   <div v-for="(item , index) in computedMenu"
        :key="index"
        class="menu-item">
-    <q-expansion-item v-if="!loading && item.children && item.children.length > 0 && item.show"
+    <q-expansion-item v-if="!loading && item.children && item.children.length > 0 && item.show && hasOneOfThisRoles(item.roles)"
                       :header-style="{height:'40px', borderRadius: '14px'}"
                       :label="item.title"
                       :icon="item.icon"
@@ -18,6 +18,7 @@
                :key="i">
             <menu-item v-if="subItem.children && subItem.children.length > 0"
                        :items="[subItem]"
+                       :user="user"
                        @item-selected="itemSelected(item)" />
             <q-item v-else
                     v-ripple
@@ -46,7 +47,7 @@
       </div>
     </q-expansion-item>
     <!--    (item.title === clickedItem.title) || -->
-    <q-item v-else-if="!loading && !item.children"
+    <q-item v-else-if="!loading && !item.children && hasOneOfThisRoles(item.roles)"
             v-ripple
             clickable
             :to="redirectRoute(item)"
@@ -70,6 +71,8 @@
 </template>
 
 <script>
+import { User } from 'src/models/User.js'
+
 export default {
   name: 'MenuItem',
   props: {
@@ -77,6 +80,10 @@ export default {
       type: String,
       default: ''
     },
+    user: {
+      type: User,
+      default: new User()
+    },
     menu: {
       // ToDO: will be deprecate
       type: Array,
@@ -149,6 +156,9 @@ export default {
     },
     inactiveAllItems () {
 
+    },
+    hasOneOfThisRoles (roles) {
+      return !roles || roles.find(role => this.user.hasRole(role))
     }
   }
 }

+ 32 - 1
src/components/Template/SideBard/AdminPanelSideBar.vue

@@ -11,22 +11,26 @@
     </div>
     <q-list class="side-menu-list"
             padding>
-      <menu-item :menu="adminMenuItems" />
+      <menu-item :menu="adminMenuItems"
+                 :user="user" />
     </q-list>
   </div>
 </template>
 
 <script>
+import { mixinAuthData } from 'src/mixin/Mixins.js'
 import menuItem from 'src/components/Menu/SideMenu/MenuItem.vue'
 
 export default {
   name: 'AdminPanelSideBar',
   components: { menuItem },
+  mixins: [mixinAuthData],
   data () {
     return {
       adminMenuItems: [
         {
           title: 'کاربران',
+          roles: ['superuser'],
           routeName: 'Admin.User.Index',
           icon: 'groups',
           show: true,
@@ -34,6 +38,7 @@ export default {
         },
         {
           title: 'دوره های آموزشی',
+          roles: ['superuser', 'educational_department_head'],
           icon: 'import_contacts',
           routeName: null,
           show: true,
@@ -42,12 +47,14 @@ export default {
           children: [
             {
               title: 'درس ها و چارت آموزشی',
+              roles: ['superuser', 'educational_department_head'],
               routeName: 'Admin.Category.Index',
               show: true,
               active: false
             },
             {
               title: 'دوره های آموزشی',
+              roles: ['superuser', 'educational_department_head'],
               routeName: 'Admin.Classroom.Index',
               show: true,
               active: false
@@ -56,6 +63,7 @@ export default {
         },
         {
           title: 'حلقه های مباحثاتی',
+          roles: ['superuser', 'educational_department_head'],
           icon: 'diversity_2',
           routeName: null,
           show: true,
@@ -64,12 +72,14 @@ export default {
           children: [
             {
               title: 'درس ها و چارت آموزشی',
+              roles: ['superuser', 'educational_department_head'],
               routeName: 'Admin.Category.DiscussionCircles.Index',
               show: true,
               active: false
             },
             {
               title: 'حلقه های مباحثاتی',
+              roles: ['superuser', 'educational_department_head'],
               routeName: 'Admin.Classroom.DiscussionCircles.Index',
               show: true,
               active: false
@@ -78,13 +88,23 @@ export default {
         },
         {
           title: 'درخواست های آموزش',
+          roles: ['superuser', 'educational_department_head'],
           routeName: 'Admin.Ticket.List.Educational',
           icon: 'local_activity',
           show: true,
           active: false
         },
+        {
+          title: 'دوره های من',
+          roles: ['superuser', 'team_leader'],
+          routeName: 'Admin.Leader.MyClassrooms.Index',
+          icon: 'diversity_3',
+          show: true,
+          active: false
+        },
         {
           title: 'محتوا',
+          roles: ['superuser'],
           icon: 'live_tv',
           routeName: null,
           show: true,
@@ -93,18 +113,21 @@ export default {
           children: [
             {
               title: 'دسته بندی ها',
+              roles: ['superuser'],
               routeName: 'Admin.ContentCategory.List',
               show: true,
               active: false
             },
             {
               title: 'لیست محتوا ها',
+              roles: ['superuser'],
               routeName: 'Admin.Content.List',
               show: true,
               active: false
             },
             {
               title: 'درخواست ها',
+              roles: ['superuser'],
               routeName: 'Admin.Content.Ticket',
               show: true,
               active: false
@@ -113,6 +136,7 @@ export default {
         },
         {
           title: 'بلاگ',
+          roles: ['superuser'],
           icon: 'rss_feed',
           routeName: null,
           show: true,
@@ -121,12 +145,14 @@ export default {
           children: [
             {
               title: 'دسته بندی ها',
+              roles: ['superuser'],
               routeName: 'Admin.PostCategory.List',
               show: true,
               active: false
             },
             {
               title: 'لیست پست ها',
+              roles: ['superuser'],
               routeName: 'Admin.Post.List',
               show: true,
               active: false
@@ -135,6 +161,7 @@ export default {
         },
         {
           title: 'مدیریت مالی',
+          roles: ['superuser', 'financial_department_head'],
           icon: 'payments',
           routeName: null,
           show: true,
@@ -143,18 +170,21 @@ export default {
           children: [
             {
               title: 'صورتحساب ها',
+              roles: ['superuser', 'financial_department_head'],
               routeName: 'Admin.Invoice.List',
               show: true,
               active: false
             },
             {
               title: 'پرداخت ها',
+              roles: ['superuser', 'financial_department_head'],
               routeName: 'Admin.Payment.List',
               show: true,
               active: false
             },
             {
               title: 'درخواست ها',
+              roles: ['superuser', 'financial_department_head'],
               routeName: 'Admin.Invoice.Ticket.List',
               show: true,
               active: false
@@ -163,6 +193,7 @@ export default {
         },
         {
           title: 'تمام درخواست ها',
+          roles: ['superuser'],
           routeName: 'Admin.Ticket.List',
           icon: 'confirmation_number',
           show: true,

+ 244 - 0
src/components/Widgets/Classroom/LeaderMyClassroomList/LeaderMyClassroomList.vue

@@ -0,0 +1,244 @@
+<template>
+  <div class="LeaderMyClassroomList">
+    <entity-index v-if="mounted"
+                  ref="entityIndex"
+                  v-model:value="inputs"
+                  title="لیست دوره های من"
+                  :api="api"
+                  :table="table"
+                  :table-keys="tableKeys"
+                  :show-expand-button="false"
+                  :show-reload-button="false"
+                  :show-search-button="false">
+      <template v-slot:entity-index-table-cell="{inputData, showConfirmRemoveDialog}">
+        <template v-if="inputData.col.name === 'number'">
+          {{ inputData.rowNumber }}
+        </template>
+        <template v-else-if="inputData.col.name === 'action'">
+          <div class="action-column-entity-index">
+            <q-btn size="md"
+                   color="primary"
+                   label="جزییات"
+                   :to="{name: 'Admin.Classroom.Show', params: {id: inputData.props.row.id}}"
+                   class="q-mr-md" />
+            <delete-btn @click="showConfirmRemoveDialog(inputData.props.row, 'id', getRemoveMessage(inputData.props.row))" />
+          </div>
+        </template>
+        <template v-else>
+          {{ inputData.col.value }}
+        </template>
+      </template>
+    </entity-index>
+  </div>
+</template>
+
+<script>
+import { shallowRef } from 'vue'
+import { EntityIndex } from 'quasar-crud'
+import Enums from 'src/assets/Enums/Enums.js'
+import ShamsiDate from 'src/assets/ShamsiDate.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+import BtnControl from 'src/components/Control/btn.vue'
+import DeleteBtn from 'src/components/Control/DeleteBtn.vue'
+
+const BtnControlComp = shallowRef(BtnControl)
+
+export default {
+  name: 'LeaderMyClassroomList',
+  components: {
+    EntityIndex,
+    DeleteBtn
+  },
+  data () {
+    return {
+      mounted: false,
+      inputs: [
+        {
+          type: 'select',
+          name: 'status',
+          options: Enums.classroomStatuses,
+          value: null,
+          label: 'وضعیت دوره',
+          placeholder: ' ',
+          col: 'col-md-2 col-12'
+        },
+        {
+          type: 'select',
+          name: 'unit',
+          options: [],
+          value: null,
+          label: 'درس',
+          placeholder: ' ',
+          col: 'col-md-2 col-12'
+        },
+        { type: 'hidden', name: 'unit__category__type', value: 'TRAINING' },
+        { type: BtnControlComp, name: 'btn', label: 'جستجو', placeholder: ' ', atClick: () => {}, col: 'col-md-2 col-12' }
+      ],
+      api: APIGateway.classroom.APIAdresses.base,
+      table: {
+        columns: [
+          {
+            name: 'number',
+            required: true,
+            label: 'شماره',
+            align: 'left',
+            field: () => ''
+          },
+          {
+            name: 'id',
+            required: true,
+            label: 'شناسه',
+            align: 'left',
+            field: row => row.id
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'نام دوره',
+            align: 'left',
+            field: row => row.title
+          },
+          {
+            name: 'audience_gender_type',
+            required: true,
+            label: 'جنسیت',
+            align: 'left',
+            field: row => (row.audience_gender_type === 'FEMALE') ? 'خواهران' : (row.audience_gender_type === 'MALE') ? 'برادران' : 'خواهران و برادران'
+          },
+          {
+            name: 'status',
+            required: true,
+            label: 'وضعیت',
+            align: 'left',
+            field: row => this.getClassroomStatusesTitle(row.status)
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'نوع برگزاری',
+            align: 'left',
+            field: row => this.getClassroomHoldingTypeTitle(row.holding_type)
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'هزینه(ریال)',
+            align: 'left',
+            field: row => row.price
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'استاد مربوطه',
+            align: 'left',
+            field: row => row.professor_info?.firstname + ' ' + row.professor_info?.lastname
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'تاریخ و زمان ثبت نام',
+            align: 'left',
+            field: row => row.beginning_registration_period ? ShamsiDate.getDateTime(row.beginning_registration_period) : '-'
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'ترم برگزاری',
+            align: 'left',
+            field: row => (row.beginning_registration_period) ? ShamsiDate.getTerm(row.beginning_registration_period) : '-'
+          },
+          {
+            name: 'action',
+            required: true,
+            label: 'عملیات',
+            align: 'left',
+            field: ''
+          }
+        ],
+        data: []
+      },
+      tableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
+      }
+    }
+  },
+  mounted () {
+    this.setActionBtn()
+    this.mounted = true
+    this.getUnits()
+  },
+  methods: {
+    setActionBtn () {
+      this.inputs.forEach((item, index) => {
+        if (item.name === 'btn') {
+          this.inputs[index].atClick = this.search
+        }
+      })
+    },
+    search () {
+      this.$refs.entityIndex.search()
+    },
+    getUnits () {
+      APIGateway.unit.index({ per_page: 9999 })
+        .then((units) => {
+          this.loadSelectOptions('unit', this.getSelectOptions(units.list.list, 'id', 'title'))
+        })
+        .catch(() => {
+
+        })
+    },
+    loadSelectOptions (name, value) {
+      const inputIndex = this.inputs.findIndex(input => input.name === name)
+      this.inputs[inputIndex].options = value
+    },
+    getSelectOptions (result, value, label) {
+      return result.map(item => {
+        return {
+          value: item[value],
+          label: item[label]
+        }
+      })
+    },
+    getRemoveMessage (row) {
+      return 'آیا از حذف ' + row.title + ' اطمینان دارید؟'
+    },
+    getClassroomHoldingTypeTitle (type) {
+      const target = Enums.classroomHoldingTypes.find(item => item.value === type)
+      if (!target) {
+        return '-'
+      }
+
+      return target.label
+    },
+    getClassroomStatusesTitle (type) {
+      const target = Enums.classroomStatuses.find(item => item.value === type)
+      if (!target) {
+        return '-'
+      }
+
+      return target.label
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.LeaderMyClassroomList {
+  .add-new-action-row {
+    display: flex;
+    flex-flow: row;
+    align-items: center;
+    justify-content: flex-end;
+    margin-bottom: 22px;
+  }
+  .action-column-entity-index {
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/Classroom/LeaderMyClassroomList/OptionPanel.vue

@@ -0,0 +1,21 @@
+<template>
+  <option-panel-tabs v-model:options="localOptions">
+    <template #main-tab>
+      ...
+    </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]
+})
+</script>

+ 16 - 2
src/models/User.js

@@ -61,8 +61,22 @@ class User extends Model {
       { key: 'address' },
       { key: 'moballegh_info' },
       { key: 'user_permissions' }
-
-    ])
+    ], {
+      gender: {
+        infoKey: 'gender_info',
+        enumListKey: 'genderEnums',
+        enums: [
+          {
+            label: 'مذکر',
+            value: 1
+          },
+          {
+            label: 'مونث',
+            value: 0
+          }
+        ]
+      }
+    })
 
     if (this.user_id !== null) {
       this.id = this.user_id

+ 23 - 0
src/pages/Admin/Classroom/LeaderMyClassrooms.vue

@@ -0,0 +1,23 @@
+<template>
+  <q-page-builder v-model:sections="currenSections"
+                  v-model:options="pageConfig"
+                  :editable="pageBuilderEditable"
+                  :loading="pageBuilderLoading" />
+</template>
+
+<script>
+import { mixinPageOptions } from 'src/mixin/Mixins.js'
+
+export default {
+  name: 'Admin.Classroom.Show',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'LeaderMyClassroomList' }], options: { style: { paddingTop: '' } } }], options: { className: '', height: 'auto', boxed: true, boxedWidth: 1200, gutterXSize: 'md', gutterYSize: 'md', absolute: 'none', paddingOfBoxedInFullWidth: '10px', alignment: { justifyContent: { global: null, xl: null, lg: null, md: null, sm: null, xs: null }, alignItems: { global: null, xl: null, lg: null, md: null, sm: null, xs: null }, alignContent: { global: null, xl: null, lg: null, md: null, sm: null, xs: null } }, style: { maxWidth: '1200px', width: '1200px' } } }] } }]
+    }
+  },
+  created() {
+    this.currenSections = this.sections
+  }
+}
+</script>

+ 8 - 1
src/router/routes.js

@@ -552,7 +552,6 @@ const routes = [
             name: 'Admin.Classroom',
             path: 'classrooms',
             component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'دوره های آموزشی', route: { name: 'Admin.Classroom.Index' } },
             children: [
               { name: 'Admin.Classroom.Index', path: '', component: () => import('src/pages/Admin/Classroom/index.vue') },
               { name: 'Admin.Classroom.Create', path: 'create', component: () => import('src/pages/Admin/Classroom/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
@@ -569,6 +568,14 @@ const routes = [
               { name: 'Admin.Classroom.Ticket', path: 'ticket', component: () => import('src/pages/Admin/Classroom/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } }
             ]
           },
+          {
+            name: 'Admin.Leader',
+            path: 'leader',
+            component: () => import('layouts/bareLayout.vue'),
+            children: [
+              { name: 'Admin.Leader.MyClassrooms.Index', path: 'my_classrooms', component: () => import('src/pages/Admin/Classroom/LeaderMyClassrooms.vue') }
+            ]
+          },
           {
             name: 'Admin.Classroom.DiscussionCircles',
             path: 'discussion-circles-classrooms',