DEV: Add case-converter common lib and use with AdminPlugin (#27725)

The AdminPlugin JS model uses a similar pattern to chat models,
where it is a plain JS class manually converting provided
snake_case attributes from the serializer to JS camelCase.

However this doesn't work when it comes to using `add_to_serializer`
in plugins since core does not know about these new attributes.

Instead, we can use a JS function to convert snake_case to camelCase
and use that when initializing AdminPlugin. This commit also moves
similar functions to a new case-converter.js file in
discourse-common/lib.
This commit is contained in:
Martin Brennan 2024-07-05 13:22:48 +10:00 committed by GitHub
parent 33c68b28b6
commit 964945a11f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 57 additions and 26 deletions

View File

@ -1,5 +1,6 @@
import { cached, tracked } from "@glimmer/tracking";
import { capitalize } from "@ember/string";
import { snakeCaseToCamelCase } from "discourse-common/lib/case-converter";
import I18n from "discourse-i18n";
export default class AdminPlugin {
@ -10,24 +11,9 @@ export default class AdminPlugin {
@tracked enabled;
constructor(args = {}) {
this.about = args.about;
this.adminRoute = args.admin_route;
this.commitHash = args.commit_hash;
this.commitUrl = args.commit_url;
this.enabled = args.enabled;
this.enabledSetting = args.enabled_setting;
this.hasSettings = args.has_settings;
this.hasOnlyEnabledSetting = args.has_only_enabled_setting;
this.id = args.id;
this.isOfficial = args.is_official;
this.isDiscourseOwned = args.is_discourse_owned;
this.label = args.label;
this.name = args.name;
this.url = args.url;
this.version = args.version;
this.metaUrl = args.meta_url;
this.authors = args.authors;
this.extras = args.extras;
Object.keys(args).forEach((key) => {
this[snakeCaseToCamelCase(key)] = args[key];
});
}
get useNewShowRoute() {

View File

@ -0,0 +1,17 @@
// Converts snake_case to camelCase, useful for converting
// rails serializer attributes to JS object keys.
export function snakeCaseToCamelCase(str) {
return str.replace(/_([a-z])/g, (match, letter) => letter.toUpperCase());
}
// Converts camelCase to dash-case, useful for converting
// JS object keys to HTML attributes.
export function camelCaseToDash(str) {
return str.replace(/([a-zA-Z])(?=[A-Z])/g, "$1-").toLowerCase();
}
// Converts camelCase to snake_case, useful for converting
// JS object keys to Rails serializer attributes.
export function camelCaseToSnakeCase(str) {
return str.replace(/([a-zA-Z])(?=[A-Z])/g, "$1_").toLowerCase();
}

View File

@ -1,8 +1,6 @@
let isWhiteSpace, escapeHtml;
import { camelCaseToDash } from "discourse-common/lib/case-converter";
function camelCaseToDash(str) {
return str.replace(/([a-zA-Z])(?=[A-Z])/g, "$1-").toLowerCase();
}
let isWhiteSpace, escapeHtml;
export function applyDataAttributes(token, attributes, defaultName) {
const { _default, ...attrs } = attributes;

View File

@ -5,6 +5,7 @@ import { CANCELLED_STATUS } from "discourse/lib/autocomplete";
import { userPath } from "discourse/lib/url";
import { emailValid } from "discourse/lib/utilities";
import { isTesting } from "discourse-common/config/environment";
import { camelCaseToSnakeCase } from "discourse-common/lib/case-converter";
import discourseDebounce from "discourse-common/lib/debounce";
import discourseLater from "discourse-common/lib/later";
@ -22,10 +23,6 @@ export function resetUserSearchCache() {
oldSearch = null;
}
export function camelCaseToSnakeCase(text) {
return text.replace(/([a-zA-Z])(?=[A-Z])/g, "$1_").toLowerCase();
}
function performSearch(
term,
topicId,

View File

@ -0,0 +1,32 @@
import { setupTest } from "ember-qunit";
import { module, test } from "qunit";
import {
camelCaseToDash,
camelCaseToSnakeCase,
snakeCaseToCamelCase,
} from "discourse-common/lib/case-converter";
module("Unit | discourse-common | case-converter", function (hooks) {
setupTest(hooks);
test("camelCaseToSnakeCase", function (assert) {
assert.equal(camelCaseToSnakeCase("camelCase"), "camel_case");
assert.equal(camelCaseToSnakeCase("camelCase99"), "camel_case99");
assert.equal(camelCaseToSnakeCase("camelCaseId"), "camel_case_id");
assert.equal(camelCaseToSnakeCase("camelCaseUrl"), "camel_case_url");
});
test("camelCaseToDash", function (assert) {
assert.equal(camelCaseToDash("camelCase"), "camel-case");
assert.equal(camelCaseToDash("camelCaseToDash99"), "camel-case-to-dash99");
assert.equal(camelCaseToDash("camelCaseId"), "camel-case-id");
assert.equal(camelCaseToDash("camelCaseUrl"), "camel-case-url");
});
test("snakeCaseToCamelCase", function (assert) {
assert.equal(snakeCaseToCamelCase("snake_case"), "snakeCase");
assert.equal(snakeCaseToCamelCase("snake_case99"), "snakeCase99");
assert.equal(snakeCaseToCamelCase("some_id"), "someId");
assert.equal(snakeCaseToCamelCase("some_url"), "someUrl");
});
});

View File

@ -91,6 +91,7 @@ module PrettyText
discourse-common/addon/lib/deprecated
discourse-common/addon/lib/escape
discourse-common/addon/lib/avatar-utils
discourse-common/addon/lib/case-converter
discourse/app/lib/to-markdown
discourse/app/static/markdown-it/features
].each do |f|