-
Notifications
You must be signed in to change notification settings - Fork 342
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use features of base component for FileUpload
#5590
Merged
romaricpascal
merged 3 commits into
spike-enhanced-file-upload
from
enhanced-file-upload-base-class
Jan 10, 2025
Merged
Use features of base component for FileUpload
#5590
romaricpascal
merged 3 commits into
spike-enhanced-file-upload
from
enhanced-file-upload-base-class
Jan 10, 2025
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ahead of using `ConfigurableComponent` add tests for errors that won't be handled by the base class, so we know the functionality is still there. Tests for the errors thrown by `ConfiguableComponent` will be added when the class gets used.
Use the recently added class for consistency with the other components. Also adds the tests related to the behaviour provided by the `ConfigurableComponent` class
Make the error message when the `<input>` does not have the expected type consistent with the messages from the other errors thrown by the component.
📋 StatsFile sizes
Modules
View stats and visualisations on the review app Action run for 6b4d4fa |
JavaScript changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
index 721a7e7fd..a58c936ee 100644
--- a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
+++ b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.js
@@ -120,7 +120,12 @@ class ConfigurableComponent extends GOVUKFrontendComponent {
super(e), this._config = void 0;
const i = this.constructor;
if (void 0 === i.defaults) throw new ConfigError(formatErrorMessage(i, "Config passed as parameter into constructor but no defaults defined"));
- const s = normaliseDataset(i, this._$root.dataset);
+ const s = function(Component, t) {
+ if (void 0 === Component.schema) throw new ConfigError(formatErrorMessage(Component, "Config passed as parameter into constructor but no schema defined"));
+ const e = {};
+ for (const [n, i] of Object.entries(Component.schema.properties)) n in t && (e[n] = normaliseString(t[n], i)), "object" === (null == i ? void 0 : i.type) && (e[n] = extractConfigByNamespace(Component.schema, t, n));
+ return e
+ }(i, this._$root.dataset);
this._config = mergeConfigs(i.defaults, null != n ? n : {}, this[t](s), s)
}
}
@@ -141,13 +146,6 @@ function normaliseString(t, e) {
return i
}
-function normaliseDataset(Component, t) {
- if (void 0 === Component.schema) throw new ConfigError(formatErrorMessage(Component, "Config passed as parameter into constructor but no schema defined"));
- const e = {};
- for (const [n, i] of Object.entries(Component.schema.properties)) n in t && (e[n] = normaliseString(t[n], i)), "object" === (null == i ? void 0 : i.type) && (e[n] = extractConfigByNamespace(Component.schema, t, n));
- return e
-}
-
function mergeConfigs(...t) {
const e = {};
for (const n of t)
@@ -750,11 +748,10 @@ ExitThisPage.moduleName = "govuk-exit-this-page", ExitThisPage.defaults = Object
}
}
});
-class FileUpload extends GOVUKFrontendComponent {
+class FileUpload extends ConfigurableComponent {
constructor(t, e = {}) {
- if (super(t), this.$wrapper = void 0, this.$button = void 0, this.$status = void 0, this.config = void 0, this.i18n = void 0, !(this.$root instanceof HTMLInputElement)) return;
- if ("file" !== this.$root.type) throw new ElementError("File upload: Form field must be an input of type `file`.");
- if (this.config = mergeConfigs(FileUpload.defaults, e, normaliseDataset(FileUpload, this.$root.dataset)), this.i18n = new I18n(this.config.i18n, {
+ if (super(t, e), this.$wrapper = void 0, this.$button = void 0, this.$status = void 0, this.i18n = void 0, "file" !== this.$root.type) throw new ElementError(formatErrorMessage(FileUpload, "Form field must be an input of type `file`."));
+ if (this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(this.$root, "lang")
}), this.$label = document.querySelector(`[for="${this.$root.id}"]`), !this.$label) throw new ElementError({
component: FileUpload,
@@ -771,9 +768,9 @@ class FileUpload extends GOVUKFrontendComponent {
if (!("files" in this.$root)) return;
if (!this.$root.files) return;
const t = this.$root.files.length;
- this.$status && this.i18n && (this.$status.innerText = 0 === t ? this.i18n.t("filesSelectedDefault") : 1 === t ? this.$root.files[0].name : this.i18n.t("filesSelected", {
+ this.$status.innerText = 0 === t ? this.i18n.t("filesSelectedDefault") : 1 === t ? this.$root.files[0].name : this.i18n.t("filesSelected", {
count: t
- }))
+ })
}
onClick() {
this.$label instanceof HTMLElement && this.$label.click()
Action run for 6b4d4fa |
Other changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/all.bundle.js b/packages/govuk-frontend/dist/govuk/all.bundle.js
index a2e6c5c58..c781bbe48 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.js
@@ -1658,26 +1658,22 @@
* File upload component
*
* @preserve
+ * @augments ConfigurableComponent<FileUploadConfig,HTMLInputElement>
*/
- class FileUpload extends GOVUKFrontendComponent {
+ class FileUpload extends ConfigurableComponent {
/**
* @param {Element | null} $root - File input element
* @param {FileUploadConfig} [config] - File Upload config
*/
constructor($root, config = {}) {
- super($root);
+ super($root, config);
this.$wrapper = void 0;
this.$button = void 0;
this.$status = void 0;
- this.config = void 0;
this.i18n = void 0;
- if (!(this.$root instanceof HTMLInputElement)) {
- return;
- }
if (this.$root.type !== 'file') {
- throw new ElementError('File upload: Form field must be an input of type `file`.');
+ throw new ElementError(formatErrorMessage(FileUpload, 'Form field must be an input of type `file`.'));
}
- this.config = mergeConfigs(FileUpload.defaults, config, normaliseDataset(FileUpload, this.$root.dataset));
this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(this.$root, 'lang')
});
@@ -1722,9 +1718,6 @@
return;
}
const fileCount = this.$root.files.length;
- if (!this.$status || !this.i18n) {
- return;
- }
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
} else if (fileCount === 1) {
diff --git a/packages/govuk-frontend/dist/govuk/all.bundle.mjs b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
index f261b255d..213c3ce51 100644
--- a/packages/govuk-frontend/dist/govuk/all.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/all.bundle.mjs
@@ -1652,26 +1652,22 @@ ExitThisPage.schema = Object.freeze({
* File upload component
*
* @preserve
+ * @augments ConfigurableComponent<FileUploadConfig,HTMLInputElement>
*/
-class FileUpload extends GOVUKFrontendComponent {
+class FileUpload extends ConfigurableComponent {
/**
* @param {Element | null} $root - File input element
* @param {FileUploadConfig} [config] - File Upload config
*/
constructor($root, config = {}) {
- super($root);
+ super($root, config);
this.$wrapper = void 0;
this.$button = void 0;
this.$status = void 0;
- this.config = void 0;
this.i18n = void 0;
- if (!(this.$root instanceof HTMLInputElement)) {
- return;
- }
if (this.$root.type !== 'file') {
- throw new ElementError('File upload: Form field must be an input of type `file`.');
+ throw new ElementError(formatErrorMessage(FileUpload, 'Form field must be an input of type `file`.'));
}
- this.config = mergeConfigs(FileUpload.defaults, config, normaliseDataset(FileUpload, this.$root.dataset));
this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(this.$root, 'lang')
});
@@ -1716,9 +1712,6 @@ class FileUpload extends GOVUKFrontendComponent {
return;
}
const fileCount = this.$root.files.length;
- if (!this.$status || !this.i18n) {
- return;
- }
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
} else if (fileCount === 1) {
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js
index 69b24f51d..095ec7ec6 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js
@@ -150,6 +150,32 @@
*/
GOVUKFrontendComponent.elementType = HTMLElement;
+ const configOverride = Symbol.for('configOverride');
+ class ConfigurableComponent extends GOVUKFrontendComponent {
+ [configOverride](param) {
+ return {};
+ }
+
+ /**
+ * Returns the root element of the component
+ *
+ * @protected
+ * @returns {ConfigurationType} - the root element of component
+ */
+ get config() {
+ return this._config;
+ }
+ constructor($root, config) {
+ super($root);
+ this._config = void 0;
+ const childConstructor = this.constructor;
+ if (typeof childConstructor.defaults === 'undefined') {
+ throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
+ }
+ const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
+ this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
+ }
+ }
function normaliseString(value, property) {
const trimmedValue = value ? value.trim() : '';
let output;
@@ -459,26 +485,22 @@
* File upload component
*
* @preserve
+ * @augments ConfigurableComponent<FileUploadConfig,HTMLInputElement>
*/
- class FileUpload extends GOVUKFrontendComponent {
+ class FileUpload extends ConfigurableComponent {
/**
* @param {Element | null} $root - File input element
* @param {FileUploadConfig} [config] - File Upload config
*/
constructor($root, config = {}) {
- super($root);
+ super($root, config);
this.$wrapper = void 0;
this.$button = void 0;
this.$status = void 0;
- this.config = void 0;
this.i18n = void 0;
- if (!(this.$root instanceof HTMLInputElement)) {
- return;
- }
if (this.$root.type !== 'file') {
- throw new ElementError('File upload: Form field must be an input of type `file`.');
+ throw new ElementError(formatErrorMessage(FileUpload, 'Form field must be an input of type `file`.'));
}
- this.config = mergeConfigs(FileUpload.defaults, config, normaliseDataset(FileUpload, this.$root.dataset));
this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(this.$root, 'lang')
});
@@ -523,9 +545,6 @@
return;
}
const fileCount = this.$root.files.length;
- if (!this.$status || !this.i18n) {
- return;
- }
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
} else if (fileCount === 1) {
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs
index 65b4aae36..72de1cc29 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs
@@ -144,6 +144,32 @@ class GOVUKFrontendComponent {
*/
GOVUKFrontendComponent.elementType = HTMLElement;
+const configOverride = Symbol.for('configOverride');
+class ConfigurableComponent extends GOVUKFrontendComponent {
+ [configOverride](param) {
+ return {};
+ }
+
+ /**
+ * Returns the root element of the component
+ *
+ * @protected
+ * @returns {ConfigurationType} - the root element of component
+ */
+ get config() {
+ return this._config;
+ }
+ constructor($root, config) {
+ super($root);
+ this._config = void 0;
+ const childConstructor = this.constructor;
+ if (typeof childConstructor.defaults === 'undefined') {
+ throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
+ }
+ const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
+ this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
+ }
+}
function normaliseString(value, property) {
const trimmedValue = value ? value.trim() : '';
let output;
@@ -453,26 +479,22 @@ I18n.pluralRules = {
* File upload component
*
* @preserve
+ * @augments ConfigurableComponent<FileUploadConfig,HTMLInputElement>
*/
-class FileUpload extends GOVUKFrontendComponent {
+class FileUpload extends ConfigurableComponent {
/**
* @param {Element | null} $root - File input element
* @param {FileUploadConfig} [config] - File Upload config
*/
constructor($root, config = {}) {
- super($root);
+ super($root, config);
this.$wrapper = void 0;
this.$button = void 0;
this.$status = void 0;
- this.config = void 0;
this.i18n = void 0;
- if (!(this.$root instanceof HTMLInputElement)) {
- return;
- }
if (this.$root.type !== 'file') {
- throw new ElementError('File upload: Form field must be an input of type `file`.');
+ throw new ElementError(formatErrorMessage(FileUpload, 'Form field must be an input of type `file`.'));
}
- this.config = mergeConfigs(FileUpload.defaults, config, normaliseDataset(FileUpload, this.$root.dataset));
this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(this.$root, 'lang')
});
@@ -517,9 +539,6 @@ class FileUpload extends GOVUKFrontendComponent {
return;
}
const fileCount = this.$root.files.length;
- if (!this.$status || !this.i18n) {
- return;
- }
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
} else if (fileCount === 1) {
diff --git a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs
index a1ff0baf8..596c4a95a 100644
--- a/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs
+++ b/packages/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs
@@ -1,33 +1,29 @@
import { closestAttributeValue } from '../../common/closest-attribute-value.mjs';
-import { mergeConfigs, normaliseDataset } from '../../common/configuration.mjs';
+import { ConfigurableComponent } from '../../common/configuration.mjs';
+import { formatErrorMessage } from '../../common/index.mjs';
import { ElementError } from '../../errors/index.mjs';
-import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs';
import { I18n } from '../../i18n.mjs';
/**
* File upload component
*
* @preserve
+ * @augments ConfigurableComponent<FileUploadConfig,HTMLInputElement>
*/
-class FileUpload extends GOVUKFrontendComponent {
+class FileUpload extends ConfigurableComponent {
/**
* @param {Element | null} $root - File input element
* @param {FileUploadConfig} [config] - File Upload config
*/
constructor($root, config = {}) {
- super($root);
+ super($root, config);
this.$wrapper = void 0;
this.$button = void 0;
this.$status = void 0;
- this.config = void 0;
this.i18n = void 0;
- if (!(this.$root instanceof HTMLInputElement)) {
- return;
- }
if (this.$root.type !== 'file') {
- throw new ElementError('File upload: Form field must be an input of type `file`.');
+ throw new ElementError(formatErrorMessage(FileUpload, 'Form field must be an input of type `file`.'));
}
- this.config = mergeConfigs(FileUpload.defaults, config, normaliseDataset(FileUpload, this.$root.dataset));
this.i18n = new I18n(this.config.i18n, {
locale: closestAttributeValue(this.$root, 'lang')
});
@@ -72,9 +68,6 @@ class FileUpload extends GOVUKFrontendComponent {
return;
}
const fileCount = this.$root.files.length;
- if (!this.$status || !this.i18n) {
- return;
- }
if (fileCount === 0) {
this.$status.innerText = this.i18n.t('filesSelectedDefault');
} else if (fileCount === 1) {
Action run for 6b4d4fa |
patrickpatrickpatrick
approved these changes
Jan 10, 2025
1 task
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR makes
FileUpload
extendConfigurableComponent
rather thanGOVUKFrontendComponent
so it's consistent with the other components receiving configuration.It also adds tests for the errors thrown during initialisation and makes their error message consistent.
Fixes #5615