From 36ba7a38855257a8903de8f61347643a26db9600 Mon Sep 17 00:00:00 2001 From: Dave Roberts Date: Wed, 16 Jul 2025 14:35:48 +0100 Subject: [PATCH 01/25] Formatted test and config code and updated test files --- .github/workflows/tests.yml | 2 +- eslint.config.mjs | 2 +- package.json | 8 +- .../button/lib/remove-curval-button.test.js | 2 +- .../button/lib/show-blank-button.test.ts | 2 +- .../components/card/lib/component.test.ts | 7 +- .../collapsible/lib/component.test.ts | 2 +- .../components/data-table/lib/helper.test.ts | 3 +- .../form-group/autosave/lib/autosave.test.ts | 1 + .../form-group/filter/lib/component.js | 8 +- .../form-group/select-widget/lib/component.js | 4 +- .../help-view/lib/component.test.ts | 1 + .../components/markdown/lib/component.js | 1 + .../components/modal/lib/component.js | 1 + .../components/timeline/lib/component.js | 2 +- src/frontend/js/lib/set-field-value.test.ts | 2 + .../lib/encryptedStorage.test.ts | 6 + .../js/lib/util/filedrag/lib/filedrag.test.ts | 1 + .../storageProvider/lib/storageProvider.ts | 8 +- .../typeahead/lib/TypeaheadBuilder.test.ts | 1 + .../js/lib/util/upload/UploadControl.ts | 2 +- src/frontend/testing/globals.definitions.ts | 4 +- yarn.lock | 460 +++++++++--------- 23 files changed, 282 insertions(+), 248 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3617186fd..30891144e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -187,7 +187,7 @@ jobs: strategy: matrix: - node-version: [20.x, 22.x] + node-version: [22.x, 24.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: diff --git a/eslint.config.mjs b/eslint.config.mjs index 12c843cd7..bf77196cb 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -8,7 +8,7 @@ import stylistic from "@stylistic/eslint-plugin"; import jsdoc from "eslint-plugin-jsdoc"; export default defineConfig([ - { settings: { react: { version: "detect" } } }, + { settings: { react: { version: "19" } } }, { ignores: ["*.cjs", "eslint.config.mjs", "**/public/**", "**/node_modules/**", "**/cypress/**", "cypress.config.ts", ".stylelintrc.js", "src/frontend/testing/**", "src/frontend/css/stylesheets/external/**", "src/frontend/components/dashboard/lib/react/polyfills/**", "babel.config.js", "webpack.config.js", "jest.config.js", "tsconfig.json", "src/frontend/js/lib/jqplot/**", "src/frontend/js/lib/jquery/**", "src/frontend/js/lib/plotly/**", "src/frontend/components/timeline/**", "fengari-web.js"] }, { files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], plugins: { js }, extends: ["js/recommended"] }, { files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], languageOptions: { globals: { ...globals.browser, ...globals.jquery, ...globals.jest } } }, diff --git a/package.json b/package.json index ed011cbd2..c8ce8dbe7 100644 --- a/package.json +++ b/package.json @@ -65,15 +65,17 @@ "@types/react-dom": "^19.2.3", "@types/react-grid-layout": "^1.0.0", "@types/typeahead.js": "^0.11.6", + "@webpack-cli/serve": "^2.0.1", "autoprefixer": "^10.5.0", "babel-loader": "^10.1.1", + "buffer": "^6.0.3", "clean-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^14.0.0", "core-js": "^3.49.0", "css-loader": "^7.1.4", "cypress": "^15.16.0", - "eslint": "^9.0.0", - "eslint-plugin-jsdoc": "^63.0.2", + "eslint": "^10.5.0", + "eslint-plugin-jsdoc": "^63.0.5", "eslint-plugin-react": "^7.37.5", "globals": "^17.6.0", "jest": "^30.4.2", @@ -86,7 +88,7 @@ "terser-webpack-plugin": "^5.6.1", "ts-loader": "~9.5.2", "typescript": "~5.8.0", - "typescript-eslint": "^8.61.0", + "typescript-eslint": "^8.61.1", "webpack": "^5.107.2", "webpack-cli": "^7.0.3" }, diff --git a/src/frontend/components/button/lib/remove-curval-button.test.js b/src/frontend/components/button/lib/remove-curval-button.test.js index a22dd35f8..5d854852c 100644 --- a/src/frontend/components/button/lib/remove-curval-button.test.js +++ b/src/frontend/components/button/lib/remove-curval-button.test.js @@ -61,4 +61,4 @@ describe('RemoveCurvalButton', () => { button.click(); expect(current.children.length).toBe(0); }); -}); \ No newline at end of file +}); diff --git a/src/frontend/components/button/lib/show-blank-button.test.ts b/src/frontend/components/button/lib/show-blank-button.test.ts index 3d13895ca..ee0237e2a 100644 --- a/src/frontend/components/button/lib/show-blank-button.test.ts +++ b/src/frontend/components/button/lib/show-blank-button.test.ts @@ -29,4 +29,4 @@ describe('ShowBlankButton', () => { button.trigger('click'); expect(item.css('display')).toBe('none'); }); -}); \ No newline at end of file +}); diff --git a/src/frontend/components/card/lib/component.test.ts b/src/frontend/components/card/lib/component.test.ts index ae8c0225e..c932cfe1b 100644 --- a/src/frontend/components/card/lib/component.test.ts +++ b/src/frontend/components/card/lib/component.test.ts @@ -169,10 +169,9 @@ describe('ExpandableCardComponent', () => { if (!target) throw new Error('Target not found'); // Set the items in the card to be invisible, as if there was nothing to show const $target = $(target); - $target.find('.list--fields').find('ul li') - .each((_i, el) => { - $(el).css('display', 'none'); - }); + $target.find('.list--fields').find('ul li').each((_i, el) => { + $(el).css('display', 'none'); + }); $target.find('.linkspace-field').each((_i, el) => { $(el).css('display', 'none'); }); diff --git a/src/frontend/components/collapsible/lib/component.test.ts b/src/frontend/components/collapsible/lib/component.test.ts index 84786d424..f4e7a7673 100644 --- a/src/frontend/components/collapsible/lib/component.test.ts +++ b/src/frontend/components/collapsible/lib/component.test.ts @@ -37,7 +37,7 @@ describe('Collapsible', () => { it('should toggle the collapsible content', () => { const target = document.getElementById('target'); - if(target === null) throw new Error('Target element not found'); + if (target === null) throw new Error('Target element not found'); new Collapsible(target as HTMLElement); const button = target.querySelector('.btn-collapsible') as HTMLButtonElement; const titleCollapsed = target.querySelector('.btn__title--collapsed') as HTMLSpanElement; diff --git a/src/frontend/components/data-table/lib/helper.test.ts b/src/frontend/components/data-table/lib/helper.test.ts index a355e773f..d19ed794c 100644 --- a/src/frontend/components/data-table/lib/helper.test.ts +++ b/src/frontend/components/data-table/lib/helper.test.ts @@ -4,6 +4,7 @@ import { addRow, clearTable, updateRow } from './helper'; describe.skip('helper - Jest really doesn\'t like JQuery right now!', () => { beforeEach(() => { + // create the DOM structure for the tests document.body.innerHTML = ` @@ -71,4 +72,4 @@ describe.skip('helper - Jest really doesn\'t like JQuery right now!', () => { clearTable($(target)); expect(target.querySelectorAll('tbody tr').length).toBe(1); }); -}); \ No newline at end of file +}); diff --git a/src/frontend/components/form-group/autosave/lib/autosave.test.ts b/src/frontend/components/form-group/autosave/lib/autosave.test.ts index e88811f25..113cc014e 100644 --- a/src/frontend/components/form-group/autosave/lib/autosave.test.ts +++ b/src/frontend/components/form-group/autosave/lib/autosave.test.ts @@ -2,6 +2,7 @@ import AutosaveBase from './autosaveBase'; import { describe, it, expect, beforeAll, afterAll } from '@jest/globals'; +// Mocking the AutosaveBase class for testing class TestAutosave extends AutosaveBase { initAutosave(): void { console.log('initAutosave'); diff --git a/src/frontend/components/form-group/filter/lib/component.js b/src/frontend/components/form-group/filter/lib/component.js index 242c54236..107dbda0a 100644 --- a/src/frontend/components/form-group/filter/lib/component.js +++ b/src/frontend/components/form-group/filter/lib/component.js @@ -172,13 +172,7 @@ class FilterComponent extends Component { }; // This is required to ensure that the correct query is sent each time - const buildQuery = () => { - return { - q: $ruleInputText.val(), - oi: filterConfig.instanceId, - csrf_token: $('body').data('csrf') - }; - }; + const buildQuery = () => { return { q: $ruleInputText.val(), oi: filterConfig.instanceId }; }; const builder = new TypeaheadBuilder(); builder diff --git a/src/frontend/components/form-group/select-widget/lib/component.js b/src/frontend/components/form-group/select-widget/lib/component.js index 6cb5da7c2..498856a56 100644 --- a/src/frontend/components/form-group/select-widget/lib/component.js +++ b/src/frontend/components/form-group/select-widget/lib/component.js @@ -510,7 +510,6 @@ class SelectWidgetComponent extends Component { return $li; } - //Some odd scoping issues here - but it works /** * Updates the JSON data for the select widget. * @param {string} url - The URL to fetch the JSON data from. @@ -600,7 +599,8 @@ class SelectWidgetComponent extends Component { }); } else { - const errorMessage = data.message; + const errorMessage = + data.error === 1 ? data.message : 'Oops! Something went wrong.'; const errorLi = $( '
  • @@ -72,4 +71,4 @@ describe.skip('helper - Jest really doesn\'t like JQuery right now!', () => { clearTable($(target)); expect(target.querySelectorAll('tbody tr').length).toBe(1); }); -}); +}); \ No newline at end of file diff --git a/src/frontend/components/form-group/autosave/lib/autosave.test.ts b/src/frontend/components/form-group/autosave/lib/autosave.test.ts index 113cc014e..e88811f25 100644 --- a/src/frontend/components/form-group/autosave/lib/autosave.test.ts +++ b/src/frontend/components/form-group/autosave/lib/autosave.test.ts @@ -2,7 +2,6 @@ import AutosaveBase from './autosaveBase'; import { describe, it, expect, beforeAll, afterAll } from '@jest/globals'; -// Mocking the AutosaveBase class for testing class TestAutosave extends AutosaveBase { initAutosave(): void { console.log('initAutosave'); diff --git a/src/frontend/components/form-group/select-widget/lib/component.js b/src/frontend/components/form-group/select-widget/lib/component.js index 498856a56..66b380e7f 100644 --- a/src/frontend/components/form-group/select-widget/lib/component.js +++ b/src/frontend/components/form-group/select-widget/lib/component.js @@ -11,6 +11,7 @@ import { initValidationOnField } from 'validation'; * SelectWidgets can depend on each other; * for instance if Value "1" is selected in Widget "A", * Widget "B" might not be displayed. + * @todo This uses deprecated code - update to newer "$.on" and "$.off" functionality */ class SelectWidgetComponent extends Component { /** @@ -608,29 +609,27 @@ class SelectWidgetComponent extends Component { ); this.$available.append(errorLi); } - }) - .fail(function (jqXHR, textStatus, textError) { - const errorMessage = jqXHR.responseJSON.message; - logging.error( - 'Failed to make request to ' + - url + - ': ' + - textStatus + - ': ' + - textError - ); - const errorLi = $( - '
  • ' - ); - self.$available.append(errorLi); - }) - .always(function () { - if (hideSpinner) { - self.$available.find('.spinner').attr('hidden', ''); - } - }); + }).fail(function (jqXHR, textStatus, textError) { + const errorMessage = jqXHR.responseJSON?.message ?? 'Oops! Something went wrong'; + logging.error( + 'Failed to make request to ' + + url + + ': ' + + textStatus + + ': ' + + textError + ); + const errorLi = $( + '
  • ' + ); + self.$available.append(errorLi); + }).always(function () { + if (hideSpinner) { + self.$available.find('.spinner').attr('hidden', ''); + } + }); } /** diff --git a/src/frontend/components/form-group/textarea/lib/component.js b/src/frontend/components/form-group/textarea/lib/component.js index af75d807b..f54529aad 100644 --- a/src/frontend/components/form-group/textarea/lib/component.js +++ b/src/frontend/components/form-group/textarea/lib/component.js @@ -67,5 +67,4 @@ class TextareaComponent extends Component { $textarea.css('height', `${adjustedHeight}rem`); } } - export default TextareaComponent; diff --git a/src/frontend/components/form-group/tree/lib/component.js b/src/frontend/components/form-group/tree/lib/component.js index ea010da60..a421aa317 100644 --- a/src/frontend/components/form-group/tree/lib/component.js +++ b/src/frontend/components/form-group/tree/lib/component.js @@ -212,8 +212,6 @@ class TreeComponent extends Component { /** * Handle the deletion of a node from the jstree. - * @returns {boolean} Returns true if a node was deleted, false otherwise. - * @todo Why does this have a return value? */ handleDelete() { const ref = this.$treeContainer.jstree(true); @@ -224,25 +222,21 @@ class TreeComponent extends Component { } ref.delete_node(sel); - return true; } /** * Handle the renaming of a node in the jstree. - * @returns {boolean} Returns true if a node was renamed, false otherwise. - * @todo Why does this have a return value? */ handleRename() { const ref = this.$treeContainer.jstree(true); let sel = ref.get_selected(); if (!sel.length) { - return false; + return; } sel = sel[0]; ref.edit(sel); - return true; } } diff --git a/src/frontend/components/help-view/lib/component.test.ts b/src/frontend/components/help-view/lib/component.test.ts index b5e4fa94c..d5720a849 100644 --- a/src/frontend/components/help-view/lib/component.test.ts +++ b/src/frontend/components/help-view/lib/component.test.ts @@ -2,7 +2,6 @@ import HelpView from './component'; import { describe, it, expect } from '@jest/globals'; -// Mock class to test the HelpView component exposing private members class TestHelpView extends HelpView { public get button() { return this.$button; diff --git a/src/frontend/components/modal/modals/curval/lib/component.js b/src/frontend/components/modal/modals/curval/lib/component.js index 56ff993d6..81be90c55 100644 --- a/src/frontend/components/modal/modals/curval/lib/component.js +++ b/src/frontend/components/modal/modals/curval/lib/component.js @@ -71,9 +71,9 @@ class CurvalModalComponent extends ModalComponent { } const instance_name = $target.data('curval-instance-name'); // Load the modal and load each value into its fields - $m.find('.modal-body').load(self.getURL(current_id, instance_name, layout_id), function(){ + $m.find('.modal-body').load(self.getURL(current_id, instance_name, layout_id), function () { initializeRegisteredComponents($m.get(0)); - $m.find('.linkspace-field').each(function(){ + $m.find('.linkspace-field').each(function () { const $field = $(this); const key = `linkspace-column-${$field.data('column-id')}-${$('body').data('layout-identifier')}-${record_id}`; const vals = values[key]; @@ -102,12 +102,12 @@ class CurvalModalComponent extends ModalComponent { let guid = form.data('guid'); const $formGroup = $('div[data-column-id=' + col_id + ']'); const valueSelector = $formGroup.data('value-selector'); - const self=this; + const self = this; const $field = $(`#curval_list_${col_id}`).closest('.linkspace-field'); const current_id = form.data('current-id'); const textValue = jQuery - .map(modal_field_ids, function(element) { + .map(modal_field_ids, function (element) { const value = values['field' + element]; return $('
    ') .text(value) @@ -120,7 +120,7 @@ class CurvalModalComponent extends ModalComponent { // No strict requirement for alias here, but it is needed below, so for the sake of consistency const row_cells = $('
    ', self.context); - jQuery.map($field.data('modal-field-ids'), function(element) { + jQuery.map($field.data('modal-field-ids'), function (element) { let value = values['field' + element]; value = $('
    ').text(value) .html(); @@ -134,7 +134,7 @@ class CurvalModalComponent extends ModalComponent { const editButton = $( `
    `, @@ -213,9 +213,9 @@ class CurvalModalComponent extends ModalComponent { $answersList.append(`
  • -
    - -
    '; strHTML += ( `
  • ', self.context); - jQuery.map($field.data('modal-field-ids'), function (element) { + jQuery.map($field.data('modal-field-ids'), function(element) { let value = values['field' + element]; value = $('
    ').text(value) .html(); @@ -134,7 +134,7 @@ class CurvalModalComponent extends ModalComponent { const editButton = $( `
    `, @@ -213,9 +213,9 @@ class CurvalModalComponent extends ModalComponent { $answersList.append(`
  • -
    - -
  • `, @@ -222,7 +222,7 @@ class CurvalModalComponent extends ModalComponent {
    -
    diff --git a/src/frontend/components/more-less/lib/component.js b/src/frontend/components/more-less/lib/component.js index 6c32e3297..edc616a6c 100644 --- a/src/frontend/components/more-less/lib/component.js +++ b/src/frontend/components/more-less/lib/component.js @@ -166,7 +166,7 @@ class MoreLessComponent extends Component { const toggleLabel = 'Show ' + column + ' ⇒'; const $expandToggle = $(' diff --git a/views/admin/default_welcome_email.tt b/views/admin/default_welcome_email.tt index 1f6a4b70e..cd05a5413 100644 --- a/views/admin/default_welcome_email.tt +++ b/views/admin/default_welcome_email.tt @@ -10,15 +10,15 @@
    [% INCLUDE fields/hidden.tt name="csrf_token" value=csrf_token; %] - +
    Default welcome email - +
    - +
    [% @@ -33,7 +33,7 @@ %]
    - +
    [% @@ -48,7 +48,7 @@ %]
    - +
    [% @@ -79,7 +79,7 @@ type = "button", name = "update", value = "update", - class = "btn btn-default", + class = "btn btn-primary", label = "Save" }] }]; diff --git a/views/admin/user_editable_personal_details.tt b/views/admin/user_editable_personal_details.tt index cf10b2bc7..320495d72 100644 --- a/views/admin/user_editable_personal_details.tt +++ b/views/admin/user_editable_personal_details.tt @@ -18,8 +18,8 @@ Allow users to edit the following details of their account
    - -
    + +
      [% FOREACH field in instance.user_fields %] @@ -58,7 +58,7 @@ type = "button", name = "update", value = "update", - class = "btn btn-default", + class = "btn btn-primary", label = "Save" }] }]; diff --git a/views/approval.tt b/views/approval.tt index 5a6be6034..93e66883e 100644 --- a/views/approval.tt +++ b/views/approval.tt @@ -2,7 +2,7 @@

      [% IF records.size %]
    - @@ -144,7 +144,7 @@ class CurvalModalComponent extends ModalComponent { const removeButton = $( ` -
    - + diff --git a/views/chronology.tt b/views/chronology.tt index 74d1abac5..06d3d5caf 100644 --- a/views/chronology.tt +++ b/views/chronology.tt @@ -14,14 +14,16 @@ action_datetime = version.datetime.as_string; action_type = initial ? 'created' : 'updated'; action_by = version.editor.id ? " by " _ version.editor.as_string : ''; - + %] -
    -

    - [% action_datetime _ " - " _ " record " _ action_type _ action_by | html %] -

    - -
    +
    +
    +

    + [% action_datetime _ " - " _ " record " _ action_type _ action_by | html %] +

    +
    + +
    Table for [% layout.record_name_plural | html %] requiring approvalTable for [% layout.record_name_plural | html %] requiring approval
    ID Submitted by
    - + @@ -53,15 +53,15 @@
    Table for departmentsTable for departments
    Name
    - + @@ -72,8 +73,8 @@ [% FOREACH metric IN metricgroup.metrics %] - + [% END %] [% INCLUDE tables/basic_row.tt row=header_row %] diff --git a/views/team.tt b/views/team.tt index 992a98d43..eddbc2620 100644 --- a/views/team.tt +++ b/views/team.tt @@ -8,7 +8,7 @@ [% IF team.id %] [% END %] -
    +
    @@ -17,7 +17,7 @@

    [% IF team.id %] - Delete + Delete [% END %]

    @@ -28,10 +28,10 @@
    Table for metric groupsTable for metric groups
    X-axis value
    - - - + + +
    -
    -

    - Metrics help -

    - -
    +
    +
    +

    + Metrics help +

    +
    + +

    Use this page to define a set of metrics to plot graphs against. @@ -137,7 +140,7 @@

    - +
    @@ -153,7 +156,7 @@
    [% IF button_type == "button" %] - [% ELSE %] diff --git a/views/tables/basic_cell_modal_button.tt b/views/tables/basic_cell_modal_button.tt index d55f3306f..dc15a89f9 100644 --- a/views/tables/basic_cell_modal_button.tt +++ b/views/tables/basic_cell_modal_button.tt @@ -6,9 +6,9 @@
    [% table_caption | html %][% table_caption | html %]
    - + @@ -53,7 +53,7 @@
    Table for teamsTable for teams
    Name
    - + @@ -53,7 +53,7 @@
    Table for titlesTable for titles
    Name
    - +
    Table for topicsTable for topics
    @@ -430,7 +426,7 @@ label = "Back" }] right_buttons = [{ - class = "btn-js-next btn-default" + class = "btn-js-next btn-primary" label = "Next" }]; %] @@ -467,7 +463,7 @@ class = "btn-inverted btn-js-skip" label = "Skip creating fields" }, { - class = "btn-js-next btn-default" + class = "btn-js-next btn-primary" label = "Next" }]; %] @@ -616,7 +612,7 @@ -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "show_calculator" @@ -641,7 +637,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "show_datepicker_date" @@ -662,7 +658,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "default_today" @@ -687,7 +683,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "show_datepicker_date-range" @@ -719,7 +715,7 @@
    -
    @@ -751,7 +747,7 @@ @@ -764,7 +760,7 @@

    Each value in the tree is referred to as a node.

    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "end_node_only" @@ -805,7 +801,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "default_to_login" @@ -880,7 +876,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "no_alerts_calc_rag" @@ -969,7 +965,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "no_alerts_calc" @@ -1036,7 +1032,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "show_add" @@ -1058,7 +1054,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "delete_not_used" @@ -1080,7 +1076,7 @@
    -
    +
    [% INCLUDE fields/sub/checkbox.tt id = "override_permissions" @@ -1161,7 +1157,7 @@
    -
    +
    [% PROCESS builder.tt builder_id = instance_layout.instance_id @@ -1193,7 +1189,7 @@ label = "Back" }] right_buttons = [{ - class = "btn-js-next btn-default" + class = "btn-js-next btn-primary" label = "Next" }]; %] @@ -1219,12 +1215,6 @@ # prepare table config table_id = 'custom_field_permissions_table'; table_class = 'table-lines table-no-margin'; - table_layout = { - topStart => "search", - topEnd => "pageLength", - bottomStart => "paging", - bottomEnd => "info" - } table_language = { emptyTable => "There are no groups available", lengthMenu => "Rows per page _MENU_", @@ -1232,7 +1222,7 @@ next => "Next", previous => "Previous" }, - search => "Search in groups:", + search => "Search in groups:", searchPlaceholder => "Search group" } table_page_length = 5; @@ -1419,7 +1409,7 @@ label = "Back" }] right_buttons = [{ - class = "btn-js-next btn-default" + class = "btn-js-next btn-primary" label = "Next" }]; %] @@ -1450,19 +1440,13 @@ [% table_id = 'fields'; table_class = 'table-lines'; - table_layout = { - topStart => "search", - topEnd => "pageLength", - bottomStart => "paging", - bottomEnd => "info" - } table_language = { lengthMenu => "Rows per page _MENU_", paginate => { next => "Next", previous => "Previous" }, - search => "Search in fields:", + search => "Search in fields:", searchPlaceholder => "Search field" } table_page_length = 5; @@ -1501,7 +1485,7 @@ label = "Back" }] right_buttons = [{ - class = "btn-js-save btn-default" + class = "btn-js-save btn-primary" label = "Save" }]; %] diff --git a/views/wizard/timeline_options.tt b/views/wizard/timeline_options.tt index 9e330ebf4..0824a6fe0 100644 --- a/views/wizard/timeline_options.tt +++ b/views/wizard/timeline_options.tt @@ -6,7 +6,7 @@