From 0f51fb57bb1fedf10e5082cae1ccf22d0b5c459e Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 11:52:31 +0300 Subject: [PATCH 01/20] Refactor on gitignore file --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitignore b/.gitignore index 185e66319..e3408dc73 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,15 @@ node_modules /dist +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +testem.log +/typings + # local env files .env.local .env.*.local From 40064aafa67d8eb279da38fd576499f8a1708635 Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 11:53:46 +0300 Subject: [PATCH 02/20] Fixed AutoComplete error --- src/components/autocomplete/AutoComplete.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/autocomplete/AutoComplete.vue b/src/components/autocomplete/AutoComplete.vue index 728e6366c..ce018acf3 100644 --- a/src/components/autocomplete/AutoComplete.vue +++ b/src/components/autocomplete/AutoComplete.vue @@ -143,7 +143,7 @@ export default { this.focus(); this.hideOverlay(); }, - onMultiContainerClick(event) { + onMultiContainerClick() { this.focus(); }, removeItem(event, index) { From de3fc250ce7d065a13745336084ca1d29bfa6efc Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 11:54:23 +0300 Subject: [PATCH 03/20] Fixed type error on Calendar --- src/components/calendar/Calendar.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/calendar/Calendar.vue b/src/components/calendar/Calendar.vue index fab4708e6..e5d4bcc7c 100644 --- a/src/components/calendar/Calendar.vue +++ b/src/components/calendar/Calendar.vue @@ -87,7 +87,7 @@ export default { panelStyle: null, locale: { type: Object, - default: { + default: () => ({ firstDayOfWeek: 0, dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], @@ -97,7 +97,7 @@ export default { today: 'Today', clear: 'Clear', dateFormat: 'mm/dd/yy' - } + }) } }, computed: { From 272fa24e8f8a57f2ddbfee24bdca3ff6defe684f Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 11:55:02 +0300 Subject: [PATCH 04/20] Fixed PageLinks errors --- src/components/paginator/PageLinks.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/paginator/PageLinks.vue b/src/components/paginator/PageLinks.vue index 991c28520..cf6428b47 100644 --- a/src/components/paginator/PageLinks.vue +++ b/src/components/paginator/PageLinks.vue @@ -17,9 +17,9 @@ return ( <span class="p-paginator-pages"> { - this.value.map((pageLink, i) => { - return <button key={pageLink} class={['p-paginator-page p-paginator-element p-link', { - 'p-highlight': ((pageLink - 1) === this.page)}]} on-click={e => this.onPageLinkClick(e, pageLink)}>{pageLink}</button> + this.value.map(pageLink => { + return (<button key={pageLink} class={['p-paginator-page p-paginator-element p-link', { + 'p-highlight': ((pageLink - 1) === this.page)}]} on-click={e => this.onPageLinkClick(e, pageLink)}>{pageLink}</button>) }) } </span> From f2d3fb491cb1bf57939a2d2eed948967a2cdd73d Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 11:55:36 +0300 Subject: [PATCH 05/20] Fixed SelectButton errors --- src/components/selectbutton/SelectButton.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/selectbutton/SelectButton.vue b/src/components/selectbutton/SelectButton.vue index 3c28a3f49..37cecac69 100644 --- a/src/components/selectbutton/SelectButton.vue +++ b/src/components/selectbutton/SelectButton.vue @@ -1,7 +1,7 @@ <template> <div class="p-selectbutton p-buttonset p-component p-buttonset"> <div v-for="(option, i) of options" :key="getOptionLabel(option)" :aria-label="getOptionLabel(option)" - @click="onOptionSelect($event, option, i)" @keydown.enter.prevent="onOptionSelect($event, option, i)" @keydown.space.prevent="onOptionSelect($event, option, i)" + @click="onOptionSelect($event, option, i)" @keydown.enter.prevent="onOptionSelect($event, option, i)" @keydown.space.prevent="onOptionSelect($event, option)" :tabindex="isOptionDisabled(option) ? null : '0'" @focus="onFocus($event, i)" @blur="onBlur($event)" :class="['p-button p-component p-button-text-only', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option), 'p-focus': (i === focusedIndex)}]"> <slot name="option" :option="option" :index="i"> @@ -41,7 +41,7 @@ export default { isOptionDisabled(option) { return this.optionDisabled ? ObjectUtils.resolveFieldData(option, this.optionDisabled) : false; }, - onOptionSelect(event, option, index) { + onOptionSelect(event, option) { if (this.disabled || this.isOptionDisabled(option)) { return; } From a9349aa4ba2c6345dce336cb2980310828d42aa4 Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 11:55:56 +0300 Subject: [PATCH 06/20] Refactor handlestyle method on Slider --- src/components/slider/Slider.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/slider/Slider.vue b/src/components/slider/Slider.vue index a64a0c039..b9783ef93 100644 --- a/src/components/slider/Slider.vue +++ b/src/components/slider/Slider.vue @@ -278,8 +278,9 @@ export default { handleStyle() { if (this.horizontal) return {'left': this.handlePosition + '%'}; - else if (this.vertical) + else return {'bottom': this.handlePosition + '%'}; + }, handlePosition() { if (this.value === 0) From a8493d07e962741c5dbc7b864ccb2f54f30b9145 Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 11:56:27 +0300 Subject: [PATCH 07/20] Fixed Spinner errors --- src/components/spinner/Spinner.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/spinner/Spinner.vue b/src/components/spinner/Spinner.vue index 714a296ed..517097252 100644 --- a/src/components/spinner/Spinner.vue +++ b/src/components/spinner/Spinner.vue @@ -129,7 +129,7 @@ export default { input: event => { this.$emit('input', event.target.value) }, - focus: event => { + focus: () => { this.focused = true; }, blur: event => { From 9b3fc566288284aa7cf4684a3583e1b734333f10 Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 12:14:35 +0300 Subject: [PATCH 08/20] Fixed Slider errors --- src/components/slider/Slider.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/slider/Slider.vue b/src/components/slider/Slider.vue index b9783ef93..bcfd77187 100644 --- a/src/components/slider/Slider.vue +++ b/src/components/slider/Slider.vue @@ -307,13 +307,13 @@ export default { rangeStartHandleStyle() { if (this.horizontal) return {'left': this.rangeStartPosition + '%'}; - else if (this.vertical) + else return {'bottom': this.rangeStartPosition + '%'}; }, rangeEndHandleStyle() { if (this.horizontal) return {'left': this.rangeEndPosition + '%'}; - else if (this.vertical) + else return {'bottom': this.rangeEndPosition + '%'}; }, } From ed612397f6a8aa409ebdce93761356aa9ac07a3a Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 12:15:55 +0300 Subject: [PATCH 09/20] Fixed editor error --- src/components/editor/Editor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/editor/Editor.vue b/src/components/editor/Editor.vue index 1854c70d4..2f35e74f6 100644 --- a/src/components/editor/Editor.vue +++ b/src/components/editor/Editor.vue @@ -64,7 +64,7 @@ export default { this.renderValue(newValue); } }, - mounted() { + mounted() { this.quill = new Quill(this.$refs.editorElement, { modules: { toolbar: this.$refs.toolbarElement From 4b3837655592a1e699095781bf830848a7f15854 Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 12:17:38 +0300 Subject: [PATCH 10/20] fixed PageLinks error --- src/components/paginator/PageLinks.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/paginator/PageLinks.vue b/src/components/paginator/PageLinks.vue index cf6428b47..7e45b4be0 100644 --- a/src/components/paginator/PageLinks.vue +++ b/src/components/paginator/PageLinks.vue @@ -19,7 +19,7 @@ { this.value.map(pageLink => { return (<button key={pageLink} class={['p-paginator-page p-paginator-element p-link', { - 'p-highlight': ((pageLink - 1) === this.page)}]} on-click={e => this.onPageLinkClick(e, pageLink)}>{pageLink}</button>) + 'p-highlight': ((pageLink - 1) === this.page)}]} on-click={e => this.onPageLinkClick(e, pageLink)}>{pageLink}</button>) }) } </span> From 41d8be4bbba9eb65dc92fb4209d390cfa6fc6efe Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 13:00:20 +0300 Subject: [PATCH 11/20] Fixed eslint issue on Spinner --- src/components/spinner/Spinner.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/spinner/Spinner.vue b/src/components/spinner/Spinner.vue index 517097252..7e51dc8d5 100644 --- a/src/components/spinner/Spinner.vue +++ b/src/components/spinner/Spinner.vue @@ -124,16 +124,18 @@ export default { }, computed: { listeners() { + let vm = this; + return { ...this.$listeners, input: event => { this.$emit('input', event.target.value) }, focus: () => { - this.focused = true; + vm.focused = true; }, blur: event => { - this.focused = false; + vm.focused = false; const parsedValue = this.parseValue(event.target.value); this.$emit('input', parsedValue); From 57b5d60274a4a42d35a3f7fc245c030eaecf63fa Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 13:00:49 +0300 Subject: [PATCH 12/20] Fixed eslint issue on Password --- src/components/password/Password.vue | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/password/Password.vue b/src/components/password/Password.vue index 727c29317..6fd819597 100644 --- a/src/components/password/Password.vue +++ b/src/components/password/Password.vue @@ -78,6 +78,8 @@ export default { }, computed: { listeners() { + let vm = this; + return { ...this.$listeners, input: event => this.$emit('input', event.target.value), @@ -87,8 +89,8 @@ export default { this.createPanel(); } - this.panel.style.zIndex = String(DomHandler.generateZIndex()); - this.panel.style.display = 'block'; + vm.panel.style.zIndex = String(DomHandler.generateZIndex()); + vm.panel.style.display = 'block'; setTimeout(() => { DomHandler.addClass(this.panel, 'p-input-overlay-visible'); DomHandler.removeClass(this.panel, 'p-input-overlay-hidden'); @@ -104,7 +106,7 @@ export default { DomHandler.removeClass(this.panel, 'p-input-overlay-visible'); setTimeout(() => { - this.panel.style.display = 'none'; + vm.panel.style.display = 'none'; DomHandler.removeClass(this.panel, 'p-input-overlay-hidden'); }, 150); } @@ -138,8 +140,8 @@ export default { } } - this.meter.style.backgroundPosition = meterPos; - this.info.textContent = label; + vm.meter.style.backgroundPosition = meterPos; + vm.info.textContent = label; } this.$emit('keyup', event); From beafc5a03f6f510f663aba1762686bd96b955c34 Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 13:37:34 +0300 Subject: [PATCH 13/20] Fixed #7 - Refactor on multiSelect --- src/components/multiselect/MultiSelect.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/multiselect/MultiSelect.vue b/src/components/multiselect/MultiSelect.vue index d2f10800a..4c9005543 100644 --- a/src/components/multiselect/MultiSelect.vue +++ b/src/components/multiselect/MultiSelect.vue @@ -251,7 +251,7 @@ export default { bindOutsideClickListener() { if (!this.outsideClickListener) { this.outsideClickListener = (event) => { - if (this.overlayVisible && this.$refs.overlay && !this.$refs.overlay.contains(event.target)) { + if (this.overlayVisible && this.isOutsideClicked(event)) { this.overlayVisible = false; } }; @@ -264,6 +264,9 @@ export default { this.outsideClickListener = null; } }, + isOutsideClicked(event) { + return !(this.$refs.container.isSameNode(event.target) || this.$refs.container.contains(event.target) || (this.$refs.overlay && this.$refs.overlay.contains(event.target))); + }, getLabelByValue(val) { let label = null; From fd6b9abc25029bf9890157b31264b31bcc4e54d7 Mon Sep 17 00:00:00 2001 From: mertsincan <sincan.mert@gmail.com> Date: Fri, 3 May 2019 16:18:41 +0300 Subject: [PATCH 14/20] Fixed #6 - Fixed editor issue --- src/components/editor/Editor.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/editor/Editor.vue b/src/components/editor/Editor.vue index 2f35e74f6..e77e1cf8f 100644 --- a/src/components/editor/Editor.vue +++ b/src/components/editor/Editor.vue @@ -60,8 +60,10 @@ export default { }, quill: null, watch: { - value(newValue) { + value(newValue, oldValue) { + if (newValue !== oldValue && this.quill && !this.quill.hasFocus()) { this.renderValue(newValue); + } } }, mounted() { From dbb5146eb8f49f15541659406db76d9ce4a8d128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merve=20=C3=96z=C3=A7if=C3=A7i?= <merveozcifci7@gmail.com> Date: Tue, 7 May 2019 13:24:05 +0300 Subject: [PATCH 15/20] DataView component initial --- public/demo/data/cars-large.json | 1204 +++++++++++++++++ public/demo/data/cars-medium.json | 54 + public/demo/data/cars-small.json | 14 + src/AppMenu.vue | 1 + src/components/dataview/DataView.css | 41 + src/components/dataview/DataView.vue | 168 +++ .../dataview/DataViewLayoutOptions.vue | 41 + src/main.js | 4 + src/router.js | 5 + src/service/CarService.js | 16 + src/views/dataview/DataViewDemo.vue | 86 ++ src/views/dataview/DataViewDoc.vue | 297 ++++ 12 files changed, 1931 insertions(+) create mode 100644 public/demo/data/cars-large.json create mode 100644 public/demo/data/cars-medium.json create mode 100644 public/demo/data/cars-small.json create mode 100644 src/components/dataview/DataView.css create mode 100644 src/components/dataview/DataView.vue create mode 100644 src/components/dataview/DataViewLayoutOptions.vue create mode 100644 src/service/CarService.js create mode 100644 src/views/dataview/DataViewDemo.vue create mode 100644 src/views/dataview/DataViewDoc.vue diff --git a/public/demo/data/cars-large.json b/public/demo/data/cars-large.json new file mode 100644 index 000000000..751150284 --- /dev/null +++ b/public/demo/data/cars-large.json @@ -0,0 +1,1204 @@ +{ + "data":[ + { + "vin":"ee8a89d8", + "brand":"Fiat", + "year":1987, + "color":"Maroon" + }, + { + "vin":"642b3edc", + "brand":"Renault", + "year":1968, + "color":"White" + }, + { + "vin":"19ec7580", + "brand":"Renault", + "year":1981, + "color":"Black" + }, + { + "vin":"39980f30", + "brand":"VW", + "year":1986, + "color":"Red" + }, + { + "vin":"ec9cc4e4", + "brand":"Fiat", + "year":1981, + "color":"Brown" + }, + { + "vin":"09a06548", + "brand":"VW", + "year":1965, + "color":"Green" + }, + { + "vin":"05c47246", + "brand":"Mercedes", + "year":2007, + "color":"Blue" + }, + { + "vin":"a9cb87aa", + "brand":"Fiat", + "year":1962, + "color":"Green" + }, + { + "vin":"eae758fa", + "brand":"BMW", + "year":1999, + "color":"Yellow" + }, + { + "vin":"1241c403", + "brand":"Jaguar", + "year":1964, + "color":"Yellow" + }, + { + "vin":"13f853a7", + "brand":"Honda", + "year":2006, + "color":"White" + }, + { + "vin":"447d9ed9", + "brand":"Jaguar", + "year":2005, + "color":"Orange" + }, + { + "vin":"78fa052e", + "brand":"Jaguar", + "year":1990, + "color":"Orange" + }, + { + "vin":"8b77772a", + "brand":"Mercedes", + "year":1991, + "color":"Blue" + }, + { + "vin":"23ba7e86", + "brand":"Honda", + "year":1975, + "color":"Yellow" + }, + { + "vin":"9bacb32d", + "brand":"Volvo", + "year":1968, + "color":"Brown" + }, + { + "vin":"62094d91", + "brand":"Mercedes", + "year":1962, + "color":"Green" + }, + { + "vin":"dc7003f4", + "brand":"Jaguar", + "year":1976, + "color":"Maroon" + }, + { + "vin":"08607aef", + "brand":"Mercedes", + "year":1987, + "color":"Maroon" + }, + { + "vin":"45eee33a", + "brand":"BMW", + "year":1980, + "color":"Silver" + }, + { + "vin":"f199ec5c", + "brand":"Jaguar", + "year":1961, + "color":"Green" + }, + { + "vin":"b34cd9e8", + "brand":"VW", + "year":1993, + "color":"Silver" + }, + { + "vin":"54b20b02", + "brand":"Renault", + "year":1967, + "color":"Brown" + }, + { + "vin":"5dd8766e", + "brand":"Honda", + "year":1998, + "color":"Orange" + }, + { + "vin":"df50ce22", + "brand":"Mercedes", + "year":1964, + "color":"White" + }, + { + "vin":"ecb3e9e1", + "brand":"Honda", + "year":2003, + "color":"Silver" + }, + { + "vin":"750d731d", + "brand":"Renault", + "year":1962, + "color":"Blue" + }, + { + "vin":"bec38cf4", + "brand":"Renault", + "year":1960, + "color":"Blue" + }, + { + "vin":"b7752002", + "brand":"Jaguar", + "year":1964, + "color":"Black" + }, + { + "vin":"315fe9c4", + "brand":"Fiat", + "year":1985, + "color":"Red" + }, + { + "vin":"be65f786", + "brand":"Mercedes", + "year":1963, + "color":"Orange" + }, + { + "vin":"786a7d57", + "brand":"Mercedes", + "year":2003, + "color":"Black" + }, + { + "vin":"a3aee412", + "brand":"Volvo", + "year":2003, + "color":"Maroon" + }, + { + "vin":"749e6bdd", + "brand":"Audi", + "year":1995, + "color":"Brown" + }, + { + "vin":"8cc40f50", + "brand":"BMW", + "year":1961, + "color":"Brown" + }, + { + "vin":"5de63a6f", + "brand":"Renault", + "year":1961, + "color":"White" + }, + { + "vin":"bdae1e20", + "brand":"Jaguar", + "year":2008, + "color":"Blue" + }, + { + "vin":"290cc891", + "brand":"VW", + "year":1992, + "color":"Brown" + }, + { + "vin":"007e1014", + "brand":"Renault", + "year":1966, + "color":"Black" + }, + { + "vin":"429c502d", + "brand":"Honda", + "year":1995, + "color":"Silver" + }, + { + "vin":"c336f9b6", + "brand":"Honda", + "year":1991, + "color":"Maroon" + }, + { + "vin":"a6783ba3", + "brand":"Honda", + "year":2004, + "color":"Yellow" + }, + { + "vin":"2ddaf8d5", + "brand":"Volvo", + "year":1982, + "color":"Blue" + }, + { + "vin":"c09c4b15", + "brand":"VW", + "year":1991, + "color":"Blue" + }, + { + "vin":"4609844c", + "brand":"Honda", + "year":1972, + "color":"Black" + }, + { + "vin":"8db7df27", + "brand":"Audi", + "year":1982, + "color":"Blue" + }, + { + "vin":"dcc58086", + "brand":"Audi", + "year":2001, + "color":"Brown" + }, + { + "vin":"f1274cbe", + "brand":"Fiat", + "year":1995, + "color":"Silver" + }, + { + "vin":"0858a5d4", + "brand":"Renault", + "year":1992, + "color":"Green" + }, + { + "vin":"c2d42bb6", + "brand":"Volvo", + "year":1972, + "color":"Green" + }, + { + "vin":"5535cd5a", + "brand":"Renault", + "year":1980, + "color":"Silver" + }, + { + "vin":"e3313e1e", + "brand":"Honda", + "year":2009, + "color":"Orange" + }, + { + "vin":"f4dea691", + "brand":"BMW", + "year":2002, + "color":"Brown" + }, + { + "vin":"ec15a449", + "brand":"Honda", + "year":1990, + "color":"Yellow" + }, + { + "vin":"80b74a0e", + "brand":"BMW", + "year":1979, + "color":"Yellow" + }, + { + "vin":"513fe268", + "brand":"Honda", + "year":1987, + "color":"White" + }, + { + "vin":"6934c8f8", + "brand":"Renault", + "year":1989, + "color":"Red" + }, + { + "vin":"6a4c3ad0", + "brand":"Honda", + "year":1994, + "color":"Yellow" + }, + { + "vin":"e0acd7b5", + "brand":"Mercedes", + "year":1965, + "color":"Red" + }, + { + "vin":"2f31ac35", + "brand":"Jaguar", + "year":1991, + "color":"Brown" + }, + { + "vin":"36104237", + "brand":"VW", + "year":1992, + "color":"Silver" + }, + { + "vin":"5be099b4", + "brand":"BMW", + "year":1991, + "color":"Yellow" + }, + { + "vin":"e2f55f31", + "brand":"BMW", + "year":1967, + "color":"Silver" + }, + { + "vin":"11274338", + "brand":"Mercedes", + "year":1999, + "color":"Blue" + }, + { + "vin":"f710e177", + "brand":"Fiat", + "year":2007, + "color":"White" + }, + { + "vin":"d8375b4b", + "brand":"Volvo", + "year":1977, + "color":"Blue" + }, + { + "vin":"a27ddfe3", + "brand":"VW", + "year":1978, + "color":"Blue" + }, + { + "vin":"d8848162", + "brand":"BMW", + "year":2008, + "color":"Black" + }, + { + "vin":"e9cb3677", + "brand":"BMW", + "year":2004, + "color":"Black" + }, + { + "vin":"c9dc321d", + "brand":"BMW", + "year":1989, + "color":"Red" + }, + { + "vin":"4c75c610", + "brand":"Volvo", + "year":1972, + "color":"Yellow" + }, + { + "vin":"1c90c93d", + "brand":"Audi", + "year":2004, + "color":"Silver" + }, + { + "vin":"5ccc9f7f", + "brand":"Jaguar", + "year":1961, + "color":"Red" + }, + { + "vin":"94498bc0", + "brand":"Fiat", + "year":1965, + "color":"Silver" + }, + { + "vin":"1d1a21f3", + "brand":"Honda", + "year":1985, + "color":"Red" + }, + { + "vin":"ea463ad3", + "brand":"BMW", + "year":1992, + "color":"Blue" + }, + { + "vin":"c24bdeb2", + "brand":"Honda", + "year":1991, + "color":"Red" + }, + { + "vin":"af3b744b", + "brand":"Audi", + "year":1998, + "color":"Green" + }, + { + "vin":"bebd5a96", + "brand":"Jaguar", + "year":1989, + "color":"Black" + }, + { + "vin":"6ef9dbf3", + "brand":"Fiat", + "year":1962, + "color":"Orange" + }, + { + "vin":"eede8f1e", + "brand":"Jaguar", + "year":1977, + "color":"Brown" + }, + { + "vin":"9d11b02d", + "brand":"BMW", + "year":1971, + "color":"Yellow" + }, + { + "vin":"1d4223a1", + "brand":"Mercedes", + "year":1975, + "color":"Brown" + }, + { + "vin":"4d118346", + "brand":"Mercedes", + "year":1985, + "color":"Brown" + }, + { + "vin":"cce76f06", + "brand":"Honda", + "year":1980, + "color":"Maroon" + }, + { + "vin":"2af398ed", + "brand":"Renault", + "year":1970, + "color":"Yellow" + }, + { + "vin":"c0ddab4c", + "brand":"Audi", + "year":2003, + "color":"Silver" + }, + { + "vin":"a27ea639", + "brand":"Mercedes", + "year":1968, + "color":"Yellow" + }, + { + "vin":"e6441f09", + "brand":"Jaguar", + "year":1982, + "color":"Green" + }, + { + "vin":"c4c59d58", + "brand":"Fiat", + "year":2005, + "color":"Orange" + }, + { + "vin":"9d31fc0a", + "brand":"Mercedes", + "year":1974, + "color":"Brown" + }, + { + "vin":"b0ffce2d", + "brand":"Volvo", + "year":1966, + "color":"Yellow" + }, + { + "vin":"ca7e52e3", + "brand":"Honda", + "year":1971, + "color":"Orange" + }, + { + "vin":"56b36f0e", + "brand":"Mercedes", + "year":2008, + "color":"Orange" + }, + { + "vin":"ba045e1e", + "brand":"Jaguar", + "year":1968, + "color":"White" + }, + { + "vin":"fd579989", + "brand":"BMW", + "year":1975, + "color":"Black" + }, + { + "vin":"084850a3", + "brand":"Audi", + "year":1990, + "color":"Red" + }, + { + "vin":"e39245ab", + "brand":"BMW", + "year":1969, + "color":"White" + }, + { + "vin":"41ab14a1", + "brand":"Jaguar", + "year":1987, + "color":"Silver" + }, + { + "vin":"7ec4c1c0", + "brand":"Jaguar", + "year":1980, + "color":"Black" + }, + { + "vin":"bf1c14aa", + "brand":"Audi", + "year":1984, + "color":"Yellow" + }, + { + "vin":"adeff567", + "brand":"Volvo", + "year":2000, + "color":"Brown" + }, + { + "vin":"61e5e07d", + "brand":"Mercedes", + "year":1978, + "color":"Orange" + }, + { + "vin":"7555e46a", + "brand":"Audi", + "year":1966, + "color":"Blue" + }, + { + "vin":"95babbd1", + "brand":"Honda", + "year":1998, + "color":"Black" + }, + { + "vin":"ff6885f7", + "brand":"Audi", + "year":1996, + "color":"White" + }, + { + "vin":"5b5a0031", + "brand":"Audi", + "year":1968, + "color":"Brown" + }, + { + "vin":"de63c575", + "brand":"Mercedes", + "year":1989, + "color":"Yellow" + }, + { + "vin":"6bf3bfbc", + "brand":"Audi", + "year":1968, + "color":"Green" + }, + { + "vin":"d2d2e8d4", + "brand":"Fiat", + "year":1985, + "color":"Green" + }, + { + "vin":"edcab1f7", + "brand":"VW", + "year":1979, + "color":"Silver" + }, + { + "vin":"03234e20", + "brand":"Mercedes", + "year":1962, + "color":"Orange" + }, + { + "vin":"de2a7b08", + "brand":"Honda", + "year":2007, + "color":"Blue" + }, + { + "vin":"717b8282", + "brand":"BMW", + "year":1999, + "color":"Yellow" + }, + { + "vin":"790e7f03", + "brand":"Volvo", + "year":1983, + "color":"White" + }, + { + "vin":"8eefb223", + "brand":"Jaguar", + "year":1983, + "color":"Silver" + }, + { + "vin":"5e524acd", + "brand":"Jaguar", + "year":1994, + "color":"Maroon" + }, + { + "vin":"26b1aff9", + "brand":"BMW", + "year":1965, + "color":"Black" + }, + { + "vin":"c007a623", + "brand":"Renault", + "year":1968, + "color":"Maroon" + }, + { + "vin":"76733e83", + "brand":"Honda", + "year":1991, + "color":"White" + }, + { + "vin":"ef3c14f7", + "brand":"Fiat", + "year":1987, + "color":"Brown" + }, + { + "vin":"2b4ca005", + "brand":"Honda", + "year":2009, + "color":"Silver" + }, + { + "vin":"8191dbb6", + "brand":"BMW", + "year":2005, + "color":"Black" + }, + { + "vin":"f6b3bd94", + "brand":"Renault", + "year":1967, + "color":"Yellow" + }, + { + "vin":"abb19f41", + "brand":"Volvo", + "year":1975, + "color":"Blue" + }, + { + "vin":"7470c95f", + "brand":"Renault", + "year":1996, + "color":"Black" + }, + { + "vin":"5f1b57a3", + "brand":"Volvo", + "year":1986, + "color":"Red" + }, + { + "vin":"ed47a74b", + "brand":"BMW", + "year":2007, + "color":"Brown" + }, + { + "vin":"ed6030f7", + "brand":"Honda", + "year":1990, + "color":"Red" + }, + { + "vin":"944c71dc", + "brand":"Mercedes", + "year":1991, + "color":"Silver" + }, + { + "vin":"c7d838a5", + "brand":"VW", + "year":1980, + "color":"Yellow" + }, + { + "vin":"712db898", + "brand":"Audi", + "year":1965, + "color":"Red" + }, + { + "vin":"99acc06f", + "brand":"BMW", + "year":1995, + "color":"Silver" + }, + { + "vin":"6c68ffa5", + "brand":"Jaguar", + "year":1999, + "color":"Green" + }, + { + "vin":"63893922", + "brand":"Renault", + "year":1991, + "color":"Brown" + }, + { + "vin":"dca5f739", + "brand":"Jaguar", + "year":2002, + "color":"Blue" + }, + { + "vin":"16da6dcb", + "brand":"Jaguar", + "year":2006, + "color":"Blue" + }, + { + "vin":"fe9ca30c", + "brand":"Fiat", + "year":1967, + "color":"Maroon" + }, + { + "vin":"f0193ac7", + "brand":"Mercedes", + "year":1979, + "color":"Orange" + }, + { + "vin":"145f5551", + "brand":"Jaguar", + "year":1993, + "color":"Brown" + }, + { + "vin":"24714317", + "brand":"Mercedes", + "year":1971, + "color":"White" + }, + { + "vin":"1a9c6e4e", + "brand":"Jaguar", + "year":1997, + "color":"Yellow" + }, + { + "vin":"c9b7ef72", + "brand":"Fiat", + "year":1992, + "color":"Maroon" + }, + { + "vin":"b1b6c375", + "brand":"Fiat", + "year":1963, + "color":"Silver" + }, + { + "vin":"7254a003", + "brand":"Audi", + "year":1982, + "color":"White" + }, + { + "vin":"6f0de80f", + "brand":"Renault", + "year":1987, + "color":"Blue" + }, + { + "vin":"e3048f87", + "brand":"Fiat", + "year":1989, + "color":"Blue" + }, + { + "vin":"361e435a", + "brand":"BMW", + "year":1973, + "color":"Green" + }, + { + "vin":"59e6a9f3", + "brand":"BMW", + "year":1964, + "color":"Maroon" + }, + { + "vin":"b791fe05", + "brand":"Mercedes", + "year":1993, + "color":"Yellow" + }, + { + "vin":"68b0dd88", + "brand":"BMW", + "year":2002, + "color":"Green" + }, + { + "vin":"5b439d1f", + "brand":"BMW", + "year":1964, + "color":"Maroon" + }, + { + "vin":"9a7ac9e3", + "brand":"Renault", + "year":1988, + "color":"White" + }, + { + "vin":"d214751d", + "brand":"Honda", + "year":1997, + "color":"White" + }, + { + "vin":"72229390", + "brand":"Mercedes", + "year":1996, + "color":"White" + }, + { + "vin":"b5fbbeee", + "brand":"VW", + "year":1999, + "color":"Brown" + }, + { + "vin":"8972b543", + "brand":"Audi", + "year":1973, + "color":"Black" + }, + { + "vin":"7bc21024", + "brand":"Renault", + "year":1980, + "color":"Yellow" + }, + { + "vin":"5d661964", + "brand":"Renault", + "year":2005, + "color":"Silver" + }, + { + "vin":"a6ccc2d8", + "brand":"Honda", + "year":1994, + "color":"Blue" + }, + { + "vin":"c1f15f28", + "brand":"Volvo", + "year":1999, + "color":"Black" + }, + { + "vin":"161512ce", + "brand":"VW", + "year":1962, + "color":"Black" + }, + { + "vin":"16e0b448", + "brand":"Fiat", + "year":1990, + "color":"Green" + }, + { + "vin":"f0734442", + "brand":"Audi", + "year":1966, + "color":"Orange" + }, + { + "vin":"5e233279", + "brand":"Audi", + "year":1964, + "color":"Green" + }, + { + "vin":"1de720b2", + "brand":"Renault", + "year":2003, + "color":"Orange" + }, + { + "vin":"46efaeb2", + "brand":"Jaguar", + "year":1993, + "color":"Green" + }, + { + "vin":"88f2354c", + "brand":"Jaguar", + "year":2006, + "color":"Black" + }, + { + "vin":"04819fd6", + "brand":"Mercedes", + "year":1983, + "color":"White" + }, + { + "vin":"401771c8", + "brand":"Volvo", + "year":1962, + "color":"Silver" + }, + { + "vin":"8600877b", + "brand":"VW", + "year":1996, + "color":"Black" + }, + { + "vin":"946bd645", + "brand":"Honda", + "year":1991, + "color":"Red" + }, + { + "vin":"ad078e69", + "brand":"Fiat", + "year":1991, + "color":"Brown" + }, + { + "vin":"93138901", + "brand":"Mercedes", + "year":1961, + "color":"Silver" + }, + { + "vin":"f365dfa4", + "brand":"Mercedes", + "year":1980, + "color":"Black" + }, + { + "vin":"22647161", + "brand":"Audi", + "year":2007, + "color":"Blue" + }, + { + "vin":"92d1ee27", + "brand":"Jaguar", + "year":1977, + "color":"Silver" + }, + { + "vin":"137c2b3a", + "brand":"Honda", + "year":1970, + "color":"Blue" + }, + { + "vin":"b05b5235", + "brand":"BMW", + "year":1967, + "color":"Yellow" + }, + { + "vin":"1afbf400", + "brand":"Audi", + "year":1966, + "color":"Maroon" + }, + { + "vin":"8530ae50", + "brand":"BMW", + "year":1979, + "color":"Brown" + }, + { + "vin":"c9a487a3", + "brand":"Volvo", + "year":1981, + "color":"Silver" + }, + { + "vin":"5cb0bed6", + "brand":"Honda", + "year":1962, + "color":"Orange" + }, + { + "vin":"cf7d0b45", + "brand":"Fiat", + "year":1997, + "color":"Green" + }, + { + "vin":"bc762dd0", + "brand":"Jaguar", + "year":2000, + "color":"Yellow" + }, + { + "vin":"97207a61", + "brand":"VW", + "year":1976, + "color":"Blue" + }, + { + "vin":"17680899", + "brand":"Mercedes", + "year":2006, + "color":"Silver" + }, + { + "vin":"d8a98d30", + "brand":"Renault", + "year":1990, + "color":"Green" + }, + { + "vin":"ff01ead0", + "brand":"Audi", + "year":1962, + "color":"Blue" + }, + { + "vin":"38b30a61", + "brand":"Fiat", + "year":1977, + "color":"White" + }, + { + "vin":"9a6793c1", + "brand":"Renault", + "year":1983, + "color":"Red" + }, + { + "vin":"b1f27273", + "brand":"Mercedes", + "year":2007, + "color":"Brown" + }, + { + "vin":"0fa8c1aa", + "brand":"Jaguar", + "year":1982, + "color":"Blue" + }, + { + "vin":"a7520f42", + "brand":"Volvo", + "year":2008, + "color":"Maroon" + }, + { + "vin":"494eba81", + "brand":"BMW", + "year":1966, + "color":"Silver" + }, + { + "vin":"683535b8", + "brand":"Renault", + "year":2003, + "color":"White" + }, + { + "vin":"62e5d216", + "brand":"Audi", + "year":1962, + "color":"Orange" + }, + { + "vin":"16a65b56", + "brand":"Jaguar", + "year":2009, + "color":"Blue" + }, + { + "vin":"d00250a3", + "brand":"BMW", + "year":1978, + "color":"Blue" + }, + { + "vin":"f3c3909d", + "brand":"Renault", + "year":2003, + "color":"Green" + } + ] +} \ No newline at end of file diff --git a/public/demo/data/cars-medium.json b/public/demo/data/cars-medium.json new file mode 100644 index 000000000..cf6869973 --- /dev/null +++ b/public/demo/data/cars-medium.json @@ -0,0 +1,54 @@ +{ + "data":[ + {"vin":"a1653d4d","brand":"VW","year":1998,"color":"White","price":10000}, + {"vin":"ddeb9b10","brand":"Mercedes","year":1985,"color":"Green","price":25000}, + {"vin":"d8ebe413","brand":"Jaguar","year":1979,"color":"Silver","price":30000}, + {"vin":"aab227b7","brand":"Audi","year":1970,"color":"Black","price":12000}, + {"vin":"631f7412","brand":"Volvo","year":1992,"color":"Red","price":15500}, + {"vin":"7d2d22b0","brand":"VW","year":1993,"color":"Maroon","price":40000}, + {"vin":"50e900ca","brand":"Fiat","year":1964,"color":"Blue","price":25000}, + {"vin":"4bbcd603","brand":"Renault","year":1983,"color":"Maroon","price":22000}, + {"vin":"70214c7e","brand":"Renault","year":1961,"color":"Black","price":19000}, + {"vin":"ec229a92","brand":"Audi","year":1984,"color":"Brown","price":36000}, + {"vin":"1083ee40","brand":"VW","year":1984,"color":"Silver","price":215000}, + {"vin":"6e0da3ab","brand":"Volvo","year":1987,"color":"Silver","price":32000}, + {"vin":"5aee636b","brand":"Jaguar","year":1995,"color":"Maroon","price":20000}, + {"vin":"7cc43997","brand":"Jaguar","year":1984,"color":"Orange","price":14000}, + {"vin":"88ec9f66","brand":"Honda","year":1989,"color":"Maroon","price":36000}, + {"vin":"f5a4a5f5","brand":"BMW","year":1986,"color":"Blue","price":28000}, + {"vin":"15b9a5c9","brand":"Mercedes","year":1986,"color":"Orange","price":14000}, + {"vin":"f7e18d01","brand":"Mercedes","year":1991,"color":"White","price":25000}, + {"vin":"cec593d7","brand":"VW","year":1992,"color":"Blue","price":36000}, + {"vin":"d5bac4f0","brand":"Renault","year":2001,"color":"Blue","price":25000}, + {"vin":"56b527c8","brand":"Jaguar","year":1990,"color":"Yellow","price":52000}, + {"vin":"1ac011ff","brand":"Audi","year":1966,"color":"Maroon","price":45000}, + {"vin":"fc074185","brand":"BMW","year":1962,"color":"Blue","price":54000}, + {"vin":"606ba663","brand":"Honda","year":1982,"color":"Blue","price":22000}, + {"vin":"d05060b8","brand":"Mercedes","year":2003,"color":"Silver","price":15000}, + {"vin":"46e4bbe8","brand":"Mercedes","year":1986,"color":"White","price":18000}, + {"vin":"c29da0d7","brand":"BMW","year":1983,"color":"Brown","price":32000}, + {"vin":"24622f70","brand":"VW","year":1973,"color":"Maroon","price":36000}, + {"vin":"7f573d2c","brand":"Mercedes","year":1991,"color":"Red","price":21000}, + {"vin":"b69e6f5c","brand":"Jaguar","year":1993,"color":"Yellow","price":16000}, + {"vin":"ead9bf1d","brand":"Fiat","year":1968,"color":"Maroon","price":43000}, + {"vin":"bc58113e","brand":"Renault","year":1981,"color":"Silver","price":36000}, + {"vin":"2989d5b1","brand":"Honda","year":2006,"color":"Blue","price":240000}, + {"vin":"c243e3a0","brand":"Fiat","year":1990,"color":"Maroon","price":15000}, + {"vin":"e3d3ebf3","brand":"Audi","year":1996,"color":"White","price":28000}, + {"vin":"45337e7a","brand":"Mercedes","year":1982,"color":"Blue","price":14000}, + {"vin":"36e9cf7e","brand":"Fiat","year":2000,"color":"Orange","price":26000}, + {"vin":"036bf135","brand":"Mercedes","year":1973,"color":"Black","price":22000}, + {"vin":"ad612e9f","brand":"Mercedes","year":1975,"color":"Red","price":45000}, + {"vin":"97c6e1e9","brand":"Volvo","year":1967,"color":"Green","price":42000}, + {"vin":"ae962274","brand":"Volvo","year":1982,"color":"Red","price":36000}, + {"vin":"81f8972a","brand":"BMW","year":2007,"color":"Black","price":56000}, + {"vin":"f8506743","brand":"Audi","year":1975,"color":"Blue","price":42000}, + {"vin":"596859d1","brand":"Fiat","year":2002,"color":"Green","price":48000}, + {"vin":"d83c1d9a","brand":"Volvo","year":1972,"color":"Black","price":29000}, + {"vin":"32f41550","brand":"Mercedes","year":1978,"color":"Brown","price":17000}, + {"vin":"c28cd2e4","brand":"Volvo","year":1982,"color":"Silver","price":24000}, + {"vin":"80890dcc","brand":"Audi","year":1962,"color":"White","price":36000}, + {"vin":"4bf1aeb5","brand":"VW","year":2000,"color":"Silver","price":24000}, + {"vin":"45ca4786","brand":"BMW","year":1995,"color":"Maroon","price":50000} + ] +} \ No newline at end of file diff --git a/public/demo/data/cars-small.json b/public/demo/data/cars-small.json new file mode 100644 index 000000000..7a2bc59ef --- /dev/null +++ b/public/demo/data/cars-small.json @@ -0,0 +1,14 @@ +{ + "data": [ + {"brand": "VW", "year": 2012, "color": "Orange", "vin": "dsad231ff"}, + {"brand": "Audi", "year": 2011, "color": "Black", "vin": "gwregre345"}, + {"brand": "Renault", "year": 2005, "color": "Gray", "vin": "h354htr"}, + {"brand": "BMW", "year": 2003, "color": "Blue", "vin": "j6w54qgh"}, + {"brand": "Mercedes", "year": 1995, "color": "Orange", "vin": "hrtwy34"}, + {"brand": "Volvo", "year": 2005, "color": "Black", "vin": "jejtyj"}, + {"brand": "Honda", "year": 2012, "color": "Yellow", "vin": "g43gr"}, + {"brand": "Jaguar", "year": 2013, "color": "Orange", "vin": "greg34"}, + {"brand": "Ford", "year": 2000, "color": "Black", "vin": "h54hw5"}, + {"brand": "Fiat", "year": 2013, "color": "Red", "vin": "245t2s"} + ] +} diff --git a/src/AppMenu.vue b/src/AppMenu.vue index be749747c..98b9b5c51 100644 --- a/src/AppMenu.vue +++ b/src/AppMenu.vue @@ -50,6 +50,7 @@ </a> <div :class="{'submenuhide': activeMenuIndex !== 2, 'submenushow': activeMenuIndex === 2}"> <div> + <router-link to="/dataview">● DataView</router-link> <router-link to="/fullcalendar">● FullCalendar</router-link> <router-link to="/paginator">● Paginator</router-link> </div> diff --git a/src/components/dataview/DataView.css b/src/components/dataview/DataView.css new file mode 100644 index 000000000..c9ff59649 --- /dev/null +++ b/src/components/dataview/DataView.css @@ -0,0 +1,41 @@ +.p-dataview .p-paginator { + text-align: center; +} + +.p-dataview-column { + padding: .25em; +} + +.p-dataview-content-empty { + padding: .25em .625em; +} + +.p-dataview .p-dataview-header, +.p-dataview .p-dataview-footer { + text-align: center; + padding: .5em .75em; +} + +.p-dataview .p-dataview-header { + border-bottom: 0 none; +} + +.p-dataview .p-dataview-footer { + border-top: 0 none; +} + +.p-dataview .p-paginator-top { + border-bottom: 0 none; +} + +.p-dataview .p-paginator-bottom { + border-top: 0 none; +} + +.p-dataview.p-dataview-list > .p-dataview-content > div.p-grid > div { + width: 100%; +} + +.p-dataview-loading-icon { + font-size: 2em; +} \ No newline at end of file diff --git a/src/components/dataview/DataView.vue b/src/components/dataview/DataView.vue new file mode 100644 index 000000000..2e2e3dbac --- /dev/null +++ b/src/components/dataview/DataView.vue @@ -0,0 +1,168 @@ +<template> + <div :class="containerClass"> + <div class="p-dataview-header" v-if="$scopedSlots.header"> + <slot name="header"></slot> + </div> + <Paginator v-if="paginatorTop" :rows="rows" :first="first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" + :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}"></Paginator> + <div class="p-dataview-content"> + <div class="p-grid"> + <template v-for="(data,index) of (value)"> + <slot v-if="$scopedSlots.listItem && layout === 'list'" name="listItem" :data="data" :index="index"></slot> + <slot v-if="$scopedSlots.gridItem && layout === 'grid'" name="gridItem" :data="data" :index="index"></slot> + </template> + <div v-if="isEmpty" class="p-col-12">{{emptyMessage}}</div> + </div> + </div> + <Paginator v-if="paginatorBottom" :rows="rows" :first="first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" + :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}"></Paginator> + <div class="p-dataview-footer" v-if="$scopedSlots.footer"> + <slot name="footer"></slot> + </div> + </div> +</template> +<script> + import ObjectUtils from '../utils/ObjectUtils'; + export default { + props: { + value: { + type: Array, + default: null + }, + layout: { + type: String, + default: 'list' + }, + rows: { + type: Number, + default: null + }, + first: { + type: Number, + default: 0 + }, + totalRecords: { + type: Number, + default: null + }, + paginator: { + type: Boolean, + default: false + }, + paginatorPosition: { + type: String, + default: 'bottom' + }, + alwaysShowPaginator: { + type: Boolean, + default: true + }, + paginatorTemplate: { + type: String, + default: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLinks' + }, + pageLinkSize: { + type: Number, + default: 5 + }, + rowsPerPageOptions: { + type: Array, + default: null + }, + currentPageReportTemplate: { + type: String, + default: '({currentPage} of {totalPages})' + }, + emptyMessage: { + type: String, + default: 'No records found' + }, + sortField: { + type: String, + default: null + }, + sortOrder: { + type: Number, + default: null + }, + lazy: { + type: Boolean, + default: false + } + }, + methods: { + sort() { + if (this.value) { + const value = [...this.value]; + + value.sort((data1, data2) => { + let value1 = ObjectUtils.resolveFieldData(data1, this.sortField); + let value2 = ObjectUtils.resolveFieldData(data2, this.sortField); + let result = null; + + if (value1 == null && value2 != null) + result = -1; + else if (value1 != null && value2 == null) + result = 1; + else if (value1 == null && value2 == null) + result = 0; + else if (typeof value1 === 'string' && typeof value2 === 'string') + result = value1.localeCompare(value2, undefined, { numeric: true }); + else + result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; + + return (this.sortOrder * result); + }); + + return value; + } + else { + return null; + } + }, + processData() { + let data = this.value; + + if (data && data.length) { + if (this.sortField) { + data = this.sort(); + } + } + + return data; + } + }, + computed: { + containerClass() { + return ['p-dataview p-component', { + 'p-dataview-list': (this.layout === 'list'), + 'p-dataview-grid': (this.layout === 'grid') + } + ] + }, + getTotalRecords() { + if (this.totalRecords) + return this.totalRecords; + else + return this.value ? this.value.length : 0; + }, + isEmpty() { + return (!this.value || this.value.length === 0); + }, + paginatorTop() { + if(this.paginatorPosition && (this.paginatorPosition !== 'bottom' || this.paginatorPosition === 'both')) { + return true + } + else + return null; + }, + paginatorBottom() { + if(this.paginatorPosition && (this.paginatorPosition !== 'top' || this.paginatorPosition === 'both')) { + return true + } + else + return null; + } + } + } +</script> \ No newline at end of file diff --git a/src/components/dataview/DataViewLayoutOptions.vue b/src/components/dataview/DataViewLayoutOptions.vue new file mode 100644 index 000000000..b486cef5b --- /dev/null +++ b/src/components/dataview/DataViewLayoutOptions.vue @@ -0,0 +1,41 @@ +<template> + <div class="p-dataview-layout-options p-selectbutton p-buttonset"> + <button :class="buttonListClass" @click="changeLayout($event,'list')"> + <i class="pi pi-bars p-button-icon-left"></i> + <span class="p-button-text p-clickable">p-btn</span> + </button> + <button :class="buttonGridClass" @click="changeLayout($event,'grid')"> + <i class="pi pi-th-large p-button-icon-left"></i> + <span class="p-button-text p-clickable">p-btn</span> + </button> + </div> +</template> +<script> + export default { + props: { + layout: { + type: String, + default: null + } + }, + computed: { + buttonListClass(){ + return [ + 'p-button p-button-icon-only', + {'p-highlight': this.layout === 'list'} + ] + }, + buttonGridClass(){ + return [ + 'p-button p-button-icon-only', + {'p-highlight': this.layout === 'grid'} + ] + } + }, + methods: { + changeLayout(event, layoutMode){ + this.$emit('change', {originalEvent: event, value: layoutMode}); + } + } + } +</script> \ No newline at end of file diff --git a/src/main.js b/src/main.js index ce19b4443..a91d42289 100644 --- a/src/main.js +++ b/src/main.js @@ -10,6 +10,8 @@ import Card from './components/card/Card'; import Chart from './components/chart/Chart'; import Checkbox from './components/checkbox/Checkbox'; import Chips from './components/chips/Chips'; +import DataView from './components/dataview/DataView'; +import DataViewLayoutOptions from './components/dataview/DataViewLayoutOptions'; import Dialog from './components/dialog/Dialog'; import Dropdown from './components/dropdown/Dropdown'; import Editor from './components/editor/Editor'; @@ -63,6 +65,8 @@ Vue.component('Card', Card); Vue.component('Chart', Chart); Vue.component('Checkbox', Checkbox); Vue.component('Chips', Chips); +Vue.component('DataView', DataView); +Vue.component('DataViewLayoutOptions', DataViewLayoutOptions); Vue.component('Dialog', Dialog); Vue.component('Dropdown', Dropdown); Vue.component('Editor', Editor); diff --git a/src/router.js b/src/router.js index cea779ab6..7ddd14a0d 100644 --- a/src/router.js +++ b/src/router.js @@ -85,6 +85,11 @@ export default new Router({ path: '/chips', name: 'chips', component: () => import('./views/chips/ChipsDemo.vue') + }, + { + path: '/dataview', + name: 'dataview', + component: () => import('./views/dataview/DataViewDemo.vue') }, { path: '/dialog', diff --git a/src/service/CarService.js b/src/service/CarService.js new file mode 100644 index 000000000..98a1dbb80 --- /dev/null +++ b/src/service/CarService.js @@ -0,0 +1,16 @@ +import axios from 'axios' + +export default class CarService { + + getCarsSmall() { + return axios.get('demo/data/cars-small.json').then(res => res.data.data); + } + + getCarsMedium() { + return axios.get('demo/data/cars-medium.json').then(res => res.data.data); + } + + getCarsLarge() { + return axios.get('demo/data/cars-large.json').then(res => res.data.data); + } +} \ No newline at end of file diff --git a/src/views/dataview/DataViewDemo.vue b/src/views/dataview/DataViewDemo.vue new file mode 100644 index 000000000..715fa1f4a --- /dev/null +++ b/src/views/dataview/DataViewDemo.vue @@ -0,0 +1,86 @@ +<template> + <div> + <div class="content-section introduction"> + <div class="feature-intro"> + <h1>DataView</h1> + <p>DataView displays data in grid or list layout with pagination and sorting features.</p> + </div> + </div> + + <div class="content-section implementation"> + <h3 class="first">Default</h3> + <DataView :value="cars" :layout="layout" paginatorPosition='both' :paginator="true" :rows="20"> + <template #header> + <div class="p-grid"> + <div class="p-col-6" style="text-align: right"></div> + <div class="p-col-6" style="text-align: right"> + <DataViewLayoutOptions :layout="layout" @change="changeMode"></DataViewLayoutOptions> + </div> + </div> + </template> + <template #listItem="slotProps" > + <div class="p-col-12 car-details" style="padding: 2em; border-bottom: 1px solid #d9d9d9"> + <div class="p-grid"> + <div class="p-col-12 p-md-3"> + <img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/> + </div> + <div class="p-col-12 p-md-8 car-data"> + <div>Vin: <b>{{slotProps.data.vin}}</b></div> + <div>Year: <b>{{slotProps.data.year}}</b></div> + <div>Brand: <b>{{slotProps.data.brand}}</b></div> + <div>Color: <b>{{slotProps.data.color}}</b></div> + </div> + + <div class="p-col-12 p-md-1 search-icon" style="margin-top: 40px"> + <Button icon="pi pi-search"></Button> + </div> + </div> + </div> + </template> + <template #gridItem="slotProps"> + <div style="padding: .5em" class="p-col-12 p-md-3"> + <img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/> + <div class="car-detail">{{slotProps.data.year}} - {{slotProps.data.color}}</div> + <hr class="ui-widget-content" style="border-top: 0" /> + <Button icon="pi pi-search"></Button> + </div> + </template> + </DataView> + </div> + + <DataViewDoc /> + </div> +</template> + +<script> + import CarService from '../../service/CarService'; + import DataViewDoc from './DataViewDoc'; + + export default { + data() { + return { + cars: null, + layout: 'list', + } + }, + carService: null, + created() { + this.carService = new CarService(); + }, + mounted() { + this.carService.getCarsLarge().then(data => this.cars = data); + }, + methods: { + changeMode(event) { + this.layout = event.value; + } + }, + components: { + 'DataViewDoc': DataViewDoc + } + } +</script> + +<style scoped> + +</style> \ No newline at end of file diff --git a/src/views/dataview/DataViewDoc.vue b/src/views/dataview/DataViewDoc.vue new file mode 100644 index 000000000..cbe7a70ec --- /dev/null +++ b/src/views/dataview/DataViewDoc.vue @@ -0,0 +1,297 @@ +<template> + <div class="content-section documentation"> + <TabView> + <TabPanel header="Documentation"> + <h3>Import</h3> + <CodeHighlight lang="javascript"> +import DataView from 'primevue/dataview'; + </CodeHighlight> + + <!--<h3>Getting Started</h3> + <p><i>first</i>, <i>rows</i> and <i>totalRecords</i> are the required properties of the Paginator.</p> + <CodeHighlight> + <Paginator :first.sync="first" :rows="10" :totalRecords="totalItemsCount"></Paginator> + </CodeHighlight> + + <h3>Start Offset</h3> + <p><i>first</i> property defines the index of the first item displayed by the paginator and should be used with the sync operator. + This is useful in cases where the paginator needs to be controlled programmatically such as resetting or navigating to a certain page.</p> + <CodeHighlight> + <Paginator :first.sync="offset" :rows="10" :totalRecords="totalItemsCount"></Paginator> + </CodeHighlight> + + <h3>Rows Per Page</h3> + <p>Number of items per page can be changed by the user using a dropdown with the <i>rowsPerPageOptions</i> property which accepts an array of possible values. + As <i>rows</i> also change when the dropdown changes, use the sync operator for two-way binding.</p> + <CodeHighlight> + <Paginator :first.sync="offset" :rows.sync="rows" :totalRecords="totalItemsCount" :rowsPerPageOptions="[10,20,30]"></Paginator> + </CodeHighlight> + + <h3>Template</h3> + <p>Paginator elements can be customized using the template property using the predefined keys, default value is + "FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown". Here are the available elements that + can be placed inside a paginator in any order.</p> + + <ul> + <li>FirstPageLink</li> + <li>PrevPageLink</li> + <li>PageLinks</li> + <li>NextPageLink</li> + <li>LastPageLink</li> + <li>RowsPerPageDropdown</li> + <li>CurrentPageReport</li> + </ul> + + <CodeHighlight> + <Paginator :first.sync="offset" :rows="10" :totalRecords="totalItemsCount" + template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"></Paginator> + </CodeHighlight> + + <h3>Custom Content</h3> + <p>There are two slots available named "left" and "right" to add custom content to these locations. Both slots get + a state object as a slot property to provide the current page, first index and the rows. + </p> + <CodeHighlight> + <template v-pre> + <Paginator :first.sync="offset" :rows="10" :totalRecords="totalItemsCount"> + <template #left="slotProps"> + Page: {{slotProps.state.page}} + First: {{slotProps.state.first}} + Rows: {{slotProps.state.rows}} + </template> + <template #right> + <Button type="button" icon="pi pi-search" /> + </template> + </Paginator> + </template> + </CodeHighlight> + + <h3>Page Change Event</h3> + <p>Paginator provides only one event called <i>page-change</i> that passes all the information about the change event.</p> + <CodeHighlight> + <Paginator :first.sync="offset" :rows="10" :totalRecords="totalItemsCount" @page-change="onPage($event)"></Paginator> + </CodeHighlight> + + <CodeHighlight lang="javascript"> + onPage(event) { + //event.page: New page number + //event.first: Index of first record + //event.rows: Number of rows to display in new page + //event.pageCount: Total number of pages + } + </CodeHighlight> + + <h3>Properties</h3> + <div class="doc-tablewrapper"> + <table class="doc-table"> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Default</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>totalRecords</td> + <td>number</td> + <td>0</td> + <td>Number of total records.</td> + </tr> + <tr> + <td>rows</td> + <td>number</td> + <td>0</td> + <td>Data count to display per page.</td> + </tr> + <tr> + <td>first</td> + <td>number</td> + <td>0</td> + <td>Zero-relative number of the first row to be displayed.</td> + </tr> + <tr> + <td>pageLinkSize</td> + <td>number</td> + <td>5</td> + <td>Number of page links to display.</td> + </tr> + <tr> + <td>rowsPerPageOptions</td> + <td>array</td> + <td>null</td> + <td>Array of integer values to display inside rows per page dropdown.</td> + </tr> + <tr> + <td>template</td> + <td>string</td> + <td>FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown</td> + <td>Template of the paginator.</td> + </tr> + <tr> + <td>currentPageReportTemplate</td> + <td>string</td> + <td>({currentPage} of {totalPages})</td> + <td>Template of the current page report element.</td> + </tr> + </tbody> + </table> + </div> + + <h3>Events</h3> + <div class="doc-tablewrapper"> + <table class="doc-table"> + <thead> + <tr> + <th>Name</th> + <th>Parameters</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>page-change</td> + <td>event.page: New page number <br/> + event.first: Index of first record <br/> + event.rows: Number of rows to display in new page <br/> + event.pageCount: Total number of pages + </td> + <td>Callback to invoke when page changes, the event object contains information about the new state.</td> + </tr> + </tbody> + </table> + </div> + + <h3>Styling</h3> + <p>Following is the list of structural style classes, for theming classes visit <router-link to="/theming">theming</router-link> page.</p> + <div class="doc-tablewrapper"> + <table class="doc-table"> + <thead> + <tr> + <th>Name</th> + <th>Element</th> + </tr> + </thead> + <tbody> + <tr> + <td>p-paginator</td> + <td>Container element.</td> + </tr> + <tr> + <td>p-paginator-first</td> + <td>First page element.</td> + </tr> + <tr> + <td>p-paginator-prev</td> + <td>Previous page element.</td> + </tr> + <tr> + <td>p-paginator-pages</td> + <td>Container of page links.</td> + </tr> + <tr> + <td>p-paginator-page</td> + <td>A page link.</td> + </tr> + <tr> + <td>p-paginator-next</td> + <td>Next pge element.</td> + </tr> + <tr> + <td>p-paginator-last</td> + <td>Last page element.</td> + </tr> + <tr> + <td>p-paginator-rpp-options</td> + <td>Rows per page dropdown.</td> + </tr> + </tbody> + </table> + + <h3>Dependencies</h3> + <p>None.</p> + </div> + </TabPanel> + + <TabPanel header="Source"> + <a href="https://github.com/primefaces/primereact/tree/master/src/showcase/paginator" class="btn-viewsource" target="_blank" rel="noopener noreferrer"> + <span>View on GitHub</span> + </a> + <CodeHighlight> + <template> + <div> + <div class="content-section introduction"> + <div class="feature-intro"> + <h1>Paginator</h1> + <p>Paginator is a generic component to display content in paged format.</p> + </div> + </div> + + <div class="content-section implementation"> + <h3 class="first">Default</h3> + <Paginator :first.sync="first" :rows.sync="rows" :totalRecords="totalRecords" :rowsPerPageOptions="[10,20,30]"></Paginator> + + <h3>Custom Template</h3> + <Paginator :first.sync="first2" :rows="1" :totalRecords="totalRecords2" @page-change="onPageChangeCustom($event)" template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"> + <template #left> + <Button type="button" icon="pi pi-refresh" @click="reset()"/> + </template> + <template #right> + <Button type="button" icon="pi pi-search" /> + </template> + </Paginator> + + <div class="image-gallery"> + <img :src="'/demo/images/nature/' + image + '.jpg'" /> + </div> + </div> + + <PaginatorDoc /> + </div> + </template> + </CodeHighlight> + + <CodeHighlight lang="javascript"> + import PaginatorDoc from './PaginatorDoc'; + + export default { + data() { + return { + first: 0, + rows: 10, + totalRecords: 50, + first2: 0, + totalRecords2: 12, + image: 'nature1' + } + }, + methods: { + onPageChangeCustom(event) { + this.image = 'nature' + (event.page + 1); + }, + reset() { + this.first2 = 0; + this.image = 'nature1'; + } + }, + components: { + 'PaginatorDoc': PaginatorDoc + } + } + </CodeHighlight> + + <CodeHighlight lang="css"> + .p-button.p-button-icon-only { + border-radius: 0; + } + + .image-gallery { + text-align: center; + padding: 1em; + } + </CodeHighlight>--> + </TabPanel> + </TabView> + </div> +</template> \ No newline at end of file From 0f4b1f09a86e2c23b3ef26d68461416f0d09cc67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merve=20=C3=96z=C3=A7if=C3=A7i?= <merveozcifci7@gmail.com> Date: Tue, 7 May 2019 15:54:32 +0300 Subject: [PATCH 16/20] sort and pagination added (DataView) --- src/components/dataview/DataView.vue | 54 ++++++++++++++++++++-------- src/views/dataview/DataViewDemo.vue | 28 +++++++++++++-- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/components/dataview/DataView.vue b/src/components/dataview/DataView.vue index 2e2e3dbac..9680993ae 100644 --- a/src/components/dataview/DataView.vue +++ b/src/components/dataview/DataView.vue @@ -3,18 +3,18 @@ <div class="p-dataview-header" v-if="$scopedSlots.header"> <slot name="header"></slot> </div> - <Paginator v-if="paginatorTop" :rows="rows" :first="first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" + <Paginator v-if="paginatorTop" :rows.sync="rows" :first.sync="firstPage" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}"></Paginator> <div class="p-dataview-content"> <div class="p-grid"> - <template v-for="(data,index) of (value)"> + <template v-for="(data,index) of (templateItems)"> <slot v-if="$scopedSlots.listItem && layout === 'list'" name="listItem" :data="data" :index="index"></slot> <slot v-if="$scopedSlots.gridItem && layout === 'grid'" name="gridItem" :data="data" :index="index"></slot> </template> <div v-if="isEmpty" class="p-col-12">{{emptyMessage}}</div> </div> </div> - <Paginator v-if="paginatorBottom" :rows="rows" :first="first" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" + <Paginator v-if="paginatorBottom" :rows.sync="rows" :first.sync="firstPage" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}"></Paginator> <div class="p-dataview-footer" v-if="$scopedSlots.footer"> <slot name="footer"></slot> @@ -90,7 +90,23 @@ default: false } }, + data() { + return { + firstPage: this.first ? this.first : 0 + } + }, methods: { + processData() { + let data = this.value; + + if (data && data.length) { + if (this.sortField) { + data = this.sort(); + } + } + + return data; + }, sort() { if (this.value) { const value = [...this.value]; @@ -119,17 +135,6 @@ else { return null; } - }, - processData() { - let data = this.value; - - if (data && data.length) { - if (this.sortField) { - data = this.sort(); - } - } - - return data; } }, computed: { @@ -162,6 +167,27 @@ } else return null; + }, + templateItems (){ + let value = this.processData(); + + if (value && value.length) { + if (this.paginator) { + const rows = this.rows; + const first = this.lazy ? 0 : this.firstPage; + const last = rows + first; + let items = []; + + for (let i = first; i < last; i++) { + items.push(value[i]); + } + return items; + } + else { + return value; + } + } + else return null; } } } diff --git a/src/views/dataview/DataViewDemo.vue b/src/views/dataview/DataViewDemo.vue index 715fa1f4a..a686ee380 100644 --- a/src/views/dataview/DataViewDemo.vue +++ b/src/views/dataview/DataViewDemo.vue @@ -9,10 +9,12 @@ <div class="content-section implementation"> <h3 class="first">Default</h3> - <DataView :value="cars" :layout="layout" paginatorPosition='both' :paginator="true" :rows="20"> + <DataView :value="cars" :layout="layout" paginatorPosition='both' :paginator="true" :rows="5" :sortOrder="sortOrder" :sortField="sortField"> <template #header> <div class="p-grid"> - <div class="p-col-6" style="text-align: right"></div> + <div class="p-col-6" style="text-align: left"> + <Dropdown v-model="sortKey" :options="sortOptions" optionLabel="label" placeholder="Sort By" @change="onSortChange($event)"/> + </div> <div class="p-col-6" style="text-align: right"> <DataViewLayoutOptions :layout="layout" @change="changeMode"></DataViewLayoutOptions> </div> @@ -61,6 +63,14 @@ return { cars: null, layout: 'list', + sortKey: null, + sortOrder: null, + sortField: null, + sortOptions: [ + {label: 'Newest First', value: '!year'}, + {label: 'Oldest First', value: 'year'}, + {label: 'Brand', value: 'brand'} + ] } }, carService: null, @@ -73,6 +83,20 @@ methods: { changeMode(event) { this.layout = event.value; + }, + onSortChange(event){ + const value = event.value.value; + + if (value.indexOf('!') === 0) { + this.sortOrder = -1; + this.sortField = value.substring(1, value.length); + this.sortKey = value; + } + else { + this.sortOrder = 1; + this.sortField = value; + this.sortKey = value; + } } }, components: { From d1fb198e5b13a12f08108e430ff20aa13bf16346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merve=20=C3=96z=C3=A7if=C3=A7i?= <merveozcifci7@gmail.com> Date: Tue, 7 May 2019 15:59:31 +0300 Subject: [PATCH 17/20] Showcase fix --- public/demo/images/car/VW.png | Bin 0 -> 10802 bytes src/components/dataview/DataView.vue | 2 +- src/views/dataview/DataViewDemo.vue | 12 +++++++----- 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 public/demo/images/car/VW.png diff --git a/public/demo/images/car/VW.png b/public/demo/images/car/VW.png new file mode 100644 index 0000000000000000000000000000000000000000..cd6ce019773be792f91763a1b70a6b150ee9b3c1 GIT binary patch literal 10802 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 literal 0 HcmV?d00001 diff --git a/src/components/dataview/DataView.vue b/src/components/dataview/DataView.vue index 9680993ae..97ec22888 100644 --- a/src/components/dataview/DataView.vue +++ b/src/components/dataview/DataView.vue @@ -59,7 +59,7 @@ }, paginatorTemplate: { type: String, - default: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLinks' + default: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink' }, pageLinkSize: { type: Number, diff --git a/src/views/dataview/DataViewDemo.vue b/src/views/dataview/DataViewDemo.vue index a686ee380..8b46f2eae 100644 --- a/src/views/dataview/DataViewDemo.vue +++ b/src/views/dataview/DataViewDemo.vue @@ -9,7 +9,7 @@ <div class="content-section implementation"> <h3 class="first">Default</h3> - <DataView :value="cars" :layout="layout" paginatorPosition='both' :paginator="true" :rows="5" :sortOrder="sortOrder" :sortField="sortField"> + <DataView :value="cars" :layout="layout" paginatorPosition='both' :paginator="true" :rows="20" :sortOrder="sortOrder" :sortField="sortField"> <template #header> <div class="p-grid"> <div class="p-col-6" style="text-align: left"> @@ -41,10 +41,12 @@ </template> <template #gridItem="slotProps"> <div style="padding: .5em" class="p-col-12 p-md-3"> - <img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/> - <div class="car-detail">{{slotProps.data.year}} - {{slotProps.data.color}}</div> - <hr class="ui-widget-content" style="border-top: 0" /> - <Button icon="pi pi-search"></Button> + <Panel :header="slotProps.data.vin" style="text-align: center"> + <img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/> + <div class="car-detail">{{slotProps.data.year}} - {{slotProps.data.color}}</div> + <hr class="ui-widget-content" style="border-top: 0" /> + <Button icon="pi pi-search"></Button> + </Panel> </div> </template> </DataView> From 1158948a1a536194eb951e8a42da181ccbe13804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merve=20=C3=96z=C3=A7if=C3=A7i?= <merveozcifci7@gmail.com> Date: Tue, 7 May 2019 16:22:09 +0300 Subject: [PATCH 18/20] Style fix --- src/assets/styles/primevue.css | 1 + src/components/dataview/DataView.vue | 8 ++++---- src/views/dataview/DataViewDemo.vue | 11 +++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/assets/styles/primevue.css b/src/assets/styles/primevue.css index 96772d54e..dd458720d 100644 --- a/src/assets/styles/primevue.css +++ b/src/assets/styles/primevue.css @@ -5,6 +5,7 @@ @import '../../components/card/Card.css'; @import '../../components/checkbox/Checkbox.css'; @import '../../components/chips/Chips.css'; +@import '../../components/dataview/DataView.css'; @import '../../components/dialog/Dialog.css'; @import '../../components/dropdown/Dropdown.css'; @import '../../components/fieldset/Fieldset.css'; diff --git a/src/components/dataview/DataView.vue b/src/components/dataview/DataView.vue index 97ec22888..398a47155 100644 --- a/src/components/dataview/DataView.vue +++ b/src/components/dataview/DataView.vue @@ -3,7 +3,7 @@ <div class="p-dataview-header" v-if="$scopedSlots.header"> <slot name="header"></slot> </div> - <Paginator v-if="paginatorTop" :rows.sync="rows" :first.sync="firstPage" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" + <Paginator v-if="paginatorTop" :rows.sync="rows" :first.sync="firstRecord" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}"></Paginator> <div class="p-dataview-content"> <div class="p-grid"> @@ -14,7 +14,7 @@ <div v-if="isEmpty" class="p-col-12">{{emptyMessage}}</div> </div> </div> - <Paginator v-if="paginatorBottom" :rows.sync="rows" :first.sync="firstPage" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" + <Paginator v-if="paginatorBottom" :rows.sync="rows" :first.sync="firstRecord" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}"></Paginator> <div class="p-dataview-footer" v-if="$scopedSlots.footer"> <slot name="footer"></slot> @@ -92,7 +92,7 @@ }, data() { return { - firstPage: this.first ? this.first : 0 + firstRecord: this.first ? this.first : 0 } }, methods: { @@ -174,7 +174,7 @@ if (value && value.length) { if (this.paginator) { const rows = this.rows; - const first = this.lazy ? 0 : this.firstPage; + const first = this.lazy ? 0 : this.firstRecord; const last = rows + first; let items = []; diff --git a/src/views/dataview/DataViewDemo.vue b/src/views/dataview/DataViewDemo.vue index 8b46f2eae..10b975cdc 100644 --- a/src/views/dataview/DataViewDemo.vue +++ b/src/views/dataview/DataViewDemo.vue @@ -88,16 +88,17 @@ }, onSortChange(event){ const value = event.value.value; + const sortValue = event.value; if (value.indexOf('!') === 0) { this.sortOrder = -1; this.sortField = value.substring(1, value.length); - this.sortKey = value; + this.sortKey = sortValue; } else { this.sortOrder = 1; this.sortField = value; - this.sortKey = value; + this.sortKey = sortValue; } } }, @@ -107,6 +108,8 @@ } </script> -<style scoped> - +<style lang="scss"> +.p-dropdown { + width: 12em; +} </style> \ No newline at end of file From 8b32e2c99d839101600f7b80d816ca5cbc14fa7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merve=20=C3=96z=C3=A7if=C3=A7i?= <merveozcifci7@gmail.com> Date: Thu, 9 May 2019 10:04:41 +0300 Subject: [PATCH 19/20] Paginator template added --- src/components/dataview/DataView.vue | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/dataview/DataView.vue b/src/components/dataview/DataView.vue index 398a47155..63723a7a7 100644 --- a/src/components/dataview/DataView.vue +++ b/src/components/dataview/DataView.vue @@ -4,7 +4,14 @@ <slot name="header"></slot> </div> <Paginator v-if="paginatorTop" :rows.sync="rows" :first.sync="firstRecord" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" - :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}"></Paginator> + :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-top': paginatorTop}"> + <template #left v-if="$scopedSlots.paginatorLeft"> + <slot name="paginatorLeft"></slot> + </template> + <template #right v-if="$scopedSlots.paginatorRight"> + <slot name="paginatorRight"></slot> + </template> + </Paginator> <div class="p-dataview-content"> <div class="p-grid"> <template v-for="(data,index) of (templateItems)"> @@ -15,7 +22,14 @@ </div> </div> <Paginator v-if="paginatorBottom" :rows.sync="rows" :first.sync="firstRecord" :totalRecords="getTotalRecords" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions" - :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}"></Paginator> + :currentPageReportTemplate="currentPageReportTemplate" :class="{'p-paginator-bottom': paginatorBottom}"> + <template #left v-if="$scopedSlots.paginatorLeft"> + <slot name="paginatorLeft"></slot> + </template> + <template #right v-if="$scopedSlots.paginatorRight"> + <slot name="paginatorRight"></slot> + </template> + </Paginator> <div class="p-dataview-footer" v-if="$scopedSlots.footer"> <slot name="footer"></slot> </div> From 70fef9b78c54af3c6a00ab5369a3fb38f285b13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merve=20=C3=96z=C3=A7if=C3=A7i?= <merveozcifci7@gmail.com> Date: Thu, 9 May 2019 12:33:24 +0300 Subject: [PATCH 20/20] Dataview doc added --- src/views/dataview/DataViewDoc.vue | 530 +++++++++++++++++++---------- 1 file changed, 345 insertions(+), 185 deletions(-) diff --git a/src/views/dataview/DataViewDoc.vue b/src/views/dataview/DataViewDoc.vue index cbe7a70ec..99c6a7ebb 100644 --- a/src/views/dataview/DataViewDoc.vue +++ b/src/views/dataview/DataViewDoc.vue @@ -7,79 +7,177 @@ import DataView from 'primevue/dataview'; </CodeHighlight> - <!--<h3>Getting Started</h3> - <p><i>first</i>, <i>rows</i> and <i>totalRecords</i> are the required properties of the Paginator.</p> - <CodeHighlight> - <Paginator :first.sync="first" :rows="10" :totalRecords="totalItemsCount"></Paginator> - </CodeHighlight> + <h3>Getting Started</h3> + <p>DataView requires a collection of items as its value and one or more templates depending on the layout mode e.g. list and grid. Throughout the samples, a car interface having vin, brand, year and color properties are used to define an object to be displayed by the dataview. Cars are loaded by a CarService that connects to a server to fetch the cars.</p> +<CodeHighlight lang="js"> +<template v-pre> +data() { + return { + cars: null, + } +}, +carService: null, +created() { + this.carService = new CarService(); +}, +mounted() { + this.carService.getCarsLarge().then(data => this.cars = data); +} +</template> +</CodeHighlight> - <h3>Start Offset</h3> - <p><i>first</i> property defines the index of the first item displayed by the paginator and should be used with the sync operator. - This is useful in cases where the paginator needs to be controlled programmatically such as resetting or navigating to a certain page.</p> - <CodeHighlight> - <Paginator :first.sync="offset" :rows="10" :totalRecords="totalItemsCount"></Paginator> - </CodeHighlight> + <h3>Layouts</h3> + <p>DataView has two layout modes; "list" and "grid" where a separate template is used to render an item in each mode. In list mode name of the template is "listItem" whereas + in grid mode it is "gridItem".</p> + <p>Note that there is no restriction to use both layouts at the same time, you may configure only one layout using the layout property with the corresponding template.</p> +<CodeHighlight> +<template v-pre> +<template #listItem="slotProps" > + <div class="p-col-12 car-details" style="padding: 2em; border-bottom: 1px solid #d9d9d9"> + <div class="p-grid"> + <div class="p-col-12 p-md-3"> + <img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/> + </div> + <div class="p-col-12 p-md-8 car-data"> + <div>Vin: <b>{{slotProps.data.vin}}</b></div> + <div>Year: <b>{{slotProps.data.year}}</b></div> + <div>Brand: <b>{{slotProps.data.brand}}</b></div> + <div>Color: <b>{{slotProps.data.color}}</b></div> + </div> - <h3>Rows Per Page</h3> - <p>Number of items per page can be changed by the user using a dropdown with the <i>rowsPerPageOptions</i> property which accepts an array of possible values. - As <i>rows</i> also change when the dropdown changes, use the sync operator for two-way binding.</p> - <CodeHighlight> - <Paginator :first.sync="offset" :rows.sync="rows" :totalRecords="totalItemsCount" :rowsPerPageOptions="[10,20,30]"></Paginator> - </CodeHighlight> + <div class="p-col-12 p-md-1 search-icon" style="margin-top: 40px"> + <Button icon="pi pi-search"></Button> + </div> + </div> + </div> +</template> +<template #gridItem="slotProps"> + <div style="padding: .5em" class="p-col-12 p-md-3"> + <Panel :header="slotProps.data.vin" style="text-align: center"> + <img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/> + <div class="car-detail">{{slotProps.data.year}} - {{slotProps.data.color}}</div> + <hr class="ui-widget-content" style="border-top: 0" /> + <Button icon="pi pi-search"></Button> + </Panel> + </div> +</template> +</template> +</CodeHighlight> - <h3>Template</h3> - <p>Paginator elements can be customized using the template property using the predefined keys, default value is - "FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown". Here are the available elements that - can be placed inside a paginator in any order.</p> + <h3>Sections</h3> + <p>Header and Footer are the two sections that are capable of displaying custom content.</p> +<CodeHighlight> +<template #header>List of Cars</template> +</CodeHighlight> - <ul> - <li>FirstPageLink</li> - <li>PrevPageLink</li> - <li>PageLinks</li> - <li>NextPageLink</li> - <li>LastPageLink</li> - <li>RowsPerPageDropdown</li> - <li>CurrentPageReport</li> - </ul> - - <CodeHighlight> - <Paginator :first.sync="offset" :rows="10" :totalRecords="totalItemsCount" - template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"></Paginator> - </CodeHighlight> - - <h3>Custom Content</h3> - <p>There are two slots available named "left" and "right" to add custom content to these locations. Both slots get - a state object as a slot property to provide the current page, first index and the rows. + <h3>DataViewLayoutOptions</h3> + <p>When both layout modes are enabled in DataView, a UI element would be necessary to let the user toggle between the view. DataViewLayoutOptions is a helper component + to display a buttonset to choose the layout mode in DataView. Location of the DataViewLayoutOptions should be inside the DataView component. If you prefer a different UI element + you can create your own that updates the layout property of the DataView. </p> - <CodeHighlight> - <template v-pre> - <Paginator :first.sync="offset" :rows="10" :totalRecords="totalItemsCount"> - <template #left="slotProps"> - Page: {{slotProps.state.page}} - First: {{slotProps.state.first}} - Rows: {{slotProps.state.rows}} - </template> - <template #right> - <Button type="button" icon="pi pi-search" /> - </template> - </Paginator> - </template> - </CodeHighlight> +<CodeHighlight> +<template #header> + <DataViewLayoutOptions :layout="layout" @change="changeMode"></DataViewLayoutOptions> +</template> - <h3>Page Change Event</h3> - <p>Paginator provides only one event called <i>page-change</i> that passes all the information about the change event.</p> - <CodeHighlight> - <Paginator :first.sync="offset" :rows="10" :totalRecords="totalItemsCount" @page-change="onPage($event)"></Paginator> - </CodeHighlight> +<template #footer> + <DataViewLayoutOptions :layout="layout" @change="changeMode"></DataViewLayoutOptions> +</template> +</CodeHighlight> - <CodeHighlight lang="javascript"> - onPage(event) { - //event.page: New page number - //event.first: Index of first record - //event.rows: Number of rows to display in new page - //event.pageCount: Total number of pages - } - </CodeHighlight> + <h3>Paginator</h3> + <p>Pagination is enabled by setting paginator property to true, rows attribute defines the number of rows per page and pageLinks specify the the number + of page links to display. To customize the left and right side of the paginators, use "paginatorLeft" and "paginatorRight" templates.</p> +<CodeHighlight> +<template v-pre> +<DataView :value="cars" :layout="layout" paginatorPosition='both' :paginator="true" :rows="20"> + <template #paginatorLeft> + <Button type="button" icon="pi pi-refresh"/> + </template> + <template #paginatorRight> + <Button type="button" icon="pi pi-search" /> + </template> + <template #header> + List of Cars + </template> + <template #listItem="slotProps" > + <div>Vin: <b>{{slotProps.data.vin}}</b></div> + </template> + <template #gridItem="slotProps"> + <div>Vin: <b>{{slotProps.data.vin}}</b></div> + </template> +</DataView> +</template> +</CodeHighlight> + + <h3>Sorting</h3> + <p>sortField and sortOrder properties are available for sorting functionality, for flexibility there is no built-in UI available so that a custom UI can be used for the sorting element. + Here is an example that uses a dropdown where simply updating the sortField-sortOrder bindings of the DataView initiates sorting.</p> +<CodeHighlight> +<template v-pre> +<DataView :value="cars" :layout="layout" :sortOrder="sortOrder" :sortField="sortField"> + <template #paginatorLeft> + <Button type="button" icon="pi pi-refresh"/> + </template> + <template #paginatorRight> + <Button type="button" icon="pi pi-search" /> + </template> + <template #header> + List of Cars + </template> + <template #listItem="slotProps" > + <div>Vin: <b>{{slotProps.data.vin}}</b></div> + </template> + <template #gridItem="slotProps"> + <div>Vin: <b>{{slotProps.data.vin}}</b></div> + </template> +</DataView> +</template> +</CodeHighlight> + + <h3>Properties of DataViewLayoutOptions</h3> + <div class="doc-tablewrapper"> + <table class="doc-table"> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Default</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>layout</td> + <td>string</td> + <td>list</td> + <td>Layout of the items, valid values are "list" and "grid".</td> + </tr> + </tbody> + </table> + </div> + + <h3>Events of DataViewLayoutOptions</h3> + <div class="doc-tablewrapper"> + <table class="doc-table"> + <thead> + <tr> + <th>Name</th> + <th>Parameters</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>change</td> + <td>event.originalEvent: browser event <br/> + event.value = layout mode e.g. "list" or "grid" + </td> + <td>Callback to invoke when layout mode is changed.</td> + </tr> + </tbody> + </table> + </div> <h3>Properties</h3> <div class="doc-tablewrapper"> @@ -94,22 +192,58 @@ import DataView from 'primevue/dataview'; </thead> <tbody> <tr> - <td>totalRecords</td> - <td>number</td> - <td>0</td> - <td>Number of total records.</td> + <td>value</td> + <td>array</td> + <td>null</td> + <td>An array of objects to display.</td> + </tr> + <tr> + <td>layout</td> + <td>string</td> + <td>list</td> + <td>Layout of the items, valid values are "list" and "grid".</td> </tr> <tr> <td>rows</td> <td>number</td> - <td>0</td> - <td>Data count to display per page.</td> + <td>null</td> + <td>Number of rows to display per page.</td> </tr> <tr> <td>first</td> <td>number</td> <td>0</td> - <td>Zero-relative number of the first row to be displayed.</td> + <td>Index of the first record to render.</td> + </tr> + <tr> + <td>totalRecords</td> + <td>number</td> + <td>null</td> + <td>Number of total records, defaults to length of value when not defined.</td> + </tr> + <tr> + <td>paginator</td> + <td>boolean</td> + <td>false</td> + <td>When specified as true, enables the pagination.</td> + </tr> + <tr> + <td>paginatorPosition</td> + <td>string</td> + <td>bottom</td> + <td>Position of the paginator, options are "top","bottom" or "both".</td> + </tr> + <tr> + <td>alwaysShowPaginator</td> + <td>boolean</td> + <td>true</td> + <td>Whether to show it even there is only one page.</td> + </tr> + <tr> + <td>paginatorTemplate</td> + <td>string</td> + <td>FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown</td> + <td>Template of the paginator.</td> </tr> <tr> <td>pageLinkSize</td> @@ -123,41 +257,35 @@ import DataView from 'primevue/dataview'; <td>null</td> <td>Array of integer values to display inside rows per page dropdown.</td> </tr> - <tr> - <td>template</td> - <td>string</td> - <td>FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown</td> - <td>Template of the paginator.</td> - </tr> <tr> <td>currentPageReportTemplate</td> <td>string</td> <td>({currentPage} of {totalPages})</td> <td>Template of the current page report element.</td> </tr> - </tbody> - </table> - </div> - - <h3>Events</h3> - <div class="doc-tablewrapper"> - <table class="doc-table"> - <thead> <tr> - <th>Name</th> - <th>Parameters</th> - <th>Description</th> + <td>emptyMessage</td> + <td>string</td> + <td>No records found.</td> + <td>Text to display when there is no data.</td> </tr> - </thead> - <tbody> <tr> - <td>page-change</td> - <td>event.page: New page number <br/> - event.first: Index of first record <br/> - event.rows: Number of rows to display in new page <br/> - event.pageCount: Total number of pages - </td> - <td>Callback to invoke when page changes, the event object contains information about the new state.</td> + <td>sortField</td> + <td>string</td> + <td>null</td> + <td>Name of the field to sort data by default.</td> + </tr> + <tr> + <td>sortOrder</td> + <td>number</td> + <td>null</td> + <td>Order to sort the data by default.</td> + </tr> + <tr> + <td>lazy</td> + <td>boolean</td> + <td>false</td> + <td>Defines if data is loaded and interacted with in lazy manner.</td> </tr> </tbody> </table> @@ -175,36 +303,28 @@ import DataView from 'primevue/dataview'; </thead> <tbody> <tr> - <td>p-paginator</td> + <td>p-dataview</td> <td>Container element.</td> </tr> <tr> - <td>p-paginator-first</td> - <td>First page element.</td> + <td>p-dataview-list</td> + <td>Container element in list layout.</td> </tr> <tr> - <td>p-paginator-prev</td> - <td>Previous page element.</td> + <td>p-dataview-grid</td> + <td>Container element in grid layout.</td> </tr> <tr> - <td>p-paginator-pages</td> - <td>Container of page links.</td> + <td>p-dataview-header</td> + <td>Header section.</td> </tr> <tr> - <td>p-paginator-page</td> - <td>A page link.</td> + <td>p-dataview-footer</td> + <td>Footer section.</td> </tr> <tr> - <td>p-paginator-next</td> - <td>Next pge element.</td> - </tr> - <tr> - <td>p-paginator-last</td> - <td>Last page element.</td> - </tr> - <tr> - <td>p-paginator-rpp-options</td> - <td>Rows per page dropdown.</td> + <td>p-dataview-content</td> + <td>Container of items.</td> </tr> </tbody> </table> @@ -215,82 +335,122 @@ import DataView from 'primevue/dataview'; </TabPanel> <TabPanel header="Source"> - <a href="https://github.com/primefaces/primereact/tree/master/src/showcase/paginator" class="btn-viewsource" target="_blank" rel="noopener noreferrer"> + <a href="https://github.com/primefaces/primereact/tree/master/src/showcase/dataview" class="btn-viewsource" target="_blank" rel="noopener noreferrer"> <span>View on GitHub</span> </a> - <CodeHighlight> - <template> - <div> - <div class="content-section introduction"> - <div class="feature-intro"> - <h1>Paginator</h1> - <p>Paginator is a generic component to display content in paged format.</p> +<CodeHighlight> +<template v-pre> +<template> + <div> + <div class="content-section introduction"> + <div class="feature-intro"> + <h1>DataView</h1> + <p>DataView displays data in grid or list layout with pagination and sorting features.</p> + </div> + </div> + + <div class="content-section implementation"> + <h3 class="first">Default</h3> + <DataView :value="cars" :layout="layout" paginatorPosition='both' :paginator="true" :rows="20" :sortOrder="sortOrder" :sortField="sortField"> + <template #header> + <div class="p-grid"> + <div class="p-col-6" style="text-align: left"> + <Dropdown v-model="sortKey" :options="sortOptions" optionLabel="label" placeholder="Sort By" @change="onSortChange($event)"/> + </div> + <div class="p-col-6" style="text-align: right"> + <DataViewLayoutOptions :layout="layout" @change="changeMode"></DataViewLayoutOptions> + </div> </div> + </template> + <template #listItem="slotProps" > + <div class="p-col-12 car-details" style="padding: 2em; border-bottom: 1px solid #d9d9d9"> + <div class="p-grid"> + <div class="p-col-12 p-md-3"> + <img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/> + </div> + <div class="p-col-12 p-md-8 car-data"> + <div>Vin: <b>{{slotProps.data.vin}}</b></div> + <div>Year: <b>{{slotProps.data.year}}</b></div> + <div>Brand: <b>{{slotProps.data.brand}}</b></div> + <div>Color: <b>{{slotProps.data.color}}</b></div> + </div> + + <div class="p-col-12 p-md-1 search-icon" style="margin-top: 40px"> + <Button icon="pi pi-search"></Button> + </div> + </div> </div> - - <div class="content-section implementation"> - <h3 class="first">Default</h3> - <Paginator :first.sync="first" :rows.sync="rows" :totalRecords="totalRecords" :rowsPerPageOptions="[10,20,30]"></Paginator> - - <h3>Custom Template</h3> - <Paginator :first.sync="first2" :rows="1" :totalRecords="totalRecords2" @page-change="onPageChangeCustom($event)" template="FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"> - <template #left> - <Button type="button" icon="pi pi-refresh" @click="reset()"/> - </template> - <template #right> - <Button type="button" icon="pi pi-search" /> - </template> - </Paginator> - - <div class="image-gallery"> - <img :src="'/demo/images/nature/' + image + '.jpg'" /> - </div> + </template> + <template #gridItem="slotProps"> + <div style="padding: .5em" class="p-col-12 p-md-3"> + <Panel :header="slotProps.data.vin" style="text-align: center"> + <img :src="'/demo/images/car/' + slotProps.data.brand + '.png'" :alt="slotProps.data.brand"/> + <div class="car-detail">{{slotProps.data.year}} - {{slotProps.data.color}}</div> + <hr class="ui-widget-content" style="border-top: 0" /> + <Button icon="pi pi-search"></Button> + </Panel> </div> + </template> + </DataView> + </div> + </div> +</template> +</template> +</CodeHighlight> - <PaginatorDoc /> - </div> - </template> - </CodeHighlight> +<CodeHighlight lang="javascript"> +import CarService from '../../service/CarService'; - <CodeHighlight lang="javascript"> - import PaginatorDoc from './PaginatorDoc'; +export default { + data() { + return { + cars: null, + layout: 'list', + sortKey: null, + sortOrder: null, + sortField: null, + sortOptions: [ + {label: 'Newest First', value: '!year'}, + {label: 'Oldest First', value: 'year'}, + {label: 'Brand', value: 'brand'} + ] + } + }, + carService: null, + created() { + this.carService = new CarService(); + }, + mounted() { + this.carService.getCarsLarge().then(data => this.cars = data); + }, + methods: { + changeMode(event) { + this.layout = event.value; + }, + onSortChange(event){ + const value = event.value.value; + const sortValue = event.value; - export default { - data() { - return { - first: 0, - rows: 10, - totalRecords: 50, - first2: 0, - totalRecords2: 12, - image: 'nature1' - } - }, - methods: { - onPageChangeCustom(event) { - this.image = 'nature' + (event.page + 1); - }, - reset() { - this.first2 = 0; - this.image = 'nature1'; - } - }, - components: { - 'PaginatorDoc': PaginatorDoc - } - } - </CodeHighlight> + if (value.indexOf('!') === 0) { + this.sortOrder = -1; + this.sortField = value.substring(1, value.length); + this.sortKey = sortValue; + } + else { + this.sortOrder = 1; + this.sortField = value; + this.sortKey = sortValue; + } + } + } +} +</CodeHighlight> - <CodeHighlight lang="css"> - .p-button.p-button-icon-only { - border-radius: 0; - } - - .image-gallery { - text-align: center; - padding: 1em; - } - </CodeHighlight>--> +<CodeHighlight lang="css"> +.p-dropdown { + width: 12em; +} +</CodeHighlight> </TabPanel> </TabView> </div>