ClassroomShow.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. <template>
  2. <breadcrumbs style="margin-top: 29px; margin-bottom: 19px;" />
  3. <div class="flex justify-end">
  4. <q-btn flat
  5. color="grey"
  6. @click="$router.go(-1)">
  7. بازگشت
  8. >
  9. </q-btn>
  10. </div>
  11. <q-card>
  12. <q-tabs v-model="tab"
  13. dense
  14. class="text-grey"
  15. active-color="primary"
  16. indicator-color="primary"
  17. align="justify"
  18. narrow-indicator>
  19. <q-tab v-if="canShowTabPageForClassroomType('classroomInfo')"
  20. name="classroomInfo"
  21. :label="` اطلاعات ${classroomTypeTitle}`" />
  22. <q-tab v-if="canShowOtherTabsOfClassroom && canShowTabPageForClassroomType('educations')"
  23. name="educations"
  24. :label="educationsTabTitle" />
  25. <q-tab v-if="canShowOtherTabsOfClassroom && canShowTabPageForClassroomType('team')"
  26. name="team"
  27. label="گروه" />
  28. <q-tab v-if="canShowOtherTabsOfClassroom && canShowTabPageForClassroomType('exams')"
  29. name="exams"
  30. label="آزمون" />
  31. <q-tab v-if="canShowOtherTabsOfClassroom && canShowTabPageForClassroomType('projects')"
  32. name="projects"
  33. label="پروژه" />
  34. <q-tab v-if="canShowOtherTabsOfClassroom && classroom.live_streaming_url && canShowTabPageForClassroomType('live_streaming_url')"
  35. name="live_streaming_url"
  36. label="بخش آنلاین" />
  37. </q-tabs>
  38. <q-separator />
  39. <q-tab-panels v-model="tab"
  40. animated>
  41. <q-tab-panel name="classroomInfo">
  42. <show-classroom-info v-if="mounted"
  43. :options="{ profileMode: true }"
  44. :classroom-type="localOptions.classroomType"
  45. @onloadn="onloadnClassroom" />
  46. </q-tab-panel>
  47. <q-tab-panel name="educations"
  48. class="q-pa-none">
  49. <entity-index v-if="mounted"
  50. ref="entityIndex"
  51. v-model:value="sessionsInputs"
  52. :title="educationsListTitle"
  53. :api="sessionsApi"
  54. :table="sessionsTable"
  55. :table-keys="sessionsTableKeys"
  56. :table-grid-size="$q.screen.lt.sm"
  57. :show-expand-button="false"
  58. :show-reload-button="false"
  59. :show-search-button="false">
  60. <template #entity-index-table-cell="{inputData}">
  61. <template v-if="inputData.col.name === 'number'">
  62. {{ inputData.rowNumber }}
  63. </template>
  64. <template v-else-if="inputData.col.name === 'action'">
  65. <q-btn size="md"
  66. color="primary"
  67. label="جزییات"
  68. :to="{name: 'UserPanel.Profile.SessionInfo', params: {id: inputData.props.row.id}}" />
  69. </template>
  70. <template v-else>
  71. {{ inputData.col.value }}
  72. </template>
  73. </template>
  74. <template #entity-index-table-item-cell="{inputData}">
  75. <entity-index-grid-item :input-data="inputData">
  76. <template #col="{col, row}">
  77. <template v-if="col.name === 'number'">
  78. {{ inputData.rowNumber }}
  79. </template>
  80. <template v-else-if="col.name === 'action'">
  81. <q-btn size="md"
  82. color="primary"
  83. label="جزییات"
  84. :to="{name: 'UserPanel.Profile.SessionInfo', params: {id: row.id}}" />
  85. </template>
  86. </template>
  87. </entity-index-grid-item>
  88. </template>
  89. </entity-index>
  90. </q-tab-panel>
  91. <q-tab-panel name="team"
  92. class="q-pa-none">
  93. <entity-index v-if="mounted"
  94. ref="teamsList"
  95. v-model:value="teamsListInputs"
  96. title="لیست گروه ها"
  97. :api="teamsListApi"
  98. :table="teamsListTable"
  99. :table-keys="teamsListTableKeys"
  100. :show-search-button="false"
  101. :show-reload-button="false"
  102. :show-expand-button="false">
  103. <template v-slot:entity-index-table-cell="{inputData}">
  104. <template v-if="inputData.col.name === 'number'">
  105. {{ inputData.rowNumber }}
  106. </template>
  107. <template v-else-if="inputData.col.name === 'action'">
  108. <div class="action-column-entity-index">
  109. <q-btn size="md"
  110. color="primary"
  111. :flat="inputData.props.row.join_status !== 'ENABLED'"
  112. :disable="inputData.props.row.join_status !== 'ENABLED'"
  113. :label="getTeamJoinStatusLabel(inputData.props.row)"
  114. class="q-mr-md"
  115. :loading="joinTeamLoading"
  116. @click="joinTeam(inputData.props.row)" />
  117. </div>
  118. </template>
  119. <template v-else>
  120. {{ inputData.col.value }}
  121. </template>
  122. </template>
  123. </entity-index>
  124. <q-skeleton v-else
  125. type="rect"
  126. height="200px" />
  127. </q-tab-panel>
  128. <q-tab-panel name="exams">
  129. آزمون
  130. </q-tab-panel>
  131. <q-tab-panel name="projects"
  132. class="q-pa-none">
  133. <entity-index v-if="mounted"
  134. ref="projectList"
  135. v-model:value="projectListInputs"
  136. title="لیست پروژه ها"
  137. :api="projectListApi"
  138. :table="projectListTable"
  139. :table-keys="projectListTableKeys"
  140. :show-search-button="false"
  141. :show-reload-button="false"
  142. :show-expand-button="false">
  143. <template v-slot:entity-index-table-cell="{inputData}">
  144. <template v-if="inputData.col.name === 'number'">
  145. {{ inputData.rowNumber }}
  146. </template>
  147. <template v-else-if="inputData.col.name === 'actions'">
  148. <div class="action-column-entity-index">
  149. <q-btn size="md"
  150. color="primary"
  151. label="جزییات"
  152. :to="{name: 'UserPanel.Profile.Classroom.Project.Show', params: {classroom_id: $route.params.id, project_id: inputData.props.row.id}}"
  153. class="q-mr-md" />
  154. </div>
  155. </template>
  156. <template v-else>
  157. {{ inputData.col.value }}
  158. </template>
  159. </template>
  160. </entity-index>
  161. <q-skeleton v-else
  162. type="rect"
  163. height="200px" />
  164. </q-tab-panel>
  165. <q-tab-panel v-if="classroom.live_streaming_url"
  166. name="live_streaming_url">
  167. <q-btn class="full-width q-mb-lg"
  168. color="primary"
  169. @click="goToLiveStreamUrl">
  170. رفتن به کلاس
  171. </q-btn>
  172. <q-banner>
  173. <div class="q-mb-md">
  174. نام کاربری اسکای روم:
  175. {{ user.national_code }}
  176. </div>
  177. <div>
  178. کلمه عبور اسکای روم:
  179. 1234
  180. </div>
  181. </q-banner>
  182. <iframe :src="classroom.live_streaming_url"
  183. title="W3Schools Free Online Web Tutorials"
  184. style="height: 80vh"
  185. class="full-width" />
  186. </q-tab-panel>
  187. </q-tab-panels>
  188. </q-card>
  189. </template>
  190. <script>
  191. import { EntityIndex } from 'quasar-crud'
  192. import { Team } from 'src/models/Team.js'
  193. import ShamsiDate from 'src/assets/ShamsiDate.js'
  194. import { APIGateway } from 'src/api/APIGateway.js'
  195. import { Classroom } from 'src/models/Classroom.js'
  196. import { mixinAuth, mixinWidget } from 'src/mixin/Mixins.js'
  197. import EntityIndexGridItem from 'src/components/EntityIndexGridItem.vue'
  198. import { Registration, RegistrationList } from 'src/models/Registration.js'
  199. import Breadcrumbs from 'src/components/Widgets/Breadcrumbs/Breadcrumbs.vue'
  200. import { ProjectAttendanceSheets } from 'src/models/ProjectAttendanceSheets.js'
  201. import { SessionAttendanceSheets } from 'src/models/SessionAttendanceSheets.js'
  202. import ShowClassroomInfo from 'src/components/Widgets/Other/ShowClassroomInfo/ShowClassroomInfo.vue'
  203. export default {
  204. name: 'ClassroomShow',
  205. components: {
  206. EntityIndex,
  207. Breadcrumbs,
  208. ShowClassroomInfo,
  209. EntityIndexGridItem
  210. },
  211. mixins: [mixinAuth, mixinWidget],
  212. data () {
  213. const classroomId = this.$route.params.id
  214. // const userId = this.$store.getters['Auth/user'].id
  215. return {
  216. mounted: false,
  217. tab: 'classroomInfo',
  218. inputs: [],
  219. sessionsInputs: [
  220. { type: 'hidden', name: 'classroom', value: classroomId }
  221. ],
  222. defaultOptions: {
  223. classroomType: 'TRAINING'
  224. },
  225. api: APIGateway.classroom.get(classroomId),
  226. sessionsApi: APIGateway.session.APIAdresses.attendanceSheets,
  227. classroom: new Classroom(),
  228. table: {
  229. columns: [
  230. {
  231. name: 'number',
  232. required: true,
  233. label: 'شماره',
  234. align: 'left',
  235. field: () => ''
  236. },
  237. {
  238. name: 'id',
  239. required: true,
  240. label: 'شناسه',
  241. align: 'left',
  242. field: row => row.id
  243. },
  244. {
  245. name: 'title',
  246. required: true,
  247. label: 'عنوان',
  248. align: 'left',
  249. field: row => row.title
  250. },
  251. {
  252. name: 'beginning_time',
  253. required: true,
  254. label: 'زمان شروع',
  255. align: 'left',
  256. field: row => row.beginning_time ? ShamsiDate.getDateTime(row.beginning_time) : '-'
  257. },
  258. {
  259. name: 'ending_time',
  260. required: true,
  261. label: 'زمان پایان',
  262. align: 'left',
  263. field: row => row.ending_time ? ShamsiDate.getDateTime(row.ending_time) : '-'
  264. },
  265. {
  266. name: 'action',
  267. required: true,
  268. label: 'جزییات',
  269. align: 'left',
  270. field: ''
  271. }
  272. ]
  273. },
  274. sessionsTable: {
  275. columns: [
  276. {
  277. name: 'number',
  278. required: true,
  279. label: 'شماره',
  280. align: 'left',
  281. field: () => ''
  282. },
  283. {
  284. name: 'id',
  285. required: true,
  286. label: 'شناسه',
  287. align: 'left',
  288. field: row => row.id
  289. },
  290. {
  291. name: 'title',
  292. required: true,
  293. label: 'عنوان',
  294. align: 'left',
  295. field: row => row.title
  296. },
  297. {
  298. name: 'beginning_time',
  299. required: true,
  300. label: 'زمان شروع',
  301. align: 'left',
  302. field: row => row.beginning_time ? ShamsiDate.getDateTime(row.beginning_time) : '-'
  303. },
  304. {
  305. name: 'ending_time',
  306. required: true,
  307. label: 'زمان پایان',
  308. align: 'left',
  309. field: row => row.ending_time ? ShamsiDate.getDateTime(row.ending_time) : '-'
  310. },
  311. {
  312. name: 'assignment_status',
  313. required: true,
  314. label: 'وضعیت تکلیف',
  315. align: 'left',
  316. field: row => (new SessionAttendanceSheets(this.getCurrentUserAttendanceSheet(row))).assignment_status_info.label
  317. },
  318. {
  319. name: 'attendance_status',
  320. required: true,
  321. label: 'وضعیت حضور و غیاب',
  322. align: 'left',
  323. field: row => (new SessionAttendanceSheets(this.getCurrentUserAttendanceSheet(row))).attendance_status_info.label
  324. },
  325. {
  326. name: 'action',
  327. required: true,
  328. label: 'جزییات',
  329. align: 'left',
  330. field: ''
  331. }
  332. ]
  333. },
  334. sessionsTableKeys: {
  335. data: 'results',
  336. total: 'count',
  337. currentPage: 'current',
  338. perPage: 'per_page',
  339. pageKey: 'page'
  340. },
  341. tableKeys: {
  342. data: 'results',
  343. total: 'count',
  344. currentPage: 'current',
  345. perPage: 'per_page',
  346. pageKey: 'page'
  347. },
  348. projectListInputs: [
  349. { type: 'hidden', name: 'classroom', value: classroomId }
  350. // { type: 'hidden', name: 'owner', value: userId }
  351. ],
  352. // projectListApi: APIGateway.projectAttendanceSheets.APIAdresses.base,
  353. projectListApi: APIGateway.project.APIAdresses.attendanceSheetsList,
  354. projectListTable: {
  355. columns: [
  356. {
  357. name: 'number',
  358. required: true,
  359. label: 'شماره',
  360. align: 'left',
  361. field: () => ''
  362. },
  363. {
  364. name: 'id',
  365. required: true,
  366. label: 'شناسه',
  367. align: 'left',
  368. field: row => row.id
  369. },
  370. {
  371. name: 'title',
  372. required: true,
  373. label: 'عنوان پروژه',
  374. align: 'left',
  375. field: row => row.title
  376. },
  377. {
  378. name: 'creation_time',
  379. required: true,
  380. label: 'زمان شروع',
  381. align: 'left',
  382. field: row => row?.beginning_doing_period ? ShamsiDate.getDateTime(row.beginning_doing_period) : '-'
  383. },
  384. {
  385. name: 'creation_time',
  386. required: true,
  387. label: 'زمان پایان',
  388. align: 'left',
  389. field: row => row?.ending_doing_period ? ShamsiDate.getDateTime(row.ending_doing_period) : '-'
  390. },
  391. {
  392. name: 'status',
  393. required: true,
  394. label: 'وضعیت',
  395. align: 'left',
  396. field: row => (new ProjectAttendanceSheets(this.getProjectAttendanceSheets(row))).answer_status_info.label
  397. },
  398. {
  399. name: 'actions',
  400. required: true,
  401. label: 'عملیات',
  402. align: 'left',
  403. field: ''
  404. }
  405. ]
  406. },
  407. projectListTableKeys: {
  408. data: 'results',
  409. total: 'count',
  410. currentPage: 'current',
  411. perPage: 'per_page',
  412. pageKey: 'page'
  413. },
  414. registrations: new RegistrationList(),
  415. classroomRegistration: new Registration(),
  416. joinTeamLoading: false,
  417. teamsListInputs: [
  418. { type: 'hidden', name: 'classroom', value: classroomId }
  419. ],
  420. teamsListApi: APIGateway.team.APIAdresses.classroomTeamsWithJoinStatus,
  421. teamsListTable: {
  422. columns: [
  423. {
  424. name: 'number',
  425. required: true,
  426. label: 'شماره',
  427. align: 'left',
  428. field: () => ''
  429. },
  430. {
  431. name: 'id',
  432. required: true,
  433. label: 'شناسه',
  434. align: 'left',
  435. field: row => row.id
  436. },
  437. {
  438. name: 'title',
  439. required: true,
  440. label: 'عنوان گروه',
  441. align: 'left',
  442. field: row => row.title
  443. },
  444. {
  445. name: 'leader_info',
  446. required: true,
  447. label: 'سرگروه',
  448. align: 'left',
  449. field: row => row.leader_info?.firstname + ' ' + row.leader_info?.lastname
  450. },
  451. {
  452. name: 'used_capacity',
  453. required: true,
  454. label: 'ظرفیت استفاده شده',
  455. align: 'left',
  456. field: row => row.used_capacity
  457. },
  458. {
  459. name: 'capacity',
  460. required: true,
  461. label: 'ظرفیت',
  462. align: 'left',
  463. field: row => row.capacity
  464. },
  465. {
  466. name: 'action',
  467. required: true,
  468. label: ' ',
  469. align: 'left',
  470. field: ''
  471. }
  472. ],
  473. data: []
  474. },
  475. teamsListTableKeys: {
  476. data: 'results',
  477. total: 'count',
  478. currentPage: 'current',
  479. perPage: 'per_page',
  480. pageKey: 'page'
  481. }
  482. }
  483. },
  484. computed: {
  485. classroomTypeTitle () {
  486. if (this.localOptions.classroomType === 'TRAINING') {
  487. return 'دوره'
  488. }
  489. if (this.localOptions.classroomType === 'EVENT') {
  490. return 'رویداد'
  491. }
  492. return 'دوره'
  493. },
  494. listTitle () {
  495. if (this.localOptions.classroomType === 'TRAINING') {
  496. return 'لیست دوره های آموزشی'
  497. }
  498. if (this.localOptions.classroomType === 'EVENT') {
  499. return 'لیست رویدادها'
  500. }
  501. return 'لیست دوره های آموزشی'
  502. },
  503. educationsListTitle () {
  504. if (this.localOptions.classroomType === 'TRAINING') {
  505. return 'لیست جلسات'
  506. }
  507. if (this.localOptions.classroomType === 'EVENT') {
  508. return 'لیست برنامه ها'
  509. }
  510. return 'لیست جلسات'
  511. },
  512. educationsTabTitle () {
  513. if (this.localOptions.classroomType === 'TRAINING') {
  514. return 'جدول آموزشی'
  515. }
  516. if (this.localOptions.classroomType === 'EVENT') {
  517. return 'لیست برنامه ها'
  518. }
  519. return 'جدول آموزشی'
  520. },
  521. canShowTabPageForClassroomType () {
  522. return (tabName) => {
  523. const tabs = {
  524. TRAINING: [
  525. 'classroomInfo',
  526. 'educations',
  527. 'team',
  528. 'exams',
  529. 'projects',
  530. 'live_streaming_url'
  531. ],
  532. EVENT: [
  533. 'classroomInfo',
  534. 'educations',
  535. 'live_streaming_url'
  536. ]
  537. }
  538. return tabs[this.localOptions.classroomType].includes(tabName)
  539. }
  540. },
  541. classroomId () {
  542. return this.$route.params.id
  543. },
  544. canShowOtherTabsOfClassroom () {
  545. return !this.classroomRegistration.loading && (this.classroomRegistration.status === 'REGISTERED' || this.classroomRegistration.status === 'ENROLLED')
  546. }
  547. },
  548. mounted () {
  549. this.getRegistrationInfo()
  550. this.mounted = true
  551. },
  552. methods: {
  553. getTeamJoinStatusLabel (team) {
  554. if (team.join_status === 'ENABLED') {
  555. return 'عضو شوید'
  556. }
  557. return (new Team(team)).join_status_info.label
  558. },
  559. joinTeam (team) {
  560. this.joinTeamLoading = true
  561. APIGateway.team.register(team.id)
  562. .then(() => {
  563. this.joinTeamLoading = false
  564. this.$refs.teamsList.search()
  565. })
  566. .catch(() => {
  567. this.joinTeamLoading = false
  568. this.$refs.teamsList.search()
  569. })
  570. },
  571. getRegistrationInfo () {
  572. this.registrations.loading = true
  573. this.classroomRegistration.loading = true
  574. APIGateway.registration.index({ classroom: this.$route.params.id })
  575. .then(({ list }) => {
  576. this.registrations = new RegistrationList(list)
  577. if (this.registrations.list.length > 0) {
  578. this.classroomRegistration = this.registrations.list[0]
  579. }
  580. this.registrations.loading = false
  581. this.classroomRegistration.loading = false
  582. })
  583. .catch(() => {
  584. this.registrations.loading = false
  585. this.classroomRegistration.loading = false
  586. })
  587. },
  588. getCurrentUserAttendanceSheet (session) {
  589. if (!session?.session_attendance_sheets || session.session_attendance_sheets.length === 0) {
  590. return null
  591. }
  592. return session.session_attendance_sheets[0]
  593. },
  594. getProjectAttendanceSheets (project) {
  595. if (!project?.project_attendance_sheets || project.project_attendance_sheets.length === 0) {
  596. return null
  597. }
  598. return project.project_attendance_sheets[0]
  599. },
  600. goToLiveStreamUrl () {
  601. window.open(this.classroom.live_streaming_url, '_blank')
  602. },
  603. onloadnClassroom (classroom) {
  604. this.classroom = new Classroom(classroom)
  605. this.$store.commit('AppLayout/updateBreadcrumbs', {
  606. visible: true,
  607. loading: false,
  608. path: [
  609. {
  610. label: this.classroomTypeTitle + 'های من',
  611. to: { name: this.localOptions.classroomType === 'TRAINING' ? 'UserPanel.Profile.AllClassrooms' : 'UserPanel.Profile.AllEvents' }
  612. },
  613. {
  614. label: this.classroom.title,
  615. to: { name: 'UserPanel.Profile.ClassroomInfo', params: { id: this.classroom.id } }
  616. }
  617. ]
  618. })
  619. }
  620. }
  621. }
  622. </script>