mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Vue Datatables (#2597)
* Adding Vue components for Charts and Multi Select * List Views * Improve UI of datatable * Refactor Vue Datatable for reusability
This commit is contained in:
parent
0faf91dd5d
commit
9204510193
@ -109,7 +109,7 @@ class ClientDatatable extends EntityDatatable
|
||||
* @param $data Std Class of client datatable rows
|
||||
* @return object Rendered action column items
|
||||
*/
|
||||
private function buildActionColumn($data) : object
|
||||
private function buildActionColumn($data)
|
||||
{
|
||||
|
||||
//if(auth()->user()->is_admin())
|
||||
@ -157,4 +157,70 @@ class ClientDatatable extends EntityDatatable
|
||||
|
||||
}
|
||||
|
||||
public function buildOptions()
|
||||
{
|
||||
return collect([
|
||||
'per_page' => 20,
|
||||
'sort_order' => [
|
||||
[
|
||||
'field' => 'name',
|
||||
'sortField' => 'name',
|
||||
'direction' => 'asc',
|
||||
]
|
||||
],
|
||||
'fields' => [
|
||||
[
|
||||
'name' => '__checkbox', // <----
|
||||
'title' => '',
|
||||
'titleClass' => 'center aligned',
|
||||
'dataClass' => 'center aligned'
|
||||
],
|
||||
[
|
||||
'name' => 'name',
|
||||
'title' => trans('texts.name'),
|
||||
'sortField' => 'name',
|
||||
'visible' => false,
|
||||
'dataClass' => 'center aligned'
|
||||
],
|
||||
[
|
||||
'name' => 'contact',
|
||||
'title' => trans('texts.contact'),
|
||||
'sortField' => 'contact',
|
||||
'visible' => false,
|
||||
'dataClass' => 'center aligned'
|
||||
],
|
||||
[
|
||||
'name' => 'email',
|
||||
'title' => trans('texts.email'),
|
||||
'sortField' => 'email',
|
||||
'dataClass' => 'center aligned'
|
||||
],
|
||||
[
|
||||
'name' => 'client_created_at',
|
||||
'title' => trans('texts.date_created'),
|
||||
'sortField' => 'client_created_at',
|
||||
'dataClass' => 'center aligned'
|
||||
],
|
||||
[
|
||||
'name' => 'last_login',
|
||||
'title' => trans('texts.last_login'),
|
||||
'sortField' => 'last_login',
|
||||
'dataClass' => 'center aligned'
|
||||
],
|
||||
[
|
||||
'name' => 'balance',
|
||||
'title' => trans('texts.balance'),
|
||||
'sortField' => 'balance',
|
||||
'dataClass' => 'center aligned'
|
||||
],
|
||||
[
|
||||
'name' => '__component:client-actions',
|
||||
'title' => '',
|
||||
'titleClass' => 'center aligned',
|
||||
'dataClass' => 'center aligned'
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@ -20,6 +20,13 @@ class ClientFilters extends QueryFilters
|
||||
return $this->builder->where('balance', $parts->operator, $parts->value);
|
||||
}
|
||||
|
||||
public function between_balance($balance)
|
||||
{
|
||||
$parts = explode(":", $balance);
|
||||
|
||||
return $this->builder->whereBetween('balance', [$parts[0], $parts[1]]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter by popularity.
|
||||
|
@ -41,7 +41,11 @@ class ClientController extends Controller
|
||||
if(request('page'))
|
||||
return $this->clientDatatable->query(request(), $this->getCurrentCompanyId());
|
||||
|
||||
return view('client.vue_list');
|
||||
$data = [
|
||||
'datatable' => $this->clientDatatable->buildOptions()
|
||||
];
|
||||
|
||||
return view('client.vue_list', $data);
|
||||
/*
|
||||
if (request()->ajax()) {
|
||||
|
||||
@ -212,4 +216,9 @@ class ClientController extends Controller
|
||||
//
|
||||
}
|
||||
|
||||
public function builk()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,9 +31,7 @@
|
||||
"predis/predis": "^1.1",
|
||||
"spatie/laravel-html": "^2.19",
|
||||
"webpatser/laravel-countries": "dev-master#75992ad",
|
||||
"wildbit/postmark-php": "^2.6",
|
||||
"yajra/laravel-datatables": "^1.0",
|
||||
"yajra/laravel-datatables-html": "^3.0"
|
||||
"wildbit/postmark-php": "^2.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"beyondcode/laravel-dump-server": "^1.0",
|
||||
|
956
composer.lock
generated
956
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -159,8 +159,6 @@ return [
|
||||
Illuminate\Translation\TranslationServiceProvider::class,
|
||||
Illuminate\Validation\ValidationServiceProvider::class,
|
||||
Illuminate\View\ViewServiceProvider::class,
|
||||
Yajra\DataTables\DataTablesServiceProvider::class,
|
||||
Yajra\DataTables\HtmlServiceProvider::class,
|
||||
/*
|
||||
* Dependency Service Providers
|
||||
*/
|
||||
|
@ -1,70 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
* Namespaces used by the generator.
|
||||
*/
|
||||
'namespace' => [
|
||||
/*
|
||||
* Base namespace/directory to create the new file.
|
||||
* This is appended on default Laravel namespace.
|
||||
* Usage: php artisan datatables:make User
|
||||
* Output: App\DataTables\UserDataTable
|
||||
* With Model: App\User (default model)
|
||||
* Export filename: users_timestamp
|
||||
*/
|
||||
'base' => 'DataTables',
|
||||
|
||||
/*
|
||||
* Base namespace/directory where your model's are located.
|
||||
* This is appended on default Laravel namespace.
|
||||
* Usage: php artisan datatables:make Post --model
|
||||
* Output: App\DataTables\PostDataTable
|
||||
* With Model: App\Post
|
||||
* Export filename: posts_timestamp
|
||||
*/
|
||||
'model' => '',
|
||||
],
|
||||
|
||||
/*
|
||||
* Set Custom stub folder
|
||||
*/
|
||||
//'stub' => '/resources/custom_stub',
|
||||
|
||||
/*
|
||||
* PDF generator to be used when converting the table to pdf.
|
||||
* Available generators: excel, snappy
|
||||
* Snappy package: barryvdh/laravel-snappy
|
||||
* Excel package: maatwebsite/excel
|
||||
*/
|
||||
'pdf_generator' => 'snappy',
|
||||
|
||||
/*
|
||||
* Snappy PDF options.
|
||||
*/
|
||||
'snappy' => [
|
||||
'options' => [
|
||||
'no-outline' => true,
|
||||
'margin-left' => '0',
|
||||
'margin-right' => '0',
|
||||
'margin-top' => '10mm',
|
||||
'margin-bottom' => '10mm',
|
||||
],
|
||||
'orientation' => 'landscape',
|
||||
],
|
||||
|
||||
/*
|
||||
* Default html builder parameters.
|
||||
*/
|
||||
'parameters' => [
|
||||
'dom' => 'Bfrtip',
|
||||
'order' => [[0, 'desc']],
|
||||
'buttons' => [
|
||||
'create',
|
||||
'export',
|
||||
'print',
|
||||
'reset',
|
||||
'reload',
|
||||
],
|
||||
],
|
||||
];
|
@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
* Request key name to parse includes on fractal.
|
||||
*/
|
||||
'includes' => 'include',
|
||||
|
||||
/*
|
||||
* Default fractal serializer.
|
||||
*/
|
||||
'serializer' => League\Fractal\Serializer\DataArraySerializer::class,
|
||||
];
|
@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
* Default table attributes when generating the table.
|
||||
*/
|
||||
'table' => [
|
||||
'class' => 'table table-hover',
|
||||
'id' => 'ninja',
|
||||
],
|
||||
/*
|
||||
* Default condition to determine if a parameter is a callback or not
|
||||
* Callbacks needs to start by those terms or they will be casted to string
|
||||
*/
|
||||
'callback' => ['$', '$.', 'function'],
|
||||
];
|
@ -1,116 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
* DataTables search options.
|
||||
*/
|
||||
'search' => [
|
||||
/*
|
||||
* Smart search will enclose search keyword with wildcard string "%keyword%".
|
||||
* SQL: column LIKE "%keyword%"
|
||||
*/
|
||||
'smart' => true,
|
||||
|
||||
/*
|
||||
* Multi-term search will explode search keyword using spaces resulting into multiple term search.
|
||||
*/
|
||||
'multi_term' => true,
|
||||
|
||||
/*
|
||||
* Case insensitive will search the keyword in lower case format.
|
||||
* SQL: LOWER(column) LIKE LOWER(keyword)
|
||||
*/
|
||||
'case_insensitive' => true,
|
||||
|
||||
/*
|
||||
* Wild card will add "%" in between every characters of the keyword.
|
||||
* SQL: column LIKE "%k%e%y%w%o%r%d%"
|
||||
*/
|
||||
'use_wildcards' => false,
|
||||
],
|
||||
|
||||
/*
|
||||
* DataTables internal index id response column name.
|
||||
*/
|
||||
'index_column' => 'DT_Row_Index',
|
||||
|
||||
/*
|
||||
* List of available builders for DataTables.
|
||||
* This is where you can register your custom dataTables builder.
|
||||
*/
|
||||
'engines' => [
|
||||
'eloquent' => \Yajra\DataTables\EloquentDataTable::class,
|
||||
'query' => \Yajra\DataTables\QueryDataTable::class,
|
||||
'collection' => \Yajra\DataTables\CollectionDataTable::class,
|
||||
'resource' => \Yajra\DataTables\ApiResourceDataTable::class,
|
||||
],
|
||||
|
||||
/*
|
||||
* DataTables accepted builder to engine mapping.
|
||||
* This is where you can override which engine a builder should use
|
||||
* Note, only change this if you know what you are doing!
|
||||
*/
|
||||
'builders' => [
|
||||
//Illuminate\Database\Eloquent\Relations\Relation::class => 'eloquent',
|
||||
//Illuminate\Database\Eloquent\Builder::class => 'eloquent',
|
||||
//Illuminate\Database\Query\Builder::class => 'query',
|
||||
//Illuminate\Support\Collection::class => 'collection',
|
||||
],
|
||||
|
||||
/*
|
||||
* Nulls last sql pattern for Posgresql & Oracle.
|
||||
* For MySQL, use '-%s %s'
|
||||
*/
|
||||
'nulls_last_sql' => '%s %s NULLS LAST',
|
||||
|
||||
/*
|
||||
* User friendly message to be displayed on user if error occurs.
|
||||
* Possible values:
|
||||
* null - The exception message will be used on error response.
|
||||
* 'throw' - Throws a \Yajra\DataTables\Exceptions\Exception. Use your custom error handler if needed.
|
||||
* 'custom message' - Any friendly message to be displayed to the user. You can also use translation key.
|
||||
*/
|
||||
'error' => env('DATATABLES_ERROR', null),
|
||||
|
||||
/*
|
||||
* Default columns definition of dataTable utility functions.
|
||||
*/
|
||||
'columns' => [
|
||||
/*
|
||||
* List of columns hidden/removed on json response.
|
||||
*/
|
||||
'excess' => ['rn', 'row_num'],
|
||||
|
||||
/*
|
||||
* List of columns to be escaped. If set to *, all columns are escape.
|
||||
* Note: You can set the value to empty array to disable XSS protection.
|
||||
*/
|
||||
'escape' => '*',
|
||||
|
||||
/*
|
||||
* List of columns that are allowed to display html content.
|
||||
* Note: Adding columns to list will make us available to XSS attacks.
|
||||
*/
|
||||
'raw' => ['action'],
|
||||
|
||||
/*
|
||||
* List of columns are are forbidden from being searched/sorted.
|
||||
*/
|
||||
'blacklist' => ['password', 'remember_token'],
|
||||
|
||||
/*
|
||||
* List of columns that are only allowed fo search/sort.
|
||||
* If set to *, all columns are allowed.
|
||||
*/
|
||||
'whitelist' => '*',
|
||||
],
|
||||
|
||||
/*
|
||||
* JsonResponse header and options config.
|
||||
*/
|
||||
'json' => [
|
||||
'header' => [],
|
||||
'options' => 0,
|
||||
],
|
||||
|
||||
];
|
@ -20,7 +20,7 @@
|
||||
"axios": "^0.18",
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"bootstrap": "^4.0.0",
|
||||
"chart.js": "^2.7.2",
|
||||
"chart.js": "^2.7.3",
|
||||
"cross-env": "^5.1",
|
||||
"flag-icon-css": "3.2.0",
|
||||
"font-awesome": "^4.7",
|
||||
@ -45,8 +45,10 @@
|
||||
"socket.io-client": "^2.1.1",
|
||||
"ts-loader": "3.5.0",
|
||||
"typescript": "^3.1.6",
|
||||
"vue-chartjs": "^3.4.0",
|
||||
"vue-events": "^3.1.0",
|
||||
"vue-i18n": "^8.3.0",
|
||||
"vue-multiselect": "^2.1.3",
|
||||
"vue-select": "^2.5.1",
|
||||
"vue-toastr": "^2.0.16"
|
||||
}
|
||||
|
10
public/js/client_edit.js
vendored
10
public/js/client_edit.js
vendored
@ -34374,6 +34374,8 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
/* 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__);
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_vue__ = __webpack_require__("./node_modules/vue/dist/vue.common.js");
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_vue___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_vue__);
|
||||
// lodash handles our translations
|
||||
|
||||
|
||||
@ -34383,11 +34385,13 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
// 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);
|
||||
__WEBPACK_IMPORTED_MODULE_2_vue___default.a.component('vue-toastr', __WEBPACK_IMPORTED_MODULE_1_vue_toastr___default.a);
|
||||
|
||||
// Global translation helper
|
||||
Vue.prototype.trans = function (string) {
|
||||
__WEBPACK_IMPORTED_MODULE_2_vue___default.a.prototype.trans = function (string) {
|
||||
return __WEBPACK_IMPORTED_MODULE_0_lodash__["get"](i18n, string);
|
||||
};
|
||||
|
||||
@ -34397,7 +34401,7 @@ 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;
|
||||
__WEBPACK_IMPORTED_MODULE_2_vue___default.a.config.devtools = true;
|
||||
|
||||
window.axios.defaults.headers.common = {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
|
10
public/js/client_edit.min.js
vendored
10
public/js/client_edit.min.js
vendored
@ -34374,6 +34374,8 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
/* 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__);
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_vue__ = __webpack_require__("./node_modules/vue/dist/vue.common.js");
|
||||
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_vue___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_vue__);
|
||||
// lodash handles our translations
|
||||
|
||||
|
||||
@ -34383,11 +34385,13 @@ Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
// 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);
|
||||
__WEBPACK_IMPORTED_MODULE_2_vue___default.a.component('vue-toastr', __WEBPACK_IMPORTED_MODULE_1_vue_toastr___default.a);
|
||||
|
||||
// Global translation helper
|
||||
Vue.prototype.trans = function (string) {
|
||||
__WEBPACK_IMPORTED_MODULE_2_vue___default.a.prototype.trans = function (string) {
|
||||
return __WEBPACK_IMPORTED_MODULE_0_lodash__["get"](i18n, string);
|
||||
};
|
||||
|
||||
@ -34397,7 +34401,7 @@ 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;
|
||||
__WEBPACK_IMPORTED_MODULE_2_vue___default.a.config.devtools = true;
|
||||
|
||||
window.axios.defaults.headers.common = {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
|
21282
public/js/client_list.js
vendored
21282
public/js/client_list.js
vendored
File diff suppressed because one or more lines are too long
21282
public/js/client_list.min.js
vendored
21282
public/js/client_list.min.js
vendored
File diff suppressed because one or more lines are too long
2
resources/js/src/bootstrap.js
vendored
2
resources/js/src/bootstrap.js
vendored
@ -7,6 +7,8 @@ import Toastr from 'vue-toastr';
|
||||
// Import toastr scss file: need webpack sass-loader
|
||||
require('vue-toastr/src/vue-toastr.scss');
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
// Register vue component
|
||||
Vue.component('vue-toastr',Toastr);
|
||||
|
||||
|
@ -1,13 +1,22 @@
|
||||
//import * as Vue from 'vue';
|
||||
require('../bootstrap');
|
||||
|
||||
/* Must be declare in every child view*/
|
||||
declare var i18n;
|
||||
|
||||
import Vue from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
|
||||
Vue.component('client-list', require('../components/client/ClientList.vue'));
|
||||
Vue.component('client-actions', require('../components/client/ClientActions.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'));
|
||||
Vue.component('vuetable-query-filter', require('../components/client/ClientFilters.vue'));
|
||||
Vue.component('vuetable-multi-select', require('../components/util/VuetableMultiSelect.vue'));
|
||||
Vue.component('list-actions', require('../components/util/VueListActions.vue'));
|
||||
|
||||
|
||||
window.onload = function () {
|
||||
|
||||
|
23
resources/js/src/components/client/ClientFilters.vue
Normal file
23
resources/js/src/components/client/ClientFilters.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<vuetable-filter-bar></vuetable-filter-bar>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
export default {
|
||||
|
||||
mounted() {
|
||||
console.dir('loaded');
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
</style>
|
@ -1,12 +1,11 @@
|
||||
<template>
|
||||
|
||||
<div>
|
||||
<vuetable-filter-bar></vuetable-filter-bar>
|
||||
|
||||
<vuetable ref="vuetable"
|
||||
api-url="/clients"
|
||||
:fields="fields"
|
||||
:per-page="20"
|
||||
:per-page="perPage"
|
||||
:sort-order="sortOrder"
|
||||
:append-params="moreParams"
|
||||
:css="css.table"
|
||||
@ -39,76 +38,27 @@ import VuetableCss from '../util/VuetableCss'
|
||||
Vue.use(VueEvents)
|
||||
|
||||
export default {
|
||||
|
||||
components: {
|
||||
Vuetable,
|
||||
VuetablePagination,
|
||||
VuetablePaginationInfo
|
||||
},
|
||||
data () {
|
||||
data: function () {
|
||||
return {
|
||||
css: VuetableCss,
|
||||
sortOrder: [
|
||||
{
|
||||
field: 'name',
|
||||
sortField: 'name',
|
||||
direction: 'asc'
|
||||
}
|
||||
],
|
||||
perPage: this.datatable.per_page,
|
||||
sortOrder: this.datatable.sort_order,
|
||||
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'
|
||||
},
|
||||
{
|
||||
name: '__component:client-actions', // <----
|
||||
title: '',
|
||||
titleClass: 'center aligned',
|
||||
dataClass: 'center aligned'
|
||||
}
|
||||
]
|
||||
fields: this.datatable.fields
|
||||
}
|
||||
},
|
||||
//props: ['list'],
|
||||
props: ['datatable'],
|
||||
mounted() {
|
||||
|
||||
this.$events.$on('filter-set', eventData => this.onFilterSet(eventData))
|
||||
this.$events.$on('filter-reset', e => this.onFilterReset())
|
||||
|
||||
console.dir(this.datatable)
|
||||
},
|
||||
beforeMount: function () {
|
||||
|
||||
@ -144,7 +94,8 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style type="text/css">
|
||||
|
||||
.pagination {
|
||||
margin: 0;
|
||||
float: right;
|
||||
@ -180,4 +131,12 @@ export default {
|
||||
.pagination-info {
|
||||
float: left;
|
||||
}
|
||||
th {
|
||||
background: #777777;
|
||||
color: #fff;
|
||||
}
|
||||
.sortable th i:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
</style>
|
42
resources/js/src/components/util/VueListActions.vue
Normal file
42
resources/js/src/components/util/VueListActions.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
|
||||
<div class="d-flex justify-content-start">
|
||||
|
||||
<div class="p-2">
|
||||
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary btn-lg">Archive</button>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(81px, 38px, 0px);">
|
||||
<a class="dropdown-item" href="#">Archive</a>
|
||||
<a class="dropdown-item" href="#">Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mr-auto p-2">
|
||||
<vuetable-multi-select></vuetable-multi-select>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto p-2">
|
||||
<vuetable-query-filter></vuetable-query-filter>
|
||||
</div>
|
||||
|
||||
<div class="p-2">
|
||||
<button class="btn btn-primary btn-lg ">{{ trans('texts.new_client') }}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
@ -1,6 +1,6 @@
|
||||
export default {
|
||||
table: {
|
||||
tableClass: 'table table-bordered table-hover',
|
||||
tableClass: 'table table-striped table-hover',
|
||||
loadingClass: 'loading',
|
||||
ascendingIcon: 'fa fa-angle-double-up',
|
||||
descendingIcon: 'fa fa-angle-double-down',
|
||||
|
@ -1,15 +1,11 @@
|
||||
<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">
|
||||
@ -38,4 +34,7 @@
|
||||
.form-inline > * {
|
||||
margin:5px 10px;
|
||||
}
|
||||
.form-control {
|
||||
min-height: 40px;
|
||||
}
|
||||
</style>
|
42
resources/js/src/components/util/VuetableMultiSelect.vue
Normal file
42
resources/js/src/components/util/VuetableMultiSelect.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<!-- Vue component -->
|
||||
<template>
|
||||
<div style="width:300px;">
|
||||
<multiselect v-model="value"
|
||||
:options="options"
|
||||
:multiple="true"
|
||||
:placeholder="trans('texts.status')"
|
||||
@input="onChange"
|
||||
></multiselect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import Multiselect from 'vue-multiselect'
|
||||
|
||||
export default {
|
||||
// OR register locally
|
||||
components: { Multiselect },
|
||||
data () {
|
||||
return {
|
||||
value: 'active',
|
||||
options: ['active', 'archived', 'deleted']
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onChange (value) {
|
||||
console.dir(this.value)
|
||||
this.value = value
|
||||
if (value.indexOf('Reset me!') !== -1) this.value = []
|
||||
},
|
||||
onSelect (option) {
|
||||
if (option === 'Disable me!') this.isDisabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -1,4 +1,4 @@
|
||||
@extends('layouts.master', ['header' => $header])
|
||||
@extends('layouts.master', ['header' => $header])
|
||||
|
||||
@section('body')
|
||||
<main class="main" id="client_create">
|
||||
@ -9,7 +9,7 @@
|
||||
<form @submit.prevent="onSubmit" @keydown="form.errors.clear($event.target.name)">
|
||||
<div class="container-fluid">
|
||||
|
||||
<vue-toastr ref="toastr"></vue-toastr>
|
||||
<vue-toastr ref="toastr"></vue-toastr>
|
||||
|
||||
<div class="row">
|
||||
<!-- Client Details and Address Column -->
|
||||
|
@ -10,23 +10,18 @@
|
||||
<!-- 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 class="container-fluid" id="client_list">
|
||||
|
||||
<list-actions></list-actions>
|
||||
|
||||
<div style="background: #fff;">
|
||||
|
||||
<client-list :datatable="{{ $datatable }}"></client-list>
|
||||
|
||||
</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>
|
||||
|
@ -42,11 +42,17 @@ Route::group(['middleware' => ['auth:user', 'db']], function () {
|
||||
Route::resource('dashboard', 'DashboardController'); // name = (dashboard. index / create / show / update / destroy / edit
|
||||
Route::get('logout', 'Auth\LoginController@logout')->name('user.logout');
|
||||
Route::resource('invoices', 'InvoiceController'); // name = (invoices. index / create / show / update / destroy / edit
|
||||
Route::post('invoices/bulk', 'InvoiceController@bulk')->name('invoices.bulk');
|
||||
Route::resource('clients', 'ClientController'); // name = (clients. index / create / show / update / destroy / edit
|
||||
Route::post('clients/bulk', 'ClientController@bulk')->name('clients.bulk');
|
||||
Route::resource('tasks', 'TaskController'); // name = (tasks. index / create / show / update / destroy / edit
|
||||
Route::post('tasks/bulk', 'TaskController@bulk')->name('tasks.bulk');
|
||||
Route::resource('payments', 'PaymentController'); // name = (payments. index / create / show / update / destroy / edit
|
||||
Route::post('payments/bulk', 'PaymentController@bulk')->name('payments.bulk');
|
||||
Route::resource('credits', 'CreditController'); // name = (credits. index / create / show / update / destroy / edit
|
||||
Route::post('credits/bulk', 'CreditController@bulk')->name('credits.bulk');
|
||||
Route::resource('expenses', 'ExpenseController'); // name = (expenses. index / create / show / update / destroy / edit
|
||||
Route::post('expenses/bulk', 'ExpenseController@bulk')->name('expenses.bulk');
|
||||
Route::resource('user', 'UserProfileController'); // name = (clients. index / create / show / update / destroy / edit
|
||||
Route::get('settings', 'SettingsController@index')->name('user.settings');
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user