diff --git a/packages/data-table-view/package.json b/packages/data-table-view/package.json index 1b6ece5e64a17ebca7b4872aedd4905218a53594..be073389b2aa12bb6dd1bd916b98a76e72aef523 100644 --- a/packages/data-table-view/package.json +++ b/packages/data-table-view/package.json @@ -1,7 +1,7 @@ { "name": "vpu-data-table-view", "version": "1.0.0", - "main": "src/vpu-data-table-view.js", + "main": "src/index.js", "devDependencies": { "chai": "^4.2.0", "glob": "^7.1.4", @@ -26,12 +26,13 @@ "vpu-common": "file:./vendor/common" }, "dependencies": { + "@open-wc/scoped-elements": "^1.0.9", + "datatables.net-buttons": "^1.6.1", + "datatables.net-buttons-dt": "^1.6.1", "datatables.net-dt": "^1.10.20", "datatables.net-responsive": "^2.2.3", "datatables.net-responsive-dt": "^2.2.3", - "datatables.net-buttons": "^1.6.1", - "datatables.net-buttons-dt": "^1.6.1", - "i18next": "^17.0.3", + "i18next": "^19.3.2", "jquery": "^3.4.1", "jszip": "^3.2.2", "lit-element": "^2.2.1", diff --git a/packages/data-table-view/src/data-table-view.js b/packages/data-table-view/src/data-table-view.js new file mode 100644 index 0000000000000000000000000000000000000000..5750d542b9fee0d48f09bdfcd5a3a39d5eca4170 --- /dev/null +++ b/packages/data-table-view/src/data-table-view.js @@ -0,0 +1,328 @@ +import $ from 'jquery'; +import dt from 'datatables.net'; +import resp from 'datatables.net-responsive'; +import resp2 from 'datatables.net-responsive-dt'; +import jszip from 'jszip/dist/jszip.js'; +import bttn from 'datatables.net-buttons-dt'; +import bttn2 from 'datatables.net-buttons'; +import bttnHtml5 from 'datatables.net-buttons/js/buttons.html5.js'; +import bttnPrint from 'datatables.net-buttons/js/buttons.print.js'; +import {i18n} from './i18n'; +import {css, html, LitElement, unsafeCSS} from 'lit-element'; +import de from '../assets/datatables/i18n/German'; +import en from '../assets/datatables/i18n/English'; +import {getIconSVGURL} from 'vpu-common'; +import * as commonUtils from 'vpu-common/utils'; +import * as commonStyles from 'vpu-common/styles'; + +dt(window, $); +resp(window, $); +resp2(window, $); +bttn(window, $); +bttn2(window, $); +bttnHtml5(window, $, jszip); +bttnPrint(window, $); + +export class DataTableView extends LitElement { + constructor() { + super(); + this.lang = 'de'; + // datatable properties + this.table = null; + this.responsive = null; + this.paging = false; + this.searching = false; + this.columns = []; + this.columnDefs = []; + this.data = []; + this.cssStyle = ''; + this.exportable = false; + this.exportName = 'Data Export'; + this.columnSearching = false; + } + + setCSSStyle(style) { + this.cssStyle = style; + } + + static get properties() { + return { + lang: { type: String }, + table: { type: Object, attribute: false }, + paging: { type: Boolean }, + searching: { type: Boolean }, + columns: { type: Array, attribute: false }, + columnDefs: { type: Array, attribute: false }, + data: { type: Array, attribute: false }, + cssStyle: { type: String, attribute: false }, + exportable: { type: Boolean }, + exportName: { type: String, attribute: 'export-name' }, + columnSearching: { type: Boolean, attribute: 'column-searching'}, + }; + } + + set_columns(cols) { + this.columns = cols; + return this; + } + set_columnDefs(defs) { + this.columnDefs = defs; + return this; + } + add_row(row) { + this.data.push(row); + this.table.row.add(row); + return this; + } + draw() { + this.table.draw(); + return this; + } + columnSearch(col, str) { + this.table.column(col).search(str).draw(); + } + columnReduce(col, func, init=0) { + return this.table.column(col, { search: 'applied' }).data().reduce( func, init); + } + on(eventName, func) { + this.table.on(eventName, func); + return this; + } + + set_datatable(data, languageChange = false) { + const lang_obj = this.lang === 'de' ? de : en; + + if (typeof this.columns === 'undefined' || !this.columns.length) { + if (data.length) + throw new Error('columns not set-up'); + return this; + } + + if (this.columnSearching) { + const existing_tfoot = this.shadowRoot.querySelector('table tfoot'); + if (existing_tfoot === null || !existing_tfoot.hasChildNodes() || languageChange) { + if (existing_tfoot !== null) { + existing_tfoot.remove(); + } + + const fragment = document.createDocumentFragment(); + const tfoot = document.createElement('tfoot'); + const tr = document.createElement('tr'); + this.columns.forEach(function (element, index) { + const th = document.createElement('td'); + if (element !== null + && (typeof element.visible === 'undefined' || element.visible !== false) + && (typeof element.searchable === 'undefined' || element.searchable !== false)) { + const input = document.createElement('input'); + input.type = 'text'; + input.className = 'column-search-line'; + input.id = 'input-col-' + index; + input.placeholder = i18n.t('column-search-placeholder', {fieldName: element.title}); + th.appendChild(input); + } + tr.appendChild(th); + }); + tfoot.appendChild(tr); + fragment.appendChild(tfoot); + this.shadowRoot.querySelector('table').appendChild(fragment); + } + } + + this.table = $(this.shadowRoot.querySelector('table')).DataTable({ + destroy: true, + autoWidth: true, + language: lang_obj, + paging: this.paging, + searching: this.searching, + columns: this.columns, + columnDefs: this.columnDefs, + dom: (this.exportable ? '<"export-btn"B>' : '') + 'lfrtip', + buttons: [ + { + extend: 'excelHtml5', + text: i18n.t('export-excel'), + title: this.exportName, + filename: this.exportName, + className: 'button is-small', + }, + { + extend: 'csvHtml5', + text: i18n.t('export-csv'), + title: this.exportName, + filename: this.exportName, + className: 'button is-small', + charset: 'UTF-8', + bom: true, + fieldSeparator: this.lang === 'en' ? ',' : ';' + }, + { + extend: 'print', + text: i18n.t('print'), + title: this.exportName, + className: 'button is-small', + }, + ] + }); + + const dataTableLength = sessionStorage.getItem('vpu-data-table-length'); + + //Retrieve page length from session storage + if (dataTableLength !== null) { + this.table.page.len(dataTableLength); + } + + //Save page length in session storage + this.table.on('length.dt', function ( e, settings, len ) { + sessionStorage.setItem('vpu-data-table-length', len); + }); + + this.data = data; + + this.table.clear(); + if (this.data.length) { this.table.rows.add(this.data); } + this.table.draw(); + + new $.fn.dataTable.Responsive(this.table, { + details: true + }); + + if (this.columnSearching) { + const thisTable = this.table; + const that = this; + this.columns.forEach(function (element, index) { + if (element !== null + && (typeof element.visible === 'undefined' || element.visible !== false) + && (typeof element.searchable === 'undefined' || element.searchable !== false)) { + const input = that.shadowRoot.querySelector('#input-col-' + index); + if (input) { + ['keyup', 'change', 'clear'].forEach(function (event) { + input.addEventListener(event, function () { + const column = thisTable.column(index); + if (column.search() !== input.value) { + column.search(input.value).draw(); + } + }); + }); + } + } + }); + } + return this; + } + + update(changedProperties) { + let languageChange = false; + + changedProperties.forEach((oldValue, propName) => { + if (propName === "lang") { + i18n.changeLanguage(this.lang).catch(e => { console.log(e)}); + languageChange = true; + } + }); + + this.updateComplete.then(this.set_datatable(this.data, languageChange)).catch(e => { console.log(e)}); + super.update(changedProperties); + } + + static get styles() { + // language=css + const orderExpandIconOverrides = css` + table.dataTable.dtr-inline.collapsed > tbody > tr[role="row"] > td:first-child::before, table.dataTable.dtr-inline.collapsed > tbody > tr[role="row"] > th:first-child::before { + all: initial; + top: 0.7em; + left: 0.4em; + height: 1em; + width: 1em; + display: block; + cursor: pointer; + position: absolute; + box-sizing: content-box; + text-align: center; + text-indent: 0 !important; + line-height: 0.9em; + color: var(--vpu-primary-text-color); + background-color: var(--vpu-primary-bg-color); + content: '+'; + } + + table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child::before, table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child::before { + content: '-'; + } + + table.dataTable thead .sorting { + background-image: url('${unsafeCSS(getIconSVGURL('chevron-up'))}'), url('${unsafeCSS(getIconSVGURL('chevron-down'))}'); + background-position: 100% 40%, 100% 60%; + background-size: 0.5em, 0.5em; + } + + table.dataTable thead .sorting_desc { + background-image: url('${unsafeCSS(getIconSVGURL('chevron-up'))}'); + background-position: 100% 50%; + background-size: 0.8em; + } + + table.dataTable thead .sorting_asc { + background-image: url('${unsafeCSS(getIconSVGURL('chevron-down'))}'); + background-size: 0.8em; + background-position: 100% 50%; + } + `; + + // language=css + return css` + ${commonStyles.getThemeCSS()} + ${commonStyles.getGeneralCSS()} + ${commonStyles.getButtonCSS()} + ${orderExpandIconOverrides} + + .dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { + color: var(--vpu-muted-text); + border-radius: var(--vpu-border-radius); + background: transparent; + } + + .export-btn { + margin-bottom: .6rem; + } + + select { + border-radius: calc(var(--vpu-border-radius)/2); + height: 28px; + margin-left: 3px; + } + + :host { + display: block; + } + + .dataTables_filter input { + border-radius: 0; + border-style: solid; + border-color: var(--vpu-dark); + border-width: 1px; + padding: 0.1em; + } + + table.dataTable .column-search-line { + width: 100%; + } + `; + } + + render() { + commonUtils.initAssetBaseURL('vpu-data-table-view-src'); + let dt_css = commonUtils.getAssetURL('local/vpu-data-table-view/css/jquery.dataTables.min.css'); + let rs_css = commonUtils.getAssetURL('local/vpu-data-table-view/css/responsive.dataTables.min.css'); + let bt_css = commonUtils.getAssetURL('local/vpu-data-table-view/css/buttons.dataTables.min.css'); + + return html` + <link rel="stylesheet" href="${dt_css}"> + <link rel="stylesheet" href="${rs_css}"> + <link rel="stylesheet" href="${bt_css}"> + <style> + ${this.cssStyle} + </style> + <div><table width="100%"></table></div> + `; + } +} \ No newline at end of file diff --git a/packages/data-table-view/src/index.js b/packages/data-table-view/src/index.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/packages/data-table-view/src/vpu-data-table-view-demo.js b/packages/data-table-view/src/vpu-data-table-view-demo.js index 6a9aa78e438810897035994d45690a31761c9ff4..58c48a2187bcee8736ff6682860874534970fa64 100644 --- a/packages/data-table-view/src/vpu-data-table-view-demo.js +++ b/packages/data-table-view/src/vpu-data-table-view-demo.js @@ -1,17 +1,25 @@ -import 'vpu-auth'; -import './vpu-data-table-view.js'; +import {Auth} from 'vpu-auth'; +import {DataTableView} from './data-table-view.js'; import {i18n} from './i18n'; import {css, html, LitElement} from 'lit-element'; +import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import * as commonUtils from 'vpu-common/utils'; import * as commonStyles from 'vpu-common/styles'; -class DataTableViewDemo extends LitElement { +class DataTableViewDemo extends ScopedElementsMixin(LitElement) { constructor() { super(); this.lang = 'de'; this.noAuth = false; } + static get scopedElements() { + return { + 'vpu-data-table-view': DataTableView, + 'vpu-auth': Auth, + }; + } + static get properties() { return { lang: { type: String }, @@ -183,29 +191,7 @@ class DataTableViewDemo extends LitElement { <vpu-data-table-view lang="${this.lang}" id="vdtv2"></vpu-data-table-view> </div> </div> - <div class="content"> - <h4>Common Table</h4> - <div class="box"> - <!-- <vpu-data-table-view lang="${this.lang}" paging searching> --> - <table class="display"> - <thead> - <tr> - <th>A</th> - <th>B</th> - <th>C</th> - </tr> - </thead> - <tbody> - <tr> - <td>abc</td> - <td>123</td> - <td>a-2-4-g</td> - </tr> - </tbody> - </table> - <!-- </vpu-data-table-view> --> - </div> - </div> + </section> `; } diff --git a/packages/data-table-view/src/vpu-data-table-view.js b/packages/data-table-view/src/vpu-data-table-view.js index cd9e3d617e2e1b1d67daae0429404201563988ac..bb9e5eaaf76989ee6ced7743a5aaa1225cbbdbf0 100644 --- a/packages/data-table-view/src/vpu-data-table-view.js +++ b/packages/data-table-view/src/vpu-data-table-view.js @@ -1,330 +1,4 @@ -import $ from 'jquery'; -import dt from 'datatables.net'; -import resp from 'datatables.net-responsive'; -import resp2 from 'datatables.net-responsive-dt'; -import jszip from 'jszip/dist/jszip.js'; -import bttn from 'datatables.net-buttons-dt'; -import bttn2 from 'datatables.net-buttons'; -import bttnHtml5 from 'datatables.net-buttons/js/buttons.html5.js'; -import bttnPrint from 'datatables.net-buttons/js/buttons.print.js'; -import {i18n} from './i18n'; -import {css, html, LitElement, unsafeCSS} from 'lit-element'; -import de from '../assets/datatables/i18n/German'; -import en from '../assets/datatables/i18n/English'; -import {getIconSVGURL} from 'vpu-common/vpu-icon'; import * as commonUtils from 'vpu-common/utils'; -import * as commonStyles from 'vpu-common/styles'; - -dt(window, $); -resp(window, $); -resp2(window, $); -bttn(window, $); -bttn2(window, $); -bttnHtml5(window, $, jszip); -bttnPrint(window, $); - -class DataTableView extends LitElement { - constructor() { - super(); - this.lang = 'de'; - // datatable properties - this.table = null; - this.responsive = null; - this.paging = false; - this.searching = false; - this.columns = []; - this.columnDefs = []; - this.data = []; - this.cssStyle = ''; - this.exportable = false; - this.exportName = 'Data Export'; - this.columnSearching = false; - } - - setCSSStyle(style) { - this.cssStyle = style; - } - - static get properties() { - return { - lang: { type: String }, - table: { type: Object, attribute: false }, - paging: { type: Boolean }, - searching: { type: Boolean }, - columns: { type: Array, attribute: false }, - columnDefs: { type: Array, attribute: false }, - data: { type: Array, attribute: false }, - cssStyle: { type: String, attribute: false }, - exportable: { type: Boolean }, - exportName: { type: String, attribute: 'export-name' }, - columnSearching: { type: Boolean, attribute: 'column-searching'}, - }; - } - - set_columns(cols) { - this.columns = cols; - return this; - } - set_columnDefs(defs) { - this.columnDefs = defs; - return this; - } - add_row(row) { - this.data.push(row); - this.table.row.add(row); - return this; - } - draw() { - this.table.draw(); - return this; - } - columnSearch(col, str) { - this.table.column(col).search(str).draw(); - } - columnReduce(col, func, init=0) { - return this.table.column(col, { search: 'applied' }).data().reduce( func, init); - } - on(eventName, func) { - this.table.on(eventName, func); - return this; - } - - set_datatable(data, languageChange = false) { - const lang_obj = this.lang === 'de' ? de : en; - - if (typeof this.columns === 'undefined' || !this.columns.length) { - if (data.length) - throw new Error('columns not set-up'); - return this; - } - - if (this.columnSearching) { - const existing_tfoot = this.shadowRoot.querySelector('table tfoot'); - if (existing_tfoot === null || !existing_tfoot.hasChildNodes() || languageChange) { - if (existing_tfoot !== null) { - existing_tfoot.remove(); - } - - const fragment = document.createDocumentFragment(); - const tfoot = document.createElement('tfoot'); - const tr = document.createElement('tr'); - this.columns.forEach(function (element, index) { - const th = document.createElement('td'); - if (element !== null - && (typeof element.visible === 'undefined' || element.visible !== false) - && (typeof element.searchable === 'undefined' || element.searchable !== false)) { - const input = document.createElement('input'); - input.type = 'text'; - input.className = 'column-search-line'; - input.id = 'input-col-' + index; - input.placeholder = i18n.t('column-search-placeholder', {fieldName: element.title}); - th.appendChild(input); - } - tr.appendChild(th); - }); - tfoot.appendChild(tr); - fragment.appendChild(tfoot); - this.shadowRoot.querySelector('table').appendChild(fragment); - } - } - - this.table = $(this.shadowRoot.querySelector('table')).DataTable({ - destroy: true, - autoWidth: true, - language: lang_obj, - paging: this.paging, - searching: this.searching, - columns: this.columns, - columnDefs: this.columnDefs, - dom: (this.exportable ? '<"export-btn"B>' : '') + 'lfrtip', - buttons: [ - { - extend: 'excelHtml5', - text: i18n.t('export-excel'), - title: this.exportName, - filename: this.exportName, - className: 'button is-small', - }, - { - extend: 'csvHtml5', - text: i18n.t('export-csv'), - title: this.exportName, - filename: this.exportName, - className: 'button is-small', - charset: 'UTF-8', - bom: true, - fieldSeparator: this.lang === 'en' ? ',' : ';' - }, - { - extend: 'print', - text: i18n.t('print'), - title: this.exportName, - className: 'button is-small', - }, - ] - }); - - const dataTableLength = sessionStorage.getItem('vpu-data-table-length'); - - //Retrieve page length from session storage - if (dataTableLength !== null) { - this.table.page.len(dataTableLength); - } - - //Save page length in session storage - this.table.on('length.dt', function ( e, settings, len ) { - sessionStorage.setItem('vpu-data-table-length', len); - }); - - this.data = data; - - this.table.clear(); - if (this.data.length) { this.table.rows.add(this.data); } - this.table.draw(); - - new $.fn.dataTable.Responsive(this.table, { - details: true - }); - - if (this.columnSearching) { - const thisTable = this.table; - const that = this; - this.columns.forEach(function (element, index) { - if (element !== null - && (typeof element.visible === 'undefined' || element.visible !== false) - && (typeof element.searchable === 'undefined' || element.searchable !== false)) { - const input = that.shadowRoot.querySelector('#input-col-' + index); - if (input) { - ['keyup', 'change', 'clear'].forEach(function (event) { - input.addEventListener(event, function () { - const column = thisTable.column(index); - if (column.search() !== input.value) { - column.search(input.value).draw(); - } - }); - }); - } - } - }); - } - return this; - } - - update(changedProperties) { - let languageChange = false; - - changedProperties.forEach((oldValue, propName) => { - if (propName === "lang") { - i18n.changeLanguage(this.lang).catch(e => { console.log(e)}); - languageChange = true; - } - }); - - this.updateComplete.then(this.set_datatable(this.data, languageChange)).catch(e => { console.log(e)}); - super.update(changedProperties); - } - - static get styles() { - // language=css - const orderExpandIconOverrides = css` - table.dataTable.dtr-inline.collapsed > tbody > tr[role="row"] > td:first-child::before, table.dataTable.dtr-inline.collapsed > tbody > tr[role="row"] > th:first-child::before { - all: initial; - top: 0.7em; - left: 0.4em; - height: 1em; - width: 1em; - display: block; - cursor: pointer; - position: absolute; - box-sizing: content-box; - text-align: center; - text-indent: 0 !important; - line-height: 0.9em; - color: var(--vpu-primary-text-color); - background-color: var(--vpu-primary-bg-color); - content: '+'; - } - - table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child::before, table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child::before { - content: '-'; - } - - table.dataTable thead .sorting { - background-image: url('${unsafeCSS(getIconSVGURL('chevron-up'))}'), url('${unsafeCSS(getIconSVGURL('chevron-down'))}'); - background-position: 100% 40%, 100% 60%; - background-size: 0.5em, 0.5em; - } - - table.dataTable thead .sorting_desc { - background-image: url('${unsafeCSS(getIconSVGURL('chevron-up'))}'); - background-position: 100% 50%; - background-size: 0.8em; - } - - table.dataTable thead .sorting_asc { - background-image: url('${unsafeCSS(getIconSVGURL('chevron-down'))}'); - background-size: 0.8em; - background-position: 100% 50%; - } - `; - - // language=css - return css` - ${commonStyles.getThemeCSS()} - ${commonStyles.getGeneralCSS()} - ${commonStyles.getButtonCSS()} - ${orderExpandIconOverrides} - - .dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { - color: var(--vpu-muted-text); - border-radius: var(--vpu-border-radius); - background: transparent; - } - - .export-btn { - margin-bottom: .6rem; - } - - select { - border-radius: calc(var(--vpu-border-radius)/2); - height: 28px; - margin-left: 3px; - } - - :host { - display: block; - } - - .dataTables_filter input { - border-radius: 0; - border-style: solid; - border-color: var(--vpu-dark); - border-width: 1px; - padding: 0.1em; - } - - table.dataTable .column-search-line { - width: 100%; - } - `; - } - - render() { - commonUtils.initAssetBaseURL('vpu-data-table-view-src'); - let dt_css = commonUtils.getAssetURL('local/vpu-data-table-view/css/jquery.dataTables.min.css'); - let rs_css = commonUtils.getAssetURL('local/vpu-data-table-view/css/responsive.dataTables.min.css'); - let bt_css = commonUtils.getAssetURL('local/vpu-data-table-view/css/buttons.dataTables.min.css'); - - return html` - <link rel="stylesheet" href="${dt_css}"> - <link rel="stylesheet" href="${rs_css}"> - <link rel="stylesheet" href="${bt_css}"> - <style> - ${this.cssStyle} - </style> - <div><table width="100%"></table></div> - `; - } -} +import {DataTableView} from './data-table-view.js'; commonUtils.defineCustomElement('vpu-data-table-view', DataTableView); diff --git a/packages/data-table-view/vendor/auth b/packages/data-table-view/vendor/auth index 688c31162459f6f642fe76494c6201d29b635ab2..b9fbe487a8a6117ae90a423a8ba318a0321bf51b 160000 --- a/packages/data-table-view/vendor/auth +++ b/packages/data-table-view/vendor/auth @@ -1 +1 @@ -Subproject commit 688c31162459f6f642fe76494c6201d29b635ab2 +Subproject commit b9fbe487a8a6117ae90a423a8ba318a0321bf51b diff --git a/packages/data-table-view/vendor/common b/packages/data-table-view/vendor/common index 356b9b33c853361ba9585ccb40e61d1293b09922..9c6dc1fd5e004eba32e31adf8e4485a26c345fe0 160000 --- a/packages/data-table-view/vendor/common +++ b/packages/data-table-view/vendor/common @@ -1 +1 @@ -Subproject commit 356b9b33c853361ba9585ccb40e61d1293b09922 +Subproject commit 9c6dc1fd5e004eba32e31adf8e4485a26c345fe0