[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>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e1a582395f
Коммит
086e6d9df6
@@ -116,6 +116,9 @@ type PluginSettingsSection struct {
|
|||||||
|
|
||||||
// If true, the section will load the custom component registered using `registry.registerAdminConsoleCustomSection`
|
// If true, the section will load the custom component registered using `registry.registerAdminConsoleCustomSection`
|
||||||
Custom bool `json:"custom" yaml:"custom"`
|
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 {
|
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},
|
}, false},
|
||||||
|
|||||||
@@ -167,6 +167,89 @@ describe('custom plugin sections and settings', () => {
|
|||||||
expect(screen.queryByText('Custom Section 2')).not.toBeInTheDocument();
|
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', () => {
|
it('custom sections with plugin enabled should render as expected', () => {
|
||||||
const CustomSection1 = () => {
|
const CustomSection1 = () => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -95,8 +95,10 @@ function makeGetPluginSchema() {
|
|||||||
if (customSections[key]) {
|
if (customSections[key]) {
|
||||||
component = customSections[key]?.component;
|
component = customSections[key]?.component;
|
||||||
settings = parsePluginSettings(section.settings);
|
settings = parsePluginSettings(section.settings);
|
||||||
|
} else if (section.fallback) {
|
||||||
|
settings = parsePluginSettings(section.settings);
|
||||||
} else {
|
} 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 = [{
|
settings = [{
|
||||||
key: key + 'disabledWarning',
|
key: key + 'disabledWarning',
|
||||||
type: Constants.SettingsTypes.TYPE_BANNER,
|
type: Constants.SettingsTypes.TYPE_BANNER,
|
||||||
@@ -134,8 +136,11 @@ function makeGetPluginSchema() {
|
|||||||
if (plugin.id !== appsPluginID || appsFeatureFlagIsEnabled) {
|
if (plugin.id !== appsPluginID || appsFeatureFlagIsEnabled) {
|
||||||
const pluginEnableSetting = getEnablePluginSetting(plugin) as AdminDefinitionSetting;
|
const pluginEnableSetting = getEnablePluginSetting(plugin) as AdminDefinitionSetting;
|
||||||
|
|
||||||
if (plugin.settings_schema && plugin.settings_schema.sections?.every((s) => s.custom && !customSections[s.key.toLowerCase()])) {
|
const hasAllCustomSectionsDisabled = 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 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 = {
|
const warningBanner = {
|
||||||
key: 'admin.plugin.customSections.pluginDisabledWarning',
|
key: 'admin.plugin.customSections.pluginDisabledWarning',
|
||||||
type: Constants.SettingsTypes.TYPE_BANNER,
|
type: Constants.SettingsTypes.TYPE_BANNER,
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export type PluginSettingSection = {
|
|||||||
header?: string;
|
header?: string;
|
||||||
footer?: string;
|
footer?: string;
|
||||||
custom?: boolean;
|
custom?: boolean;
|
||||||
|
fallback?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PluginSetting = {
|
export type PluginSetting = {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user