ali 2 gadi atpakaļ
vecāks
revīzija
da337f3f2f

+ 2 - 0
src/api/APIGateway.js

@@ -9,6 +9,7 @@ import EventAPI from 'src/api/models/Event.js'
 import MediaAPI from 'src/api/models/Media.js'
 import TicketAPI from 'src/api/models/Ticket.js'
 import WalletAPI from 'src/api/models/Wallet.js'
+import TestSetAPI from 'src/api/models/TestSet.js'
 import InvoiceAPI from 'src/api/models/Invoice.js'
 import PaymentAPI from 'src/api/models/Payment.js'
 import SessionAPI from 'src/api/models/Session.js'
@@ -49,6 +50,7 @@ export const APIGateway = {
   media: new MediaAPI(),
   ticket: new TicketAPI(),
   wallet: new WalletAPI(),
+  testSet: new TestSetAPI(),
   project: new ProjectAPI(),
   invoice: new InvoiceAPI(),
   payment: new PaymentAPI(),

+ 71 - 0
src/api/models/TestSet.js

@@ -0,0 +1,71 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+import { TestSet, TestSetList } from 'src/models/TestSet.js'
+
+export default class TestSetAPI extends APIRepository {
+  constructor() {
+    super('test_sets', appApi)
+    this.APIAdresses = {
+      base: '/lma/test_sets',
+      byId: (id) => '/lma/test_sets/' + id
+    }
+    this.CacheList = {
+      base: this.name + this.APIAdresses.base
+    }
+    this.restUrl = (id) => this.APIAdresses.base + '/' + id
+    /* Setting the callback functions for the CRUD operations. */
+    this.setCrudCallbacks({
+      get: (response) => { return new TestSet(response.data) },
+      post: (response) => { return new TestSet(response.data) },
+      put: (response) => { return new TestSet(response.data) },
+      delete: (response) => { return response.data }
+    })
+  }
+
+  index(data) {
+    return this.sendRequest({
+      apiMethod: 'get',
+      api: this.api,
+      request: this.APIAdresses.base,
+      data: this.getNormalizedSendData({
+        category: null, // Number
+        per_page: 10, // Number
+        page: 1 // Number
+      }, data),
+      resolveCallback: (response) => {
+        const paginate = response.data
+        const results = response.data.results
+        delete paginate.results
+        return {
+          list: new TestSetList(results),
+          paginate
+          // {
+          //   "count": 1,
+          //   "num_pages": 1,
+          //   "per_page": 10,
+          //   "current": 1,
+          //   "next": null,
+          //   "previous": null,
+          // }
+        }
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
+  get(id) {
+    return this.sendRequest({
+      apiMethod: 'get',
+      api: this.api,
+      request: this.APIAdresses.byId(id),
+      resolveCallback: (response) => {
+        return new TestSet(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+}

+ 7 - 2
src/components/Widgets/Classroom/AdminClassroomShow/AdminClassroomShow.vue

@@ -73,8 +73,11 @@
                    class="q-pa-none">
         <project-list :classroom-id="$route.params.id" />
       </q-tab-panel>
-      <q-tab-panel name="exams">
-        آزمون
+      <q-tab-panel name="exams"
+                   class="q-pa-none">
+        <test-list :classroom-id="$route.params.id"
+                   :classroom="classroom"
+                   :classroom-type="localOptions.classroomType" />
       </q-tab-panel>
       <q-tab-panel name="members"
                    class="q-pa-none">
@@ -105,6 +108,7 @@
 
 <script>
 import TeamList from './components/TeamList.vue'
+import TestList from './components/TestList.vue'
 import { mixinWidget } from 'src/mixin/Mixins.js'
 import { Classroom } from 'src/models/Classroom.js'
 import LeaderList from './components/LeaderList.vue'
@@ -122,6 +126,7 @@ export default {
   name: 'Admin.Classroom.Show',
   components: {
     TeamList,
+    TestList,
     LeaderList,
     GraderList,
     SessionList,

+ 209 - 0
src/components/Widgets/Classroom/AdminClassroomShow/components/TestList.vue

@@ -0,0 +1,209 @@
+<template>
+  <entity-index v-if="classroomLoaded"
+                ref="testList"
+                v-model:value="testListInputs"
+                :title="listTitle"
+                :api="testListApi"
+                :table="testListTable"
+                :table-keys="testListTableKeys"
+                :show-search-button="false"
+                :show-reload-button="false"
+                :show-expand-button="false">
+    <template #toolbar>
+      <q-btn color="primary"
+             outline
+             :loading="addNewSessionLoading"
+             @click="addNewSession">
+        {{ addBtnTitle }}
+      </q-btn>
+    </template>
+    <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 === 'actions'">
+        <div class="action-column-entity-index">
+          <q-btn size="md"
+                 outline
+                 color="primary"
+                 label="بررسی"
+                 :to="{name: sessionAttendanceSheetList, params: {classroom_id: classroomId, session_id: inputData.props.row.id}}"
+                 class="q-mr-md" />
+          <q-btn size="md"
+                 color="primary"
+                 label="جزییات"
+                 :to="{name: 'Admin.Session.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>
+  <q-skeleton v-else
+              type="rect"
+              height="200px" />
+</template>
+
+<script>
+import { EntityIndex } from 'quasar-crud'
+import ShamsiDate from 'src/assets/ShamsiDate.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+import { Classroom } from 'src/models/Classroom.js'
+import DeleteBtn from 'src/components/Control/DeleteBtn.vue'
+import { FormBuilderAssist } from 'quasar-form-builder'
+
+export default {
+  name: 'TestList',
+  components: {
+    DeleteBtn,
+    EntityIndex
+  },
+  props: {
+    classroom: {
+      type: Classroom,
+      default: new Classroom()
+    },
+    classroomType: {
+      type: String,
+      default: 'TRAINING'
+    }
+  },
+  data () {
+    return {
+      classroomLoaded: false,
+      listTitle: 'لیست آزمون ها',
+      addBtnTitle: 'افزودن آزمون',
+      addNewSessionLoading: false,
+
+      testListInputs: [
+        { type: 'hidden', name: 'unit', value: null }
+      ],
+      testListApi: APIGateway.session.APIAdresses.base,
+      testListTable: {
+        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: 'beginning_time',
+            required: true,
+            label: 'زمان شروع آزمون',
+            align: 'left',
+            field: row => row.beginning_time ? ShamsiDate.getDateTime(row.beginning_time) : '-'
+          },
+          {
+            name: 'ending_time',
+            required: true,
+            label: 'زمان پایان آزمون',
+            align: 'left',
+            field: row => row.ending_time ? ShamsiDate.getDateTime(row.ending_time) : '-'
+          },
+          {
+            name: 'actions',
+            required: true,
+            label: 'عملیات',
+            align: 'left',
+            field: ''
+          }
+        ]
+      },
+      testListTableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
+      }
+    }
+  },
+  computed: {
+    classroomId () {
+      return this.classroom.id
+    },
+    sessionAttendanceSheetList () {
+      if (this.classroomType === 'TRAINING') {
+        return 'Admin.Classroom.Session.AttendanceSheetList'
+      }
+      if (this.classroomType === 'EVENT') {
+        return 'Admin.Event.Session.AttendanceSheetList'
+      }
+      return 'Admin.Classroom.Session.AttendanceSheetList'
+    }
+  },
+  watch: {
+    classroomId (newValue) {
+      if (!newValue) {
+        return
+      }
+
+      const unitId = newValue.unit || newValue.unit_info.id
+      FormBuilderAssist.setAttributeByName(this.testListInputs, 'unit', 'value', unitId)
+      this.classroomLoaded = true
+    }
+  },
+  mounted () {
+    this.setClassroomTypeOfInputs()
+  },
+  methods: {
+    setClassroomTypeOfInputs () {
+      if (this.classroomType === 'TRAINING') {
+        this.listTitle = 'لیست آزمون ها'
+        this.addBtnTitle = 'افزودن آزمون'
+      }
+      if (this.classroomType === 'EVENT') {
+        this.listTitle = 'لیست برنامه ها'
+        this.addBtnTitle = 'افزودن برنامه'
+        this.testListTable.columns.forEach(col => {
+          if (col.name === 'title') {
+            col.label = 'عنوان برنامه'
+          }
+          if (col.name === 'beginning_time') {
+            col.label = 'زمان شروع برنامه'
+          }
+          if (col.name === 'ending_time') {
+            col.label = 'زمان پایان برنامه'
+          }
+        })
+      }
+    },
+    addNewSession () {
+      this.addNewSessionLoading = true
+      APIGateway.session.create({
+        title: '-',
+        classroom: this.classroomId
+      })
+        .then(() => {
+          this.$refs.testList.search()
+          this.addNewSessionLoading = false
+        })
+        .catch(() => {
+          this.addNewSessionLoading = false
+        })
+    },
+    getRemoveMessage (row) {
+      return 'آیا از حذف ' + row.title + ' اطمینان دارید؟'
+    }
+  }
+}
+</script>

+ 2 - 2
src/components/Widgets/Test/AdminTestCreate/AdminTestCreate.vue

@@ -48,7 +48,7 @@ export default {
       api: APIGateway.test.APIAdresses.base,
       entityIdKey: 'id',
       entityParamKey: 'id',
-      showRouteName: 'Admin.Unit.Test.Show',
+      showRouteName: 'Admin.Unit.TestSet.Show',
       inputs: [
         { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان آزمون', placeholder: ' ', col: 'col-md-6 col-12' },
         { type: 'inputEditor', name: 'description', responseKey: 'description', label: 'توضیحات آزمون', col: 'col-md-12 col-12' },
@@ -70,7 +70,7 @@ export default {
       this.entityLoading = true
       this.$refs.entityCreate.createEntity()
         .then((response) => {
-          this.$router.push({ name: 'Admin.Unit.Test.Show', params: { unit_id: this.$route.params.unit_id, id: response.data.id } })
+          this.$router.push({ name: 'Admin.Unit.TestSet.Show', params: { unit_id: this.$route.params.unit_id, id: response.data.id } })
           this.entityLoading = false
         })
         .catch(() => {

+ 52 - 0
src/models/TestSet.js

@@ -0,0 +1,52 @@
+import { Collection, Model } from 'js-abstract-model'
+
+class TestSet extends Model {
+  constructor (data) {
+    super(data, [
+      { key: 'id' },
+      { key: 'title' },
+      { key: 'description' },
+      { key: 'level' },
+      { key: 'unit' },
+      {
+        key: 'test_questions',
+        default: []
+      }
+    ], {
+      level: {
+        infoKey: 'level_info',
+        enumListKey: 'levelEnums',
+        enums: [
+          {
+            label: 'سطح یک',
+            value: 'LEVEL1'
+          },
+          {
+            label: 'سطح دو',
+            value: 'LEVEL2'
+          },
+          {
+            label: 'سطح سه',
+            value: 'LEVEL3'
+          },
+          {
+            label: 'سطح چهار',
+            value: 'LEVEL4'
+          },
+          {
+            label: 'سطح پنج',
+            value: 'LEVEL5'
+          }
+        ]
+      }
+    })
+  }
+}
+
+class TestSetList extends Collection {
+  model () {
+    return TestSet
+  }
+}
+
+export { TestSet, TestSetList }

+ 1 - 1
src/pages/Admin/Test/Create.vue

@@ -9,7 +9,7 @@
 import { mixinPageOptions } from 'src/mixin/Mixins.js'
 
 export default {
-  name: 'Admin.Unit.Test.Create',
+  name: 'Admin.Unit.TestSet.Create',
   mixins: [mixinPageOptions],
   data: () => {
     return {

+ 1 - 1
src/pages/Admin/Test/Show.vue

@@ -9,7 +9,7 @@
 import { mixinPageOptions } from 'src/mixin/Mixins.js'
 
 export default {
-  name: 'Admin.Unit.Test.Show',
+  name: 'Admin.Unit.TestSet.Show',
   mixins: [mixinPageOptions],
   data: () => {
     return {

+ 2 - 2
src/pages/Admin/Unit/show.vue

@@ -113,7 +113,7 @@
                      outline
                      label="ایجاد آزمون جدید"
                      :loading="newSessionLoading"
-                     :to="{name: 'Admin.Unit.Test.Create', params: {unit_id: $route.params.id}}" />
+                     :to="{name: 'Admin.Unit.TestSet.Create', params: {unit_id: $route.params.id}}" />
             </div>
           </template>
           <template #entity-index-table-cell="{inputData, showConfirmRemoveDialog}">
@@ -123,7 +123,7 @@
                   <q-btn size="md"
                          color="primary"
                          label="تعیین جزییات"
-                         :to="{name: 'Admin.Unit.Test.Show', params: {unit_id: $route.params.id, id: inputData.props.row.id}}" />
+                         :to="{name: 'Admin.Unit.TestSet.Show', params: {unit_id: $route.params.id, id: inputData.props.row.id}}" />
                   <delete-btn @click="showConfirmRemoveDialog(inputData.props.row, 'id', getRemoveMessage(inputData.props.row))" />
                 </div>
               </div>

+ 4 - 4
src/router/routes.js

@@ -570,12 +570,12 @@ const routes = [
                 ]
               },
               {
-                name: 'Admin.Unit.Test',
-                path: ':unit_id/tests',
+                name: 'Admin.Unit.TestSet',
+                path: ':unit_id/test_set',
                 component: () => import('src/layouts/bareLayout.vue'),
                 children: [
-                  { name: 'Admin.Unit.Test.Show', path: ':id', component: () => import('src/pages/Admin/Test/Show.vue') },
-                  { name: 'Admin.Unit.Test.Create', path: 'create', component: () => import('src/pages/Admin/Test/Create.vue') }
+                  { name: 'Admin.Unit.TestSet.Show', path: ':id', component: () => import('src/pages/Admin/Test/Show.vue') },
+                  { name: 'Admin.Unit.TestSet.Create', path: 'create', component: () => import('src/pages/Admin/Test/Create.vue') }
                 ]
               }
             ]