mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 05:02:36 +01:00
Datatables using Vue (#2568)
* Vue DataTables * Vue Datatables - Pagination * Sort Vue Tables * Working on Vue Datatables * Apply filter to vue table * Search implementation for vue datatables * Clean up
This commit is contained in:
parent
f9ea784d63
commit
43342fb98b
@ -2,8 +2,95 @@
|
||||
|
||||
namespace App\Datatables;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Utils\Traits\UserSessionAttributes;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ClientDatatable
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* ?sort=&page=1&per_page=20
|
||||
*/
|
||||
public static function query(Request $request, int $company_id)
|
||||
{
|
||||
/**
|
||||
*
|
||||
* $sort_col is returned col|asc
|
||||
* needs to be exploded
|
||||
*
|
||||
*/
|
||||
$sort_col = explode("|", $request->input('sort'));
|
||||
|
||||
return response()->json(self::find($company_id, $request->input('filter'))->orderBy($sort_col[0], $sort_col[1])->paginate($request->input('per_page')), 200);
|
||||
}
|
||||
|
||||
|
||||
private static function find(int $company_id, $filter, $userId = false)
|
||||
{
|
||||
$query = DB::table('clients')
|
||||
->join('companies', 'companies.id', '=', 'clients.company_id')
|
||||
->join('client_contacts', 'client_contacts.client_id', '=', 'clients.id')
|
||||
->where('clients.company_id', '=', $company_id)
|
||||
->where('client_contacts.is_primary', '=', true)
|
||||
->where('client_contacts.deleted_at', '=', null)
|
||||
//->whereRaw('(clients.name != "" or contacts.first_name != "" or contacts.last_name != "" or contacts.email != "")') // filter out buy now invoices
|
||||
->select(
|
||||
DB::raw('COALESCE(clients.currency_id, companies.currency_id) currency_id'),
|
||||
DB::raw('COALESCE(clients.country_id, companies.country_id) country_id'),
|
||||
DB::raw("CONCAT(COALESCE(client_contacts.first_name, ''), ' ', COALESCE(client_contacts.last_name, '')) contact"),
|
||||
'clients.id',
|
||||
'clients.name',
|
||||
'clients.private_notes',
|
||||
'client_contacts.first_name',
|
||||
'client_contacts.last_name',
|
||||
'clients.balance',
|
||||
'clients.last_login',
|
||||
'clients.created_at',
|
||||
'clients.created_at as client_created_at',
|
||||
'client_contacts.phone',
|
||||
'client_contacts.email',
|
||||
'clients.deleted_at',
|
||||
'clients.is_deleted',
|
||||
'clients.user_id',
|
||||
'clients.id_number'
|
||||
);
|
||||
/*
|
||||
if(Auth::user()->account->customFieldsOption('client1_filter')) {
|
||||
$query->addSelect('clients.custom_value1');
|
||||
}
|
||||
|
||||
if(Auth::user()->account->customFieldsOption('client2_filter')) {
|
||||
$query->addSelect('clients.custom_value2');
|
||||
}
|
||||
|
||||
$this->applyFilters($query, ENTITY_CLIENT);
|
||||
*/
|
||||
if ($filter) {
|
||||
$query->where(function ($query) use ($filter) {
|
||||
$query->where('clients.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('clients.id_number', 'like', '%'.$filter.'%')
|
||||
->orWhere('client_contacts.first_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('client_contacts.last_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('client_contacts.email', 'like', '%'.$filter.'%');
|
||||
});
|
||||
/*
|
||||
if(Auth::user()->account->customFieldsOption('client1_filter')) {
|
||||
$query->orWhere('clients.custom_value1', 'like' , '%'.$filter.'%');
|
||||
}
|
||||
|
||||
if(Auth::user()->account->customFieldsOption('client2_filter')) {
|
||||
$query->orWhere('clients.custom_value2', 'like' , '%'.$filter.'%');
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if ($userId) {
|
||||
$query->where('clients.user_id', '=', $userId);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Datatables\ClientDatatable;
|
||||
use App\Http\Requests\Client\EditClientRequest;
|
||||
use App\Http\Requests\Client\StoreClientRequest;
|
||||
use App\Http\Requests\Client\UpdateClientRequest;
|
||||
@ -31,13 +32,14 @@ class ClientController extends Controller
|
||||
$this->clientRepo = $clientRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Builder $builder)
|
||||
public function index()
|
||||
{
|
||||
|
||||
if(request('page'))
|
||||
return ClientDatatable::query(request(), $this->getCurrentCompanyId());
|
||||
|
||||
return view('client.vue_list');
|
||||
/*
|
||||
if (request()->ajax()) {
|
||||
|
||||
/*
|
||||
@ -49,7 +51,8 @@ class ClientController extends Controller
|
||||
});
|
||||
*/
|
||||
|
||||
$clients = Client::query()->where('company_id', '=', $this->getCurrentCompanyId());
|
||||
/*
|
||||
$clients = Client::query();
|
||||
|
||||
return DataTables::of($clients->get())
|
||||
->addColumn('full_name', function ($clients) {
|
||||
@ -95,6 +98,7 @@ class ClientController extends Controller
|
||||
$data['html'] = $html;
|
||||
|
||||
return view('client.list', $data);
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,21 +31,9 @@ class RouteServiceProvider extends ServiceProvider
|
||||
Route::bind('client', function ($value) {
|
||||
$client = \App\Models\Client::where('id', $this->decodePrimaryKey($value))->first() ?? abort(404);
|
||||
$client->load('contacts', 'primary_contact');
|
||||
|
||||
return $client;
|
||||
|
||||
});
|
||||
|
||||
|
||||
Route::bind('c', function ($value) {
|
||||
$client = \App\Models\Client::where('id', $this->decodePrimaryKey($value))->first() ?? abort(404);
|
||||
$client->load('contacts', 'primary_contact');
|
||||
|
||||
return $client;
|
||||
|
||||
});
|
||||
|
||||
|
||||
Route::bind('invoice', function ($value) {
|
||||
return \App\Models\Invoice::where('id', $this->decodePrimaryKey($value))->first() ?? abort(404);
|
||||
});
|
||||
|
977
composer.lock
generated
977
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@
|
||||
"@types/core-js": "^0.9.36",
|
||||
"@types/jest": "^23.3.9",
|
||||
"axios": "^0.18",
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"bootstrap": "^4.0.0",
|
||||
"chart.js": "^2.7.2",
|
||||
"cross-env": "^5.1",
|
||||
@ -32,7 +33,8 @@
|
||||
"popper.js": "^1.12",
|
||||
"simple-line-icons": "2.4.1",
|
||||
"ts-jest": "^23.10.5",
|
||||
"vue": "^2.5.17"
|
||||
"vue": "^2.5.17",
|
||||
"vuetable-2": "^1.7.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.118",
|
||||
@ -43,6 +45,7 @@
|
||||
"socket.io-client": "^2.1.1",
|
||||
"ts-loader": "3.5.0",
|
||||
"typescript": "^3.1.6",
|
||||
"vue-events": "^3.1.0",
|
||||
"vue-i18n": "^8.3.0",
|
||||
"vue-select": "^2.5.1",
|
||||
"vue-toastr": "^2.0.16"
|
||||
|
12
public/js/client_create.js
vendored
12
public/js/client_create.js
vendored
@ -14979,18 +14979,6 @@ new vue_1.default({
|
||||
form: new form_1.default(client_object)
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
//console.log('mounted')
|
||||
},
|
||||
beforeMount: function () {
|
||||
//console.log('before mount')
|
||||
},
|
||||
created: function () {
|
||||
//console.dir('created')
|
||||
},
|
||||
updated: function () {
|
||||
//console.dir('updated')
|
||||
},
|
||||
methods: {
|
||||
remove: function (contact) {
|
||||
var index = this.form.contacts.indexOf(contact);
|
||||
|
12
public/js/client_create.min.js
vendored
12
public/js/client_create.min.js
vendored
@ -14979,18 +14979,6 @@ new vue_1.default({
|
||||
form: new form_1.default(client_object)
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
//console.log('mounted')
|
||||
},
|
||||
beforeMount: function () {
|
||||
//console.log('before mount')
|
||||
},
|
||||
created: function () {
|
||||
//console.dir('created')
|
||||
},
|
||||
updated: function () {
|
||||
//console.dir('updated')
|
||||
},
|
||||
methods: {
|
||||
remove: function (contact) {
|
||||
var index = this.form.contacts.indexOf(contact);
|
||||
|
92
public/js/client_edit.js
vendored
92
public/js/client_edit.js
vendored
@ -34363,6 +34363,78 @@ module.exports = function(module) {
|
||||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/js/src/bootstrap.js":
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash__ = __webpack_require__("./node_modules/lodash/lodash.js");
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash__);
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_toastr__ = __webpack_require__("./node_modules/vue-toastr/dist/vue-toastr.js");
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_toastr___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_vue_toastr__);
|
||||
// lodash handles our translations
|
||||
|
||||
|
||||
// import Toastr
|
||||
|
||||
|
||||
// Import toastr scss file: need webpack sass-loader
|
||||
__webpack_require__("./node_modules/vue-toastr/src/vue-toastr.scss");
|
||||
|
||||
// Register vue component
|
||||
Vue.component('vue-toastr', __WEBPACK_IMPORTED_MODULE_1_vue_toastr___default.a);
|
||||
|
||||
// Global translation helper
|
||||
Vue.prototype.trans = function (string) {
|
||||
return __WEBPACK_IMPORTED_MODULE_0_lodash__["get"](i18n, string);
|
||||
};
|
||||
|
||||
window.axios = __webpack_require__("./node_modules/axios/index.js");
|
||||
window.Vue = __webpack_require__("./node_modules/vue/dist/vue.common.js");
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
/* Development only*/
|
||||
Vue.config.devtools = true;
|
||||
|
||||
window.axios.defaults.headers.common = {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
};
|
||||
|
||||
/**
|
||||
* Next we will register the CSRF Token as a common header with Axios so that
|
||||
* all outgoing HTTP requests automatically have it attached. This is just
|
||||
* a simple convenience so we don't have to attach every token manually.
|
||||
*/
|
||||
|
||||
var token = document.head.querySelector('meta[name="csrf-token"]');
|
||||
|
||||
if (token) {
|
||||
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
|
||||
} else {
|
||||
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
|
||||
}
|
||||
|
||||
/**
|
||||
* Echo exposes an expressive API for subscribing to channels and listening
|
||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||
* allows your team to easily build robust real-time web applications.
|
||||
*/
|
||||
|
||||
// import Echo from 'laravel-echo'
|
||||
|
||||
// window.Pusher = require('pusher-js');
|
||||
|
||||
// window.Echo = new Echo({
|
||||
// broadcaster: 'pusher',
|
||||
// key: process.env.MIX_PUSHER_APP_KEY,
|
||||
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
||||
// encrypted: true
|
||||
// });
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/js/src/client/client_edit.ts":
|
||||
@ -34370,28 +34442,14 @@ module.exports = function(module) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
/* Allows us to use our native translation easily using {{ trans() }} syntax */
|
||||
//const _ = require('lodash');
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/* Allows us to use our native translation easily using {{ trans() }} syntax */
|
||||
//const _ = require('lodash');
|
||||
var _ = __importStar(__webpack_require__("./node_modules/lodash/lodash.js"));
|
||||
__webpack_require__("./resources/js/src/bootstrap.js");
|
||||
var vue_1 = __importDefault(__webpack_require__("./node_modules/vue/dist/vue.common.js"));
|
||||
// import Toastr
|
||||
var vue_toastr_1 = __importDefault(__webpack_require__("./node_modules/vue-toastr/dist/vue-toastr.js"));
|
||||
// import toastr scss file: need webpack sass-loader
|
||||
__webpack_require__("./node_modules/vue-toastr/src/vue-toastr.scss");
|
||||
// Register vue component
|
||||
vue_1.default.component('vue-toastr', vue_toastr_1.default);
|
||||
vue_1.default.prototype.trans = function (string) { return _.get(i18n, string); };
|
||||
/**
|
||||
* Next, we will create a fresh Vue application instance and attach it to
|
||||
* the page. Then, you may begin adding components to this application
|
||||
|
92
public/js/client_edit.min.js
vendored
92
public/js/client_edit.min.js
vendored
@ -34363,6 +34363,78 @@ module.exports = function(module) {
|
||||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/js/src/bootstrap.js":
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash__ = __webpack_require__("./node_modules/lodash/lodash.js");
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash__);
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_toastr__ = __webpack_require__("./node_modules/vue-toastr/dist/vue-toastr.js");
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_toastr___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_vue_toastr__);
|
||||
// lodash handles our translations
|
||||
|
||||
|
||||
// import Toastr
|
||||
|
||||
|
||||
// Import toastr scss file: need webpack sass-loader
|
||||
__webpack_require__("./node_modules/vue-toastr/src/vue-toastr.scss");
|
||||
|
||||
// Register vue component
|
||||
Vue.component('vue-toastr', __WEBPACK_IMPORTED_MODULE_1_vue_toastr___default.a);
|
||||
|
||||
// Global translation helper
|
||||
Vue.prototype.trans = function (string) {
|
||||
return __WEBPACK_IMPORTED_MODULE_0_lodash__["get"](i18n, string);
|
||||
};
|
||||
|
||||
window.axios = __webpack_require__("./node_modules/axios/index.js");
|
||||
window.Vue = __webpack_require__("./node_modules/vue/dist/vue.common.js");
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
/* Development only*/
|
||||
Vue.config.devtools = true;
|
||||
|
||||
window.axios.defaults.headers.common = {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
};
|
||||
|
||||
/**
|
||||
* Next we will register the CSRF Token as a common header with Axios so that
|
||||
* all outgoing HTTP requests automatically have it attached. This is just
|
||||
* a simple convenience so we don't have to attach every token manually.
|
||||
*/
|
||||
|
||||
var token = document.head.querySelector('meta[name="csrf-token"]');
|
||||
|
||||
if (token) {
|
||||
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
|
||||
} else {
|
||||
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
|
||||
}
|
||||
|
||||
/**
|
||||
* Echo exposes an expressive API for subscribing to channels and listening
|
||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||
* allows your team to easily build robust real-time web applications.
|
||||
*/
|
||||
|
||||
// import Echo from 'laravel-echo'
|
||||
|
||||
// window.Pusher = require('pusher-js');
|
||||
|
||||
// window.Echo = new Echo({
|
||||
// broadcaster: 'pusher',
|
||||
// key: process.env.MIX_PUSHER_APP_KEY,
|
||||
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
||||
// encrypted: true
|
||||
// });
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/js/src/client/client_edit.ts":
|
||||
@ -34370,28 +34442,14 @@ module.exports = function(module) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
/* Allows us to use our native translation easily using {{ trans() }} syntax */
|
||||
//const _ = require('lodash');
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/* Allows us to use our native translation easily using {{ trans() }} syntax */
|
||||
//const _ = require('lodash');
|
||||
var _ = __importStar(__webpack_require__("./node_modules/lodash/lodash.js"));
|
||||
__webpack_require__("./resources/js/src/bootstrap.js");
|
||||
var vue_1 = __importDefault(__webpack_require__("./node_modules/vue/dist/vue.common.js"));
|
||||
// import Toastr
|
||||
var vue_toastr_1 = __importDefault(__webpack_require__("./node_modules/vue-toastr/dist/vue-toastr.js"));
|
||||
// import toastr scss file: need webpack sass-loader
|
||||
__webpack_require__("./node_modules/vue-toastr/src/vue-toastr.scss");
|
||||
// Register vue component
|
||||
vue_1.default.component('vue-toastr', vue_toastr_1.default);
|
||||
vue_1.default.prototype.trans = function (string) { return _.get(i18n, string); };
|
||||
/**
|
||||
* Next, we will create a fresh Vue application instance and attach it to
|
||||
* the page. Then, you may begin adding components to this application
|
||||
|
18368
public/js/client_list.js
vendored
Normal file
18368
public/js/client_list.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
18368
public/js/client_list.min.js
vendored
Normal file
18368
public/js/client_list.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
public/js/coreui.js
vendored
4
public/js/coreui.js
vendored
@ -60,7 +60,7 @@
|
||||
/******/ __webpack_require__.p = "/";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 3);
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 4);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
@ -12576,7 +12576,7 @@ PerfectScrollbar.prototype.removePsClasses = function removePsClasses () {
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3:
|
||||
/***/ 4:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__("./node_modules/@coreui/coreui/dist/js/coreui.js");
|
||||
|
4
public/js/coreui.min.js
vendored
4
public/js/coreui.min.js
vendored
@ -60,7 +60,7 @@
|
||||
/******/ __webpack_require__.p = "/";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 3);
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 4);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
@ -12576,7 +12576,7 @@ PerfectScrollbar.prototype.removePsClasses = function removePsClasses () {
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3:
|
||||
/***/ 4:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__("./node_modules/@coreui/coreui/dist/js/coreui.js");
|
||||
|
4
public/js/localization.js
vendored
4
public/js/localization.js
vendored
@ -60,7 +60,7 @@
|
||||
/******/ __webpack_require__.p = "/";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 2);
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 3);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
@ -11548,7 +11548,7 @@ new vue_1.default({
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 2:
|
||||
/***/ 3:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__("./resources/js/src/settings/localization.ts");
|
||||
|
4
public/js/localization.min.js
vendored
4
public/js/localization.min.js
vendored
@ -60,7 +60,7 @@
|
||||
/******/ __webpack_require__.p = "/";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 2);
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 3);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
@ -11548,7 +11548,7 @@ new vue_1.default({
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 2:
|
||||
/***/ 3:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__("./resources/js/src/settings/localization.ts");
|
||||
|
20
resources/js/src/bootstrap.js
vendored
20
resources/js/src/bootstrap.js
vendored
@ -1,8 +1,17 @@
|
||||
/**
|
||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
||||
* to our Laravel back-end. This library automatically handles sending the
|
||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
||||
*/
|
||||
// lodash handles our translations
|
||||
import * as _ from "lodash"
|
||||
|
||||
// import Toastr
|
||||
import Toastr from 'vue-toastr';
|
||||
|
||||
// Import toastr scss file: need webpack sass-loader
|
||||
require('vue-toastr/src/vue-toastr.scss');
|
||||
|
||||
// Register vue component
|
||||
Vue.component('vue-toastr',Toastr);
|
||||
|
||||
// Global translation helper
|
||||
Vue.prototype.trans = string => _.get(i18n, string);
|
||||
|
||||
window.axios = require('axios');
|
||||
window.Vue = require('vue');
|
||||
@ -16,6 +25,7 @@ window.axios.defaults.headers.common = {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
};
|
||||
|
||||
/**
|
||||
* Next we will register the CSRF Token as a common header with Axios so that
|
||||
* all outgoing HTTP requests automatically have it attached. This is just
|
||||
|
@ -21,18 +21,6 @@ declare var hashed_id: string;
|
||||
form: new Form(<Client>client_object)
|
||||
}
|
||||
},
|
||||
mounted(this: any) {
|
||||
//console.log('mounted')
|
||||
},
|
||||
beforeMount: function () {
|
||||
//console.log('before mount')
|
||||
},
|
||||
created:function() {
|
||||
//console.dir('created')
|
||||
},
|
||||
updated:function() {
|
||||
//console.dir('updated')
|
||||
},
|
||||
methods:{
|
||||
remove(this:any, contact:any){
|
||||
let index = this.form.contacts.indexOf(contact);
|
||||
|
@ -1,19 +1,12 @@
|
||||
/* Allows us to use our native translation easily using {{ trans() }} syntax */
|
||||
//const _ = require('lodash');
|
||||
import * as _ from "lodash"
|
||||
|
||||
require('../bootstrap');
|
||||
|
||||
/* Must be declare in every child view*/
|
||||
declare var i18n;
|
||||
|
||||
import Vue from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
// import Toastr
|
||||
import Toastr from 'vue-toastr';
|
||||
// import toastr scss file: need webpack sass-loader
|
||||
require('vue-toastr/src/vue-toastr.scss');
|
||||
// Register vue component
|
||||
Vue.component('vue-toastr',Toastr);
|
||||
|
||||
Vue.prototype.trans = string => _.get(i18n, string);
|
||||
|
||||
/**
|
||||
* Next, we will create a fresh Vue application instance and attach it to
|
||||
@ -25,7 +18,6 @@ Vue.component('client-address', require('../components/client/ClientAddress.vue'
|
||||
Vue.component('generic-address', require('../components/generic/Address.vue'));
|
||||
Vue.component('client-edit-form', require('../components/client/ClientEditForm.vue'));
|
||||
Vue.component('contact-edit', require('../components/client/ClientContactEdit.vue'));
|
||||
|
||||
|
||||
window.onload = function () {
|
||||
|
||||
|
17
resources/js/src/client/client_list.ts
Normal file
17
resources/js/src/client/client_list.ts
Normal file
@ -0,0 +1,17 @@
|
||||
//import * as Vue from 'vue';
|
||||
import Vue from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
Vue.component('client-list', require('../components/client/ClientList.vue'));
|
||||
Vue.component('vuetable', require('vuetable-2/src/components/Vuetable'));
|
||||
Vue.component('vuetable-pagination', require('vuetable-2/src/components/VuetablePagination'));
|
||||
Vue.component('vuetable-pagination-bootstrap', require('../components/util/VuetablePaginationBootstrap'));
|
||||
Vue.component('vuetable-filter-bar', require('../components/util/VuetableFilterBar'));
|
||||
|
||||
window.onload = function () {
|
||||
|
||||
const app = new Vue({
|
||||
el: '#client_list'
|
||||
});
|
||||
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<form @submit.prevent="onSubmit" @keydown="form.errors.clear($event.target.name)">
|
||||
|
||||
|
||||
<div class="row">
|
||||
<!-- Client Details and Address Column -->
|
||||
<div class="col-md-6">
|
||||
@ -46,17 +45,12 @@
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
|
||||
import Vue from 'vue';
|
||||
import axios from 'axios';
|
||||
import Form from '../../utils/form';
|
||||
import Client from '../../models/client-model';
|
||||
|
||||
|
197
resources/js/src/components/client/ClientList.vue
Normal file
197
resources/js/src/components/client/ClientList.vue
Normal file
@ -0,0 +1,197 @@
|
||||
<template>
|
||||
|
||||
<div>
|
||||
<vuetable-filter-bar></vuetable-filter-bar>
|
||||
|
||||
<vuetable ref="vuetable"
|
||||
api-url="/clients"
|
||||
:fields="fields"
|
||||
:per-page="20"
|
||||
:sort-order="sortOrder"
|
||||
:append-params="moreParams"
|
||||
pagination-path=""
|
||||
@vuetable:pagination-data="onPaginationData"></vuetable>
|
||||
|
||||
<div class="vuetable-pagination ui basic segment grid">
|
||||
|
||||
<vuetable-pagination-info ref="paginationInfo"></vuetable-pagination-info>
|
||||
|
||||
<vuetable-pagination ref="pagination"
|
||||
:css="css.pagination"
|
||||
@vuetable-pagination:change-page="onChangePage"></vuetable-pagination>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import Vuetable from 'vuetable-2/src/components/Vuetable.vue'
|
||||
import VuetablePagination from 'vuetable-2/src/components/VuetablePagination.vue'
|
||||
import VuetablePaginationInfo from 'vuetable-2/src/components/VuetablePaginationInfo.vue'
|
||||
import Vue from 'vue'
|
||||
import VueEvents from 'vue-events'
|
||||
|
||||
Vue.use(VueEvents)
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Vuetable,
|
||||
VuetablePagination,
|
||||
VuetablePaginationInfo
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
sortOrder: [
|
||||
{
|
||||
field: 'name',
|
||||
sortField: 'name',
|
||||
direction: 'asc'
|
||||
}
|
||||
],
|
||||
moreParams: {},
|
||||
fields: [
|
||||
{
|
||||
name: '__checkbox', // <----
|
||||
title: '',
|
||||
titleClass: 'center aligned',
|
||||
dataClass: 'center aligned'
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
sortField: 'name',
|
||||
dataClass: 'center aligned'
|
||||
},
|
||||
{
|
||||
name: 'contact',
|
||||
sortField: 'contact',
|
||||
dataClass: 'center aligned'
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
sortField: 'email',
|
||||
dataClass: 'center aligned'
|
||||
},
|
||||
{
|
||||
name: 'client_created_at',
|
||||
title: 'Date created',
|
||||
sortField: 'client_created_at',
|
||||
dataClass: 'center aligned'
|
||||
},
|
||||
{
|
||||
name: 'last_login',
|
||||
title: 'Last login',
|
||||
sortField: 'last_login',
|
||||
dataClass: 'center aligned'
|
||||
},
|
||||
{
|
||||
name: 'balance',
|
||||
sortField: 'balance',
|
||||
dataClass: 'center aligned'
|
||||
}
|
||||
],
|
||||
css: {
|
||||
table: {
|
||||
tableClass: 'table table-striped table-bordered table-hovered',
|
||||
loadingClass: 'loading',
|
||||
ascendingIcon: 'glyphicon glyphicon-chevron-up',
|
||||
descendingIcon: 'glyphicon glyphicon-chevron-down',
|
||||
handleIcon: 'glyphicon glyphicon-menu-hamburger',
|
||||
},
|
||||
pagination: {
|
||||
infoClass: 'pull-left',
|
||||
wrapperClass: 'vuetable-pagination pull-right',
|
||||
activeClass: 'btn-primary',
|
||||
disabledClass: 'disabled',
|
||||
pageClass: 'btn btn-border',
|
||||
linkClass: 'btn btn-border',
|
||||
icons: {
|
||||
first: '',
|
||||
prev: '',
|
||||
next: '',
|
||||
last: '',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
//props: ['list'],
|
||||
mounted() {
|
||||
|
||||
this.$events.$on('filter-set', eventData => this.onFilterSet(eventData))
|
||||
this.$events.$on('filter-reset', e => this.onFilterReset())
|
||||
|
||||
},
|
||||
beforeMount: function () {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
onPaginationData (paginationData : any) {
|
||||
|
||||
this.$refs.pagination.setPaginationData(paginationData)
|
||||
this.$refs.paginationInfo.setPaginationData(paginationData)
|
||||
|
||||
},
|
||||
onChangePage (page : any) {
|
||||
|
||||
this.$refs.vuetable.changePage(page)
|
||||
|
||||
},
|
||||
onFilterSet (filterText) {
|
||||
|
||||
this.moreParams = {
|
||||
'filter': filterText
|
||||
}
|
||||
Vue.nextTick( () => this.$refs.vuetable.refresh())
|
||||
|
||||
},
|
||||
onFilterReset () {
|
||||
this.moreParams = {}
|
||||
Vue.nextTick( () => this.$refs.vuetable.refresh())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.pagination {
|
||||
margin: 0;
|
||||
float: right;
|
||||
}
|
||||
.pagination a.page {
|
||||
border: 1px solid lightgray;
|
||||
border-radius: 3px;
|
||||
padding: 5px 10px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.pagination a.page.active {
|
||||
color: white;
|
||||
background-color: #337ab7;
|
||||
border: 1px solid lightgray;
|
||||
border-radius: 3px;
|
||||
padding: 5px 10px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.pagination a.btn-nav {
|
||||
border: 1px solid lightgray;
|
||||
border-radius: 3px;
|
||||
padding: 5px 7px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.pagination a.btn-nav.disabled {
|
||||
color: lightgray;
|
||||
border: 1px solid lightgray;
|
||||
border-radius: 3px;
|
||||
padding: 5px 7px;
|
||||
margin-right: 2px;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.pagination-info {
|
||||
float: left;
|
||||
}
|
||||
</style>
|
41
resources/js/src/components/util/VuetableFilterBar.vue
Normal file
41
resources/js/src/components/util/VuetableFilterBar.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-9" style="padding:10px;">
|
||||
<div class="input-group">
|
||||
<input type="text" v-model="filterText" class="form-control" @keyup.enter="doFilter" placeholder="search">
|
||||
<button class="btn btn-primary" @click="doFilter">Go</button>
|
||||
<button class="btn btn-light" @click="resetFilter">Reset</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
filterText: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doFilter () {
|
||||
this.$events.fire('filter-set', this.filterText)
|
||||
},
|
||||
resetFilter () {
|
||||
this.filterText = '' // clear the text in text input
|
||||
this.$events.fire('filter-reset')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.form-inline > * {
|
||||
margin:5px 10px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<ul class="pagination">
|
||||
<li :class="{'disabled': isOnFirstPage}">
|
||||
<a href="" @click.prevent="loadPage('prev')">
|
||||
<span>«</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<template v-if="notEnoughPages">
|
||||
<li v-for="n in totalPage" :class="{'active': isCurrentPage(n)}">
|
||||
<a @click.prevent="loadPage(n)" v-html="n"></a>
|
||||
</li>
|
||||
</template>
|
||||
<template v-else>
|
||||
<li v-for="n in windowSize" :class="{'active': isCurrentPage(windowStart+n-1)}">
|
||||
<a @click.prevent="loadPage(windowStart+n-1)" v-html="windowStart+n-1"></a>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<li :class="{'disabled': isOnLastPage}">
|
||||
<a href="" @click.prevent="loadPage('next')">
|
||||
<span>»</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VuetablePaginationMixin from 'vuetable-2/src/components/VuetablePaginationMixin'
|
||||
export default {
|
||||
mixins: [VuetablePaginationMixin]
|
||||
}
|
||||
</script>
|
4
resources/js/src/shims-vue.d.ts
vendored
Normal file
4
resources/js/src/shims-vue.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module '*.vue' {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
}
|
@ -20,9 +20,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ui-view">
|
||||
<div id="ui-view" style="padding-top:20px;">
|
||||
<div class="animated fadeIn">
|
||||
<div class="row col-md-12 card">
|
||||
<div class="col-md-12 card">
|
||||
|
||||
{!! $html->table() !!}
|
||||
|
||||
|
38
resources/views/client/vue_list.blade.php
Normal file
38
resources/views/client/vue_list.blade.php
Normal file
@ -0,0 +1,38 @@
|
||||
@extends('layouts.master', ['header' => $header])
|
||||
|
||||
@section('head')
|
||||
|
||||
@endsection
|
||||
|
||||
@section('body')
|
||||
@parent
|
||||
<main class="main" >
|
||||
<!-- Breadcrumb-->
|
||||
{{ Breadcrumbs::render('clients') }}
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<button class="btn btn-primary btn-lg pull-right">{{ trans('texts.new_client') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="client_list" style="padding-top:20px;">
|
||||
<div class="animated fadeIn">
|
||||
<div class="col-md-12 card">
|
||||
|
||||
<client-list></client-list>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script defer src=" {{ mix('/js/client_list.min.js') }}"></script>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('footer')
|
||||
|
||||
@endsection
|
19
resources/views/vendor/mail/html/button.blade.php
vendored
Normal file
19
resources/views/vendor/mail/html/button.blade.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ $url }}" class="button button-{{ $color ?? 'primary' }}" target="_blank">{{ $slot }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
11
resources/views/vendor/mail/html/footer.blade.php
vendored
Normal file
11
resources/views/vendor/mail/html/footer.blade.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<tr>
|
||||
<td>
|
||||
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="content-cell" align="center">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
7
resources/views/vendor/mail/html/header.blade.php
vendored
Normal file
7
resources/views/vendor/mail/html/header.blade.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<tr>
|
||||
<td class="header">
|
||||
<a href="{{ $url }}">
|
||||
{{ $slot }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
54
resources/views/vendor/mail/html/layout.blade.php
vendored
Normal file
54
resources/views/vendor/mail/html/layout.blade.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
@media only screen and (max-width: 600px) {
|
||||
.inner-body {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
.button {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table class="content" width="100%" cellpadding="0" cellspacing="0">
|
||||
|
||||
|
||||
<!-- Email Body -->
|
||||
<tr>
|
||||
<td class="body" width="100%" cellpadding="0" cellspacing="0">
|
||||
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0">
|
||||
<!-- Body content -->
|
||||
<tr>
|
||||
<td class="content-cell">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
|
||||
{{ $subcopy ?? '' }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{ $footer ?? '' }}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
27
resources/views/vendor/mail/html/message.blade.php
vendored
Normal file
27
resources/views/vendor/mail/html/message.blade.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
@component('mail::layout')
|
||||
{{-- Header --}}
|
||||
@slot('header')
|
||||
@component('mail::header', ['url' => config('app.url')])
|
||||
{{ config('app.name') }}
|
||||
@endcomponent
|
||||
@endslot
|
||||
|
||||
{{-- Body --}}
|
||||
{{ $slot }}
|
||||
|
||||
{{-- Subcopy --}}
|
||||
@isset($subcopy)
|
||||
@slot('subcopy')
|
||||
@component('mail::subcopy')
|
||||
{{ $subcopy }}
|
||||
@endcomponent
|
||||
@endslot
|
||||
@endisset
|
||||
|
||||
{{-- Footer --}}
|
||||
@slot('footer')
|
||||
@component('mail::footer')
|
||||
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
|
||||
@endcomponent
|
||||
@endslot
|
||||
@endcomponent
|
13
resources/views/vendor/mail/html/panel.blade.php
vendored
Normal file
13
resources/views/vendor/mail/html/panel.blade.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<table class="panel" width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="panel-content">
|
||||
<table width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="panel-item">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
7
resources/views/vendor/mail/html/promotion.blade.php
vendored
Normal file
7
resources/views/vendor/mail/html/promotion.blade.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<table class="promotion" align="center" width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td align="center">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
13
resources/views/vendor/mail/html/promotion/button.blade.php
vendored
Normal file
13
resources/views/vendor/mail/html/promotion/button.blade.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ $url }}" class="button button-green" target="_blank">{{ $slot }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
7
resources/views/vendor/mail/html/subcopy.blade.php
vendored
Normal file
7
resources/views/vendor/mail/html/subcopy.blade.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
3
resources/views/vendor/mail/html/table.blade.php
vendored
Normal file
3
resources/views/vendor/mail/html/table.blade.php
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
<div class="table">
|
||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||
</div>
|
290
resources/views/vendor/mail/html/themes/default.css
vendored
Normal file
290
resources/views/vendor/mail/html/themes/default.css
vendored
Normal file
@ -0,0 +1,290 @@
|
||||
/* Base */
|
||||
|
||||
body, body *:not(html):not(style):not(br):not(tr):not(code) {
|
||||
font-family: Avenir, Helvetica, sans-serif;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #f5f8fa;
|
||||
color: #74787E;
|
||||
height: 100%;
|
||||
hyphens: auto;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
-moz-hyphens: auto;
|
||||
-ms-word-break: break-all;
|
||||
width: 100% !important;
|
||||
-webkit-hyphens: auto;
|
||||
-webkit-text-size-adjust: none;
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
blockquote {
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3869D4;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
|
||||
h1 {
|
||||
color: #2F3133;
|
||||
font-size: 19px;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #2F3133;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: #2F3133;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #74787E;
|
||||
font-size: 16px;
|
||||
line-height: 1.5em;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
p.sub {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Layout */
|
||||
|
||||
.wrapper {
|
||||
background-color: #f5f8fa;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
|
||||
.header {
|
||||
padding: 25px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header a {
|
||||
color: #bbbfc3;
|
||||
font-size: 19px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 white;
|
||||
}
|
||||
|
||||
/* Body */
|
||||
|
||||
.body {
|
||||
background-color: #FFFFFF;
|
||||
border-bottom: 1px solid #EDEFF2;
|
||||
border-top: 1px solid #EDEFF2;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
}
|
||||
|
||||
.inner-body {
|
||||
background-color: #FFFFFF;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
width: 570px;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 570px;
|
||||
}
|
||||
|
||||
/* Subcopy */
|
||||
|
||||
.subcopy {
|
||||
border-top: 1px solid #EDEFF2;
|
||||
margin-top: 25px;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.subcopy p {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
.footer {
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
width: 570px;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 570px;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
color: #AEAEAE;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
|
||||
.table table {
|
||||
margin: 30px auto;
|
||||
width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
}
|
||||
|
||||
.table th {
|
||||
border-bottom: 1px solid #EDEFF2;
|
||||
padding-bottom: 8px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.table td {
|
||||
color: #74787E;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
padding: 10px 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.content-cell {
|
||||
padding: 35px;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
|
||||
.action {
|
||||
margin: 30px auto;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
}
|
||||
|
||||
.button {
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
|
||||
color: #FFF;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
.button-blue,
|
||||
.button-primary {
|
||||
background-color: #3097D1;
|
||||
border-top: 10px solid #3097D1;
|
||||
border-right: 18px solid #3097D1;
|
||||
border-bottom: 10px solid #3097D1;
|
||||
border-left: 18px solid #3097D1;
|
||||
}
|
||||
|
||||
.button-green,
|
||||
.button-success {
|
||||
background-color: #2ab27b;
|
||||
border-top: 10px solid #2ab27b;
|
||||
border-right: 18px solid #2ab27b;
|
||||
border-bottom: 10px solid #2ab27b;
|
||||
border-left: 18px solid #2ab27b;
|
||||
}
|
||||
|
||||
.button-red,
|
||||
.button-error {
|
||||
background-color: #bf5329;
|
||||
border-top: 10px solid #bf5329;
|
||||
border-right: 18px solid #bf5329;
|
||||
border-bottom: 10px solid #bf5329;
|
||||
border-left: 18px solid #bf5329;
|
||||
}
|
||||
|
||||
/* Panels */
|
||||
|
||||
.panel {
|
||||
margin: 0 0 21px;
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
background-color: #EDEFF2;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.panel-item {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.panel-item p:last-of-type {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* Promotions */
|
||||
|
||||
.promotion {
|
||||
background-color: #FFFFFF;
|
||||
border: 2px dashed #9BA2AB;
|
||||
margin: 0;
|
||||
margin-bottom: 25px;
|
||||
margin-top: 25px;
|
||||
padding: 24px;
|
||||
width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
}
|
||||
|
||||
.promotion h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.promotion p {
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
}
|
1
resources/views/vendor/mail/markdown/button.blade.php
vendored
Normal file
1
resources/views/vendor/mail/markdown/button.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{ $slot }}: {{ $url }}
|
1
resources/views/vendor/mail/markdown/footer.blade.php
vendored
Normal file
1
resources/views/vendor/mail/markdown/footer.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{ $slot }}
|
1
resources/views/vendor/mail/markdown/header.blade.php
vendored
Normal file
1
resources/views/vendor/mail/markdown/header.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
[{{ $slot }}]({{ $url }})
|
9
resources/views/vendor/mail/markdown/layout.blade.php
vendored
Normal file
9
resources/views/vendor/mail/markdown/layout.blade.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{!! strip_tags($header) !!}
|
||||
|
||||
{!! strip_tags($slot) !!}
|
||||
@isset($subcopy)
|
||||
|
||||
{!! strip_tags($subcopy) !!}
|
||||
@endisset
|
||||
|
||||
{!! strip_tags($footer) !!}
|
27
resources/views/vendor/mail/markdown/message.blade.php
vendored
Normal file
27
resources/views/vendor/mail/markdown/message.blade.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
@component('mail::layout')
|
||||
{{-- Header --}}
|
||||
@slot('header')
|
||||
@component('mail::header', ['url' => config('app.url')])
|
||||
{{ config('app.name') }}
|
||||
@endcomponent
|
||||
@endslot
|
||||
|
||||
{{-- Body --}}
|
||||
{{ $slot }}
|
||||
|
||||
{{-- Subcopy --}}
|
||||
@isset($subcopy)
|
||||
@slot('subcopy')
|
||||
@component('mail::subcopy')
|
||||
{{ $subcopy }}
|
||||
@endcomponent
|
||||
@endslot
|
||||
@endisset
|
||||
|
||||
{{-- Footer --}}
|
||||
@slot('footer')
|
||||
@component('mail::footer')
|
||||
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
|
||||
@endcomponent
|
||||
@endslot
|
||||
@endcomponent
|
1
resources/views/vendor/mail/markdown/panel.blade.php
vendored
Normal file
1
resources/views/vendor/mail/markdown/panel.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{ $slot }}
|
1
resources/views/vendor/mail/markdown/promotion.blade.php
vendored
Normal file
1
resources/views/vendor/mail/markdown/promotion.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{ $slot }}
|
1
resources/views/vendor/mail/markdown/promotion/button.blade.php
vendored
Normal file
1
resources/views/vendor/mail/markdown/promotion/button.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
[{{ $slot }}]({{ $url }})
|
1
resources/views/vendor/mail/markdown/subcopy.blade.php
vendored
Normal file
1
resources/views/vendor/mail/markdown/subcopy.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{ $slot }}
|
1
resources/views/vendor/mail/markdown/table.blade.php
vendored
Normal file
1
resources/views/vendor/mail/markdown/table.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{ $slot }}
|
@ -43,7 +43,6 @@ Route::group(['middleware' => ['auth:user', 'db']], function () {
|
||||
Route::get('logout', 'Auth\LoginController@logout')->name('user.logout');
|
||||
Route::resource('invoices', 'InvoiceController'); // name = (invoices. index / create / show / update / destroy / edit
|
||||
Route::resource('clients', 'ClientController'); // name = (clients. index / create / show / update / destroy / edit
|
||||
Route::resource('c', 'CController'); // name = (clients. index / create / show / update / destroy / edit
|
||||
Route::resource('user', 'UserProfileController'); // name = (clients. index / create / show / update / destroy / edit
|
||||
Route::get('settings', 'SettingsController@index')->name('user.settings');
|
||||
|
||||
|
2
webpack.mix.js
vendored
2
webpack.mix.js
vendored
@ -29,6 +29,7 @@ mix.webpackConfig({
|
||||
|
||||
mix.js('resources/js/src/client/client_edit.ts', 'public/js');
|
||||
mix.js('resources/js/src/client/client_create.ts', 'public/js');
|
||||
mix.js('resources/js/src/client/client_list.ts', 'public/js');
|
||||
mix.js('resources/js/src/settings/localization.ts', 'public/js');
|
||||
mix.js('node_modules/@coreui/coreui/dist/js/coreui.js', 'public/js');
|
||||
|
||||
@ -40,6 +41,7 @@ mix.minify('public/js/ninja.js');
|
||||
mix.minify('public/js/coreui.js');
|
||||
mix.minify('public/js/client_edit.js');
|
||||
mix.minify('public/js/client_create.js');
|
||||
mix.minify('public/js/client_list.js');
|
||||
mix.minify('public/js/localization.js');
|
||||
|
||||
mix.styles([
|
||||
|
Loading…
Reference in New Issue
Block a user