WorkOrder.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <template>
  2. <div class="container-fluid">
  3. <div class="row my-3">
  4. <div class="col-lg-6">
  5. <div class="card h-100">
  6. <div class="card-header text-right">
  7. <button type="button" class="btn btn-default xs-toggle" data-toggle="collapse" data-target="#assetTab">
  8. <span class="sr-only">Toggle Navigation</span>
  9. <span class="icon-bar"></span>
  10. <span class="icon-bar"></span>
  11. <span class="icon-bar"></span>
  12. </button>
  13. <ul class="nav nav-pills card-header-pills nav-justified xs-collapse collapse" id="assetTab" role="tablist">
  14. <li class="nav-item">
  15. <a class="nav-link active" id="assetinfo-tab" data-toggle="pill" href="#assetinfo" role="tab" aria-controls="assetinfo" aria-selected="true">Hardware</a>
  16. </li>
  17. <!-- @if($workOrder->asset->group !== null)
  18. <li class="nav-item">
  19. <a class="nav-link" id="group-tab" data-toggle="pill" href="#group" role="tab" aria-controls="group" aria-selected="false">Group</a>
  20. </li>
  21. @endif -->
  22. <li class="nav-item">
  23. <a class="nav-link" id="credentials-tab" data-toggle="pill" href="#credentials" role="tab" aria-controls="credentials" aria-selected="false">Credentials</a>
  24. </li>
  25. </ul>
  26. </div>
  27. <div class="card-body">
  28. <div class="tab-content">
  29. <div class="tab-pane active" id="assetinfo" role="tabpanel" aria-labelledby="assetinfo-tab">
  30. <asset-info v-if="!assetLoading" :asset="asset"></asset-info>
  31. <circle-spinner v-else :color="'#663399'"></circle-spinner>
  32. </div>
  33. <!-- @if($workOrder->asset->group !== null)
  34. <div class="tab-pane" id="group" role="tabpanel" aria-labelledby="group-tab">
  35. Name: {{$workOrder->asset->group->pcgroupname}}
  36. </div>
  37. @endif -->
  38. <div class="tab-pane" id="credentials" role="tabpanel" aria-labelledby="credentials-tab">
  39. <credential-list v-if="!credentialsLoading && !credentialDescriptionsLoading" :credentials="credentials" :descriptions="credentialDescriptions" :pcid="asset.pcid"></credential-list>
  40. <circle-spinner v-else color="#663399"></circle-spinner>
  41. </div>
  42. </div>
  43. </div>
  44. </div>
  45. </div>
  46. <div class="col-lg-6">
  47. <div class="card h-100">
  48. <div class="card-header text-right">
  49. <button type="button" class="btn btn-default xs-toggle" data-toggle="collapse" data-target="#workorderTab">
  50. <span class="sr-only">Toggle Navigation</span>
  51. <span class="icon-bar"></span>
  52. <span class="icon-bar"></span>
  53. <span class="icon-bar"></span>
  54. </button>
  55. <ul class="nav nav-pills card-header-pills nav-justified xs-collapse collapse" id="workorderTab" role="tablist">
  56. <li class="nav-item">
  57. <a class="nav-link active" id="workordersumm-tab" data-toggle="pill" href="#workordersumm" role="tab" aria-controls="workordersumm" aria-selected="true">Summary</a>
  58. </li>
  59. <li class="nav-item">
  60. <a class="nav-link" id="attachments-tab" data-toggle="pill" href="#attachments" role="tab" aria-controls="attachments" aria-selected="false">Attachments</a>
  61. </li>
  62. </ul>
  63. </div>
  64. <div class='card-body'>
  65. <div class='tab-content'>
  66. <div class="tab-pane active" id="workordersumm" role="tabpanel" aria-labelledby="workordersumm-tab">
  67. <work-order-info v-if="!woLoading && !storesLoading" :work-order="workOrder" :stores="stores"></work-order-info>
  68. <circle-spinner v-else :color="'#663399'"></circle-spinner>
  69. </div>
  70. <div class="tab-pane" id="attachments" role="tabpanel" aria-labelledby="attachments-tab">
  71. TODO 2
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. <div class="row my-3 no-gutters">
  79. <div class="col-12">
  80. <div class="card">
  81. <div class="card-body">
  82. <h5 class="card-title">Customer Notes</h5>
  83. <notes v-if="!workOrderNotesLoading" :notes="publicNotes" :authusername="authUser" :note-type="0" :woid="id"></notes>
  84. <circle-spinner v-else color="#663399"></circle-spinner>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. <div class="row my-3 no-gutters">
  90. <div class="col-12">
  91. <div class="card">
  92. <div class="card-body">
  93. <h5 class="card-title">Private/Billing Notes</h5>
  94. <notes v-if="!workOrderNotesLoading" :notes="privateNotes" :authusername="authUser" :note-type="1" :woid="id"></notes>
  95. <circle-spinner v-else color="#663399"></circle-spinner>
  96. </div>
  97. </div>
  98. </div>
  99. </div>
  100. </div>
  101. </template>
  102. <script>
  103. import WorkOrderInfo from '../components/WorkOrderInfo.vue'
  104. import AssetInfo from '../components/AssetInfo.vue'
  105. import CircleSpinner from '../components/CircleSpinner.vue'
  106. import CredentialList from '../components/CredentialList.vue'
  107. import Notes from '../components/Notes.vue'
  108. export default {
  109. components: {
  110. WorkOrderInfo,
  111. AssetInfo,
  112. CircleSpinner,
  113. CredentialList,
  114. Notes,
  115. },
  116. props: {
  117. id: {
  118. type: String,
  119. required: true,
  120. }
  121. },
  122. data () {
  123. return {
  124. workOrder: {},
  125. asset: {},
  126. stores: {},
  127. credentials: {},
  128. credentialDescriptions: {},
  129. workOrderNotes: [],
  130. woLoading: true,
  131. assetLoading: true,
  132. storesLoading: true,
  133. credentialsLoading: true,
  134. credentialDescriptionsLoading: true,
  135. workOrderNotesLoading: true,
  136. authUser: localStorage.getItem('user'),
  137. }
  138. },
  139. computed: {
  140. publicNotes: function() {
  141. let notes = []
  142. notes = this.workOrderNotes.filter(note => note.notetype === 0)
  143. return notes
  144. },
  145. privateNotes: function() {
  146. let notes = []
  147. notes = this.workOrderNotes.filter(note => note.notetype === 1)
  148. return notes
  149. }
  150. },
  151. mounted () {
  152. // Get authentication info from current user from local storage
  153. let token = localStorage.getItem('jwt')
  154. let user = localStorage.getItem('user')
  155. // Set some axios config options for Content-Type and Authentication.
  156. axios.defaults.headers.common['Content-Type'] = 'application/json'
  157. axios.defaults.headers.common['Authorization'] = 'Bearer ' + token
  158. // Get WorkOrder from API
  159. axios.get('/api/workorders/'+this.id).then(response => {
  160. this.workOrder = response.data
  161. this.woLoading = false
  162. }).catch(error => {
  163. console.log(error)
  164. })
  165. // Get list of stores from API
  166. axios.get('/api/stores/').then(response => {
  167. this.stores = response.data
  168. this.storesLoading = false
  169. }).catch(error => {
  170. console.log(error)
  171. })
  172. // Get Asset from API (will most likely be replaced with list of assets
  173. // in the future. Current each WO can only have one but that is likely
  174. // to change)
  175. axios.get(`/api/workorders/${this.id}/asset`).then(response => {
  176. this.asset = response.data
  177. this.assetLoading = false
  178. // Get Credentials for this asset. May be relocated to be part of asset
  179. // Component when WOs can have more than one asset.
  180. axios.get(`/api/assets/${this.asset.pcid}/credentials`).then (response => {
  181. this.credentials = response.data
  182. this.credentialsLoading = false
  183. }).catch(error => {
  184. console.log(error)
  185. })
  186. // Get default list of Credential Descriptions. May be relocated along with
  187. // the above.
  188. axios.get('/api/credentials/descriptions').then(response => {
  189. this.credentialDescriptions = response.data
  190. this.credentialDescriptionsLoading = false
  191. }).catch(error => {
  192. console.log(error)
  193. })
  194. }).catch(error => {
  195. console.log(error)
  196. })
  197. axios.get(`/api/workorders/${this.id}/notes`).then(response => {
  198. this.workOrderNotes = response.data
  199. this.workOrderNotesLoading = false
  200. }).catch(error => {
  201. console.log(error)
  202. })
  203. Echo.channel('work-order.'+this.id)
  204. .listen('WorkOrderUpdated', (e) => {
  205. this.workOrder = e.data;
  206. });
  207. Echo.channel('wonotes.'+this.id)
  208. .listen('WorkOrderNoteAdded', (e) => {
  209. this.workOrderNotes.push(e.note)
  210. })
  211. .listen('WorkOrderNoteUpdated', (e) => {
  212. let index = this.workOrderNotes.findIndex((note) => {
  213. return note.noteid === e.note.noteid
  214. })
  215. // Note has to be edited this way, or else Vue cannot
  216. // see it to recompute the computed values.
  217. this.workOrderNotes.splice(index, 1, e.note)
  218. })
  219. .listen('WorkOrderNoteDeleted', (e) => {
  220. let index = this.notes.findIndex((note) => {
  221. return note.noteid === e.noteid
  222. })
  223. this.notes.splice(index, 1)
  224. })
  225. },
  226. }
  227. </script>