diff --git a/src/frontend/components/button/_button.scss b/src/frontend/components/button/_button.scss index 2b6ef10dd..f3de02843 100644 --- a/src/frontend/components/button/_button.scss +++ b/src/frontend/components/button/_button.scss @@ -181,7 +181,7 @@ @extend %icon-font; content: "\E80a"; - margin-right: 0.75rem; + margin-right: 0.25rem; color: $brand-secundary; background: $transparent; transition: all 0.2s ease; @@ -196,6 +196,10 @@ text-decoration: none; background: $transparent; } + + & span { + font-weight: $btn-font-weight !important; // Have to use important here otherwise the card title will override this style. + } } .btn-round { diff --git a/src/frontend/components/data-table/_data-table.scss b/src/frontend/components/data-table/_data-table.scss index 62277b6e7..aaece5753 100644 --- a/src/frontend/components/data-table/_data-table.scss +++ b/src/frontend/components/data-table/_data-table.scss @@ -18,6 +18,7 @@ text-transform: uppercase; vertical-align: top; box-shadow: none; + vertical-align: middle; &[class*="sorting_asc"], &[class*="sorting_desc"] { @@ -35,6 +36,7 @@ td { padding: 1rem; color: $gray-extra-dark; + vertical-align: middle; } } @@ -269,6 +271,7 @@ table.dataTable thead .sorting_disabled { display: flex; position: relative; align-items: flex-start; + text-align: start; } // Pagination @@ -425,39 +428,22 @@ button.btn-add { @extend .m-0; } -.dt-layout-row { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - width: 100%; - margin-bottom: $padding-base-vertical; +.dt-layout-start:has(.dt-search) { + flex-grow: 1; - &.dt-layout-row--no-padding { - padding: 0; + label { + display: none; } - .dt-start { - flex-grow: 1; - - label { - display: none; - } + .dt-search { + @extend .pe-2; + width: 100%; - .dt-search { - @extend .pe-2; + input[type="search"] { width: 100%; - - input[type="search"] { - width: 100%; - @extend .m-0; - } + @extend .m-0; } } - - &:has(.dt-start:empty + .dt-end:empty) { - display: none; - } } .dt-layout-cell:has(table.data-table) { @@ -467,10 +453,6 @@ button.btn-add { .dt-orderable-asc, .dt-orderable-desc { .data-table__header-wrapper { - text-align: center; - align-items: center; - justify-content: center; - .dt-column-title { white-space: nowrap; } @@ -617,3 +599,16 @@ th { background-color: rgba(var(--dt-row-hover), 0.075); box-shadow: none; } + +table.dataTable { + &.table-search { + &>tbody>tr>td { + padding-left: 2rem; + } + } + + // Override default alignment to left for all columns + td[class*="dt-type-"] { + text-align: left; + } +} diff --git a/src/frontend/components/data-table/lib/component.js b/src/frontend/components/data-table/lib/component.js index b654c4572..ff5870a16 100644 --- a/src/frontend/components/data-table/lib/component.js +++ b/src/frontend/components/data-table/lib/component.js @@ -55,6 +55,7 @@ class DataTableComponent extends Component { } const conf = this.getConf(); + const { columns } = conf; this.columns = columns; this.el.DataTable(conf); @@ -90,6 +91,15 @@ class DataTableComponent extends Component { }); } }); + + if(conf.responsive) { + // Render the child component when the responsive row is shown + this.el.on('responsive-display.dt', (e, datatable, row, showHide) => { + if(!showHide) return; + const child = row.child()?.[0]; + initializeRegisteredComponents(child); + }); + } } /** @@ -200,8 +210,8 @@ class DataTableComponent extends Component { getCheckboxElement(id, label) { return ( '
' + - `` + - `` + + `` + + `` + '
' ); } @@ -565,7 +575,7 @@ class DataTableComponent extends Component { thisHTML += `

${this.encodeHTMLEntities(detail.definition)}: ${strDecodedValue}

`; } }); - thisHTML += ''; + thisHTML += ''; strHTML += ( `
@@ -799,7 +809,7 @@ class DataTableComponent extends Component { const $header = $(column.header()); $header.on('click', (ev) => { - if(ev.stopPropagation) { + if (ev.stopPropagation) { ev.stopPropagation(); ev.preventDefault(); } else { @@ -808,7 +818,7 @@ class DataTableComponent extends Component { }); const headerContent = $header.html(); - if(!headerContent.includes('data-table__header-wrapper')){ + if (!headerContent.includes('data-table__header-wrapper')) { $header.html(`
${headerContent}
`); // Add sort button to column header @@ -844,7 +854,7 @@ class DataTableComponent extends Component { } }; - conf['footerCallback'] = function() { + conf['footerCallback'] = function () { const api = this.api(); // Add aggregate values to table if configured const agg = api.ajax?.json()?.aggregate; diff --git a/src/frontend/css/stylesheets/definitions/_bootstrap_base.scss b/src/frontend/css/stylesheets/definitions/_bootstrap_base.scss index ee9729c83..aa29ac473 100644 --- a/src/frontend/css/stylesheets/definitions/_bootstrap_base.scss +++ b/src/frontend/css/stylesheets/definitions/_bootstrap_base.scss @@ -76,6 +76,8 @@ $table-caption-color: $primary; $table-bg: $white; $table-color: $secondary; $table-striped-color: $secondary; +$pagination-bg: $white; +$pagination-disabled-bg: $white; // Dropdowns $dropdown-bg: $white; diff --git a/src/frontend/css/stylesheets/external.scss b/src/frontend/css/stylesheets/external.scss index ed2ed8e92..e32fbda81 100644 --- a/src/frontend/css/stylesheets/external.scss +++ b/src/frontend/css/stylesheets/external.scss @@ -1,8 +1,11 @@ // Bootstrap datepicker @import '~bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css'; -// Datatables styling for bootstrap 4 -@import '~datatables.net-bs5/css/dataTables.bootstrap5.css'; +// Datatables styling for bootstrap 5 +@import '~datatables.net-bs5/css/dataTables.bootstrap5.css', + "~datatables.net-bs5/css/dataTables.bootstrap5.min.css", + "~datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css", + "~datatables.net-rowreorder-bs5/css/rowReorder.bootstrap5.min.css"; // QueryBuilder @import 'jQuery-QueryBuilder/dist/css/query-builder.default.css'; diff --git a/src/frontend/css/stylesheets/general.scss b/src/frontend/css/stylesheets/general.scss index 63e86df4a..644c81c2a 100644 --- a/src/frontend/css/stylesheets/general.scss +++ b/src/frontend/css/stylesheets/general.scss @@ -2,11 +2,8 @@ @import "definitions/bootstrap_base"; -// Bootstrap 4.6 -@import "~bootstrap/scss/bootstrap", - "~datatables.net-bs5/css/dataTables.bootstrap5.min.css", - "~datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css", - "~datatables.net-rowreorder-bs5/css/rowReorder.bootstrap5.min.css"; +// Bootstrap 5 +@import "~bootstrap/scss/bootstrap"; @import "definitions/fonts", "definitions/mixins"; diff --git a/src/frontend/js/lib/util/gadsStorage/lib/GadsStorage.test.ts b/src/frontend/js/lib/util/gadsStorage/lib/GadsStorage.test.ts index 1d3052718..b857b76ec 100644 --- a/src/frontend/js/lib/util/gadsStorage/lib/GadsStorage.test.ts +++ b/src/frontend/js/lib/util/gadsStorage/lib/GadsStorage.test.ts @@ -86,12 +86,12 @@ describe('GadsStorage', () => { it('Should do multiple read/writes to the same value without erroring', async () => { await setupNoMockCrypto(); - expect.assertions(10); + expect.assertions(20); const myValues = [{ id: 1, value: 'value1', array: [1] }]; for (let i = 0; i < 10; i++) { const storage = new GadsStorage(); const values = JSON.stringify(myValues); - await storage.setItem('myValues', values); + await expect(storage.setItem('myValues', values)).resolves.not.toThrow(); await expect(storage.getItem('myValues')).resolves.toEqual(values); } killNoMockCrypto();