DEV: Modernise and colocate UserField component (#20267)

Dynamically setting the `layoutName` is not compatible with template colocation. Instead, we can give each field type a dedicated component and make `<UserField` a wrapper which renders the correct implementation.
This commit is contained in:
David Taylor 2023-02-13 19:06:23 +00:00 committed by GitHub
parent 87f9583dcf
commit 3bfd8c7192
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 62 additions and 40 deletions

View File

@ -0,0 +1,6 @@
<this.userFieldComponent
@field={{@field}}
@value={{@value}}
@class={{@class}}
@validation={{@validation}}
/>

View File

@ -1,34 +1,18 @@
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
import { fmt } from "discourse/lib/computed";
import Component from "@glimmer/component";
import UserFieldConfirm from "./user-fields/confirm";
import UserFieldDropdown from "./user-fields/dropdown";
import UserFieldMultiselect from "./user-fields/multiselect";
import UserFieldText from "./user-fields/text";
export default Component.extend({
classNameBindings: [":user-field", "field.field_type", "customFieldClass"],
layoutName: fmt("field.field_type", "components/user-fields/%@"),
const COMPONENTS = {
confirm: UserFieldConfirm,
dropdown: UserFieldDropdown,
multiselect: UserFieldMultiselect,
text: UserFieldText,
};
didInsertElement() {
this._super(...arguments);
let element = this.element.querySelector(
".user-field.dropdown .select-kit-header"
);
element = element || this.element.querySelector("input");
this.field.element = element;
},
@discourseComputed
noneLabel() {
return "user_fields.none";
},
@discourseComputed("field.name")
customFieldClass(fieldName) {
if (fieldName) {
fieldName = fieldName
.replace(/\s+/g, "-")
.replace(/[!\"#$%&'\(\)\*\+,\.\/:;<=>\?\@\[\\\]\^`\{\|\}~]/g, "")
.toLowerCase();
return fieldName && `user-field-${fieldName}`;
}
},
});
export default class UserFieldComponent extends Component {
get userFieldComponent() {
return COMPONENTS[this.args.field.field_type];
}
}

View File

@ -0,0 +1,32 @@
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({
classNameBindings: [":user-field", "field.field_type", "customFieldClass"],
didInsertElement() {
this._super(...arguments);
let element = this.element.querySelector(
".user-field.dropdown .select-kit-header"
);
element = element || this.element.querySelector("input");
this.field.element = element;
},
@discourseComputed
noneLabel() {
return "user_fields.none";
},
@discourseComputed("field.name")
customFieldClass(fieldName) {
if (fieldName) {
fieldName = fieldName
.replace(/\s+/g, "-")
.replace(/[!\"#$%&'\(\)\*\+,\.\/:;<=>\?\@\[\\\]\^`\{\|\}~]/g, "")
.toLowerCase();
return fieldName && `user-field-${fieldName}`;
}
},
});

View File

@ -1,3 +1,3 @@
import Component from "@ember/component";
import UserFieldBase from "./base";
export default Component.extend({});
export default class UserFieldConfirm extends UserFieldBase {}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component";
import UserFieldBase from "./base";
export default Component.extend({});
export default class UserFieldDropdown extends UserFieldBase {}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component";
import UserFieldBase from "./base";
export default Component.extend({});
export default class UserFieldMultiselect extends UserFieldBase {}

View File

@ -1,3 +1,3 @@
import Component from "@ember/component";
import UserFieldBase from "./base";
export default Component.extend({});
export default class UserFieldText extends UserFieldBase {}