├── .gitignore
├── README.md
├── composer.json
├── dist
└── js
│ └── custom-filters.js
├── mix-manifest.json
├── package.json
├── resources
├── airbnb-modified.css
└── js
│ ├── components
│ ├── DatePicker.vue
│ ├── FilterSelector.vue
│ └── SelectFilter.vue
│ └── index.js
├── src
├── CustomFilter.php
├── DateFilter.php
└── FieldServiceProvider.php
├── webpack.mix.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /vendor
3 | /node_modules
4 | package-lock.json
5 | composer.phar
6 | composer.lock
7 | phpunit.xml
8 | .phpunit.result.cache
9 | .DS_Store
10 | Thumbs.db
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DEPRECATED
2 |
3 | Since Nova 1.1.8 this feature has been adopted to the core. You should upgrade Nova and use that filter instead.
4 |
5 | ## Date Filter for Laravel Nova
6 |
7 | Nova filter that displays a Date Picker instead of a select.
8 |
9 | ### Demo
10 |
11 | 
12 |
13 | ### Install
14 |
15 | Run this command in your nova project:
16 | `composer require 64robots/nova-date-filter`
17 |
18 | ### How to use
19 |
20 | Just use DateFilter class instead of Filter
21 |
22 | ```php
23 | use R64\Filters\DateFilter;
24 |
25 | class DateFrom extends DateFilter
26 | {
27 | //
28 | }
29 | ```
30 |
31 | ### Customization
32 |
33 | As Date Filter is not a select anymore we can use options method to pass the date picker config
34 |
35 | ```php
36 | use R64\Filters\DateFilter;
37 |
38 | class DateFrom extends DateFilter
39 | {
40 | //...
41 |
42 | public function options(Request $request)
43 | {
44 | return [
45 | 'dateFormat' => 'Y-m-d', // default Y-m-d H:i:S
46 | 'placeholder' => 'My placeholder', // default __('Pick a date')
47 | 'disabled' => true, // default false
48 | 'twelveHourTime' => true, // default false
49 | 'enableTime' => true, // default false
50 | 'enableSeconds' => true, // default false
51 | ];
52 | }
53 | }
54 | ```
55 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "64robots/nova-date-filter",
3 | "description": "A Laravel Nova date filter.",
4 | "keywords": [
5 | "laravel",
6 | "nova",
7 | "date",
8 | "filter"
9 | ],
10 | "license": "MIT",
11 | "require": {
12 | "php": ">=7.1.0"
13 | },
14 | "autoload": {
15 | "psr-4": {
16 | "R64\\Filters\\": "src/"
17 | }
18 | },
19 | "extra": {
20 | "laravel": {
21 | "providers": [
22 | "R64\\Filters\\FieldServiceProvider"
23 | ]
24 | }
25 | },
26 | "config": {
27 | "sort-packages": true
28 | },
29 | "minimum-stability": "dev",
30 | "prefer-stable": true
31 | }
32 |
--------------------------------------------------------------------------------
/dist/js/custom-filters.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 | /******/
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 | /******/
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId]) {
10 | /******/ return installedModules[moduleId].exports;
11 | /******/ }
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ i: moduleId,
15 | /******/ l: false,
16 | /******/ exports: {}
17 | /******/ };
18 | /******/
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 | /******/
22 | /******/ // Flag the module as loaded
23 | /******/ module.l = true;
24 | /******/
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 | /******/
29 | /******/
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 | /******/
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 | /******/
36 | /******/ // define getter function for harmony exports
37 | /******/ __webpack_require__.d = function(exports, name, getter) {
38 | /******/ if(!__webpack_require__.o(exports, name)) {
39 | /******/ Object.defineProperty(exports, name, {
40 | /******/ configurable: false,
41 | /******/ enumerable: true,
42 | /******/ get: getter
43 | /******/ });
44 | /******/ }
45 | /******/ };
46 | /******/
47 | /******/ // getDefaultExport function for compatibility with non-harmony modules
48 | /******/ __webpack_require__.n = function(module) {
49 | /******/ var getter = module && module.__esModule ?
50 | /******/ function getDefault() { return module['default']; } :
51 | /******/ function getModuleExports() { return module; };
52 | /******/ __webpack_require__.d(getter, 'a', getter);
53 | /******/ return getter;
54 | /******/ };
55 | /******/
56 | /******/ // Object.prototype.hasOwnProperty.call
57 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
58 | /******/
59 | /******/ // __webpack_public_path__
60 | /******/ __webpack_require__.p = "";
61 | /******/
62 | /******/ // Load entry module and return exports
63 | /******/ return __webpack_require__(__webpack_require__.s = 2);
64 | /******/ })
65 | /************************************************************************/
66 | /******/ ([
67 | /* 0 */
68 | /***/ (function(module, exports) {
69 |
70 | /* globals __VUE_SSR_CONTEXT__ */
71 |
72 | // IMPORTANT: Do NOT use ES2015 features in this file.
73 | // This module is a runtime utility for cleaner component module output and will
74 | // be included in the final webpack user bundle.
75 |
76 | module.exports = function normalizeComponent (
77 | rawScriptExports,
78 | compiledTemplate,
79 | functionalTemplate,
80 | injectStyles,
81 | scopeId,
82 | moduleIdentifier /* server only */
83 | ) {
84 | var esModule
85 | var scriptExports = rawScriptExports = rawScriptExports || {}
86 |
87 | // ES6 modules interop
88 | var type = typeof rawScriptExports.default
89 | if (type === 'object' || type === 'function') {
90 | esModule = rawScriptExports
91 | scriptExports = rawScriptExports.default
92 | }
93 |
94 | // Vue.extend constructor export interop
95 | var options = typeof scriptExports === 'function'
96 | ? scriptExports.options
97 | : scriptExports
98 |
99 | // render functions
100 | if (compiledTemplate) {
101 | options.render = compiledTemplate.render
102 | options.staticRenderFns = compiledTemplate.staticRenderFns
103 | options._compiled = true
104 | }
105 |
106 | // functional template
107 | if (functionalTemplate) {
108 | options.functional = true
109 | }
110 |
111 | // scopedId
112 | if (scopeId) {
113 | options._scopeId = scopeId
114 | }
115 |
116 | var hook
117 | if (moduleIdentifier) { // server build
118 | hook = function (context) {
119 | // 2.3 injection
120 | context =
121 | context || // cached call
122 | (this.$vnode && this.$vnode.ssrContext) || // stateful
123 | (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
124 | // 2.2 with runInNewContext: true
125 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
126 | context = __VUE_SSR_CONTEXT__
127 | }
128 | // inject component styles
129 | if (injectStyles) {
130 | injectStyles.call(this, context)
131 | }
132 | // register component module identifier for async chunk inferrence
133 | if (context && context._registeredComponents) {
134 | context._registeredComponents.add(moduleIdentifier)
135 | }
136 | }
137 | // used by ssr in case component is cached and beforeCreate
138 | // never gets called
139 | options._ssrRegister = hook
140 | } else if (injectStyles) {
141 | hook = injectStyles
142 | }
143 |
144 | if (hook) {
145 | var functional = options.functional
146 | var existing = functional
147 | ? options.render
148 | : options.beforeCreate
149 |
150 | if (!functional) {
151 | // inject component registration as beforeCreate hook
152 | options.beforeCreate = existing
153 | ? [].concat(existing, hook)
154 | : [hook]
155 | } else {
156 | // for template-only hot-reload because in that case the render fn doesn't
157 | // go through the normalizer
158 | options._injectStyles = hook
159 | // register for functioal component in vue file
160 | options.render = function renderWithStyleInjection (h, context) {
161 | hook.call(context)
162 | return existing(h, context)
163 | }
164 | }
165 | }
166 |
167 | return {
168 | esModule: esModule,
169 | exports: scriptExports,
170 | options: options
171 | }
172 | }
173 |
174 |
175 | /***/ }),
176 | /* 1 */
177 | /***/ (function(module, exports) {
178 |
179 | /*
180 | MIT License http://www.opensource.org/licenses/mit-license.php
181 | Author Tobias Koppers @sokra
182 | */
183 | // css base code, injected by the css-loader
184 | module.exports = function(useSourceMap) {
185 | var list = [];
186 |
187 | // return the list of modules as css string
188 | list.toString = function toString() {
189 | return this.map(function (item) {
190 | var content = cssWithMappingToString(item, useSourceMap);
191 | if(item[2]) {
192 | return "@media " + item[2] + "{" + content + "}";
193 | } else {
194 | return content;
195 | }
196 | }).join("");
197 | };
198 |
199 | // import a list of modules into the list
200 | list.i = function(modules, mediaQuery) {
201 | if(typeof modules === "string")
202 | modules = [[null, modules, ""]];
203 | var alreadyImportedModules = {};
204 | for(var i = 0; i < this.length; i++) {
205 | var id = this[i][0];
206 | if(typeof id === "number")
207 | alreadyImportedModules[id] = true;
208 | }
209 | for(i = 0; i < modules.length; i++) {
210 | var item = modules[i];
211 | // skip already imported module
212 | // this implementation is not 100% perfect for weird media query combinations
213 | // when a module is imported multiple times with different media queries.
214 | // I hope this will never occur (Hey this way we have smaller bundles)
215 | if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
216 | if(mediaQuery && !item[2]) {
217 | item[2] = mediaQuery;
218 | } else if(mediaQuery) {
219 | item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
220 | }
221 | list.push(item);
222 | }
223 | }
224 | };
225 | return list;
226 | };
227 |
228 | function cssWithMappingToString(item, useSourceMap) {
229 | var content = item[1] || '';
230 | var cssMapping = item[3];
231 | if (!cssMapping) {
232 | return content;
233 | }
234 |
235 | if (useSourceMap && typeof btoa === 'function') {
236 | var sourceMapping = toComment(cssMapping);
237 | var sourceURLs = cssMapping.sources.map(function (source) {
238 | return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
239 | });
240 |
241 | return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
242 | }
243 |
244 | return [content].join('\n');
245 | }
246 |
247 | // Adapted from convert-source-map (MIT)
248 | function toComment(sourceMap) {
249 | // eslint-disable-next-line no-undef
250 | var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
251 | var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
252 |
253 | return '/*# ' + data + ' */';
254 | }
255 |
256 |
257 | /***/ }),
258 | /* 2 */
259 | /***/ (function(module, exports, __webpack_require__) {
260 |
261 | module.exports = __webpack_require__(3);
262 |
263 |
264 | /***/ }),
265 | /* 3 */
266 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
267 |
268 | "use strict";
269 | Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
270 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__components_DatePicker__ = __webpack_require__(4);
271 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__components_DatePicker___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__components_DatePicker__);
272 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__components_FilterSelector__ = __webpack_require__(16);
273 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__components_FilterSelector___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__components_FilterSelector__);
274 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_SelectFilter__ = __webpack_require__(19);
275 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_SelectFilter___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2__components_SelectFilter__);
276 |
277 |
278 |
279 |
280 | Nova.booting(function (Vue, router) {
281 | Vue.component('date-picker', __WEBPACK_IMPORTED_MODULE_0__components_DatePicker___default.a);
282 | Vue.component('filter-selector', __WEBPACK_IMPORTED_MODULE_1__components_FilterSelector___default.a);
283 | Vue.component('select-filter', __WEBPACK_IMPORTED_MODULE_2__components_SelectFilter___default.a);
284 | });
285 |
286 | /***/ }),
287 | /* 4 */
288 | /***/ (function(module, exports, __webpack_require__) {
289 |
290 | var disposed = false
291 | function injectStyle (ssrContext) {
292 | if (disposed) return
293 | __webpack_require__(5)
294 | }
295 | var normalizeComponent = __webpack_require__(0)
296 | /* script */
297 | var __vue_script__ = __webpack_require__(9)
298 | /* template */
299 | var __vue_template__ = __webpack_require__(15)
300 | /* template functional */
301 | var __vue_template_functional__ = false
302 | /* styles */
303 | var __vue_styles__ = injectStyle
304 | /* scopeId */
305 | var __vue_scopeId__ = "data-v-fa816ef2"
306 | /* moduleIdentifier (server only) */
307 | var __vue_module_identifier__ = null
308 | var Component = normalizeComponent(
309 | __vue_script__,
310 | __vue_template__,
311 | __vue_template_functional__,
312 | __vue_styles__,
313 | __vue_scopeId__,
314 | __vue_module_identifier__
315 | )
316 | Component.options.__file = "resources/js/components/DatePicker.vue"
317 |
318 | /* hot reload */
319 | if (false) {(function () {
320 | var hotAPI = require("vue-hot-reload-api")
321 | hotAPI.install(require("vue"), false)
322 | if (!hotAPI.compatible) return
323 | module.hot.accept()
324 | if (!module.hot.data) {
325 | hotAPI.createRecord("data-v-fa816ef2", Component.options)
326 | } else {
327 | hotAPI.reload("data-v-fa816ef2", Component.options)
328 | }
329 | module.hot.dispose(function (data) {
330 | disposed = true
331 | })
332 | })()}
333 |
334 | module.exports = Component.exports
335 |
336 |
337 | /***/ }),
338 | /* 5 */
339 | /***/ (function(module, exports, __webpack_require__) {
340 |
341 | // style-loader: Adds some css to the DOM by adding a
95 |
--------------------------------------------------------------------------------
/resources/js/components/FilterSelector.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 | {{ filter.name }}
12 |
13 |
14 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
68 |
--------------------------------------------------------------------------------
/resources/js/components/SelectFilter.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
38 |
--------------------------------------------------------------------------------
/resources/js/index.js:
--------------------------------------------------------------------------------
1 | import DatePicker from './components/DatePicker'
2 | import FilterSelector from './components/FilterSelector'
3 | import SelectFilter from './components/SelectFilter'
4 |
5 | Nova.booting((Vue, router) => {
6 | Vue.component('date-picker', DatePicker)
7 | Vue.component('filter-selector', FilterSelector)
8 | Vue.component('select-filter', SelectFilter)
9 | })
10 |
--------------------------------------------------------------------------------
/src/CustomFilter.php:
--------------------------------------------------------------------------------
1 | true,
18 | 'component' => $this->componentName(),
19 | ]);
20 | }
21 |
22 | /**
23 | * The name of the Vue component to be used for this filter
24 | *
25 | * @return string
26 | */
27 | protected abstract function componentName();
28 | }
29 |
--------------------------------------------------------------------------------
/src/DateFilter.php:
--------------------------------------------------------------------------------
1 |