mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
final tweaks
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
06cfc3e96b
commit
7dde2326bf
@ -45,7 +45,7 @@ describe("extension special characters in page registrations", () => {
|
||||
it("knows URL", () => {
|
||||
const currentPath = applicationBuilder.dis.rendererDi.inject(currentPathInjectable);
|
||||
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-id--/some-page-id");
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-name--/some-page-id");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -52,7 +52,7 @@ describe("navigate to extension page", () => {
|
||||
});
|
||||
|
||||
it("URL is correct", () => {
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-id");
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-name");
|
||||
});
|
||||
|
||||
it("query parameters is empty", () => {
|
||||
@ -71,7 +71,7 @@ describe("navigate to extension page", () => {
|
||||
});
|
||||
|
||||
it("URL is correct", () => {
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-id");
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-name");
|
||||
});
|
||||
|
||||
it("knows query parameters", () => {
|
||||
@ -99,7 +99,7 @@ describe("navigate to extension page", () => {
|
||||
});
|
||||
|
||||
it("URL is correct", () => {
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-id");
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-name");
|
||||
});
|
||||
|
||||
it("knows query parameters", () => {
|
||||
@ -121,7 +121,7 @@ describe("navigate to extension page", () => {
|
||||
});
|
||||
|
||||
it("URL is correct", () => {
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-id/some-child-page-id");
|
||||
expect(currentPath.get()).toBe("/extension/some-extension-name/some-child-page-id");
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -160,20 +160,14 @@ const extensionWithPagesHavingParameters: SetRequired<Partial<LensRendererExtens
|
||||
|
||||
params: {
|
||||
someStringParameter: "some-string-value",
|
||||
|
||||
someNumberParameter: {
|
||||
defaultValue: 42,
|
||||
|
||||
stringify: (value) => value.toString(),
|
||||
|
||||
parse: (value) => (value ? Number(value) : undefined),
|
||||
},
|
||||
|
||||
someArrayParameter: {
|
||||
defaultValue: ["some-array-value", "some-other-array-value"],
|
||||
|
||||
stringify: (value) => value.join(","),
|
||||
|
||||
parse: (value: string[]) => (!isEmpty(value) ? value : undefined),
|
||||
},
|
||||
},
|
||||
|
||||
@ -18,7 +18,7 @@ import { SubTitle } from "../layout/sub-title";
|
||||
import { NamespaceSelect } from "../+namespaces/namespace-select";
|
||||
import { Select } from "../select";
|
||||
import { Icon } from "../icon";
|
||||
import { base64, iter, object } from "../../utils";
|
||||
import { base64, iter } from "../../utils";
|
||||
import { Notifications } from "../notifications";
|
||||
import upperFirst from "lodash/upperFirst";
|
||||
import { showDetails } from "../kube-detail-params";
|
||||
@ -71,13 +71,6 @@ export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
},
|
||||
};
|
||||
|
||||
private get secretTypeOptions() {
|
||||
return object.keys(this.secretTemplate).map(type => ({
|
||||
value: type,
|
||||
label: reverseSecretTypeMap[type],
|
||||
}));
|
||||
}
|
||||
|
||||
@observable secret = this.secretTemplate;
|
||||
@observable name = "";
|
||||
@observable namespace = "default";
|
||||
@ -235,9 +228,10 @@ export class AddSecretDialog extends React.Component<AddSecretDialogProps> {
|
||||
<Select
|
||||
id="secret-input"
|
||||
themeName="light"
|
||||
options={this.secretTypeOptions}
|
||||
options={Object.keys(this.secretTemplate) as SecretType[]}
|
||||
value={type}
|
||||
onChange={option => this.type = option?.value ?? SecretType.Opaque}
|
||||
getOptionLabel={option => reverseSecretTypeMap[option.value]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -60,13 +60,9 @@ class NonInjectedClusterManager extends React.Component<Dependencies> {
|
||||
}
|
||||
|
||||
export const ClusterManager = withInjectables<Dependencies>(NonInjectedClusterManager, {
|
||||
getProps: (di) => {
|
||||
const welcomeRoute = di.inject(welcomeRouteInjectable);
|
||||
|
||||
return {
|
||||
catalogPreviousActiveTabStorage: di.inject(catalogPreviousActiveTabStorageInjectable),
|
||||
currentRouteComponent: di.inject(currentRouteComponentInjectable),
|
||||
welcomeUrl: buildURL(welcomeRoute.path),
|
||||
};
|
||||
},
|
||||
getProps: (di) => ({
|
||||
catalogPreviousActiveTabStorage: di.inject(catalogPreviousActiveTabStorageInjectable),
|
||||
currentRouteComponent: di.inject(currentRouteComponentInjectable),
|
||||
welcomeUrl: buildURL(di.inject(welcomeRouteInjectable).path),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -6,12 +6,12 @@
|
||||
import styles from "./editor-panel.module.scss";
|
||||
import throttle from "lodash/throttle";
|
||||
import React from "react";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { makeObservable, reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import type { DockStore, TabId } from "./dock/store";
|
||||
import { cssNames } from "../../utils";
|
||||
import type { MonacoEditorProps } from "../monaco-editor";
|
||||
import { MonacoEditor } from "../monaco-editor";
|
||||
import type { MonacoEditorProps, MonacoEditorRef } from "../monaco-editor";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import dockStoreInjectable from "./dock/store.injectable";
|
||||
|
||||
@ -36,7 +36,7 @@ const defaultProps: Partial<EditorPanelProps> = {
|
||||
class NonInjectedEditorPanel extends React.Component<EditorPanelProps & Dependencies> {
|
||||
static defaultProps = defaultProps as object;
|
||||
|
||||
@observable.ref editor: MonacoEditor | null = null;
|
||||
private readonly editor = React.createRef<MonacoEditorRef>();
|
||||
|
||||
constructor(props: EditorPanelProps & Dependencies) {
|
||||
super(props);
|
||||
@ -46,12 +46,12 @@ class NonInjectedEditorPanel extends React.Component<EditorPanelProps & Dependen
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
// keep focus on editor's area when <Dock/> just opened
|
||||
reaction(() => this.props.dockStore.isOpen, isOpen => isOpen && this.editor?.focus(), {
|
||||
reaction(() => this.props.dockStore.isOpen, isOpen => isOpen && this.editor.current?.focus(), {
|
||||
fireImmediately: true,
|
||||
}),
|
||||
|
||||
// focus to editor on dock's resize or turning into fullscreen mode
|
||||
this.props.dockStore.onResize(throttle(() => this.editor?.focus(), 250)),
|
||||
this.props.dockStore.onResize(throttle(() => this.editor.current?.focus(), 250)),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -68,19 +68,15 @@ class NonInjectedEditorPanel extends React.Component<EditorPanelProps & Dependen
|
||||
className={cssNames(styles.EditorPanel, className)}
|
||||
onChange={onChange}
|
||||
onError={onError}
|
||||
ref={monaco => this.editor = monaco}
|
||||
ref={this.editor}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const EditorPanel = withInjectables<Dependencies, EditorPanelProps>(
|
||||
NonInjectedEditorPanel,
|
||||
|
||||
{
|
||||
getProps: (di, props) => ({
|
||||
dockStore: di.inject(dockStoreInjectable),
|
||||
...props,
|
||||
}),
|
||||
},
|
||||
);
|
||||
export const EditorPanel = withInjectables<Dependencies, EditorPanelProps>(NonInjectedEditorPanel, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
dockStore: di.inject(dockStoreInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -35,6 +35,7 @@ export interface MonacoEditorProps {
|
||||
onDidLayoutChange?(info: editor.EditorLayoutInfo): void;
|
||||
onDidContentSizeChange?(evt: editor.IContentSizeChangedEvent): void;
|
||||
onModelChange?(model: editor.ITextModel, prev?: editor.ITextModel): void;
|
||||
innerRef?: React.ForwardedRef<MonacoEditorRef>;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
@ -47,6 +48,10 @@ export function createMonacoUri(id: MonacoEditorId): Uri {
|
||||
|
||||
const monacoViewStates = new WeakMap<Uri, editor.ICodeEditorViewState>();
|
||||
|
||||
export interface MonacoEditorRef {
|
||||
focus(): void;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedMonacoEditor extends React.Component<MonacoEditorProps & Dependencies> {
|
||||
static defaultProps = {
|
||||
@ -290,9 +295,12 @@ class NonInjectedMonacoEditor extends React.Component<MonacoEditorProps & Depend
|
||||
}
|
||||
}
|
||||
|
||||
export const MonacoEditor = withInjectables<Dependencies, MonacoEditorProps>(NonInjectedMonacoEditor, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
themeStore: di.inject(themeStoreInjectable),
|
||||
}),
|
||||
});
|
||||
export const MonacoEditor = withInjectables<Dependencies, MonacoEditorProps, MonacoEditorRef>(
|
||||
React.forwardRef<MonacoEditorRef, MonacoEditorProps & Dependencies>((props, ref) => <NonInjectedMonacoEditor innerRef={ref} {...props} />),
|
||||
{
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
themeStore: di.inject(themeStoreInjectable),
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
@ -14,7 +14,6 @@ import ReactSelect, { components, createFilter } from "react-select";
|
||||
import type { Props as ReactSelectProps, GroupBase, MultiValue, OptionsOrGroups, PropsValue, SingleValue } from "react-select";
|
||||
import type { ThemeStore } from "../../themes/store";
|
||||
import { autoBind, cssNames } from "../../utils";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import themeStoreInjectable from "../../themes/store.injectable";
|
||||
|
||||
@ -27,6 +26,11 @@ export interface SelectOption<Value> {
|
||||
isSelected?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This should not be used anymore, convert the options yourself.
|
||||
*/
|
||||
export type LegacyAutoConvertedOptions = string[];
|
||||
|
||||
export interface SelectProps<
|
||||
Value,
|
||||
/**
|
||||
@ -41,11 +45,22 @@ export interface SelectProps<
|
||||
Option extends SelectOption<Value>,
|
||||
IsMulti extends boolean,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>,
|
||||
> extends SetRequired<Omit<ReactSelectProps<Option, IsMulti, Group>, "value">, "options"> {
|
||||
id: string; // Optional only because of Extension API. Required to make Select deterministic in unit tests
|
||||
> extends Omit<ReactSelectProps<Option, IsMulti, Group>, "value" | "options"> {
|
||||
id?: string; // Optional only because of Extension API. Required to make Select deterministic in unit tests
|
||||
themeName?: "dark" | "light" | "outlined" | "lens";
|
||||
menuClass?: string;
|
||||
value?: PropsValue<Value>;
|
||||
options: NonNullable<ReactSelectProps<Option, IsMulti, Group>["options"]> | LegacyAutoConvertedOptions;
|
||||
|
||||
/**
|
||||
* @deprecated This option does nothing
|
||||
*/
|
||||
isCreatable?: boolean;
|
||||
|
||||
/**
|
||||
* @deprecated We will always auto convert options if they are of type `string`
|
||||
*/
|
||||
autoConvertOptions?: boolean;
|
||||
}
|
||||
|
||||
function isGroup<Option, Group extends GroupBase<Option>>(optionOrGroup: Option | Group): optionOrGroup is Group {
|
||||
@ -154,6 +169,15 @@ class NonInjectedSelect<
|
||||
} = this.props;
|
||||
const WrappedMenu = components.Menu ?? Menu;
|
||||
|
||||
const convertedOptions = options.map(option => (
|
||||
typeof option === "string"
|
||||
? {
|
||||
value: option,
|
||||
label: option,
|
||||
} as unknown as Option
|
||||
: option
|
||||
));
|
||||
|
||||
if (options.length > 0 && !(options?.[0] as { label?: string }).label) {
|
||||
console.warn("[SELECT]: will not display any label in dropdown");
|
||||
}
|
||||
@ -170,8 +194,8 @@ class NonInjectedSelect<
|
||||
}}
|
||||
filterOption={defaultFilter} // This is done because the default filter crashes on symbols
|
||||
isMulti={isMulti}
|
||||
options={options}
|
||||
value={this.findSelectedPropsValue(value, options, isMulti)}
|
||||
options={convertedOptions}
|
||||
value={this.findSelectedPropsValue(value, convertedOptions, isMulti)}
|
||||
onKeyDown={this.onKeyDown}
|
||||
className={cssNames("Select", this.themeClass, className)}
|
||||
classNamePrefix="Select"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user