diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml index edeea9a64..b22922aee 100644 --- a/.github/workflows/super-linter.yml +++ b/.github/workflows/super-linter.yml @@ -35,8 +35,10 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DEFAULT_BRANCH: main VALIDATE_ALL_CODEBASE: false + VALIDATE_CSS: false VALIDATE_GITHUB_ACTIONS: false VALIDATE_DOCKERFILE_HADOLINT: false + VALIDATE_JAVASCRIPT_STANDARD: false VALIDATE_JSCPD: false VALIDATE_PYTHON_MYPY: false VALIDATE_PYTHON_PYLINT: false diff --git a/Dockerfile b/Dockerfile index be0cafe18..122442d86 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ COPY jest.config.js controlpanel/frontend/static /src/ RUN npm install RUN mkdir -p dist &&\ ./node_modules/.bin/babel src/module-loader.js src/components src/javascripts -o dist/app.js -s -RUN ./node_modules/.bin/sass --load-path=node_modules/ --style=compressed src/app.scss:dist/app.css +RUN ./node_modules/.bin/sass --load-path=./ --style=compressed src/app.scss:dist/app.css WORKDIR /src RUN /node_modules/.bin/jest @@ -69,6 +69,10 @@ COPY tests tests # install javascript dependencies COPY --from=build-node dist/app.css dist/app.js static/ +COPY --from=build-node node_modules/govuk-frontend/dist/govuk/assets/fonts/. static/assets/fonts +COPY --from=build-node node_modules/govuk-frontend/dist/govuk/assets/images/. static/assets/images +COPY --from=build-node node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js static/assets/js/govuk-frontend.min.js +COPY --from=build-node node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map static/assets/js/govuk-frontend.min.js.map COPY --from=build-node node_modules/accessible-autocomplete/dist/ static/accessible-autocomplete COPY --from=build-node node_modules/govuk-frontend static/govuk-frontend COPY --from=build-node node_modules/@ministryofjustice/frontend/moj static/ministryofjustice-frontend diff --git a/Makefile b/Makefile index d7379a10d..c65327a44 100644 --- a/Makefile +++ b/Makefile @@ -58,13 +58,21 @@ build-static: build-css: mkdir static + mkdir -p static/assets/fonts + mkdir -p static/assets/images + cp -R node_modules/govuk-frontend/dist/govuk/assets/fonts/. static/assets/fonts + cp -R node_modules/govuk-frontend/dist/govuk/assets/images/. static/assets/images cp -R node_modules/accessible-autocomplete/dist/ static/accessible-autocomplete cp -R node_modules/govuk-frontend/ static/govuk-frontend cp -R node_modules/@ministryofjustice/frontend/ static/ministryofjustice-frontend cp -R node_modules/html5shiv/dist/ static/html5-shiv - ./node_modules/.bin/sass --load-path=node_modules/ --style=compressed controlpanel/frontend/static/app.scss:static/app.css + npm run css --load build-js: + mkdir -p static/assets/js + cp node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js static/assets/js/govuk-frontend.min.js + cp node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map static/assets/js/govuk-frontend.min.js.map + cp -R node_modules/jquery/dist/ static/jquery cp -R node_modules/jquery-ui/dist/ static/jquery-ui ./node_modules/.bin/babel \ diff --git a/controlpanel/frontend/jinja2/base.html b/controlpanel/frontend/jinja2/base.html index 29ca7d416..530bac928 100644 --- a/controlpanel/frontend/jinja2/base.html +++ b/controlpanel/frontend/jinja2/base.html @@ -145,7 +145,7 @@
- Warning + Warning {% for message in broadcast_messages %} {{ message }}
{% endfor %} @@ -194,8 +194,11 @@ {% block body_end %} {% block scripts %} - - + + diff --git a/controlpanel/frontend/jinja2/datasource-detail.html b/controlpanel/frontend/jinja2/datasource-detail.html index 82106174a..6646a1587 100644 --- a/controlpanel/frontend/jinja2/datasource-detail.html +++ b/controlpanel/frontend/jinja2/datasource-detail.html @@ -24,7 +24,7 @@

{{ page_title }}

- Warning + Warning This bucket was deleted by {{ user_name(bucket.deleted_by) }} on {{ bucket.deleted_at.strftime("%Y/%m/%d %H:%M:%S") }}.
All access listed below has been revoked in IAM. diff --git a/controlpanel/frontend/jinja2/govuk-frontend.html b/controlpanel/frontend/jinja2/govuk-frontend.html index 6b1d7b79c..a2874439e 100644 --- a/controlpanel/frontend/jinja2/govuk-frontend.html +++ b/controlpanel/frontend/jinja2/govuk-frontend.html @@ -18,7 +18,7 @@ {# Ensure that older IE versions always render with the correct rendering engine #} {% block headIcons %} - + @@ -35,7 +35,7 @@ - +
{% block bodyStart %}{% endblock %} diff --git a/controlpanel/frontend/jinja2/includes/auth0-connections-form.html b/controlpanel/frontend/jinja2/includes/auth0-connections-form.html index c3163c86b..9e7231b8a 100644 --- a/controlpanel/frontend/jinja2/includes/auth0-connections-form.html +++ b/controlpanel/frontend/jinja2/includes/auth0-connections-form.html @@ -22,26 +22,31 @@ {% set name = "connections" %} {% set itemHintId = id + '-item-hint' %}
+ {% set client_id_field_name = item[1] + '_auth0_client_id' %} + {% set client_secret_field_name = item[1] + '_auth0_client_secret' %} + {% set conn_name_field_name = item[1] + '_auth0_conn_name' %} + {% set has_linked_client_fields = (form.fields.get(client_id_field_name, None)) %} + {% set label_text = item[0] + " (Please provide the client credential from the provider)" if has_linked_client_fields else item[0] %} + {{ govukLabel({ - "text": item[0], + "text": label_text, "classes": 'govuk-checkboxes__label' + (' ' + (item.label|default({})).classes|default("")), "attributes": (item.label|default({})).attributes|default(""), "for": id }) }} - {% set client_id_field_name = item[1] + '_auth0_client_id' %} - {% set client_secret_field_name = item[1] + '_auth0_client_secret' %} - {% set conn_name_field_name = item[1] + '_auth0_conn_name' %} - {% set has_linked_client_fields = (form.fields.get(client_id_field_name, None)) %} - {% if has_linked_client_fields %} - {% set client_id_field = form.fields.get(client_id_field_name) %} - {% set client_secret_field = form.fields.get(client_secret_field_name) %} - {% set conn_name_field = form.fields.get(conn_name_field_name) %} - (Please provide the client credential from the provider) -
-
+
+ + {% if has_linked_client_fields %} + {% set client_id_field = form.fields.get(client_id_field_name) %} + {% set client_secret_field = form.fields.get(client_secret_field_name) %} + {% set conn_name_field = form.fields.get(conn_name_field_name) %} + +
+
+
{{ govukInput({ "name": conn_name_field_name, "classes": "govuk-!-width-one-half", @@ -77,9 +82,9 @@ "errorMessage": {"text": params.errors[client_secret_field_name]|join(". ")} if params.errors.get(client_secret_field_name) else {}, }) }} -
- {% endif %} -
+
+
+ {% endif %} {% endfor %}
{% endset -%} diff --git a/controlpanel/frontend/jinja2/ip-allowlist-list.html b/controlpanel/frontend/jinja2/ip-allowlist-list.html index 0462d4d3d..03d21b996 100644 --- a/controlpanel/frontend/jinja2/ip-allowlist-list.html +++ b/controlpanel/frontend/jinja2/ip-allowlist-list.html @@ -32,12 +32,12 @@

{{ page_title }}

{{ ip_allowlist.description }} - {{ ip_allowlist.allowed_ip_ranges }} + {{ ip_allowlist.allowed_ip_ranges.replace(",", ", ") }} - Manage IP allowlist + Manage IP allowlist diff --git a/controlpanel/frontend/jinja2/reset.html b/controlpanel/frontend/jinja2/reset.html index 3478583ff..5ecc92afb 100644 --- a/controlpanel/frontend/jinja2/reset.html +++ b/controlpanel/frontend/jinja2/reset.html @@ -33,7 +33,7 @@

Home Directory Reset

- Warning + Warning Please ensure you've copied any important files from your home directory. Important files should be stored in S3 or GitHub. diff --git a/controlpanel/frontend/jinja2/webapp-auth0-connections-update.html b/controlpanel/frontend/jinja2/webapp-auth0-connections-update.html index 1d16e15b0..e46109b77 100644 --- a/controlpanel/frontend/jinja2/webapp-auth0-connections-update.html +++ b/controlpanel/frontend/jinja2/webapp-auth0-connections-update.html @@ -9,7 +9,7 @@ Update auth0 connections - {{ app.name }} {%- endset %} -{% set page_name = "Auth0 connections" %} +{% set page_title = "Auth0 connections" %} {% block content %}

{{ legend }}

diff --git a/controlpanel/frontend/jinja2/webapp-create.html b/controlpanel/frontend/jinja2/webapp-create.html index a96d163b3..f02fa3c25 100644 --- a/controlpanel/frontend/jinja2/webapp-create.html +++ b/controlpanel/frontend/jinja2/webapp-create.html @@ -12,7 +12,7 @@ {% set new_datasource_html %} Create a new webapp data source -
+
{{ govukInput({ "name": "new_datasource_name", "classes": "govuk-!-width-one-half", @@ -35,7 +35,7 @@ {% set existing_datasource_html %} Connect an existing webapp data source -
+
{{ govukLabel({"text": "Select webapp data source"}) }} diff --git a/controlpanel/frontend/static/app.scss b/controlpanel/frontend/static/app.scss index f7ad6bb90..cb6d3d80b 100644 --- a/controlpanel/frontend/static/app.scss +++ b/controlpanel/frontend/static/app.scss @@ -4,13 +4,13 @@ $govuk-global-styles: true; $govuk-font-family-nta: "Arial"; $govuk-font-family-nta-tabular: "Arial"; -$govuk-assets-path: "/static/govuk-frontend/govuk/assets/"; +$govuk-assets-path: "/static/assets/"; // GOV.UK Frontend -@import "govuk-frontend/govuk/all"; +@import "node_modules/govuk-frontend/dist/govuk/all"; // MOJ Frontend -@import "@ministryofjustice/frontend/moj/all"; +@import "node_modules/@ministryofjustice/frontend/moj/all"; // Other component styles @import "components/all"; diff --git a/controlpanel/frontend/static/components/checkboxes/macro.html b/controlpanel/frontend/static/components/checkboxes/macro.html index 64b966f3d..d8e6d09e4 100644 --- a/controlpanel/frontend/static/components/checkboxes/macro.html +++ b/controlpanel/frontend/static/components/checkboxes/macro.html @@ -78,7 +78,7 @@ "classes": 'govuk-checkboxes__hint', "attributes": item.hint.attributes, "html": item.hint.html, - text: item.hint.text + "text": item.hint.text }) }} {%- endif %}
diff --git a/controlpanel/frontend/static/components/hint/macro.html b/controlpanel/frontend/static/components/hint/macro.html index b66e01f4d..8338ae6c4 100644 --- a/controlpanel/frontend/static/components/hint/macro.html +++ b/controlpanel/frontend/static/components/hint/macro.html @@ -1,6 +1,6 @@ {% macro govukHint(params) %} - {{ params.html|default(params.text)|safe }} - +
{% endmacro %} diff --git a/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js b/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js new file mode 100644 index 000000000..c63410e6b --- /dev/null +++ b/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js @@ -0,0 +1,38 @@ +moj.Modules.toggleCheckboxForm = { + subFormClass: 'checkbox-subform', + selector: 'data-show-if-selected', + hiddenClass: 'govuk-!-display-none', + + init() { + const panels = document.querySelectorAll(`.${this.subFormClass}`); + if (panels) { + this.bindEvents(panels); + } + }, + + bindEvents(panels) { + + panels.forEach(panel => { + const attribute = panel.getAttribute(this.selector); + var formItem = document.querySelector(`[value=${attribute}]`); + + this.setVisibility(panel, formItem.checked); + + formItem.addEventListener('change', () => { + this.togglePanel(panel); + }); + }); + }, + + togglePanel(panel) { + panel.classList.toggle(this.hiddenClass); + }, + + setVisibility(panel, show) { + if (show) { + panel.classList.remove(this.hiddenClass); + } else { + panel.classList.add(this.hiddenClass); + } + } +}; diff --git a/controlpanel/frontend/static/javascripts/modules/toggle-radio-form.js b/controlpanel/frontend/static/javascripts/modules/toggle-radio-form.js new file mode 100644 index 000000000..96a73a5a3 --- /dev/null +++ b/controlpanel/frontend/static/javascripts/modules/toggle-radio-form.js @@ -0,0 +1,55 @@ +moj.Modules.toggleRadioForm = { + panelClass: 'radio-subform', + selector: 'data-show-if-selected', + radioButtonClass: 'govuk-radios__input', + hiddenClass: 'govuk-!-display-none', + + init() { + const panels = document.querySelectorAll(`.${this.panelClass}`); + if (panels) { + this.bindEvents(panels); + } + }, + + bindEvents(panels) { + + const radios = document.querySelectorAll(`.${this.radioButtonClass}`); + + radios.forEach(radio => { + radio.addEventListener('change', () => { + const name = radio.getAttribute('name'); + + document.querySelectorAll(`input[name="${name}"]`).forEach(otherRadio => { + if (otherRadio !== radio) { + // Trigger a custom 'deselect' event on every member of the current radio group except the clicked one... + const event = new Event('deselect'); + otherRadio.dispatchEvent(event); + } + }); + }); + }); + + panels.forEach(panel => { + const attribute = panel.getAttribute(this.selector); + var formItem = document.querySelector(`#${attribute}`); + + this.setVisibility(panel, formItem.checked); + + formItem.addEventListener('change', (event) => { + this.setVisibility(panel, event.target.checked); + }); + + formItem.addEventListener('deselect', (event) => { + this.setVisibility(panel, event.target.checked); + }); + }); + }, + + setVisibility(panel, show) { + if (show) { + panel.classList.remove(this.hiddenClass); + } else { + panel.classList.add(this.hiddenClass); + } + } +}; diff --git a/controlpanel/frontend/views/app.py b/controlpanel/frontend/views/app.py index 9cd31f4b0..79bb60908 100644 --- a/controlpanel/frontend/views/app.py +++ b/controlpanel/frontend/views/app.py @@ -210,14 +210,24 @@ class UpdateAppIPAllowlists(OIDCLoginRequiredMixin, PermissionRequiredMixin, Upd permission_required = "api.update_app_ip_allowlists" fields = ["ip_allowlists"] + def format_ip_allowlists(self, allowlist): + # splits larger ip allowlists into multiple lines + + allowlist = allowlist.replace(",", ", ") + return allowlist + def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) context["app"] = self.get_object() context["env_name"] = self.request.GET.get("env_name") + context["app_ip_allowlists"] = [ { "text": ip_allowlist.name, "value": ip_allowlist.pk, + "hint": { + "text": self.format_ip_allowlists(ip_allowlist.allowed_ip_ranges), + }, "checked": ip_allowlist.pk in context["app"].env_allow_ip_ranges_ids(context["env_name"]), } diff --git a/package-lock.json b/package-lock.json index 12cfd0bea..42e09d76d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,10 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "@ministryofjustice/frontend": "0.0.17-alpha", + "@ministryofjustice/frontend": "2.1.3", "accessible-autocomplete": "2.0.4", "core-js": "3.26.1", - "govuk-frontend": "3.0.0", + "govuk-frontend": "5.4.0", "html5shiv": "3.7.3", "jquery": "3.6.1", "jquery-ui": "1.13.2", @@ -2497,14 +2497,19 @@ } }, "node_modules/@ministryofjustice/frontend": { - "version": "0.0.17-alpha", - "resolved": "https://registry.npmjs.org/@ministryofjustice/frontend/-/frontend-0.0.17-alpha.tgz", - "integrity": "sha512-UOwqFA24kd8xJY6XrWxaQxM2xzr8BHdwb5L82xPk3rG7hgEnWRppk7vt9eszqSt3Hwdfj63pD8aaMTMsi89P4Q==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@ministryofjustice/frontend/-/frontend-2.1.3.tgz", + "integrity": "sha512-kFStfY6Ckbx9OGUEf2xXAjG8oUGXpARpbogk569MTH5LnI1txVT0NieskA4Vthic+2yQ++bePtKX46U1f30rLA==", + "license": "MIT", "dependencies": { - "moment": "^2.22.2" + "govuk-frontend": "^5.0.0", + "moment": "^2.27.0" }, "engines": { "node": ">= 4.2.0" + }, + "peerDependencies": { + "jquery": "^3.6.0" } }, "node_modules/@nicolo-ribaudo/chokidar-2": { @@ -4165,9 +4170,10 @@ } }, "node_modules/govuk-frontend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-3.0.0.tgz", - "integrity": "sha512-GCrEeaQZEnsthNtfmOUFlgsieNjHOeoamSWMdD4Gdq0RPxCA9uzfrT2i3jVnlBORekKjOL0C8eFZQBSNnjtz2A==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.4.0.tgz", + "integrity": "sha512-F3YwQYrYQqIPfNxsoph6O78Ey1unCB6cy6omx8KeWY9G504lWZFBSIaiUCma1jNLw9bOUU7Ui+tXG09jjqy0Mw==", + "license": "MIT", "engines": { "node": ">= 4.2.0" } @@ -10137,11 +10143,12 @@ } }, "@ministryofjustice/frontend": { - "version": "0.0.17-alpha", - "resolved": "https://registry.npmjs.org/@ministryofjustice/frontend/-/frontend-0.0.17-alpha.tgz", - "integrity": "sha512-UOwqFA24kd8xJY6XrWxaQxM2xzr8BHdwb5L82xPk3rG7hgEnWRppk7vt9eszqSt3Hwdfj63pD8aaMTMsi89P4Q==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@ministryofjustice/frontend/-/frontend-2.1.3.tgz", + "integrity": "sha512-kFStfY6Ckbx9OGUEf2xXAjG8oUGXpARpbogk569MTH5LnI1txVT0NieskA4Vthic+2yQ++bePtKX46U1f30rLA==", "requires": { - "moment": "^2.22.2" + "govuk-frontend": "^5.0.0", + "moment": "^2.27.0" } }, "@nicolo-ribaudo/chokidar-2": { @@ -11423,9 +11430,9 @@ } }, "govuk-frontend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-3.0.0.tgz", - "integrity": "sha512-GCrEeaQZEnsthNtfmOUFlgsieNjHOeoamSWMdD4Gdq0RPxCA9uzfrT2i3jVnlBORekKjOL0C8eFZQBSNnjtz2A==" + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.4.0.tgz", + "integrity": "sha512-F3YwQYrYQqIPfNxsoph6O78Ey1unCB6cy6omx8KeWY9G504lWZFBSIaiUCma1jNLw9bOUU7Ui+tXG09jjqy0Mw==" }, "graceful-fs": { "version": "4.2.10", diff --git a/package.json b/package.json index 68d64db1b..35b7abcde 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,10 @@ "repository": "https://github.com/ministryofjustice/analytics-platform-control-panel.git", "license": "MIT", "dependencies": { - "@ministryofjustice/frontend": "0.0.17-alpha", + "@ministryofjustice/frontend": "2.1.3", + "govuk-frontend": "5.4.0", "accessible-autocomplete": "2.0.4", "core-js": "3.26.1", - "govuk-frontend": "3.0.0", "html5shiv": "3.7.3", "jquery": "3.6.1", "jquery-ui": "1.13.2", @@ -28,7 +28,7 @@ "npm-run-all": "4.1.5" }, "scripts": { - "css": "sass --load-path=node_modules/ --style=compressed controlpanel/frontend/static/app.scss:static/app.css", + "css": "sass --load-path=./ --style=compressed controlpanel/frontend/static/app.scss:static/app.css", "watch:css": "npm run css && npm run css -- --source-map true --source-map-embed true --watch", "watch:babel": "npm run babel && npm run babel -- -w", "watch": "npm-run-all --parallel watch:*",