3 Achegas bc7227bce3 ... 20724da7f8

Autor SHA1 Mensaxe Data
  Christopher Leggett 20724da7f8 Implements credential edit and live-update. %!s(int64=5) %!d(string=hai) anos
  Christopher Leggett 0710c41712 Adds credential edit modal and random password generator. %!s(int64=5) %!d(string=hai) anos
  Christopher Leggett 5443878823 Improves store name display code. %!s(int64=5) %!d(string=hai) anos

+ 39 - 0
app/Events/CredentialUpdated.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Events;
+
+use Illuminate\Broadcasting\Channel;
+use Illuminate\Broadcasting\InteractsWithSockets;
+use Illuminate\Broadcasting\PresenceChannel;
+use Illuminate\Broadcasting\PrivateChannel;
+use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
+use Illuminate\Foundation\Events\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+use App\Credential;
+
+class CredentialUpdated implements ShouldBroadcast
+{
+    use Dispatchable, InteractsWithSockets, SerializesModels;
+
+    public $data;
+
+    /**
+     * Create a new event instance.
+     *
+     * @return void
+     */
+    public function __construct($credential)
+    {
+        $this->data = $credential->toJson();
+    }
+
+    /**
+     * Get the channels the event should broadcast on.
+     *
+     * @return \Illuminate\Broadcasting\Channel|array
+     */
+    public function broadcastOn()
+    {
+        return new Channel('credentials');
+    }
+}

+ 69 - 0
app/Http/Controllers/Api/CredentialsController.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Credential;
+use App\Http\Controllers\Controller;
+use Illuminate\Http\Request;
+
+class CredentialsController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\Credential  $credential
+     * @return \Illuminate\Http\Response
+     */
+    public function show(Credential $credential)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Credential  $credential
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, Credential $credential)
+    {
+        $credential->creduser = $request->input('creduser');
+        $credential->credpass = $request->input('credpass');
+        $credential->save();
+        event(new \App\Events\CredentialUpdated($credential));
+        return response()->json($credential, 200);
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Credential  $credential
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(Credential $credential)
+    {
+        //
+    }
+}

+ 257 - 83
public/js/app.js

@@ -2063,6 +2063,27 @@ __webpack_require__.r(__webpack_exports__);
 //
 //
 //
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
 /* harmony default export */ __webpack_exports__["default"] = ({
   props: ['credential'],
   data: function data() {
@@ -2076,6 +2097,27 @@ __webpack_require__.r(__webpack_exports__);
     Echo.channel('credentials').listen('CredentialUpdated', function (e) {
       _this.data = JSON.parse(e.data);
     });
+  },
+  methods: {
+    rndStr: function rndStr(len) {
+      var text = "";
+      var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%";
+
+      for (var i = 0; i < len; i++) {
+        text += chars.charAt(Math.floor(Math.random() * chars.length));
+      }
+
+      return text;
+    },
+    getRandomPassword: function getRandomPassword() {
+      this.data.credpass = this.rndStr(16);
+    },
+    updateCredential: function updateCredential() {
+      axios.put('/api/credentials/' + this.data.credid, this.data).then(function (response) {})["catch"](function (error) {
+        console.error(error);
+      });
+      $('#credential' + this.data.credid + 'editModal').modal('hide');
+    }
   }
 });
 
@@ -2192,7 +2234,6 @@ __webpack_require__.r(__webpack_exports__);
   data: function data() {
     return {
       data: JSON.parse(this.workOrder),
-      storeName: null,
       storeList: null
     };
   },
@@ -2201,28 +2242,20 @@ __webpack_require__.r(__webpack_exports__);
 
     Echo.channel('work-orders').listen('WorkOrderUpdated', function (e) {
       _this.data = JSON.parse(e.data);
-      _this.storeName = _this.getStoreName();
     });
     axios.get('/api/stores').then(function (response) {
-      _this.storeList = response.data;
+      _this.storeList = new Map();
+      response.data.map(function (val) {
+        _this.storeList.set(val.storeid, val);
+      });
     })["catch"](function (error) {
       console.error(error);
     });
-    this.storeList = this.getStoreName();
   },
   methods: {
     updateWorkOrder: function updateWorkOrder() {
       axios.put('/api/workorders/' + this.data.woid, this.data).then(function (response) {})["catch"](function (error) {});
       $('#workordereditModal').modal('hide');
-    },
-    getStoreName: function getStoreName() {
-      var _this2 = this;
-
-      axios.get('/api/stores/' + this.data.storeid).then(function (response) {
-        _this2.storeName = response.data.storesname;
-      })["catch"](function (error) {
-        console.error(error);
-      });
     }
   }
 });
@@ -48821,6 +48854,133 @@ var render = function() {
     "div",
     { staticClass: "bg-lightgray m-1 p-2 border rounded container-fluid" },
     [
+      _c(
+        "modal",
+        {
+          attrs: {
+            id: "credential" + this.data.credid + "editModal",
+            tabindex: "-1",
+            role: "dialog",
+            "aria-labelledby":
+              "credential" + this.data.credid + "editModalLabel"
+          }
+        },
+        [
+          _c(
+            "h5",
+            {
+              staticClass: "modal-title",
+              attrs: { slot: "header", id: "credentialeditModalLabel" },
+              slot: "header"
+            },
+            [_vm._v("\r\n            Edit Credential\r\n        ")]
+          ),
+          _vm._v(" "),
+          _c("div", { attrs: { slot: "body" }, slot: "body" }, [
+            _c("div", { staticClass: "form-group" }, [
+              _c("label", { attrs: { for: "username" } }, [_vm._v("Username")]),
+              _vm._v(" "),
+              _c("input", {
+                directives: [
+                  {
+                    name: "model",
+                    rawName: "v-model",
+                    value: this.data.creduser,
+                    expression: "this.data.creduser"
+                  }
+                ],
+                staticClass: "form-control credential",
+                attrs: {
+                  type: "text",
+                  name: "username" + this.data.credid,
+                  id: "username" + this.data.credid
+                },
+                domProps: { value: this.data.creduser },
+                on: {
+                  input: function($event) {
+                    if ($event.target.composing) {
+                      return
+                    }
+                    _vm.$set(this.data, "creduser", $event.target.value)
+                  }
+                }
+              })
+            ]),
+            _vm._v(" "),
+            _c("div", { staticClass: "form-group" }, [
+              _c("label", { attrs: { for: "password" } }, [_vm._v("Password")]),
+              _vm._v(" "),
+              _c("input", {
+                directives: [
+                  {
+                    name: "model",
+                    rawName: "v-model",
+                    value: this.data.credpass,
+                    expression: "this.data.credpass"
+                  }
+                ],
+                staticClass: "form-control credential",
+                attrs: {
+                  type: "text",
+                  name: "password" + this.data.credid,
+                  id: "password" + this.data.credid
+                },
+                domProps: { value: this.data.credpass },
+                on: {
+                  input: function($event) {
+                    if ($event.target.composing) {
+                      return
+                    }
+                    _vm.$set(this.data, "credpass", $event.target.value)
+                  }
+                }
+              }),
+              _vm._v(" "),
+              _c(
+                "button",
+                {
+                  staticClass: "btn btn-secondary",
+                  attrs: { type: "button" },
+                  on: {
+                    click: function($event) {
+                      return _vm.getRandomPassword()
+                    }
+                  }
+                },
+                [_vm._v("Generate Random")]
+              )
+            ]),
+            _vm._v(" "),
+            _c("div", { staticClass: "form-group" })
+          ]),
+          _vm._v(" "),
+          _c("div", { attrs: { slot: "footer" }, slot: "footer" }, [
+            _c(
+              "button",
+              {
+                staticClass: "btn btn-secondary",
+                attrs: { type: "button", "data-dismiss": "modal" }
+              },
+              [_vm._v("Close")]
+            ),
+            _vm._v(" "),
+            _c(
+              "button",
+              {
+                staticClass: "btn btn-primary",
+                attrs: { type: "button" },
+                on: {
+                  click: function($event) {
+                    return _vm.updateCredential()
+                  }
+                }
+              },
+              [_vm._v("Save")]
+            )
+          ])
+        ]
+      ),
+      _vm._v(" "),
       _c("div", { staticClass: "row no-gutters" }, [
         _c("div", { staticClass: "h5 col-3 text-left" }, [
           _vm._v(_vm._s(this.data.creddesc))
@@ -48886,9 +49046,32 @@ var render = function() {
           ])
         ]),
         _vm._v(" "),
-        _vm._m(2)
+        _c(
+          "div",
+          {
+            staticClass: "btn-group col-lg-2 align-self-end w-25 w-lg-auto",
+            attrs: { role: "group", "aria-label": "Edit and Delete" }
+          },
+          [
+            _c(
+              "button",
+              {
+                staticClass: "btn btn-sm btn-secondary p-lg-1",
+                attrs: {
+                  type: "button",
+                  "data-toggle": "modal",
+                  "data-target": "#credential" + this.data.credid + "editModal"
+                }
+              },
+              [_c("i", { staticClass: "fas fa-fw fa-edit" })]
+            ),
+            _vm._v(" "),
+            _vm._m(2)
+          ]
+        )
       ])
-    ]
+    ],
+    1
   )
 }
 var staticRenderFns = [
@@ -48913,30 +49096,12 @@ var staticRenderFns = [
     var _h = _vm.$createElement
     var _c = _vm._self._c || _h
     return _c(
-      "div",
+      "button",
       {
-        staticClass: "btn-group col-lg-2 align-self-end w-25 w-lg-auto",
-        attrs: { role: "group", "aria-label": "Edit and Delete" }
+        staticClass: "btn btn-sm btn-danger p-lg-1",
+        attrs: { type: "button" }
       },
-      [
-        _c(
-          "button",
-          {
-            staticClass: "btn btn-sm btn-secondary p-lg-1",
-            attrs: { type: "button" }
-          },
-          [_c("i", { staticClass: "fas fa-fw fa-edit" })]
-        ),
-        _vm._v(" "),
-        _c(
-          "button",
-          {
-            staticClass: "btn btn-sm btn-danger p-lg-1",
-            attrs: { type: "button" }
-          },
-          [_c("i", { staticClass: "fas fa-fw fa-trash-alt" })]
-        )
-      ]
+      [_c("i", { staticClass: "fas fa-fw fa-trash-alt" })]
     )
   }
 ]
@@ -49208,54 +49373,59 @@ var render = function() {
             _c("div", { staticClass: "form-group" }, [
               _c("label", { attrs: { for: "storelist" } }, [_vm._v("Store")]),
               _vm._v(" "),
-              _c(
-                "select",
-                {
-                  directives: [
+              _vm.storeList
+                ? _c(
+                    "select",
                     {
-                      name: "model",
-                      rawName: "v-model",
-                      value: _vm.data.storeid,
-                      expression: "data.storeid"
-                    }
-                  ],
-                  staticClass: "form-control",
-                  attrs: { name: "storelist", id: "storelist" },
-                  on: {
-                    change: function($event) {
-                      var $$selectedVal = Array.prototype.filter
-                        .call($event.target.options, function(o) {
-                          return o.selected
-                        })
-                        .map(function(o) {
-                          var val = "_value" in o ? o._value : o.value
-                          return val
-                        })
-                      _vm.$set(
-                        _vm.data,
-                        "storeid",
-                        $event.target.multiple
-                          ? $$selectedVal
-                          : $$selectedVal[0]
-                      )
-                    }
-                  }
-                },
-                _vm._l(_vm.storeList, function(store) {
-                  return _c(
-                    "option",
-                    { key: store.storeid, domProps: { value: store.storeid } },
-                    [
-                      _vm._v(
-                        "\n                        " +
-                          _vm._s(store.storesname) +
-                          "\n                    "
+                      directives: [
+                        {
+                          name: "model",
+                          rawName: "v-model",
+                          value: _vm.data.storeid,
+                          expression: "data.storeid"
+                        }
+                      ],
+                      staticClass: "form-control",
+                      attrs: { name: "storelist", id: "storelist" },
+                      on: {
+                        change: function($event) {
+                          var $$selectedVal = Array.prototype.filter
+                            .call($event.target.options, function(o) {
+                              return o.selected
+                            })
+                            .map(function(o) {
+                              var val = "_value" in o ? o._value : o.value
+                              return val
+                            })
+                          _vm.$set(
+                            _vm.data,
+                            "storeid",
+                            $event.target.multiple
+                              ? $$selectedVal
+                              : $$selectedVal[0]
+                          )
+                        }
+                      }
+                    },
+                    _vm._l(_vm.storeList.values(), function(store) {
+                      return _c(
+                        "option",
+                        {
+                          key: store.storeid,
+                          domProps: { value: store.storeid }
+                        },
+                        [
+                          _vm._v(
+                            "\n                        " +
+                              _vm._s(store.storesname) +
+                              "\n                    "
+                          )
+                        ]
                       )
-                    ]
+                    }),
+                    0
                   )
-                }),
-                0
-              )
+                : _vm._e()
             ])
           ]),
           _vm._v(" "),
@@ -49307,7 +49477,11 @@ var render = function() {
       _c("p", [
         _c("i", { staticClass: "fas fa-fw fa-building" }),
         _vm._v(" "),
-        _c("span", [_vm._v(_vm._s(_vm.storeName))])
+        this.storeList
+          ? _c("span", [
+              _vm._v(_vm._s(this.storeList.get(this.data.storeid).storesname))
+            ])
+          : _vm._e()
       ]),
       _vm._v(" "),
       _c("p", [

+ 40 - 1
resources/js/components/credential.vue

@@ -1,5 +1,26 @@
 <template>
 <div class="bg-lightgray m-1 p-2 border rounded container-fluid">
+    <modal :id="'credential'+this.data.credid+'editModal'" tabindex="-1" role="dialog" :aria-labelledby="'credential'+this.data.credid+'editModalLabel'">
+        <h5 slot="header" class="modal-title" id="credentialeditModalLabel">
+            Edit Credential
+        </h5>
+        <div slot="body">
+            <div class="form-group">
+                <label for="username">Username</label>
+                <input type="text" :name="'username'+this.data.credid" :id="'username'+this.data.credid" class="form-control credential" v-model="this.data.creduser">
+            </div>
+            <div class="form-group">
+                <label for="password">Password</label>
+                <input type="text" :name="'password'+this.data.credid" :id="'password'+this.data.credid" class="form-control credential" v-model="this.data.credpass">
+                <button type="button" class="btn btn-secondary" @click="getRandomPassword()">Generate Random</button>
+            </div>
+            <div class="form-group"></div>
+        </div>
+        <div slot="footer">
+            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+            <button type="button" class="btn btn-primary" @click="updateCredential()">Save</button>
+        </div>
+    </modal>
     <div class="row no-gutters">
         <div class="h5 col-3 text-left">{{this.data.creddesc}}</div>
         <div class="col-9 text-right">{{this.data.creddate}}</div>
@@ -22,7 +43,7 @@
             </div>
         </div>
         <div class="btn-group col-lg-2 align-self-end w-25 w-lg-auto" role="group" aria-label="Edit and Delete">
-            <button type="button" class="btn btn-sm btn-secondary p-lg-1"><i class="fas fa-fw fa-edit"></i></button>
+            <button type="button" class="btn btn-sm btn-secondary p-lg-1" data-toggle="modal" :data-target="'#credential'+this.data.credid+'editModal'"><i class="fas fa-fw fa-edit"></i></button>
             <button type="button" class="btn btn-sm btn-danger p-lg-1"><i class="fas fa-fw fa-trash-alt"></i></button>
         </div>
     </div>
@@ -41,6 +62,24 @@ export default {
             .listen('CredentialUpdated', (e) => {
                 this.data = JSON.parse(e.data);
             });
+    },
+    methods: {
+        rndStr(len) {
+            let text = ""
+            let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%"
+        
+            for( let i=0; i < len; i++ ) {
+                text += chars.charAt(Math.floor(Math.random() * chars.length))
+            }
+            return text
+        },
+        getRandomPassword() {
+            this.data.credpass = this.rndStr(16);
+        },
+        updateCredential() {
+            axios.put('/api/credentials/' + this.data.credid, this.data).then(response => {}).catch(error =>{console.error(error)});
+            $('#credential'+this.data.credid+'editModal').modal('hide');
+        }
     }
 }
 </script>

+ 9 - 12
resources/js/components/woinfo.vue

@@ -15,8 +15,8 @@
                 </div>
                 <div class="form-group">
                     <label for="storelist">Store</label>
-                    <select name="storelist" id="storelist" class="form-control" v-model="data.storeid">
-                        <option v-for="store in storeList" v-bind:key="store.storeid" v-bind:value="store.storeid">
+                    <select name="storelist" id="storelist" class="form-control" v-if="storeList" v-model="data.storeid">
+                        <option v-for="store in storeList.values()" v-bind:key="store.storeid" v-bind:value="store.storeid">
                             {{ store.storesname }}
                         </option>
                     </select>
@@ -31,7 +31,7 @@
         <p><i class="fas fa-fw fa-info-circle"></i> <span v-text="this.data.probdesc"></span></p>
         <p><i class="far fa-fw fa-lightbulb"></i> <span v-text="this.data.suggested"></span></p>
         <p><i class="fas fa-fw fa-paste"></i> <span v-text="this.data.woid"></span></p>
-        <p><i class="fas fa-fw fa-building"></i> <span>{{ storeName }}</span></p>
+        <p><i class="fas fa-fw fa-building"></i> <span v-if="this.storeList">{{ this.storeList.get(this.data.storeid).storesname }}</span></p>
         <p><i class="fas fa-fw fa-sign-in-alt"></i> 
             <span class="dashed-underline" data-toggle="tooltip" data-placement="bottom" v-bind:title=this.getHRDate(this.data.dropdate)>
                 {{ Math.floor(this.daysSinceToday(this.data.dropdate)) }} days ago
@@ -53,7 +53,6 @@
         data() {
             return {
                 data: JSON.parse(this.workOrder),
-                storeName: null,
                 storeList: null,
             }
         },
@@ -61,10 +60,13 @@
             Echo.channel('work-orders')
                 .listen('WorkOrderUpdated', (e) => {
                     this.data = JSON.parse(e.data);
-                    this.storeName = this.getStoreName();
                 });
-            axios.get('/api/stores').then((response) => { this.storeList = response.data }).catch((error) => { console.error(error) });
-            this.storeList = this.getStoreName();
+            axios.get('/api/stores').then((response) => {
+                    this.storeList = new Map();
+                    response.data.map(val => { 
+                        this.storeList.set(val.storeid, val);
+                    });
+                }).catch((error) => { console.error(error) });
         },
         methods: {
             updateWorkOrder() {
@@ -73,11 +75,6 @@
                     .catch((error) => {});
                 $('#workordereditModal').modal('hide');
             },
-            getStoreName() {
-                axios.get('/api/stores/' + this.data.storeid)
-                    .then((response) => { this.storeName = response.data.storesname })
-                    .catch((error) => { console.error(error) });
-            }
         }
     }
 </script>

+ 2 - 2
resources/views/workorders/show.blade.php

@@ -58,7 +58,7 @@
                     </button>
                     <ul class="nav nav-pills card-header-pills nav-justified xs-collapse collapse" id="workorderTab" role="tablist">
                         <li class="nav-item">
-                            <a class="nav-link active" id="workorderinfo-tab" data-toggle="pill" href="#workorderinfo" role="tab" aria-controls="workorderinfo" aria-selected="true">Work Order Info</a>
+                            <a class="nav-link active" id="workordersumm-tab" data-toggle="pill" href="#workordersumm" role="tab" aria-controls="workordersumm" aria-selected="true">Summary</a>
                         </li>
                         <li class="nav-item">
                             <a class="nav-link" id="attachments-tab" data-toggle="pill" href="#attachments" role="tab" aria-controls="attachments" aria-selected="false">Attachments</a>
@@ -67,7 +67,7 @@
                 </div>
                 <div class='card-body'>
                     <div class='tab-content'>
-                        <div class="tab-pane active" id="workorderinfo" role="tabpanel" aria-labelledby="workorderinfo-tab">
+                        <div class="tab-pane active" id="workordersumm" role="tabpanel" aria-labelledby="workordersumm-tab">
                             <woinfo work-order="{{$workOrder}}"></woinfo>
                         </div>
                         <div class="tab-pane" id="attachments" role="tabpanel" aria-labelledby="attachments-tab">

+ 2 - 0
routes/api.php

@@ -26,4 +26,6 @@ Route::middleware('auth:api')->group( function() {
     Route::get('/stores', 'Api\StoresController@index');
     Route::get('/stores/{store}', 'Api\StoresController@show');
 
+    Route::put('/credentials/{credential}', 'Api\CredentialsController@update');
+
 });