diff --git a/app/Http/Controllers/RecordController.php b/app/Http/Controllers/RecordController.php index 349dd4c..77aa422 100644 --- a/app/Http/Controllers/RecordController.php +++ b/app/Http/Controllers/RecordController.php @@ -29,17 +29,6 @@ public function retrieve(Request $request, Record $record): JsonResponse : response()->json(RecordResource::collection($record::all())); } - /** - * Store a newly created resource in storage. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - */ - public function create(Request $request): JsonResponse - { - return response()->json([]); - } - /** * Update the specified resource in storage. * @@ -73,12 +62,9 @@ public function update(Request $request, Record $record): JsonResponse /** * Remove the specified resource from storage. - * - * @param \App\Models\Record $record - * @return \Illuminate\Http\Response */ - public function destroy(Record $record): JsonResponse + public function delete(Request $request, Record $record): JsonResponse { - return response()->json([]); + return response()->json([$record->delete()]); } } diff --git a/package-lock.json b/package-lock.json index 2b03aa9..7d2a2d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "bootstrap-vue": "^2.21.2", "laravel-mix": "^6.0.28", "popper.js": "^1.16.1", + "portal-vue": "2.1", "vue": "^2.6.12" }, "devDependencies": { diff --git a/package.json b/package.json index 1c00995..22aac6b 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "name": "alex-runyan-process-maker-code-test", "private": true, "scripts": { "development": "mix", @@ -13,6 +14,7 @@ "bootstrap-vue": "^2.21.2", "laravel-mix": "^6.0.28", "popper.js": "^1.16.1", + "portal-vue": "^2.1.7", "vue": "^2.6.12" }, "devDependencies": { diff --git a/public/css/app.css b/public/css/app.css index ff16553..3515658 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -12345,4 +12345,220 @@ input[type=color].form-control:disabled { font-size: 125%; vertical-align: text-bottom; } +/*! + * BootstrapVue Icons Custom CSS (https://bootstrap-vue.org) + */ +.bv-no-focus-ring:focus { + outline: none; +} + +@media (max-width: 575.98px) { + .bv-d-xs-down-none { + display: none !important; + } +} +@media (max-width: 767.98px) { + .bv-d-sm-down-none { + display: none !important; + } +} +@media (max-width: 991.98px) { + .bv-d-md-down-none { + display: none !important; + } +} +@media (max-width: 1199.98px) { + .bv-d-lg-down-none { + display: none !important; + } +} +.bv-d-xl-down-none { + display: none !important; +} + +.b-icon.bi { + display: inline-block; + overflow: visible; + vertical-align: -0.15em; +} +.b-icon.b-icon-animation-cylon, .b-icon.b-iconstack .b-icon-animation-cylon > g { + transform-origin: center; + -webkit-animation: 0.75s infinite ease-in-out alternate b-icon-animation-cylon; + animation: 0.75s infinite ease-in-out alternate b-icon-animation-cylon; +} +@media (prefers-reduced-motion: reduce) { + .b-icon.b-icon-animation-cylon, .b-icon.b-iconstack .b-icon-animation-cylon > g { + -webkit-animation: none; + animation: none; + } +} +.b-icon.b-icon-animation-cylon-vertical, .b-icon.b-iconstack .b-icon-animation-cylon-vertical > g { + transform-origin: center; + -webkit-animation: 0.75s infinite ease-in-out alternate b-icon-animation-cylon-vertical; + animation: 0.75s infinite ease-in-out alternate b-icon-animation-cylon-vertical; +} +@media (prefers-reduced-motion: reduce) { + .b-icon.b-icon-animation-cylon-vertical, .b-icon.b-iconstack .b-icon-animation-cylon-vertical > g { + -webkit-animation: none; + animation: none; + } +} +.b-icon.b-icon-animation-fade, .b-icon.b-iconstack .b-icon-animation-fade > g { + transform-origin: center; + -webkit-animation: 0.75s infinite ease-in-out alternate b-icon-animation-fade; + animation: 0.75s infinite ease-in-out alternate b-icon-animation-fade; +} +@media (prefers-reduced-motion: reduce) { + .b-icon.b-icon-animation-fade, .b-icon.b-iconstack .b-icon-animation-fade > g { + -webkit-animation: none; + animation: none; + } +} +.b-icon.b-icon-animation-spin, .b-icon.b-iconstack .b-icon-animation-spin > g { + transform-origin: center; + -webkit-animation: 2s infinite linear normal b-icon-animation-spin; + animation: 2s infinite linear normal b-icon-animation-spin; +} +@media (prefers-reduced-motion: reduce) { + .b-icon.b-icon-animation-spin, .b-icon.b-iconstack .b-icon-animation-spin > g { + -webkit-animation: none; + animation: none; + } +} +.b-icon.b-icon-animation-spin-reverse, .b-icon.b-iconstack .b-icon-animation-spin-reverse > g { + transform-origin: center; + animation: 2s infinite linear reverse b-icon-animation-spin; +} +@media (prefers-reduced-motion: reduce) { + .b-icon.b-icon-animation-spin-reverse, .b-icon.b-iconstack .b-icon-animation-spin-reverse > g { + -webkit-animation: none; + animation: none; + } +} +.b-icon.b-icon-animation-spin-pulse, .b-icon.b-iconstack .b-icon-animation-spin-pulse > g { + transform-origin: center; + -webkit-animation: 1s infinite steps(8) normal b-icon-animation-spin; + animation: 1s infinite steps(8) normal b-icon-animation-spin; +} +@media (prefers-reduced-motion: reduce) { + .b-icon.b-icon-animation-spin-pulse, .b-icon.b-iconstack .b-icon-animation-spin-pulse > g { + -webkit-animation: none; + animation: none; + } +} +.b-icon.b-icon-animation-spin-reverse-pulse, .b-icon.b-iconstack .b-icon-animation-spin-reverse-pulse > g { + transform-origin: center; + animation: 1s infinite steps(8) reverse b-icon-animation-spin; +} +@media (prefers-reduced-motion: reduce) { + .b-icon.b-icon-animation-spin-reverse-pulse, .b-icon.b-iconstack .b-icon-animation-spin-reverse-pulse > g { + -webkit-animation: none; + animation: none; + } +} +.b-icon.b-icon-animation-throb, .b-icon.b-iconstack .b-icon-animation-throb > g { + transform-origin: center; + -webkit-animation: 0.75s infinite ease-in-out alternate b-icon-animation-throb; + animation: 0.75s infinite ease-in-out alternate b-icon-animation-throb; +} +@media (prefers-reduced-motion: reduce) { + .b-icon.b-icon-animation-throb, .b-icon.b-iconstack .b-icon-animation-throb > g { + -webkit-animation: none; + animation: none; + } +} + +@-webkit-keyframes b-icon-animation-cylon { + 0% { + transform: translateX(-25%); + } + 100% { + transform: translateX(25%); + } +} + +@keyframes b-icon-animation-cylon { + 0% { + transform: translateX(-25%); + } + 100% { + transform: translateX(25%); + } +} +@-webkit-keyframes b-icon-animation-cylon-vertical { + 0% { + transform: translateY(25%); + } + 100% { + transform: translateY(-25%); + } +} +@keyframes b-icon-animation-cylon-vertical { + 0% { + transform: translateY(25%); + } + 100% { + transform: translateY(-25%); + } +} +@-webkit-keyframes b-icon-animation-fade { + 0% { + opacity: 0.1; + } + 100% { + opacity: 1; + } +} +@keyframes b-icon-animation-fade { + 0% { + opacity: 0.1; + } + 100% { + opacity: 1; + } +} +@-webkit-keyframes b-icon-animation-spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} +@keyframes b-icon-animation-spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} +@-webkit-keyframes b-icon-animation-throb { + 0% { + opacity: 0.5; + transform: scale(0.5); + } + 100% { + opacity: 1; + transform: scale(1); + } +} +@keyframes b-icon-animation-throb { + 0% { + opacity: 0.5; + transform: scale(0.5); + } + 100% { + opacity: 1; + transform: scale(1); + } +} +.btn .b-icon.bi, +.nav-link .b-icon.bi, +.dropdown-toggle .b-icon.bi, +.dropdown-item .b-icon.bi, +.input-group-text .b-icon.bi { + font-size: 125%; + vertical-align: text-bottom; +} diff --git a/public/js/bundle.js b/public/js/bundle.js index bf6af4c..5a6ab10 100644 --- a/public/js/bundle.js +++ b/public/js/bundle.js @@ -1,5 +1,5 @@ "use strict"; -(self["webpackChunk"] = self["webpackChunk"] || []).push([["/js/bundle"],{ +(self["webpackChunkalex_runyan_process_maker_code_test"] = self["webpackChunkalex_runyan_process_maker_code_test"] || []).push([["/js/bundle"],{ /***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-5[0].rules[0].use[0]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./resources/js/components/RecordForm.vue?vue&type=script&lang=js&": /*!*****************************************************************************************************************************************************************************************************************!*\ @@ -79,12 +79,29 @@ __webpack_require__.r(__webpack_exports__); // // // +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ name: 'RecordForm', props: ['record'], data: function data() { return { - formData: { + id: this.record.id, + form: { id: this.record.id, uuid: this.record.uuid, name: this.record.name, @@ -120,6 +137,71 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// // // // @@ -151,7 +233,12 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar name: 'RecordTable', data: function data() { return { - items: [], + records: [], + filterOn: [], + filter: null, + totalRecords: 1, + sortDirection: 'asc', + isBusy: false, fields: ['uuid', 'name', { key: 'status', sortable: true @@ -163,36 +250,35 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar id: 'edit-modal', record: {}, error: false, - errorMessage: '' + errorMessage: '', + saveText: '' } }; }, components: { RecordForm: _RecordForm__WEBPACK_IMPORTED_MODULE_1__.default }, - computed: { - hasItems: function hasItems() { - return this.items.length > 0; - }, - totalItems: function totalItems() { - return this.items.length; - } - }, methods: { edit: function edit(record, index, button) { // Bind the row item (record) to the modal // to populate the for fields for editing or // review by the user - this.editModal.record = record; // Show the edit modal + this.editModal.record = record; // Set the save button text + + this.editModal.saveText = 'Save'; // Show the edit modal this.$root.$emit('bv::show::modal', this.editModal.id, button); }, + handleFiltered: function handleFiltered(filteredItems) { + this.totalRecords = filteredItems.length; + }, handleClose: function handleClose(event) { // Reset the edit modal's target record // data only if the modal was closed if (!event.defaultPrevented) { this.editModal.record = {}; this.editModal.error = false; + this.editModal.errorMessage = ''; } }, handleOk: function handleOk(event) { @@ -203,12 +289,38 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar this.updateRecord(); }, - getRecords: function getRecords() { + deleteRecord: function deleteRecord(event) { var _this = this; - axios.post('/api/record/stored').then(function (r) { - return _this.items = r.data; - }); + // Show a confirmation modal before attempting + // to delete the record + this.confirmDelete().then(function (confirmed) { + // If the user cancels their decision to + // delete, then bail here + if (!confirmed) { + return; + } // Otherwise, fire off a DELETE request + // to the backend and act accordingly + + + _this.attemptDelete().then(function (resp) { + // Deletion was successful, so hide the edit modal + _this.$root.$emit('bv::hide::modal', _this.editModal.id); // Fresh pull of data and repopulate the table + + + _this.getRecords(); // Tell the BootstrapVue table instance to + // refresh internally as well + + + _this.$refs.table.refresh(); + })["catch"](function (e) { + // If there was a problem deleting the record, + // show an error message to the user. + // todo Showing a more specific error message from the backend would be better here + _this.editModal.error = true; + _this.editModal.errorMessage = 'An error occurred while trying to delete this record.'; + }); + })["catch"](function (e) {}); }, updateRecord: function updateRecord() { var _this2 = this; @@ -217,7 +329,7 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar // if successful (200 response), then sync // the data up for the specific record in // the table - this.attemptUpdate().then(function (resp) { + this.attemptSave().then(function (resp) { // The response property "data" is an // object representing the just now // updated record @@ -234,38 +346,93 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar })["catch"](function (e) { // Show the error message to the user // if there was an error + // todo Can be significantly improved by translating returned error message back into alerts/toasts for the user to see + _this2.editModal.errorMessage = 'An error occurred while trying to update this record.'; _this2.editModal.error = true; - })["finally"](function () {// }); }, - attemptUpdate: function attemptUpdate() { + getRecords: function getRecords() { var _this3 = this; + // Set the table state to busy while + // the records are being retrieved + this.isBusy = true; + axios.post('/api/record/stored').then(function (resp) { + return _this3.records = resp.data; + })["catch"](function (e) {})["finally"](function () { + return _this3.isBusy = false; + }); + }, + confirmDelete: function confirmDelete() { + var _this4 = this; + return _asyncToGenerator( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().mark(function _callee() { return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: - // Set the modal state to loading - _this3.editModal.loading = true; // Referencing the $ref.form here as it - // points to the new data the user has - // input in the settings, which is what - // we want to use to update the record in - // the database + return _context.abrupt("return", _this4.$bvModal.msgBoxConfirm('Are you sure you want to delete this record?', { + title: 'Confirm', + okVariant: 'danger', + okTitle: 'Yes, Delete', + cancelTitle: 'Cancel' + })); + + case 1: + case "end": + return _context.stop(); + } + } + }, _callee); + }))(); + }, + attemptDelete: function attemptDelete() { + var _this5 = this; - return _context.abrupt("return", axios.post("/api/record/update/".concat(_this3.$refs.form.formData.id), _this3.$refs.form.formData)); + return _asyncToGenerator( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().mark(function _callee2() { + return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + return _context2.abrupt("return", axios["delete"]("/api/record/delete/".concat(_this5.$refs.form.id))); + + case 1: + case "end": + return _context2.stop(); + } + } + }, _callee2); + }))(); + }, + attemptSave: function attemptSave() { + var _this6 = this; + + return _asyncToGenerator( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().mark(function _callee3() { + return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().wrap(function _callee3$(_context3) { + while (1) { + switch (_context3.prev = _context3.next) { + case 0: + _this6.editModal.saveText = 'Saving...'; // Referencing the $ref.form here as it + // points to the form data only, rather + // than the Vue instance data() + // todo Improvement here would be form validation prior to firing off the request + + return _context3.abrupt("return", axios.post("/api/record/update/".concat(_this6.$refs.form.id), _this6.$refs.form.form)); case 2: case "end": - return _context.stop(); + return _context3.stop(); } } - }, _callee); + }, _callee3); }))(); } }, beforeMount: function beforeMount() { this.getRecords(); + }, + mounted: function mounted() { + this.totalRecords = this.records.length; } }); @@ -281,16 +448,18 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.esm.js"); /* harmony import */ var _components_RecordTable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./components/RecordTable */ "./resources/js/components/RecordTable.vue"); /* harmony import */ var bootstrap_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! bootstrap-vue */ "./node_modules/bootstrap-vue/esm/index.js"); +/* harmony import */ var bootstrap_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! bootstrap-vue */ "./node_modules/bootstrap-vue/esm/icons/plugin.js"); window.axios = __webpack_require__(/*! axios */ "./node_modules/axios/index.js"); window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; vue__WEBPACK_IMPORTED_MODULE_1__.default.use(bootstrap_vue__WEBPACK_IMPORTED_MODULE_2__.BootstrapVue); +vue__WEBPACK_IMPORTED_MODULE_1__.default.use(bootstrap_vue__WEBPACK_IMPORTED_MODULE_3__.BootstrapVueIcons); window.app = new vue__WEBPACK_IMPORTED_MODULE_1__.default({ el: '#app', components: { - 'record-table': _components_RecordTable__WEBPACK_IMPORTED_MODULE_0__.default + RecordTable: _components_RecordTable__WEBPACK_IMPORTED_MODULE_0__.default } }); @@ -492,11 +661,11 @@ var render = function() { _c("b-form-input", { attrs: { type: "text", id: "uuid", disabled: "", readonly: "" }, model: { - value: _vm.formData.uuid, + value: _vm.form.uuid, callback: function($$v) { - _vm.$set(_vm.formData, "uuid", $$v) + _vm.$set(_vm.form, "uuid", $$v) }, - expression: "formData.uuid" + expression: "form.uuid" } }) ], @@ -519,11 +688,11 @@ var render = function() { _c("b-form-input", { attrs: { type: "text", id: "name" }, model: { - value: _vm.formData.name, + value: _vm.form.name, callback: function($$v) { - _vm.$set(_vm.formData, "name", $$v) + _vm.$set(_vm.form, "name", $$v) }, - expression: "formData.name" + expression: "form.name" } }) ], @@ -546,11 +715,11 @@ var render = function() { _c("b-form-select", { attrs: { options: _vm.options.status }, model: { - value: _vm.formData.status, + value: _vm.form.status, callback: function($$v) { - _vm.$set(_vm.formData, "status", $$v) + _vm.$set(_vm.form, "status", $$v) }, - expression: "formData.status" + expression: "form.status" } }) ], @@ -573,11 +742,11 @@ var render = function() { _c("b-form-textarea", { attrs: { id: "description", rows: "4" }, model: { - value: _vm.formData.description, + value: _vm.form.description, callback: function($$v) { - _vm.$set(_vm.formData, "description", $$v) + _vm.$set(_vm.form, "description", $$v) }, - expression: "formData.description" + expression: "form.description" } }) ], @@ -600,15 +769,48 @@ var render = function() { _c("b-form-textarea", { attrs: { id: "code", rows: "4" }, model: { - value: _vm.formData.code, + value: _vm.form.code, callback: function($$v) { - _vm.$set(_vm.formData, "code", $$v) + _vm.$set(_vm.form, "code", $$v) }, - expression: "formData.code" + expression: "form.code" } }) ], 1 + ), + _vm._v(" "), + _c( + "b-form-group", + { + attrs: { + id: "fieldset-horizontal", + "label-cols-lg": "2", + "content-cols-lg": "10", + "label-for": "delete", + "label-align-sm": "right" + } + }, + [ + _c( + "b-link", + { + staticClass: "text-danger", + attrs: { id: "delete", href: "javascript:" }, + on: { + click: function($event) { + return _vm.$emit( + "delete-record", + _vm.record, + $event.target + ) + } + } + }, + [_vm._v("\n Delete Record\n ")] + ) + ], + 1 ) ], 1 @@ -642,38 +844,190 @@ var render = function() { return _c( "div", [ - _c("b-table", { - attrs: { - striped: "", - hover: "", - "foot-clone": "", - "primary-key": "id", - fields: _vm.fields, - items: _vm.items - }, - scopedSlots: _vm._u([ - { - key: "cell(actions)", - fn: function(row) { - return [ - _c( - "b-button", + _c( + "b-row", + [ + _c( + "b-col", + { staticClass: "my-3", attrs: { cols: "4" } }, + [ + _c( + "b-input-group", + { attrs: { size: "sm" } }, + [ + _c("b-form-input", { + attrs: { + id: "filter-input", + type: "search", + placeholder: "Type to Search" + }, + model: { + value: _vm.filter, + callback: function($$v) { + _vm.filter = $$v + }, + expression: "filter" + } + }), + _vm._v(" "), + _c( + "b-input-group-append", + [ + _c( + "b-button", + { + attrs: { disabled: !_vm.filter }, + on: { + click: function($event) { + _vm.filter = "" + } + } + }, + [_vm._v("Clear")] + ) + ], + 1 + ) + ], + 1 + ) + ], + 1 + ), + _vm._v(" "), + _c( + "b-col", + { staticClass: "my-3", attrs: { cols: "8" } }, + [ + _c("b-form-group", { + staticClass: "mb-0 text-right", + attrs: { + label: "Filter by:", + "label-cols-sm": "4", + "label-size": "sm", + "label-align-sm": "right" + }, + scopedSlots: _vm._u([ { - staticClass: "mr-1", - attrs: { size: "sm" }, - on: { - click: function($event) { - return _vm.edit(row.item, row.index, $event.target) - } + key: "default", + fn: function(ref) { + var ariaDescribedby = ref.ariaDescribedby + return [ + _c( + "b-form-checkbox-group", + { + staticClass: "mt-1", + attrs: { "aria-describedby": ariaDescribedby }, + model: { + value: _vm.filterOn, + callback: function($$v) { + _vm.filterOn = $$v + }, + expression: "filterOn" + } + }, + [ + _c( + "b-form-checkbox", + { attrs: { value: "name" } }, + [_vm._v("Name")] + ), + _vm._v(" "), + _c( + "b-form-checkbox", + { attrs: { value: "code" } }, + [_vm._v("Code")] + ), + _vm._v(" "), + _c( + "b-form-checkbox", + { attrs: { value: "description" } }, + [_vm._v("Description")] + ), + _vm._v(" "), + _c( + "b-form-checkbox", + { attrs: { value: "status" } }, + [_vm._v("Status")] + ) + ], + 1 + ) + ] } - }, - [_vm._v("\n Edit\n ")] - ) - ] - } - } - ]) - }), + } + ]) + }) + ], + 1 + ) + ], + 1 + ), + _vm._v(" "), + _c( + "b-overlay", + { attrs: { show: _vm.isBusy } }, + [ + _c("b-table", { + ref: "table", + attrs: { + borderless: "", + striped: "", + hover: "", + "foot-clone": "", + "primary-key": "id", + "empty-filtered-text": "No records found matching your request", + filter: _vm.filter, + "filter-included-fields": _vm.filterOn, + fields: _vm.fields, + busy: _vm.isBusy, + items: _vm.records + }, + on: { + "update:busy": function($event) { + _vm.isBusy = $event + } + }, + scopedSlots: _vm._u([ + { + key: "cell(actions)", + fn: function(row) { + return [ + _c( + "b-button", + { + staticClass: "mr-2", + attrs: { size: "sm" }, + on: { + click: function($event) { + return _vm.edit(row.item, row.index, $event.target) + } + } + }, + [ + _vm._v( + "\n Edit\n " + ), + _c("b-icon", { + attrs: { + icon: "pencil", + scale: "0.75", + "aria-hidden": "true", + variant: "light" + } + }) + ], + 1 + ) + ] + } + } + ]) + }) + ], + 1 + ), _vm._v(" "), _c( "b-modal", @@ -683,14 +1037,15 @@ var render = function() { title: "Edit record", size: "lg", "cancel-title": "Cancel", - "ok-title": "Save" + "ok-title": _vm.editModal.saveText }, on: { ok: _vm.handleOk, hide: _vm.handleClose } }, [ _c("record-form", { ref: "form", - attrs: { record: _vm.editModal.record } + attrs: { record: _vm.editModal.record }, + on: { "delete-record": _vm.deleteRecord } }), _vm._v(" "), _c( @@ -707,7 +1062,9 @@ var render = function() { }, [ _vm._v( - "\n There was an error while trying to update this record.\n " + "\n " + + _vm._s(_vm.editModal.errorMessage) + + "\n " ) ] ) diff --git a/public/js/manifest.js b/public/js/manifest.js index b086706..977f1dd 100644 --- a/public/js/manifest.js +++ b/public/js/manifest.js @@ -163,7 +163,7 @@ /******/ return __webpack_require__.O(result); /******/ } /******/ -/******/ var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || []; +/******/ var chunkLoadingGlobal = self["webpackChunkalex_runyan_process_maker_code_test"] = self["webpackChunkalex_runyan_process_maker_code_test"] || []; /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); /******/ })(); diff --git a/public/js/vendor.js b/public/js/vendor.js index 8bf8278..c570ecd 100644 --- a/public/js/vendor.js +++ b/public/js/vendor.js @@ -1,4 +1,4 @@ -(self["webpackChunk"] = self["webpackChunk"] || []).push([["/js/vendor"],{ +(self["webpackChunkalex_runyan_process_maker_code_test"] = self["webpackChunkalex_runyan_process_maker_code_test"] || []).push([["/js/vendor"],{ /***/ "./node_modules/@babel/runtime/regenerator/index.js": /*!**********************************************************!*\ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index f08dcef..e09ba2a 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,6 +1,6 @@ { - "/js/bundle.js": "/js/bundle.js?id=72d8891792fa4947bf0f", - "/js/manifest.js": "/js/manifest.js?id=64e1efb5266a0bf19c41", - "/css/app.css": "/css/app.css?id=cd3922bbbd3a7fdc1b99", - "/js/vendor.js": "/js/vendor.js?id=c3b6d39c1de89c41958e" + "/js/bundle.js": "/js/bundle.js?id=f6141bfae0a673d76b02", + "/js/manifest.js": "/js/manifest.js?id=61ae721cb7a79fbfcbab", + "/css/app.css": "/css/app.css?id=aabfaf7e42a6d7b4c8c1", + "/js/vendor.js": "/js/vendor.js?id=9fbcaeef4bb5309fa1eb" } diff --git a/resources/js/app.js b/resources/js/app.js index cdebd8f..d89a5b4 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -3,11 +3,14 @@ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; import Vue from 'vue'; import RecordTable from './components/RecordTable'; -import { BootstrapVue } from 'bootstrap-vue'; +import { BootstrapVue, BootstrapVueIcons } from 'bootstrap-vue'; Vue.use(BootstrapVue); +Vue.use(BootstrapVueIcons); window.app = new Vue({ el: '#app', - components: { 'record-table': RecordTable } + components: { + RecordTable + } }); diff --git a/resources/js/components/RecordForm.vue b/resources/js/components/RecordForm.vue index 31ff79d..df9050c 100644 --- a/resources/js/components/RecordForm.vue +++ b/resources/js/components/RecordForm.vue @@ -12,7 +12,7 @@ > - + - + @@ -60,7 +60,23 @@ label-for="code" label-align-sm="right" > - + + + + + Delete Record + @@ -72,7 +88,8 @@ export default { props: ['record'], data() { return { - formData: { + id: this.record.id, + form: { id: this.record.id, uuid: this.record.uuid, name: this.record.name, diff --git a/resources/js/components/RecordTable.vue b/resources/js/components/RecordTable.vue index 7200da6..a3fbb9d 100644 --- a/resources/js/components/RecordTable.vue +++ b/resources/js/components/RecordTable.vue @@ -1,24 +1,89 @@