[MM-62066] Allow using plugin settings defined in manifest as fallback when using custom sections and plugin is disabled (#29500)

* Allow using plugin settings defined in manifest as fallback when using custom sections and plugin is disabled

* Update server/public/model/manifest.go

Co-authored-by: Christopher Poile <cpoile@gmail.com>

* Add custom setting case

---------

Co-authored-by: Christopher Poile <cpoile@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Claudio Costa
2025-01-13 11:19:59 +01:00
коммит произвёл GitHub
родитель e1a582395f
Коммит 086e6d9df6
5 изменённых файлов: 107 добавлений и 3 удалений

Просмотреть файл

@@ -116,6 +116,9 @@ type PluginSettingsSection struct {
// If true, the section will load the custom component registered using `registry.registerAdminConsoleCustomSection`
Custom bool `json:"custom" yaml:"custom"`
// If true and Custom = true, the settings defined under this section will still render as fallback (unless the individual setting is type 'custom') when the plugin is disabled.
Fallback bool `json:"fallback" yaml:"fallback"`
}
type PluginSettingsSchema struct {

Просмотреть файл

@@ -95,6 +95,18 @@ func TestIsValid(t *testing.T) {
},
},
},
{
Key: "section3",
Custom: true,
Fallback: true,
Settings: []*PluginSetting{
{
Key: "section3setting1",
DisplayName: "thedisplayname",
Type: "custom",
},
},
},
},
},
}, false},

Просмотреть файл

@@ -167,6 +167,89 @@ describe('custom plugin sections and settings', () => {
expect(screen.queryByText('Custom Section 2')).not.toBeInTheDocument();
});
it('all custom sections with plugin disabled and fallback enabled should render available settings', () => {
const state = {
...baseState,
entities: {
admin: {
plugins: {
testplugin: {
...plugin,
settings_schema: {
...plugin.settings_schema,
sections: [
{
key: 'section1',
title: 'Custom Section 1',
settings: [
{
key: 'customsection1numbersetting',
label: 'Custom Section Number Setting',
type: 'number' as const,
help_text: 'Custom Section Number Setting Help Text',
},
],
custom: true,
fallback: true,
},
{
key: 'section2',
title: 'Custom Section 2',
settings: [
{
key: 'customsection2numbersetting',
label: 'Custom Section Bool Setting',
type: 'bool' as const,
help_text: 'Custom Section Bool Setting Help Text',
},
{
key: 'customsection2customsetting',
label: 'Custom Section Custom Setting',
type: 'custom' as const,
help_text: 'Custom Section Custom Setting Help Text',
},
],
custom: true,
fallback: true,
},
],
},
},
},
},
},
};
const props = {
...baseProps,
config: {
...baseProps.config,
PluginStates: {
testplugin: {
Enabled: false,
},
},
},
};
renderWithContext(
<CustomPluginSettings
{...props}
patchConfig={jest.fn()}
/>
, {...state});
expect(screen.getByText('testplugin')).toBeInTheDocument();
expect(screen.getByTestId('PluginSettings.PluginStates.testplugin.Enable')).toBeInTheDocument();
expect(screen.queryByText('In order to view and configure plugin settings, enable the plugin and click Save.')).not.toBeInTheDocument();
expect(screen.queryByText('Custom Section 1')).toBeInTheDocument();
expect(screen.queryByText('Custom Section 2')).toBeInTheDocument();
expect(screen.getByText('Custom Section Number Setting Help Text')).toBeInTheDocument();
expect(screen.getByText('Custom Section Bool Setting Help Text')).toBeInTheDocument();
expect(screen.queryByText('Custom Section Custom Setting Help Text')).not.toBeInTheDocument();
expect(screen.getByText('In order to view this setting, enable the plugin and click Save.')).toBeInTheDocument();
});
it('custom sections with plugin enabled should render as expected', () => {
const CustomSection1 = () => {
return (

Просмотреть файл

@@ -95,8 +95,10 @@ function makeGetPluginSchema() {
if (customSections[key]) {
component = customSections[key]?.component;
settings = parsePluginSettings(section.settings);
} else if (section.fallback) {
settings = parsePluginSettings(section.settings);
} else {
// Show warning banner for custom sections when the plugin is disabled.
// Show warning banner for custom sections when the plugin is disabled and there's no fallback.
settings = [{
key: key + 'disabledWarning',
type: Constants.SettingsTypes.TYPE_BANNER,
@@ -134,8 +136,11 @@ function makeGetPluginSchema() {
if (plugin.id !== appsPluginID || appsFeatureFlagIsEnabled) {
const pluginEnableSetting = getEnablePluginSetting(plugin) as AdminDefinitionSetting;
if (plugin.settings_schema && plugin.settings_schema.sections?.every((s) => s.custom && !customSections[s.key.toLowerCase()])) {
// If the plugin is composed of purely custom sections (e.g. Calls) and it's disabled (custom components are not found), we show a single warning.
const hasAllCustomSectionsDisabled = plugin.settings_schema?.sections?.every((s) => s.custom && !customSections[s.key.toLowerCase()]);
const allCustomSectionsAllowFallback = plugin.settings_schema?.sections?.every((s) => s.custom && s.fallback);
if (plugin.settings_schema && hasAllCustomSectionsDisabled && !allCustomSectionsAllowFallback) {
// If the plugin is composed of purely custom sections (e.g. Calls), it's disabled (custom components are not found), and they don't allow a fallback, we show a single warning.
const warningBanner = {
key: 'admin.plugin.customSections.pluginDisabledWarning',
type: Constants.SettingsTypes.TYPE_BANNER,

Просмотреть файл

@@ -55,6 +55,7 @@ export type PluginSettingSection = {
header?: string;
footer?: string;
custom?: boolean;
fallback?: boolean;
};
export type PluginSetting = {