Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Stateful sidenav] Add yml setting to force spaces solution view #191743

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions src/plugins/navigation/public/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ describe('Navigation Plugin', () => {

describe('addSolutionNavigation()', () => {
it('should update the solution navigation definitions', async () => {
const { plugin, coreStart, unifiedSearch, cloud } = setup();
const { plugin, coreStart, unifiedSearch, spaces } = setup();

const { addSolutionNavigation } = plugin.start(coreStart, {
unifiedSearch,
cloud,
spaces,
});
await new Promise((resolve) => setTimeout(resolve));

Expand Down Expand Up @@ -179,13 +179,29 @@ describe('Navigation Plugin', () => {
});

describe('isSolutionNavEnabled$', () => {
// This test will need to be changed when we remove the feature flag
it('should be off by default', async () => {
const { plugin, coreStart, unifiedSearch, cloud } = setup();
it('should be off if spaces plugin not available', async () => {
const { plugin, coreStart, unifiedSearch } = setup();

const { isSolutionNavEnabled$ } = plugin.start(coreStart, {
unifiedSearch,
cloud,
});
await new Promise((resolve) => setTimeout(resolve));

const isEnabled = await firstValueFrom(isSolutionNavEnabled$);
expect(isEnabled).toBe(false);
});

it('should be off if spaces plugin `isSolutionViewEnabled` = false', async () => {
const { plugin, coreStart, unifiedSearch, spaces } = setup();
spaces.getActiveSpace$ = jest
.fn()
.mockReturnValue(of({ solution: 'es' } as Pick<Space, 'solution'>));

spaces.isSolutionViewEnabled = false;

const { isSolutionNavEnabled$ } = plugin.start(coreStart, {
unifiedSearch,
spaces,
});
await new Promise((resolve) => setTimeout(resolve));

Expand Down
4 changes: 1 addition & 3 deletions src/plugins/navigation/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ export class NavigationPublicPlugin
const extensions = this.topNavMenuExtensionsRegistry.getAll();
const chrome = core.chrome as InternalChromeStart;
const activeSpace$: Observable<Space | undefined> = spaces?.getActiveSpace$() ?? of(undefined);
const onCloud = cloud !== undefined; // The new side nav will initially only be available to cloud users
const isServerless = this.initializerContext.env.packageInfo.buildFlavor === 'serverless';

this.isSolutionNavEnabled = onCloud && !isServerless;
this.isSolutionNavEnabled = spaces?.isSolutionViewEnabled ?? false;

/*
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.spaces.maxSpaces (number?)',
'xpack.spaces.allowFeatureVisibility (false|boolean?)',
'xpack.spaces.allowSolutionVisibility (false|boolean?)',
'xpack.spaces.forceSolutionVisibility (boolean?)',
'xpack.securitySolution.enableExperimental (array?)',
'xpack.securitySolution.prebuiltRulesPackageVersion (string?)',
'xpack.securitySolution.offeringSettings (record?)',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const mockSpacesApi: SpacesApi = {
useSpaces: jest.fn(),
},
hasOnlyDefaultSpace: false,
isSolutionViewEnabled: true,
};

describe('<LegacyUrlConflictCallOut />', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const mockSpacesApi: SpacesApi = {
useSpaces: jest.fn(),
},
hasOnlyDefaultSpace: false,
isSolutionViewEnabled: true,
};

describe('useLegacyUrlRedirect', () => {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/spaces/public/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export interface ConfigType {
maxSpaces: number;
allowFeatureVisibility: boolean;
allowSolutionVisibility: boolean;
forceSolutionVisibility: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('ManagementService', () => {
maxSpaces: 1000,
allowFeatureVisibility: true,
allowSolutionVisibility: true,
forceSolutionVisibility: false,
};

describe('#setup', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const config: ConfigType = {
maxSpaces: 1000,
allowFeatureVisibility: true,
allowSolutionVisibility: true,
forceSolutionVisibility: false,
};

const eventTracker = new EventTracker({ reportEvent: jest.fn() });
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/spaces/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const createApiMock = (hasOnlyDefaultSpace: boolean): jest.Mocked<SpacesApi> =>
getActiveSpace: jest.fn(),
ui: createApiUiMock(),
hasOnlyDefaultSpace,
isSolutionViewEnabled: true,
});

type SpacesApiUiMock = Omit<jest.Mocked<SpacesApiUi>, 'components'> & {
Expand Down
26 changes: 18 additions & 8 deletions x-pack/plugins/spaces/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ export class SpacesPlugin implements Plugin<SpacesPluginSetup, SpacesPluginStart

public setup(core: CoreSetup<PluginsStart, SpacesPluginStart>, plugins: PluginsSetup) {
const hasOnlyDefaultSpace = this.config.maxSpaces === 1;
const onCloud = plugins.cloud !== undefined && plugins.cloud.isCloudEnabled;

// We only allow "solution" to be set on cloud environments, not on prem
// unless the forceSolutionVisibility flag is set
let allowSolutionVisibility = this.config.allowSolutionVisibility;
if (this.config.forceSolutionVisibility) {
allowSolutionVisibility = true;
} else if (!onCloud || this.isServerless) {
allowSolutionVisibility = false;
}

sebelga marked this conversation as resolved.
Show resolved Hide resolved
this.spacesManager = new SpacesManager(core.http);
this.spacesApi = {
ui: getUiApi({
Expand All @@ -69,15 +80,14 @@ export class SpacesPlugin implements Plugin<SpacesPluginSetup, SpacesPluginStart
getActiveSpace$: () => this.spacesManager.onActiveSpaceChange$,
getActiveSpace: () => this.spacesManager.getActiveSpace(),
hasOnlyDefaultSpace,
isSolutionViewEnabled: allowSolutionVisibility,
};

this.config = {
...this.config,
allowSolutionVisibility,
};

const onCloud = plugins.cloud !== undefined && plugins.cloud.isCloudEnabled;
if (!onCloud) {
this.config = {
...this.config,
allowSolutionVisibility: false,
};
}
registerSpacesEventTypes(core);
this.eventTracker = new EventTracker(core.analytics);

Expand Down Expand Up @@ -133,7 +143,7 @@ export class SpacesPlugin implements Plugin<SpacesPluginSetup, SpacesPluginStart

registerAnalyticsContext(core.analytics, this.spacesManager.onActiveSpaceChange$);

return { hasOnlyDefaultSpace };
return { hasOnlyDefaultSpace, isSolutionViewEnabled: allowSolutionVisibility };
sebelga marked this conversation as resolved.
Show resolved Hide resolved
}

public start(core: CoreStart) {
Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/spaces/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,9 @@ export interface SpacesApi {
* UI components and services to add spaces capabilities to an application.
*/
ui: SpacesApiUi;

/**
* Indicates whether the solution view is enabled.
*/
isSolutionViewEnabled: boolean;
}
3 changes: 3 additions & 0 deletions x-pack/plugins/spaces/server/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('config schema', () => {
"allowFeatureVisibility": true,
"allowSolutionVisibility": true,
"enabled": true,
"forceSolutionVisibility": false,
"maxSpaces": 1000,
}
`);
Expand All @@ -32,6 +33,7 @@ describe('config schema', () => {
"allowFeatureVisibility": true,
"allowSolutionVisibility": true,
"enabled": true,
"forceSolutionVisibility": false,
"maxSpaces": 1000,
}
`);
Expand All @@ -41,6 +43,7 @@ describe('config schema', () => {
"allowFeatureVisibility": true,
"allowSolutionVisibility": true,
"enabled": true,
"forceSolutionVisibility": false,
"maxSpaces": 1000,
}
`);
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/spaces/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const ConfigSchema = schema.object({
defaultValue: true,
}),
}),
forceSolutionVisibility: schema.boolean({ defaultValue: false }),
sebelga marked this conversation as resolved.
Show resolved Hide resolved
});

export function createConfig$(context: PluginInitializerContext) {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/spaces/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const config: PluginConfigDescriptor = {
maxSpaces: true,
allowFeatureVisibility: true,
allowSolutionVisibility: true,
forceSolutionVisibility: true,
},
};

Expand Down
21 changes: 15 additions & 6 deletions x-pack/plugins/spaces/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,22 @@ export class SpacesPlugin
initializerContext.config.create<ConfigType>(),
this.onCloud$,
]).pipe(
map(
([config, onCloud]): ConfigType => ({
map(([config, onCloud]): ConfigType => {
let allowSolutionVisibility = config.allowSolutionVisibility;

// We only allow "solution" to be set on cloud environments, not on prem
// unless the forceSolutionVisibility flag is set
if (config.forceSolutionVisibility) {
allowSolutionVisibility = true;
} else if (!onCloud) {
allowSolutionVisibility = false;
}

return {
...config,
// We only allow "solution" to be set on cloud environments, not on prem
allowSolutionVisibility: onCloud ? config.allowSolutionVisibility : false,
})
)
allowSolutionVisibility,
};
})
);
sebelga marked this conversation as resolved.
Show resolved Hide resolved
this.hasOnlyDefaultSpace$ = this.config$.pipe(map(({ maxSpaces }) => maxSpaces === 1));
this.log = initializerContext.logger.get();
Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/spaces/server/spaces_client/spaces_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const createMockConfig = (
maxSpaces: 1000,
allowFeatureVisibility: true,
allowSolutionVisibility: true,
forceSolutionVisibility: false,
}
) => {
return ConfigSchema.validate(mockConfig, { serverless: !mockConfig.allowFeatureVisibility });
Expand Down Expand Up @@ -313,6 +314,7 @@ describe('#create', () => {
maxSpaces,
allowFeatureVisibility: true,
allowSolutionVisibility: true,
forceSolutionVisibility: false,
});

const client = new SpacesClient(
Expand Down Expand Up @@ -350,6 +352,7 @@ describe('#create', () => {
maxSpaces,
allowFeatureVisibility: true,
allowSolutionVisibility: true,
forceSolutionVisibility: false,
});

const client = new SpacesClient(
Expand Down Expand Up @@ -386,6 +389,7 @@ describe('#create', () => {
maxSpaces,
allowFeatureVisibility: true,
allowSolutionVisibility: true,
forceSolutionVisibility: false,
});

const client = new SpacesClient(
Expand Down Expand Up @@ -433,6 +437,7 @@ describe('#create', () => {
maxSpaces,
allowFeatureVisibility: true,
allowSolutionVisibility: true,
forceSolutionVisibility: false,
});

const client = new SpacesClient(
Expand Down Expand Up @@ -476,6 +481,7 @@ describe('#create', () => {
maxSpaces,
allowFeatureVisibility: false,
allowSolutionVisibility: false,
forceSolutionVisibility: false,
});

const client = new SpacesClient(
Expand Down Expand Up @@ -513,6 +519,7 @@ describe('#create', () => {
maxSpaces,
allowFeatureVisibility: false,
allowSolutionVisibility: false,
forceSolutionVisibility: false,
});

const client = new SpacesClient(
Expand Down Expand Up @@ -553,6 +560,7 @@ describe('#create', () => {
maxSpaces,
allowFeatureVisibility: false,
allowSolutionVisibility: false,
forceSolutionVisibility: false,
});

const client = new SpacesClient(
Expand Down Expand Up @@ -723,6 +731,7 @@ describe('#update', () => {
maxSpaces: 1000,
allowFeatureVisibility: false,
allowSolutionVisibility: false,
forceSolutionVisibility: false,
});
const mockCallWithRequestRepository = savedObjectsRepositoryMock.create();
mockCallWithRequestRepository.get.mockResolvedValue(savedObject);
Expand All @@ -749,6 +758,7 @@ describe('#update', () => {
maxSpaces: 1000,
allowFeatureVisibility: false,
allowSolutionVisibility: false,
forceSolutionVisibility: false,
});
const mockCallWithRequestRepository = savedObjectsRepositoryMock.create();
mockCallWithRequestRepository.get.mockResolvedValue(savedObject);
Expand Down Expand Up @@ -781,6 +791,7 @@ describe('#update', () => {
maxSpaces: 1000,
allowFeatureVisibility: false,
allowSolutionVisibility: false,
forceSolutionVisibility: false,
});
const mockCallWithRequestRepository = savedObjectsRepositoryMock.create();
mockCallWithRequestRepository.get.mockResolvedValue(savedObject);
Expand Down