FEATURE: Remove experimental label & setting toggle for what's new (#38008)

We now have upcoming changes which makes the related setting toggle
and experimental label for the what's new page redundant. This commit
removes both as a first step towards merging these two pages together.
This commit is contained in:
Martin Brennan
2026-02-26 13:16:42 +10:00
committed by GitHub
parent 2ff2389812
commit 63b8d4c711
7 changed files with 1 additions and 386 deletions
@@ -741,17 +741,6 @@
}
}
.admin-new-feature-item__header-experimental {
color: var(--tertiary);
background-color: var(--tertiary-very-low);
padding: 0.5em;
font-size: var(--font-down-3);
margin-left: 0.5rem;
font-weight: 400;
border-radius: var(--d-border-radius);
display: inline-block;
}
.admin-new-feature-item__body {
display: flex;
justify-content: space-between;
@@ -825,13 +814,3 @@
}
}
}
.admin-new-features__experiments-filter {
display: flex;
margin-bottom: 1em;
align-items: center;
.d-toggle-switch {
margin-right: 0.5em;
}
}
-17
View File
@@ -6490,23 +6490,6 @@ en:
no_new_features_found: "There are no items in the feed or your selected filter returned no results. You can see previous new feature announcements on <a href='%{url}' target='_blank'>the Discourse Meta community</a>."
no_new_features_error: "There was an error loading the feed. You can see previous new feature announcements on <a href='%{url}' target='_blank'>the Discourse Meta community</a>."
learn_more: "Learn more..."
experimental: "Experimental"
only_experiments: "Only show experimental features"
experiment_enabled: "You have enabled the experimental feature."
experiment_disabled: "You have disabled the experimental feature."
feature_enabled: "You have enabled the feature."
feature_disabled: "You have disabled the feature."
toggled_too_fast: "You have switched the toggle too fast. Please wait a few seconds before trying again."
experiment_tooltip:
title_disabled: "Try this experimental feature"
title_enabled: "Turn off experimental feature"
content_disabled: "Give our newest feature in development a spin! It's still in the experimental stage, so we might remove it at any time. You can opt out whenever you like.<br/><br/>Changing this will enable the feature for all users."
content_enabled: "Changing this will disable the feature for all users."
feature_tooltip:
title_disabled: "Try this feature"
title_enabled: "Turn off feature"
content_disabled: "Give this new feature a spin! You can opt out whenever you like.<br/><br/>Changing this will enable the feature for all users."
content_enabled: "Changing this will disable the feature for all users."
last_checked: "Last checked"
refresh_problems: "Refresh"
@@ -1,115 +1,14 @@
/* eslint-disable ember/no-tracked-properties-from-args */
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { dasherize } from "@ember/string";
import { htmlSafe } from "@ember/template";
import CookText from "discourse/components/cook-text";
import DToggleSwitch from "discourse/components/d-toggle-switch";
import DTooltip from "discourse/float-kit/components/d-tooltip";
import icon from "discourse/helpers/d-icon";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { and, not } from "discourse/truth-helpers";
import { i18n } from "discourse-i18n";
export default class DiscourseNewFeatureItem extends Component {
@service toasts;
@tracked settingEnabled = this.args.item.setting_enabled;
@tracked toggleSettingDisabled = false;
get isExperiment() {
return this.args.item.experiment;
}
get identifier() {
return this.args.item.title ? dasherize(this.args.item.title) : null;
}
@action
async toggleExperiment() {
if (this.toggleSettingDisabled) {
this.toasts.error({
duration: "short",
data: {
message: i18n("admin.dashboard.new_features.toggled_too_fast"),
},
});
return;
}
this.settingEnabled = !this.settingEnabled;
this.toggleSettingDisabled = true;
setTimeout(() => {
this.toggleSettingDisabled = false;
}, 5000);
try {
await ajax("/admin/toggle-feature", {
type: "POST",
data: {
setting_name: this.args.item.related_site_setting,
enabled: this.settingEnabled,
},
});
const enabledMsg = this.isExperiment
? "admin.dashboard.new_features.experiment_enabled"
: "admin.dashboard.new_features.feature_enabled";
const disabledMsg = this.isExperiment
? "admin.dashboard.new_features.experiment_disabled"
: "admin.dashboard.new_features.feature_disabled";
this.toasts.success({
duration: "short",
data: {
message: this.settingEnabled ? i18n(enabledMsg) : i18n(disabledMsg),
},
});
} catch (error) {
this.settingEnabled = !this.settingEnabled;
return popupAjaxError(error);
}
}
get tooltipTitle() {
const experimentalTitleEnabled = this.isExperiment
? "admin.dashboard.new_features.experiment_tooltip.title_enabled"
: "admin.dashboard.new_features.feature_tooltip.title_enabled";
const experimentalTitleDisabled = this.isExperiment
? "admin.dashboard.new_features.feature_tooltip.title_disabled"
: "admin.dashboard.new_features.feature_tooltip.title_disabled";
return htmlSafe(
i18n(
this.settingEnabled
? experimentalTitleEnabled
: experimentalTitleDisabled
)
);
}
get tooltipDescription() {
const experimentalDescriptionEnabled = this.isExperiment
? "admin.dashboard.new_features.experiment_tooltip.content_enabled"
: "admin.dashboard.new_features.feature_tooltip.content_enabled";
const experimentalDescriptionDisabled = this.isExperiment
? "admin.dashboard.new_features.experiment_tooltip.content_disabled"
: "admin.dashboard.new_features.feature_tooltip.content_disabled";
return htmlSafe(
i18n(
this.settingEnabled
? experimentalDescriptionEnabled
: experimentalDescriptionDisabled
)
);
}
<template>
<div
class="admin-new-feature-item"
@@ -124,12 +23,6 @@ export default class DiscourseNewFeatureItem extends Component {
{{/if}}
<h3>
{{@item.title}}
{{#if @item.experiment}}
<span class="admin-new-feature-item__header-experimental">
{{icon "flask"}}
{{i18n "admin.dashboard.new_features.experimental"}}
</span>
{{/if}}
</h3>
</div>
@@ -159,28 +52,6 @@ export default class DiscourseNewFeatureItem extends Component {
</a>
{{/if}}
</div>
{{#if @item.related_site_setting}}
<div class="admin-new-feature-item__feature-toggle">
<DTooltip>
<:trigger>
<DToggleSwitch
@state={{this.settingEnabled}}
{{on "click" this.toggleExperiment}}
/>
</:trigger>
<:content>
<div class="admin-new-feature-item__tooltip">
<div class="admin-new-feature-item__tooltip-header">
{{this.tooltipTitle}}
</div>
<div class="admin-new-feature-item__tooltip-content">
{{this.tooltipDescription}}
</div>
</div>
</:content>
</DTooltip>
</div>
{{/if}}
</div>
</div>
</div>
@@ -1,14 +1,11 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import { service } from "@ember/service";
import AdminConfigAreaCard from "discourse/admin/components/admin-config-area-card";
import AdminConfigAreaEmptyList from "discourse/admin/components/admin-config-area-empty-list";
import DashboardNewFeatureItem from "discourse/admin/components/dashboard-new-feature-item";
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
import DToggleSwitch from "discourse/components/d-toggle-switch";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { bind } from "discourse/lib/decorators";
@@ -20,7 +17,6 @@ export default class DashboardNewFeatures extends Component {
@tracked newFeatures = null;
@tracked isLoading = true;
@tracked feedError = false;
@tracked onlyExperiments = false;
constructor() {
super(...arguments);
@@ -62,7 +58,7 @@ export default class DashboardNewFeatures extends Component {
get groupedNewFeatures() {
return Object.keys(this.newFeatures)
.map((date) => {
const visibleFeatures = this.newFeatures[date].filter(this.showFeature);
const visibleFeatures = this.newFeatures[date];
if (visibleFeatures.length === 0) {
return null;
@@ -94,35 +90,12 @@ export default class DashboardNewFeatures extends Component {
return "";
}
@bind
showFeature(feature) {
if (!this.onlyExperiments) {
return true;
}
return feature.experiment === true;
}
@action
toggleOnlyExperiments() {
this.onlyExperiments = !this.onlyExperiments;
}
<template>
<div
class="admin-config-area__primary-content"
{{didInsert this.loadNewFeatures}}
>
<ConditionalLoadingSpinner @condition={{this.isLoading}}>
<div class="admin-new-features__experiments-filter">
<DToggleSwitch
@state={{this.onlyExperiments}}
{{on "click" this.toggleOnlyExperiments}}
/>
<span>
{{i18n "admin.dashboard.new_features.only_experiments"}}
</span>
</div>
{{#each this.groupedNewFeatures as |groupedFeatures|}}
<AdminConfigAreaCard
class="admin-new-features__group"
-14
View File
@@ -153,20 +153,6 @@ module DiscourseUpdates
end
return nil if entries.nil?
entries.map! do |item|
next item if !item["related_site_setting"]
if !SiteSetting.respond_to?(item["related_site_setting"]) ||
SiteSetting.type_supervisor.get_type(item["related_site_setting"].to_sym) != :bool
item["related_site_setting"] = nil
item["setting_enabled"] = false
else
item["setting_enabled"] = SiteSetting.send(item["related_site_setting"].to_sym) if item
end
item
end
entries.select! do |item|
begin
valid_version =
-35
View File
@@ -277,41 +277,6 @@ RSpec.describe DiscourseUpdates do
expect(result[1]["title"]).to eq("Bells")
end
it "correctly shows features with correct boolean site settings" do
features_with_versions = [
{
"emoji" => "🤾",
"title" => "Bells",
"created_at" => 2.days.ago,
"related_site_setting" => "enable_mobile_theme",
},
{
"emoji" => "🙈",
"title" => "Whistles",
"created_at" => 3.days.ago,
"related_site_setting" => "default_theme_id",
},
{
"emoji" => "🙈",
"title" => "Confetti",
"created_at" => 4.days.ago,
"related_site_setting" => "wrong value",
},
]
Discourse.redis.set("new_features", MultiJson.dump(features_with_versions))
DiscourseUpdates.last_installed_version = "2.7.0.beta2"
result = DiscourseUpdates.new_features
expect(result.length).to eq(3)
expect(result[0]["setting_enabled"]).to eq(true)
expect(result[0]["related_site_setting"]).to eq("enable_mobile_theme")
expect(result[1]["setting_enabled"]).to eq(false)
expect(result[1]["related_site_setting"]).to be_nil
expect(result[2]["setting_enabled"]).to eq(false)
expect(result[2]["related_site_setting"]).to be_nil
end
it "correctly shows features when related plugins are installed" do
Discourse.stubs(:plugins_by_name).returns({ "discourse-ai" => true })
-142
View File
@@ -128,146 +128,4 @@ describe "Admin What's New Page", type: :system do
expect(whats_new_page).to have_emoji
expect(whats_new_page).to have_no_screenshot
end
describe "items with a related_site_setting" do
before do
set_new_features_payload(
[
{
"id" => 7,
"user_id" => 1,
"emoji" => "😍",
"title" => "New feature",
"description" => "New feature description",
"link" => "https://meta.discourse.org",
"tier" => [],
"discourse_version" => "",
"created_at" => "2023-11-10T02:52:41.462Z",
"updated_at" => "2023-11-10T04:28:47.020Z",
"related_site_setting" => "enable_form_templates",
"experiment" => false,
},
],
)
end
it "toggles the attached site setting and shows the correct state" do
whats_new_page.visit
whats_new_page.within_new_feature_item("New feature") do
expect(whats_new_page.enable_item_toggle.unchecked?).to be_truthy
whats_new_page.enable_item_toggle.toggle
end
expect(page).to have_content(I18n.t("admin_js.admin.dashboard.new_features.feature_enabled"))
whats_new_page.visit
expect(SiteSetting.enable_form_templates).to be true
expect(whats_new_page.enable_item_toggle.checked?).to be_truthy
end
end
describe "experimental items" do
it "displays experimental feature toggle and has the correct state" do
set_new_features_payload(
[
{
"id" => 7,
"user_id" => 1,
"emoji" => "😍",
"title" => "New feature",
"description" => "New feature description",
"link" => "https://meta.discourse.org",
"tier" => [],
"discourse_version" => "",
"created_at" => "2023-11-10T02:52:41.462Z",
"updated_at" => "2023-11-10T04:28:47.020Z",
"related_site_setting" => "enable_form_templates",
"experiment" => false,
},
],
)
whats_new_page.visit
expect(whats_new_page).to have_toggle_feature_button()
end
it "displays experimental text next to feature title when feature is experimental" do
set_new_features_payload(
[
{
"id" => 7,
"user_id" => 1,
"emoji" => "😍",
"title" => "New feature",
"description" => "New feature description",
"link" => "https://meta.discourse.org",
"tier" => [],
"discourse_version" => "",
"created_at" => "2023-11-10T02:52:41.462Z",
"updated_at" => "2023-11-10T04:28:47.020Z",
"related_site_setting" => "enable_form_templates",
"experiment" => true,
},
],
)
whats_new_page.visit
expect(whats_new_page).to have_experimental_text
end
it "does not display experimental text next to feature title when feature is not experimental" do
set_new_features_payload(
[
{
"id" => 7,
"user_id" => 1,
"emoji" => "😍",
"title" => "New feature",
"description" => "New feature description",
"link" => "https://meta.discourse.org",
"tier" => [],
"discourse_version" => "",
"created_at" => "2023-11-10T02:52:41.462Z",
"updated_at" => "2023-11-10T04:28:47.020Z",
},
],
)
whats_new_page.visit
expect(whats_new_page).to have_no_experimental_text
end
it "allows filtering to only show experimental items" do
set_new_features_payload(
[
{
"id" => 7,
"user_id" => 1,
"emoji" => "😍",
"title" => "New feature",
"description" => "New feature description",
"link" => "https://meta.discourse.org",
"tier" => [],
"discourse_version" => "",
"created_at" => "2023-11-10T02:52:41.462Z",
"updated_at" => "2023-11-10T04:28:47.020Z",
"related_site_setting" => "enable_form_templates",
"experiment" => true,
},
{
"id" => 8,
"user_id" => 1,
"emoji" => "🥹",
"title" => "Non experimental feature",
"description" => "Cool description",
"link" => "https://meta.discourse.org",
"tier" => [],
"discourse_version" => "",
"created_at" => "2023-11-10T02:52:41.462Z",
"updated_at" => "2023-11-10T04:28:47.020Z",
"related_site_setting" => nil,
"experiment" => false,
},
],
)
whats_new_page.visit
whats_new_page.toggle_experiments_only
expect(whats_new_page).to have_experimental_text
end
end
end