ali 3 years ago
parent
commit
d481567dbd

BIN
public/assets/images/web/default-avatar.png


+ 2 - 0
src/api/APIGateway.js

@@ -12,6 +12,7 @@ import TransactionAPI from 'src/api/models/Transaction.js'
 import PageSettingAPI from 'src/api/models/PageSetting.js'
 import RegistrationAPI from 'src/api/models/Registration.js'
 import UnitCategoryAPI from 'src/api/models/UnitCategory.js'
+import TicketCategoryAPI from 'src/api/models/TicketCategory.js'
 import SessionTemplateAPI from 'src/api/models/SessionTemplate.js'
 import ClassroomRegistrationAPI from 'src/api/models/ClassroomRegistration.js'
 
@@ -31,6 +32,7 @@ export const APIGateway = {
   pageSetting: new PageSettingAPI(),
   registration: new RegistrationAPI(),
   unitCategory: new UnitCategoryAPI(),
+  ticketCategory: new TicketCategoryAPI(),
   sessionTemplate: new SessionTemplateAPI(),
   classroomRegistration: new ClassroomRegistrationAPI()
 }

+ 1 - 1
src/api/models/Ticket.js

@@ -1,4 +1,4 @@
-import { appApi } from 'src/boot/axios'
+import { appApi } from 'src/boot/axios.js'
 import APIRepository from '../classes/APIRepository.js'
 import { Ticket, TicketList } from 'src/models/Ticket.js'
 

+ 70 - 0
src/api/models/TicketCategory.js

@@ -0,0 +1,70 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+import { Ticket, TicketList } from 'src/models/Ticket.js'
+import { TicketCategory } from 'src/models/TicketCategory.js'
+
+export default class TicketCategoryAPI extends APIRepository {
+  constructor() {
+    super('ticketCategories', appApi)
+    this.APIAdresses = {
+      base: '/mma/categories',
+      byId: (id) => '/mma/categories/' + id
+    }
+    this.restUrl = (id) => this.url + '/' + id
+    /* Setting the callback functions for the CRUD operations. */
+    this.setCrudCallbacks({
+      get: (response) => { return new TicketCategory(response.data) },
+      post: (response) => { return new TicketCategory(response.data) },
+      put: (response) => { return new TicketCategory(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 TicketList(results),
+          paginate
+          // {
+          //   "count": 1,
+          //   "num_pages": 1,
+          //   "per_page": 10,
+          //   "current": 1,
+          //   "next": null,
+          //   "previous": null,
+          // }
+        }
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
+  reply(data) {
+    return this.sendRequest({
+      apiMethod: 'put',
+      api: this.api,
+      request: this.APIAdresses.reply(data.id),
+      data: this.getNormalizedSendData({
+        body: '' // String
+      }, data),
+      resolveCallback: (response) => {
+        return new Ticket(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+}

+ 1 - 2
src/components/Template/SideBard/UserPanelSideBar.vue

@@ -83,8 +83,7 @@ export default {
         },
         {
           title: 'درخواست ها',
-          // routeName: 'Admin.User.Index',
-          scrollTo: '#introSection',
+          routeName: 'UserPanel.Ticket.List',
           show: true,
           active: false
         },

+ 2 - 2
src/components/Widgets/Ticket/TicketCreate/TicketCreate.vue

@@ -56,8 +56,8 @@ export default {
       api: APIGateway.ticket.APIAdresses.base,
       entityIdKeyInResponse: 'id',
       showRouteParamKey: 'id',
-      showRouteName: 'AdminPanel.Ticket.Show',
-      indexRouteName: 'AdminPanel.Ticket.List',
+      showRouteName: 'UserPanel.Ticket.Show',
+      indexRouteName: 'UserPanel.Ticket.List',
       inputs: [
         { type: 'select', name: 'category', responseKey: 'category', options: [], label: 'دسته', col: 'col-md-12 col-12' },
         { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان', col: 'col-md-12 col-12' },

+ 31 - 60
src/components/Widgets/Ticket/TicketList/TicketList.vue

@@ -1,43 +1,34 @@
 <template>
   <div class="TicketList"
        :style="localOptions.style">
-    <div class="title">
-      پیام‌های دریافتی
-      <div class="back-action">
-        <q-btn flat
-               :to="{name: 'UserPanel.Ticket.Create'}"
-               color="grey">
-          ارسال پیام جدید
-        </q-btn>
-      </div>
+    <div class="more-action">
+      <q-btn label="ایجاد درخواست"
+             color="primary"
+             :to="{name: 'UserPanel.Ticket.Create'}" />
     </div>
-    <q-card class="list"
-            flat>
-      <entity-index v-if="mounted"
-                    v-model:value="inputs"
-                    title=""
-                    :api="api"
-                    :table="table"
-                    :table-keys="tableKeys"
-                    :create-route-name="createRouteName"
-                    :show-search-button="false"
-                    :show-expand-button="false"
-                    :show-reload-button="false"
-                    :default-layout="false">
-        <template #entity-index-table-cell="{inputData}">
-          <template v-if="inputData.col.name === 'action'">
-            <q-btn flat
-                   color="primary"
-                   :to="{name: 'UserPanel.Ticket.Show', params: {id: inputData.props.row.id}}">
-              مشاهده جزییات
-            </q-btn>
-          </template>
-          <template v-else>
-            {{ inputData.col.value }}
-          </template>
+    <entity-index v-if="mounted"
+                  ref="entityIndex"
+                  v-model:value="inputs"
+                  title="لیست درخواست ها"
+                  :api="api"
+                  :table="table"
+                  :table-keys="tableKeys"
+                  :create-route-name="createRouteName"
+                  :show-search-button="false"
+                  :show-expand-button="false"
+                  :show-reload-button="false">
+      <template #entity-index-table-cell="{inputData}">
+        <template v-if="inputData.col.name === 'action'">
+          <q-btn color="primary"
+                 :to="{name: 'UserPanel.Ticket.Show', params: {id: inputData.props.row.id}}">
+            مشاهده جزییات
+          </q-btn>
         </template>
-      </entity-index>
-    </q-card>
+        <template v-else>
+          {{ inputData.col.value }}
+        </template>
+      </template>
+    </entity-index>
   </div>
 </template>
 
@@ -106,31 +97,11 @@ export default {
 
 <style scoped lang="scss">
 .TicketList {
-  .title {
-    font-style: normal;
-    font-weight: 700;
-    font-size: 24px;
-    line-height: 140%;
-    color: #424242;
-    margin-bottom: 27px;
-    .back-action {
-      position: absolute;
-      right: 0;
-      top: 0;
-    }
-  }
-  :deep(.list) {
-    .quasar-crud-index-table {
-      padding: 0;
-      .q-table__container {
-        background-color: transparent;
-        box-shadow: none;
-        border: none;
-        .q-table__top {
-          display: none;
-        }
-      }
-    }
+  .more-action {
+    display: flex;
+    flex-flow: row;
+    justify-content: flex-end;
+    margin-bottom: 10px;
   }
 }
 </style>

+ 9 - 5
src/components/Widgets/Ticket/TicketShow/TicketShow.vue

@@ -12,7 +12,7 @@
                       width="100px" />
         </template>
         <template v-else>
-          {{ packageTitle }}
+          ({{ ticketTitle }})
         </template>
       </div>
       <div class="back-action">
@@ -50,9 +50,10 @@
             <div style="width: 100%;">
               <q-chat-message v-for="message in repliesInfo"
                               :key="message.id"
-                              :avatar="message.creator_info.picture ? message.creator_info.picture : 'assets/images/web/sample-avatar.svg'"
+                              :avatar="message.creator_info.picture ? message.creator_info.picture : '/assets/images/web/default-avatar.png'"
                               :name="message.creator_info.firstname + ' ' + message.creator_info.lastname"
                               :text="[message.body]"
+                              text-html
                               :sent="authenticatedUser.id !== message.creator_info.id" />
               <!--                  <div>-->
               <!--                    <q-input v-model="replyBody"-->
@@ -115,7 +116,7 @@ export default {
       replyText: null,
       mounted: false,
       entityLoading: true,
-      packageTitle: '',
+      ticketTitle: '',
       authenticatedUser: new User(),
       api: APIGateway.ticket.APIAdresses.base,
       ticketCategoryList: new TicketCategoryList(),
@@ -195,18 +196,21 @@ export default {
     loadAuthData () {
       this.authenticatedUser = this.$store.getters['Auth/user']
     },
-    afterLoadInputData () {
+    afterLoadInputData (response) {
+      this.ticketTitle = response.title
       this.entityLoading = false
     },
     sendReply() {
       this.entityLoading = true
+      const body = this.replyText.replace(/\n/g, '<br>\n')
       APIGateway.ticket.reply({
         id: this.$route.params.id,
-        body: this.replyText
+        body
       })
         .then(() => {
           this.$refs.entityShow.editEntity()
             .then(() => {
+              this.replyText = null
               this.$refs.entityShow.getData()
               this.entityLoading = false
             })

+ 8 - 0
src/css/Theme/quasar-crud/input.scss

@@ -22,4 +22,12 @@
       }
     }
   }
+  &.q-textarea {
+    .q-field__inner {
+      .q-field__control {
+        height: auto;
+        min-height: 48px;
+      }
+    }
+  }
 }

+ 1 - 1
src/pages/User/Ticket/Create.vue

@@ -13,7 +13,7 @@ export default {
   mixins: [mixinPageOptions],
   data: () => {
     return {
-      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'TicketCreate' }], options: { style: { marginTop: '124px' } } }], options: {} }] } }]
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'TicketCreate' }], options: { style: { marginTop: '124px' } } }], options: { className: '', height: 'auto', boxed: true, boxedWidth: 1200, gutterXSize: 'md', gutterYSize: 'md', absolute: 'none', paddingOfBoxedInFullWidth: '30px', style: { maxWidth: '1200px', width: '1200px' } } }] } }]
     }
   },
   created() {

+ 1 - 1
src/pages/User/Ticket/Show.vue

@@ -13,7 +13,7 @@ export default {
   mixins: [mixinPageOptions],
   data: () => {
     return {
-      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'TicketShow' }], options: { style: { paddingTop: '124px' } } }], options: {} }] } }]
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'TicketShow' }], options: { style: { paddingTop: '124px', paddingBottom: '100px' } } }], options: { className: '', height: 'auto', boxed: true, boxedWidth: 1200, gutterXSize: 'md', gutterYSize: 'md', absolute: 'none', paddingOfBoxedInFullWidth: '30px', style: { maxWidth: '1200px', width: '1200px' } } }] } }]
     }
   },
   created() {