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

Fix opensearch theme version #978

Closed
Closed
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ Do not use setters, they cause more problems than they can solve.

When writing a new component, create a sibling SASS file of the same name and import directly into the **top** of the JS/TS component file. Doing so ensures the styles are never separated or lost on import and allows for better modularization (smaller individual plugin asset footprint).

All SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & OpenSearch Dashboards invisibles (SASS variables, mixins, functions) from the [`globals_[theme].scss` file](src/core/public/core_app/styles/_globals_v7light.scss).
All SASS (.scss) files will automatically build with the [EUI](https://elastic.github.io/eui/#/guidelines/sass) & OpenSearch Dashboards invisibles (SASS variables, mixins, functions) from the [`globals_[theme].scss` file](src/core/public/core_app/styles/_globals_v1light.scss).

While the styles for this component will only be loaded if the component exists on the page,
the styles **will** be global and so it is recommended to use a three letter prefix on your
Expand Down
10 changes: 5 additions & 5 deletions packages/osd-optimizer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,19 @@ Any import in a bundle which resolves into another bundles "context" directory,

## Themes

SASS imports in bundles are automatically converted to CSS for one or more themes. In development we build the `v7light` and `v7dark` themes by default to improve build performance. When producing distributable bundles the default shifts to `*` so that the distributable bundles will include all themes, preventing the bundles from needing to be rebuilt when users change the active theme in OpenSearch Dashboards's advanced settings.
SASS imports in bundles are automatically converted to CSS for one or more themes. In development we build the `v1light` and `v1dark` themes by default to improve build performance. When producing distributable bundles the default shifts to `*` so that the distributable bundles will include all themes, preventing the bundles from needing to be rebuilt when users change the active theme in OpenSearch Dashboards's advanced settings.

To customize the themes that are built for development you can specify the `OSD_OPTIMIZER_THEMES` environment variable to one or more theme tags, or use `*` to build styles for all themes. Unfortunately building more than one theme significantly impacts build performance, so try to be strategic about which themes you build.

Currently supported theme tags: `v7light`, `v7dark`, `v8light`, `v8dark`
Currently supported theme tags: `v1light`, `v1dark`

Examples:
```sh
# start OpenSearch Dashboards with only a single theme
OSD_OPTIMIZER_THEMES=v7light yarn start
OSD_OPTIMIZER_THEMES=v1light yarn start

# start OpenSearch Dashboards with dark themes for version 7 and 8
OSD_OPTIMIZER_THEMES=v7dark,v8dark yarn start
# start OpenSearch Dashboards with dark themes for version 1
OSD_OPTIMIZER_THEMES=v1dark yarn start

# start OpenSearch Dashboards with all the themes
OSD_OPTIMIZER_THEMES=* yarn start
Expand Down

This file was deleted.

This file was deleted.

39 changes: 18 additions & 21 deletions packages/osd-optimizer/src/common/theme_tags.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,70 +35,67 @@ import { parseThemeTags } from './theme_tags';
it('returns default tags when passed undefined', () => {
expect(parseThemeTags()).toMatchInlineSnapshot(`
Array [
"v7dark",
"v7light",
"v1dark",
"v1light",
]
`);
});

it('returns all tags when passed *', () => {
expect(parseThemeTags('*')).toMatchInlineSnapshot(`
Array [
"v7dark",
"v7light",
"v8dark",
"v8light",
"v1dark",
"v1light",
]
`);
});

it('returns specific tag when passed a single value', () => {
expect(parseThemeTags('v8light')).toMatchInlineSnapshot(`
expect(parseThemeTags('v1light')).toMatchInlineSnapshot(`
Array [
"v8light",
"v1light",
]
`);
});

it('returns specific tags when passed a comma separated list', () => {
expect(parseThemeTags('v8light, v7dark,v7light')).toMatchInlineSnapshot(`
expect(parseThemeTags('v1dark, v1light')).toMatchInlineSnapshot(`
Array [
"v7dark",
"v7light",
"v8light",
"v1dark",
"v1light",
]
`);
});

it('returns specific tags when passed an array', () => {
expect(parseThemeTags(['v8light', 'v7light'])).toMatchInlineSnapshot(`
expect(parseThemeTags(['v1dark', 'v1light'])).toMatchInlineSnapshot(`
Array [
"v7light",
"v8light",
"v1dark",
"v1light",
]
`);
});

it('throws when an invalid tag is in the array', () => {
expect(() => parseThemeTags(['v8light', 'v7light', 'bar'])).toThrowErrorMatchingInlineSnapshot(
`"Invalid theme tags [bar], options: [v7dark, v7light, v8dark, v8light]"`
expect(() => parseThemeTags(['v1dark', 'v1light', 'bar'])).toThrowErrorMatchingInlineSnapshot(
`"Invalid theme tags [bar], options: [v1dark, v1light]"`
);
});

it('throws when an invalid tags in comma separated list', () => {
expect(() => parseThemeTags('v8light ,v7light,bar,box ')).toThrowErrorMatchingInlineSnapshot(
`"Invalid theme tags [bar, box], options: [v7dark, v7light, v8dark, v8light]"`
expect(() => parseThemeTags('v1dark ,v1light, bar, box')).toThrowErrorMatchingInlineSnapshot(
`"Invalid theme tags [bar, box], options: [v1dark, v1light]"`
);
});

it('returns tags in alphabetical order', () => {
const tags = parseThemeTags(['v7light', 'v8light']);
const tags = parseThemeTags(['v1dark', 'v1light']);
expect(tags).toEqual(tags.slice().sort((a, b) => a.localeCompare(b)));
});

it('returns an immutable array', () => {
expect(() => {
const tags = parseThemeTags('v8light');
const tags = parseThemeTags('v1light');
// @ts-expect-error
tags.push('foo');
}).toThrowErrorMatchingInlineSnapshot(`"Cannot add property 1, object is not extensible"`);
Expand Down
6 changes: 3 additions & 3 deletions packages/osd-optimizer/src/common/theme_tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ const isArrayOfStrings = (input: unknown): input is string[] =>
Array.isArray(input) && input.every((v) => typeof v === 'string');

export type ThemeTags = readonly ThemeTag[];
export type ThemeTag = 'v7light' | 'v7dark' | 'v8light' | 'v8dark';
export const DEFAULT_THEMES = tags('v7light', 'v7dark');
export const ALL_THEMES = tags('v7light', 'v7dark', 'v8light', 'v8dark');
export type ThemeTag = 'v1light' | 'v1dark';
export const DEFAULT_THEMES = tags('v1light', 'v1dark');
export const ALL_THEMES = tags('v1light', 'v1dark');

export function parseThemeTags(input?: any): ThemeTags {
if (!input) {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ it('builds expected bundles, saves bundle counts to metadata', async () => {
<absolute path>/packages/osd-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/legacy/_other_styles.scss,
<absolute path>/packages/osd-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/legacy/styles.scss,
<absolute path>/packages/osd-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/lib.ts,
<absolute path>/packages/osd-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v7dark.scss,
<absolute path>/packages/osd-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v7light.scss,
<absolute path>/packages/osd-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v1dark.scss,
<absolute path>/packages/osd-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v1light.scss,
<absolute path>/packages/osd-optimizer/target/worker/entry_point_creator.js,
<absolute path>/packages/osd-ui-shared-deps/public_path_module_creator.js,
]
Expand Down
4 changes: 2 additions & 2 deletions packages/osd-optimizer/src/optimizer/cache_keys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ describe('getOptimizerCacheKey()', () => {
"optimizerCacheKey": "♻",
"repoRoot": <absolute path>,
"themeTags": Array [
"v7dark",
"v7light",
"v1dark",
"v1light",
],
},
}
Expand Down
4 changes: 1 addition & 3 deletions packages/osd-optimizer/src/worker/theme_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,8 @@ import { stringifyRequest, getOptions } from 'loader-utils';
import webpack from 'webpack';
import { parseThemeTags, ALL_THEMES, ThemeTag } from '../common';

const getVersion = (tag: ThemeTag) => (tag.includes('v7') ? 7 : 8);
const getIsDark = (tag: ThemeTag) => tag.includes('dark');
const compare = (a: ThemeTag, b: ThemeTag) =>
(getVersion(a) === getVersion(b) ? 1 : 0) + (getIsDark(a) === getIsDark(b) ? 1 : 0);
const compare = (a: ThemeTag, b: ThemeTag) => (getIsDark(a) === getIsDark(b) ? 1 : 0);

// eslint-disable-next-line import/no-default-export
export default function (this: webpack.loader.LoaderContext) {
Expand Down
4 changes: 2 additions & 2 deletions packages/osd-storybook/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ export default function ({ config: storybookConfig }: { config: Configuration })
additionalData(content: string, loaderContext: any) {
return `@import ${stringifyRequest(
loaderContext,
resolve(REPO_ROOT, 'src/core/public/core_app/styles/_globals_v7light.scss')
)};\n${content}`;
resolve(REPO_ROOT, 'src/core/public/core_app/styles/_globals_v1light.scss')
)};\n`;
},
sassOptions: {
includePaths: [resolve(REPO_ROOT, 'node_modules')],
Expand Down
15 changes: 4 additions & 11 deletions packages/osd-ui-shared-deps/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,19 @@
*/

import LightTheme from '@elastic/eui/dist/eui_theme_light.json';
import DarkTheme from '@elastic/eui/dist/eui_theme_dark.json';

const globals: any = typeof window === 'undefined' ? {} : window;

export type Theme = typeof LightTheme;

// in the OpenSearch Dashboards app we can rely on this global being defined, but in
// some cases (like jest) the global is undefined
export const tag: string = globals.__osdThemeTag__ || 'v7light';
export const version = tag.startsWith('v7') ? 7 : 8;
export const tag: string = globals.__osdThemeTag__ || 'v1light';
export const darkMode = tag.endsWith('dark');

export let euiLightVars: Theme;
export let euiDarkVars: Theme;
zuochengding marked this conversation as resolved.
Show resolved Hide resolved
if (version === 7) {
euiLightVars = require('@elastic/eui/dist/eui_theme_light.json');
euiDarkVars = require('@elastic/eui/dist/eui_theme_dark.json');
} else {
euiLightVars = require('@elastic/eui/dist/eui_theme_amsterdam_light.json');
euiDarkVars = require('@elastic/eui/dist/eui_theme_amsterdam_dark.json');
}
export const euiLightVars: Theme = LightTheme;
export const euiDarkVars: Theme = DarkTheme;

/**
* EUI Theme vars that automatically adjust to light/dark theme
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// v7dark global scope
// v1dark global scope
//
// prepended to all .scss imports (from JS, when v7dark theme selected)
// prepended to all .scss imports (from JS, when v1dark theme selected)

@import '@elastic/eui/src/themes/eui/eui_colors_dark';
@import '@elastic/eui/src/themes/eui/eui_globals';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// v7light global scope
// v1light global scope
//
// prepended to all .scss imports (from JS, when v7light theme selected)
// prepended to all .scss imports (from JS, when v1light theme selected)

@import '@elastic/eui/src/themes/eui/eui_colors_light';
@import '@elastic/eui/src/themes/eui/eui_globals';
Expand Down
8 changes: 0 additions & 8 deletions src/core/public/core_app/styles/_globals_v8dark.scss

This file was deleted.

8 changes: 0 additions & 8 deletions src/core/public/core_app/styles/_globals_v8light.scss

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 39 additions & 1 deletion src/core/public/ui_settings/ui_settings_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ import { UiSettingsClient } from './ui_settings_client';
let done$: Subject<unknown>;

function setup(options: { defaults?: any; initialSettings?: any } = {}) {
const { defaults = { dateFormat: { value: 'Browser' } }, initialSettings = {} } = options;
const {
defaults = { dateFormat: { value: 'Browser' }, 'theme:version': { value: 'v1' } },
initialSettings = {},
} = options;

const batchSet = jest.fn(() => ({
settings: {},
Expand All @@ -59,6 +62,41 @@ afterEach(() => {
done$.complete();
});

describe('#resetThemeVersion', () => {
it('do nothing when userValie is valid v1', () => {
const { client } = setup();
// Suppose userValue is valid themeVersion v1
client.set('theme:version', 'v1');
expect(client.get('theme:version')).toEqual('v1');

client.resetThemeVersion();
// expect no change
expect(client.get('theme:version')).toEqual('v1');
});

it('reset theme:version userValue v7 to default v1', () => {
const { client } = setup();
// Suppose userValue is cached with old themeVersion v7
client.set('theme:version', 'v7');

expect(client.get('theme:version')).toEqual('v7');
client.resetThemeVersion();
// Then theme:version is expected to be default v1
expect(client.get('theme:version')).toEqual('v1');
});

it('reset theme:version userValue v8 (beta) to default v1', () => {
const { client } = setup();
// Suppose userValue is cached with old themeVersion v8 (beta)
client.set('theme:version', 'v8 (beta)');
expect(client.get('theme:version')).toEqual('v8 (beta)');

client.resetThemeVersion();
// theme:version then is expected to be default v1
expect(client.get('theme:version')).toEqual('v1');
});
});

describe('#get', () => {
it('gives access to uiSettings values', () => {
const { client } = setup();
Expand Down
13 changes: 13 additions & 0 deletions src/core/public/ui_settings/ui_settings_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export class UiSettingsClient implements IUiSettingsClient {
this.defaults = cloneDeep(params.defaults);
this.cache = defaultsDeep({}, this.defaults, cloneDeep(params.initialSettings));

this.resetThemeVersion();

params.done$.subscribe({
complete: () => {
this.update$.complete();
Expand Down Expand Up @@ -175,6 +177,17 @@ You can use \`IUiSettingsClient.get("${key}", defaultValue)\`, which will just r
return this.updateErrors$.asObservable();
}

resetThemeVersion() {
const key = 'theme:version';
// Reset userValue to default value if any legacy theme verion exists.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: typo verion should be version

if (
this.cache[key] !== undefined &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we set the value if the cache is undefined?

(this.cache[key].userValue === 'v7' || this.cache[key].userValue === 'v8 (beta)')
) {
this.setLocally(key, this.defaults[key].value);
}
}

private assertUpdateAllowed(key: string) {
if (this.isOverridden(key)) {
throw new Error(
Expand Down
Loading