DEV: Detect hbr topic list customizations (#29793)
This commit is contained in:
parent
db15e11cb9
commit
2589545623
|
@ -16,6 +16,10 @@ const DEPRECATION_WORKFLOW = [
|
|||
handler: "silence",
|
||||
matchId: "discourse.post-menu-widget-overrides",
|
||||
},
|
||||
{
|
||||
handler: "silence",
|
||||
matchId: "discourse.hbr-topic-list-overrides",
|
||||
},
|
||||
];
|
||||
|
||||
export default DEPRECATION_WORKFLOW;
|
||||
|
|
|
@ -1,9 +1,75 @@
|
|||
import require from "require";
|
||||
import { consolePrefix } from "discourse/lib/source-identifier";
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
import { getResolverOption } from "discourse-common/resolver";
|
||||
|
||||
export const __DISCOURSE_RAW_TEMPLATES = {};
|
||||
let _needsHbrTopicList = false;
|
||||
|
||||
export function needsHbrTopicList(value) {
|
||||
if (value === undefined) {
|
||||
return _needsHbrTopicList;
|
||||
} else {
|
||||
_needsHbrTopicList = value;
|
||||
}
|
||||
}
|
||||
|
||||
export function resetNeedsHbrTopicList() {
|
||||
_needsHbrTopicList = false;
|
||||
}
|
||||
|
||||
const TOPIC_LIST_TEMPLATE_NAMES = [
|
||||
"list/action-list",
|
||||
"list/activity-column",
|
||||
"list/category-column",
|
||||
"list/new-list-header-controls",
|
||||
"list/participant-groups",
|
||||
"list/post-count-or-badges",
|
||||
"list/posters-column",
|
||||
"list/posts-count-column",
|
||||
"list/topic-excerpt",
|
||||
"list/topic-list-item",
|
||||
"list/unread-indicator",
|
||||
"list/visited-line",
|
||||
"mobile/list/topic-list-item",
|
||||
"topic-bulk-select-dropdown",
|
||||
"topic-list-header-column",
|
||||
"topic-list-header",
|
||||
"topic-post-badges",
|
||||
"topic-status",
|
||||
];
|
||||
|
||||
export function addRawTemplate(name, template, opts = {}) {
|
||||
const cleanName = name.replace(/^javascripts\//, "");
|
||||
if (
|
||||
(TOPIC_LIST_TEMPLATE_NAMES.includes(cleanName) ||
|
||||
name.includes("/connectors/")) &&
|
||||
!opts.core &&
|
||||
!opts.hasModernReplacement
|
||||
) {
|
||||
const message = `[${name}] hbr topic-list template overrides and connectors are deprecated. Use the value transformer \`topic-list-columns\` and other new topic-list plugin APIs instead.`;
|
||||
deprecated(message, {
|
||||
since: "v3.4.0.beta3-dev",
|
||||
id: "discourse.hbr-topic-list-overrides",
|
||||
});
|
||||
|
||||
let prefix;
|
||||
if (opts.themeId) {
|
||||
prefix = consolePrefix(null, {
|
||||
type: "theme",
|
||||
id: opts.themeId,
|
||||
name: opts.themeName,
|
||||
});
|
||||
} else if (opts.pluginName) {
|
||||
prefix = consolePrefix(null, {
|
||||
type: "plugin",
|
||||
name: opts.pluginName,
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(prefix, message);
|
||||
}
|
||||
|
||||
// Core templates should never overwrite themes / plugins
|
||||
if (opts.core && __DISCOURSE_RAW_TEMPLATES[name]) {
|
||||
return;
|
||||
|
|
|
@ -147,18 +147,24 @@ TemplateCompiler.prototype.processString = function (string, relativePath) {
|
|||
}
|
||||
|
||||
filename = filename.replace(/\.hbr$/, "");
|
||||
|
||||
return (
|
||||
'import { template as compiler } from "discourse-common/lib/raw-handlebars";\n' +
|
||||
'import { addRawTemplate } from "discourse-common/lib/raw-templates";\n\n' +
|
||||
"let template = compiler(" +
|
||||
this.precompile(string, false) +
|
||||
");\n\n" +
|
||||
'addRawTemplate("' +
|
||||
filename +
|
||||
'", template, { core: true });\n' +
|
||||
"export default template;"
|
||||
const hasModernReplacement = string.includes(
|
||||
"{{!-- has-modern-replacement --}}"
|
||||
);
|
||||
|
||||
return `
|
||||
import { template as compiler } from "discourse-common/lib/raw-handlebars";
|
||||
import { addRawTemplate } from "discourse-common/lib/raw-templates";
|
||||
|
||||
let template = compiler(${this.precompile(string, false)});
|
||||
|
||||
addRawTemplate("${filename}", template, {
|
||||
core: ${!pluginName},
|
||||
pluginName: ${JSON.stringify(pluginName)},
|
||||
hasModernReplacement: ${hasModernReplacement},
|
||||
});
|
||||
|
||||
export default template;
|
||||
`;
|
||||
};
|
||||
|
||||
TemplateCompiler.prototype.precompile = function (value, asObject) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<ConditionalLoadingSpinner @condition={{this.loading}}>
|
||||
{{#if this.topics}}
|
||||
{{#if this.currentUser.use_glimmer_topic_list}}
|
||||
{{#if this.currentUser.canUseGlimmerTopicList}}
|
||||
<TopicList::List
|
||||
@showPosters={{this.showPosters}}
|
||||
@hideCategory={{this.hideCategory}}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
{{#if this.topics}}
|
||||
{{#each this.topics as |t|}}
|
||||
{{#if this.currentUser.use_glimmer_topic_list}}
|
||||
{{#if this.currentUser.canUseGlimmerTopicList}}
|
||||
<TopicList::LatestTopicListItem @topic={{t}} />
|
||||
{{else}}
|
||||
<LatestTopicListItem @topic={{t}} />
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
{{/if}}
|
||||
|
||||
{{#if @model.sharedDrafts}}
|
||||
{{#if this.currentUser.use_glimmer_topic_list}}
|
||||
{{#if this.currentUser.canUseGlimmerTopicList}}
|
||||
<TopicList::List
|
||||
@listTitle="shared_drafts.title"
|
||||
@top={{this.top}}
|
||||
|
@ -88,7 +88,7 @@
|
|||
</span>
|
||||
|
||||
{{#if this.hasTopics}}
|
||||
{{#if this.currentUser.use_glimmer_topic_list}}
|
||||
{{#if this.currentUser.canUseGlimmerTopicList}}
|
||||
<TopicList::List
|
||||
@highlightLastVisited={{true}}
|
||||
@top={{this.top}}
|
||||
|
|
|
@ -21,7 +21,7 @@ export default class NewListHeaderControlsWrapper extends Component {
|
|||
}
|
||||
|
||||
<template>
|
||||
{{#if this.currentUser.use_glimmer_topic_list}}
|
||||
{{#if this.currentUser.canUseGlimmerTopicList}}
|
||||
<div class="topic-replies-toggle-wrapper">
|
||||
<NewListHeaderControls
|
||||
@current={{@current}}
|
||||
|
|
|
@ -158,7 +158,7 @@
|
|||
{{#if this.showTopics}}
|
||||
<td class="latest">
|
||||
{{#each this.category.featuredTopics as |t|}}
|
||||
{{#if this.currentUser.use_glimmer_topic_list}}
|
||||
{{#if this.currentUser.canUseGlimmerTopicList}}
|
||||
<TopicList::FeaturedTopic @topic={{t}} />
|
||||
{{else}}
|
||||
<FeaturedTopic @topic={{t}} />
|
||||
|
|
|
@ -13,7 +13,9 @@ import { observes, on } from "@ember-decorators/object";
|
|||
import $ from "jquery";
|
||||
import { topicTitleDecorators } from "discourse/components/topic-title";
|
||||
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||
import { consolePrefix } from "discourse/lib/source-identifier";
|
||||
import DiscourseURL, { groupPath } from "discourse/lib/url";
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
import { RUNTIME_OPTIONS } from "discourse-common/lib/raw-handlebars-helpers";
|
||||
import { findRawTemplate } from "discourse-common/lib/raw-templates";
|
||||
import discourseComputed, { bind } from "discourse-common/utils/decorators";
|
||||
|
@ -50,6 +52,32 @@ export function navigateToTopic(topic, href) {
|
|||
@classNameBindings(":topic-list-item", "unboundClassNames", "topic.visited")
|
||||
@attributeBindings("dataTopicId:data-topic-id", "role", "ariaLevel:aria-level")
|
||||
export default class TopicListItem extends Component {
|
||||
static reopen() {
|
||||
const message =
|
||||
"Modifying topic-list-item with `reopen` is deprecated. Use the value transformer `topic-list-columns` and other new topic-list plugin APIs instead.";
|
||||
deprecated(message, {
|
||||
since: "v3.4.0.beta3-dev",
|
||||
id: "discourse.hbr-topic-list-overrides",
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(consolePrefix(), message);
|
||||
|
||||
return super.reopen(...arguments);
|
||||
}
|
||||
|
||||
static reopenClass() {
|
||||
const message =
|
||||
"Modifying topic-list-item with `reopenClass` is deprecated. Use the value transformer `topic-list-columns` and other new topic-list plugin APIs instead.";
|
||||
deprecated(message, {
|
||||
since: "v3.4.0.beta3-dev",
|
||||
id: "discourse.hbr-topic-list-overrides",
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(consolePrefix(), message);
|
||||
|
||||
return super.reopenClass(...arguments);
|
||||
}
|
||||
|
||||
@service router;
|
||||
@service historyStore;
|
||||
|
||||
|
|
|
@ -8,13 +8,50 @@ import {
|
|||
tagName,
|
||||
} from "@ember-decorators/component";
|
||||
import { observes, on } from "@ember-decorators/object";
|
||||
import { consolePrefix } from "discourse/lib/source-identifier";
|
||||
import LoadMore from "discourse/mixins/load-more";
|
||||
import deprecated, {
|
||||
registerDeprecationHandler,
|
||||
} from "discourse-common/lib/deprecated";
|
||||
import { needsHbrTopicList } from "discourse-common/lib/raw-templates";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
registerDeprecationHandler((message, opts) => {
|
||||
if (opts?.id === "discourse.hbr-topic-list-overrides") {
|
||||
needsHbrTopicList(true);
|
||||
}
|
||||
});
|
||||
|
||||
@tagName("table")
|
||||
@classNames("topic-list")
|
||||
@classNameBindings("bulkSelectEnabled:sticky-header")
|
||||
export default class TopicList extends Component.extend(LoadMore) {
|
||||
static reopen() {
|
||||
const message =
|
||||
"Modifying topic-list with `reopen` is deprecated. Use the value transformer `topic-list-columns` and other new topic-list plugin APIs instead.";
|
||||
deprecated(message, {
|
||||
since: "v3.4.0.beta3-dev",
|
||||
id: "discourse.hbr-topic-list-overrides",
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(consolePrefix(), message);
|
||||
|
||||
return super.reopen(...arguments);
|
||||
}
|
||||
|
||||
static reopenClass() {
|
||||
const message =
|
||||
"Modifying topic-list with `reopenClass` is deprecated. Use the value transformer `topic-list-columns` and other new topic-list plugin APIs instead.";
|
||||
deprecated(message, {
|
||||
since: "v3.4.0.beta3-dev",
|
||||
id: "discourse.hbr-topic-list-overrides",
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(consolePrefix(), message);
|
||||
|
||||
return super.reopenClass(...arguments);
|
||||
}
|
||||
|
||||
@service modal;
|
||||
@service router;
|
||||
@service siteSettings;
|
||||
|
|
|
@ -293,6 +293,20 @@ class PluginApi {
|
|||
* ```
|
||||
**/
|
||||
modifyClass(resolverName, changes, opts) {
|
||||
if (
|
||||
resolverName === "component:topic-list" ||
|
||||
resolverName === "component:topic-list-item"
|
||||
) {
|
||||
const message =
|
||||
"Modifying topic-list and topic-list-item with `modifyClass` is deprecated. Use the value transformer `topic-list-columns` and other new topic-list plugin APIs instead.";
|
||||
deprecated(message, {
|
||||
since: "v3.4.0.beta3-dev",
|
||||
id: "discourse.hbr-topic-list-overrides",
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(consolePrefix(), message);
|
||||
}
|
||||
|
||||
const klass = this._resolveClass(resolverName, opts);
|
||||
if (!klass) {
|
||||
return;
|
||||
|
@ -330,6 +344,20 @@ class PluginApi {
|
|||
* ```
|
||||
**/
|
||||
modifyClassStatic(resolverName, changes, opts) {
|
||||
if (
|
||||
resolverName === "component:topic-list" ||
|
||||
resolverName === "component:topic-list-item"
|
||||
) {
|
||||
const message =
|
||||
"Modifying topic-list and topic-list-item with `modifyClassStatic` is deprecated. Use the value transformer `topic-list-columns` and other new topic-list plugin APIs instead.";
|
||||
deprecated(message, {
|
||||
since: "v3.4.0.beta3-dev",
|
||||
id: "discourse.hbr-topic-list-overrides",
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(consolePrefix(), message);
|
||||
}
|
||||
|
||||
const klass = this._resolveClass(resolverName, opts);
|
||||
if (!klass) {
|
||||
return;
|
||||
|
|
|
@ -38,6 +38,7 @@ import deprecated from "discourse-common/lib/deprecated";
|
|||
import { getOwnerWithFallback } from "discourse-common/lib/get-owner";
|
||||
import getURL, { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import discourseLater from "discourse-common/lib/later";
|
||||
import { needsHbrTopicList } from "discourse-common/lib/raw-templates";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
|
@ -1253,6 +1254,10 @@ export default class User extends RestModel.extend(Evented) {
|
|||
trackedTags(trackedTags, watchedTags, watchingFirstPostTags) {
|
||||
return [...trackedTags, ...watchedTags, ...watchingFirstPostTags];
|
||||
}
|
||||
|
||||
get canUseGlimmerTopicList() {
|
||||
return this.use_glimmer_topic_list && !needsHbrTopicList();
|
||||
}
|
||||
}
|
||||
|
||||
User.reopenClass(Singleton, {
|
||||
|
|
|
@ -98,6 +98,7 @@ import deprecated from "discourse-common/lib/deprecated";
|
|||
import { getOwnerWithFallback } from "discourse-common/lib/get-owner";
|
||||
import { restoreBaseUri } from "discourse-common/lib/get-url";
|
||||
import { cloneJSON, deepMerge } from "discourse-common/lib/object";
|
||||
import { resetNeedsHbrTopicList } from "discourse-common/lib/raw-templates";
|
||||
import { clearResolverOptions } from "discourse-common/resolver";
|
||||
import I18n from "discourse-i18n";
|
||||
import { _clearSnapshots } from "select-kit/components/composer-actions";
|
||||
|
@ -255,6 +256,7 @@ export function testCleanup(container, app) {
|
|||
resetWidgetCleanCallbacks();
|
||||
clearPluginHeaderActionComponents();
|
||||
clearRegisteredTabs();
|
||||
resetNeedsHbrTopicList();
|
||||
}
|
||||
|
||||
function cleanupCssGeneratorTags() {
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
import { module, test } from "qunit";
|
||||
import TopicList from "discourse/components/topic-list";
|
||||
import TopicListItem from "discourse/components/topic-list-item";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { rawConnectorsFor } from "discourse/lib/plugin-connectors";
|
||||
import {
|
||||
disableRaiseOnDeprecation,
|
||||
enableRaiseOnDeprecation,
|
||||
} from "discourse/tests/helpers/raise-on-deprecation";
|
||||
import { withSilencedDeprecations } from "discourse-common/lib/deprecated";
|
||||
import {
|
||||
addRawTemplate,
|
||||
needsHbrTopicList,
|
||||
removeRawTemplate,
|
||||
} from "discourse-common/lib/raw-templates";
|
||||
|
||||
module("Integration | Lib | hbr topic list detection", function (hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
disableRaiseOnDeprecation();
|
||||
});
|
||||
|
||||
hooks.afterEach(function () {
|
||||
enableRaiseOnDeprecation();
|
||||
});
|
||||
|
||||
test("template overrides", async function (assert) {
|
||||
try {
|
||||
addRawTemplate("flat-button", "non-topic list override");
|
||||
assert.false(needsHbrTopicList());
|
||||
|
||||
addRawTemplate("list/topic-list-item", "topic list override");
|
||||
assert.true(needsHbrTopicList());
|
||||
} finally {
|
||||
removeRawTemplate("flat-button");
|
||||
removeRawTemplate("list/topic-list-item");
|
||||
}
|
||||
});
|
||||
|
||||
test("hbr connectors", async function (assert) {
|
||||
assert.false(needsHbrTopicList());
|
||||
|
||||
// all raw connectors are topic list connectors
|
||||
addRawTemplate(
|
||||
"javascripts/raw-test/connectors/topic-list-after-title/foo",
|
||||
"topic list connector"
|
||||
);
|
||||
assert.strictEqual(rawConnectorsFor("topic-list-after-title").length, 1);
|
||||
assert.true(needsHbrTopicList());
|
||||
});
|
||||
|
||||
test("reopen", async function (assert) {
|
||||
withSilencedDeprecations("discourse.hbr-topic-list-overrides", () => {
|
||||
TopicList.reopen({});
|
||||
});
|
||||
assert.false(needsHbrTopicList());
|
||||
|
||||
TopicList.reopen({});
|
||||
assert.true(needsHbrTopicList());
|
||||
});
|
||||
|
||||
test("reopenClass", async function (assert) {
|
||||
withSilencedDeprecations("discourse.hbr-topic-list-overrides", () => {
|
||||
TopicListItem.reopenClass({});
|
||||
});
|
||||
assert.false(needsHbrTopicList());
|
||||
|
||||
TopicListItem.reopenClass({});
|
||||
assert.true(needsHbrTopicList());
|
||||
});
|
||||
|
||||
test("modifyClass", async function (assert) {
|
||||
withPluginApi("1.0.0", (api) => {
|
||||
api.modifyClass(
|
||||
"component:mobile-nav",
|
||||
(Superclass) => class extends Superclass {}
|
||||
);
|
||||
assert.false(needsHbrTopicList());
|
||||
|
||||
withSilencedDeprecations("discourse.hbr-topic-list-overrides", () => {
|
||||
api.modifyClass(
|
||||
"component:topic-list-item",
|
||||
(Superclass) => class extends Superclass {}
|
||||
);
|
||||
});
|
||||
assert.false(needsHbrTopicList());
|
||||
|
||||
api.modifyClass(
|
||||
"component:topic-list-item",
|
||||
(Superclass) => class extends Superclass {}
|
||||
);
|
||||
assert.true(needsHbrTopicList());
|
||||
});
|
||||
});
|
||||
|
||||
test("modifyClassStatic", async function (assert) {
|
||||
withPluginApi("1.0.0", (api) => {
|
||||
api.modifyClassStatic("component:mobile-nav", { pluginId: "test" });
|
||||
assert.false(needsHbrTopicList());
|
||||
|
||||
withSilencedDeprecations("discourse.hbr-topic-list-overrides", () => {
|
||||
api.modifyClassStatic("component:topic-list", { pluginId: "test" });
|
||||
});
|
||||
assert.false(needsHbrTopicList());
|
||||
|
||||
api.modifyClassStatic("component:topic-list", { pluginId: "test" });
|
||||
assert.true(needsHbrTopicList());
|
||||
});
|
||||
});
|
||||
});
|
|
@ -6,7 +6,7 @@ require "json_schemer"
|
|||
class Theme < ActiveRecord::Base
|
||||
include GlobalPath
|
||||
|
||||
BASE_COMPILER_VERSION = 84
|
||||
BASE_COMPILER_VERSION = 85
|
||||
|
||||
class SettingsMigrationError < StandardError
|
||||
end
|
||||
|
|
|
@ -217,6 +217,7 @@ class ThemeJavascriptCompiler
|
|||
compiled =
|
||||
DiscourseJsProcessor::Transpiler.new.compile_raw_template(hbs_template, theme_id: @theme_id)
|
||||
source_for_comment = hbs_template.gsub("*/", '*\/').indent(4, " ")
|
||||
modern_replacement_marker = hbs_template.include?("{{!-- has-modern-replacement --}}")
|
||||
@output_tree << ["#{name}.js", <<~JS]
|
||||
(function() {
|
||||
/*
|
||||
|
@ -224,7 +225,7 @@ class ThemeJavascriptCompiler
|
|||
*/
|
||||
const addRawTemplate = requirejs('discourse-common/lib/raw-templates').addRawTemplate;
|
||||
const template = requirejs('discourse-common/lib/raw-handlebars').template(#{compiled});
|
||||
addRawTemplate(#{raw_template_name(name)}, template);
|
||||
addRawTemplate(#{raw_template_name(name)}, template, { themeId: #{@theme_id}, themeName: #{@theme_name.to_json}, hasModernReplacement: #{modern_replacement_marker} });
|
||||
})();
|
||||
JS
|
||||
rescue MiniRacer::RuntimeError, DiscourseJsProcessor::TranspileError => ex
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</StyleguideExample>
|
||||
|
||||
<StyleguideExample @title="<TopicListItem> - latest" class="half-size">
|
||||
{{#if this.currentUser.use_glimmer_topic_list}}
|
||||
{{#if this.currentUser.canUseGlimmerTopicList}}
|
||||
<TopicList::LatestTopicListItem @topic={{@dummy.topic}} />
|
||||
{{else}}
|
||||
<LatestTopicListItem @topic={{@dummy.topic}} />
|
||||
|
|
Loading…
Reference in New Issue