Turn on strict mode in tsconfig.json, some helpful lints, and required cleanup where strictness necessitates it (#5195)

* Turn on strict mode in tsconfig.json

- Add route, clusterRoute, and payloadValidatedClusterRoute helper
  functions to improve types with backend routes

- Turn on the following new lints:
  - react/jsx-first-prop-new-line
  - react/jsx-wrap-multilines
  - react/jsx-one-expression-per-line
  - react/jsx-max-props-per-line
  - react/jsx-indent
  - react/jsx-indent-props

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix build

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace KubeObject scope strings with enum

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Revert package.json version changes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* revert move hostedCluster(Id)

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* change some type param names to be not single letters

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove copy-extension-themes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* add new make clean action

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix build to not use webpack for generating types

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* revert move fileNameMigration to index

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix ref logic error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix log-resource-selector.test.tsx tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-store.test.ts test by overriding createStorage to not touch file system

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster.test.ts tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube=api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixed hotbar-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kubeconfig-manager.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster-role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pods.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix delete-cluster-dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix daemonset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix replicaset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix statefulsets/dialog/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix replicasets/scale-dialog/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployments.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployments/scale/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cronjob.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix stateful-set.api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployment.api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix api-manager.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix statefulset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix job.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pods.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix scroll-spy.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix hotbar-remove-command.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog-entity-registry.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix welcome.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix verify-that-all-routes-have-route-component.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pod-tolerations.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* better fix for previous 3 fixes, plus also select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix app-paths.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-tabs.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix isReactNode typing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sub-title.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix drawer.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix list-layout.tsx and header.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix error-boundary.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix upgrade-chart/store.ts and dock-tab.store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix install-chart/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix edit-resource/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix create-resource/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix namespace-select.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix namespace-select-filter.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix crd-list.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix wrong types for extensions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix circular dependency

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix circular dependency on catalogCategoryRegistry

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix api-kube

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type errors, most <Select /> errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixing more type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* some more fixing type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* convert all KubeApis to injectable with legacy global backups

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* factor out into a common file all the exports

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* convert all KubeObjectStores to injectable with legacy global backups

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unused legacy KubeApi globals

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix bad previous commit

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* more crash fixing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* try and fix behavioural tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sidebar-and-tab-navigation-for-core.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sidebar-and-tab-navigation-for-extensions.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make ThemeStore non-singleton and fix navigation-to-terminal-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* extensions.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog-entity-registry.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix log-resource-selector.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-tabs.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix delete-cluster-dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-kubernetes-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-editor-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-proxy-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-application-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix hotbar-remove-command.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster-role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-extension-specific-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-telemetry-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix closing-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-editor-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-proxy-preferences.test.ts

- Fix other type errors too

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* final tweaks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add more tsconfig files, fix bug in <Catalog>

- Make all of history, navigation injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert all of kube-details-params/ and navigate/ to injectable

- This fixes a runtime error that was encountered during testing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix runtime errors on renderer

- remove all static uses of `createPageParam` (and then removed the
  legacy global)
- Made LensRendererExtension and LensMainExtension just used
  dependencies and not the getLegacyDi
- Fixed circular dep in extension-loader

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move registerStore calls to after injectMany

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* replace all the rest of the legacy uses of apiManager

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix stack overflow and cycles in DI

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix NamespaceSelectFilter not opening

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix WizardStep and AddNamespaceDialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix KubeApi's not being registered

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* cleanup WindowManager

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Proper fix for Wizard, fix NamespaceStore.subscribe

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Rewrite withTooltip to be more type correct

- Fixes mobx related "too many recursive actions" error

- Change all the uses of withTooltips to be functional components

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add e2e test to cover kube api registration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* cleanup internal-commands

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove cast in <Animate>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix command-palette e2e test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type error after rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix test name

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix code to help CodeQL scanner

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* update intree extension lock files

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix build-extensions picking wrong @types/react

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix tests from rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make KubeconfigSyncManager more injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix crash in test mode for Dialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* make Select snapshots deterministic

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix new type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object.store.test.ts typing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix merge build issues

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix snapshots after merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint after merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* reexport BaseKubeJsonApiObjectMetadata

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typo in terminalSpawningPool

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove duplicate license header

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typo to waitUntilDefined

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove iter use from getLegacyGlobalDiForExtensionApi

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove complex createStorage override

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* override logger with mocks only when needed for tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove specialized overrideStore flags for getDiForUnitTesting

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unnecessary | undefined types from the exactOptionalFieldTypes experiment

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* use more descriptive name for local test mocks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unnecessary addition to 'make clean' target

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove oddity of KubeObjectStore.getById(undefined) being allowed

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* rename KubeObject.getDescriptor in favour of name without fundemental JS meaning

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Simplify legacyRegisterApi when working in behaviour unit tests

- Don't emit within main environment as there should be no auto
  registering there

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* change confusing variable name in ReactiveDuration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* make visitor pattern more explicit for Entity contextMenuOpen

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* toggleDetails -> toggleKubeDetailsPane is more specific

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove outdated comment

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix bug where LensExtension dependencies are not set

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests from the revert of react 18

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix more tests from merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typings with new is-compatible-extension tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* more type fixing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Revert in-tree extension versions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Improve name of guarding injectable for stores and apis

- New name better implies that it is just a guard state and does not do
  anything

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add helper for <Select>.isMulti for storing in a Set<Value>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix is-compatible-extension.test.ts types

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton authored and GitHub committed 2022-05-16 07:17:57 -04:00
1 parent 381d77c633
commit dfcb7c3330
1062 files changed
+26512 -28689

No files matched your search

@@ -39,7 +39,6 @@ const dialogState = observable.object({
function getEmptyRepo(): HelmRepo {
return { name: "", url: "", username: "", password: "", insecureSkipTlsVerify: false, caFile: "", keyFile: "", certFile: "" };
}
@observer
export class AddHelmRepoDialog extends React.Component<AddHelmRepoDialogProps> {
private static keyExtensions = ["key", "keystore", "jks", "p12", "pfx", "pem"];
@@ -72,7 +71,7 @@ export class AddHelmRepoDialog extends React.Component<AddHelmRepoDialogProps> {
this.helmRepo[type] = value;
}
getFilePath(type: FileType) : string {
getFilePath(type: FileType) {
return this.helmRepo[type];
}
@@ -96,16 +95,29 @@ export class AddHelmRepoDialog extends React.Component<AddHelmRepoDialogProps> {
async addCustomRepo() {
try {
await HelmRepoManager.getInstance().addRepo(this.helmRepo);
Notifications.ok(<>Helm repository <b>{this.helmRepo.name}</b> has been added</>);
Notifications.ok((
<>
{"Helm repository "}
<b>{this.helmRepo.name}</b>
{" has been added."}
</>
));
this.props.onAddRepo();
this.close();
} catch (err) {
Notifications.error(<>Adding helm branch <b>{this.helmRepo.name}</b> has failed: {String(err)}</>);
Notifications.error((
<>
{"Adding helm branch "}
<b>{this.helmRepo.name}</b>
{" has failed: "}
{String(err)}
</>
));
}
}
renderFileInput(placeholder:string, fileType:FileType, fileExtensions:string[]){
return(
return (
<div className="flex gaps align-center">
<Input
placeholder={placeholder}
@@ -119,7 +131,8 @@ export class AddHelmRepoDialog extends React.Component<AddHelmRepoDialogProps> {
onClick={() => this.selectFileDialog(fileType, { name: placeholder, extensions: fileExtensions })}
tooltip="Browse"
/>
</div>);
</div>
);
}
renderOptions() {
@@ -137,14 +150,17 @@ export class AddHelmRepoDialog extends React.Component<AddHelmRepoDialogProps> {
<SubTitle title="Chart Repository Credentials" />
<Input
placeholder="Username"
value={this.helmRepo.username} onChange= {v => this.helmRepo.username = v}
value={this.helmRepo.username}
onChange= {v => this.helmRepo.username = v}
/>
<Input
type="password"
placeholder="Password"
value={this.helmRepo.password} onChange={v => this.helmRepo.password = v}
value={this.helmRepo.password}
onChange={v => this.helmRepo.password = v}
/>
</>);
</>
);
}
render() {
@@ -160,22 +176,33 @@ export class AddHelmRepoDialog extends React.Component<AddHelmRepoDialogProps> {
close={this.close}
>
<Wizard header={header} done={this.close}>
<WizardStep contentClass="flow column" nextLabel="Add" next={() => this.addCustomRepo()}>
<WizardStep
contentClass="flow column"
nextLabel="Add"
next={() => this.addCustomRepo()}
>
<div className="flex column gaps">
<Input
autoFocus required
autoFocus
required
placeholder="Helm repo name"
trim
validators={systemName}
value={this.helmRepo.name} onChange={v => this.helmRepo.name = v}
value={this.helmRepo.name}
onChange={v => this.helmRepo.name = v}
/>
<Input
required
placeholder="URL"
validators={isUrl}
value={this.helmRepo.url} onChange={v => this.helmRepo.url = v}
value={this.helmRepo.url}
onChange={v => this.helmRepo.url = v}
/>
<Button plain className="accordion" onClick={() => this.showOptions = !this.showOptions} >
<Button
plain
className="accordion"
onClick={() => this.showOptions = !this.showOptions}
>
More
<Icon
small
@@ -6,16 +6,15 @@
import React from "react";
import { observer } from "mobx-react";
import { SubTitle } from "../layout/sub-title";
import type { SelectOption } from "../select";
import { Select } from "../select";
import type { ThemeStore } from "../../theme.store";
import type { ThemeStore } from "../../themes/store";
import type { UserStore } from "../../../common/user-store";
import { Input } from "../input";
import { Switch } from "../switch";
import moment from "moment-timezone";
import { CONSTANTS, defaultExtensionRegistryUrl, ExtensionRegistryLocation } from "../../../common/user-store/preferences-helpers";
import { updateChannels, defaultExtensionRegistryUrl, defaultUpdateChannel, defaultLocaleTimezone, defaultExtensionRegistryUrlLocation } from "../../../common/user-store/preferences-helpers";
import type { IComputedValue } from "mobx";
import { action } from "mobx";
import { runInAction } from "mobx";
import { isUrl } from "../input/input_validators";
import { ExtensionSettings } from "./extension-settings";
import type { RegisteredAppPreference } from "./app-preferences/app-preference-registration";
@@ -23,16 +22,8 @@ import { withInjectables } from "@ogre-tools/injectable-react";
import appPreferencesInjectable from "./app-preferences/app-preferences.injectable";
import { Preferences } from "./preferences";
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
import themeStoreInjectable from "../../theme-store.injectable";
const timezoneOptions: SelectOption<string>[] = moment.tz.names().map(zone => ({
label: zone,
value: zone,
}));
const updateChannelOptions: SelectOption<string>[] = Array.from(
CONSTANTS.updateChannels.entries(),
([value, { label }]) => ({ value, label }),
);
import themeStoreInjectable from "../../themes/store.injectable";
import { defaultThemeId } from "../../../common/vars";
interface Dependencies {
appPreferenceItems: IComputedValue<RegisteredAppPreference[]>;
@@ -40,9 +31,44 @@ interface Dependencies {
themeStore: ThemeStore;
}
const timezoneOptions = moment.tz.names()
.map(timezone => ({
value: timezone,
label: timezone.replace("_", " "),
}));
const updateChannelOptions = Array.from(updateChannels, ([channel, { label }]) => ({
value: channel,
label,
}));
const extensionInstallRegistryOptions = [
{
value: "default",
label: "Default Url",
},
{
value: "npmrc",
label: "Global .npmrc file's Url",
},
{
value: "custom",
label: "Custom Url",
},
] as const;
const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, userStore, themeStore }) => {
const [customUrl, setCustomUrl] = React.useState(userStore.extensionRegistryUrl.customUrl || "");
const extensionSettings = appPreferenceItems.get().filter((preference) => preference.showInPreferencesTab === "application");
const themeOptions = [
{
value: "system", // TODO: replace with a sentinal value that isn't string (and serialize it differently)
label: "Sync with computer",
},
...Array.from(themeStore.themes, ([themeId, { name }]) => ({
value: themeId,
label: name,
})),
];
const extensionSettings = appPreferenceItems.get()
.filter((preference) => preference.showInPreferencesTab === "application");
return (
<Preferences data-testid="application-preferences-page">
@@ -52,37 +78,35 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, us
<SubTitle title="Theme" />
<Select
id="theme-input"
options={[
{ label: "Sync with computer", value: "system" },
...themeStore.themeOptions,
]}
options={themeOptions}
value={userStore.colorTheme}
onChange={({ value }) => userStore.colorTheme = value}
onChange={value => userStore.colorTheme = value?.value ?? defaultThemeId}
themeName="lens"
/>
</section>
<hr />
<hr/>
<section id="extensionRegistryUrl">
<SubTitle title="Extension Install Registry" />
<Select
id="extension-install-registry-input"
options={Object.values(ExtensionRegistryLocation)}
options={extensionInstallRegistryOptions}
value={userStore.extensionRegistryUrl.location}
onChange={action(({ value }) => {
userStore.extensionRegistryUrl.location = value;
onChange={value => runInAction(() => {
userStore.extensionRegistryUrl.location = value?.value ?? defaultExtensionRegistryUrlLocation;
if (userStore.extensionRegistryUrl.location === ExtensionRegistryLocation.CUSTOM) {
if (userStore.extensionRegistryUrl.location === "custom") {
userStore.extensionRegistryUrl.customUrl = "";
}
})}
themeName="lens"
/>
<p className="mt-4 mb-5 leading-relaxed">
This setting is to change the registry URL for installing extensions by name.{" "}
If you are unable to access the default registry ({defaultExtensionRegistryUrl}){" "}
you can change it in your <b>.npmrc</b>&nbsp;file or in the input below.
{"This setting is to change the registry URL for installing extensions by name. "}
{`If you are unable to access the default registry (${defaultExtensionRegistryUrl}) you can change it in your `}
<b>.npmrc</b>
{" file or in the input below."}
</p>
<Input
@@ -92,7 +116,7 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, us
onChange={setCustomUrl}
onBlur={() => userStore.extensionRegistryUrl.customUrl = customUrl}
placeholder="Custom Extension Registry URL..."
disabled={userStore.extensionRegistryUrl.location !== ExtensionRegistryLocation.CUSTOM}
disabled={userStore.extensionRegistryUrl.location !== "custom"}
/>
</section>
@@ -108,7 +132,11 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, us
<hr />
{extensionSettings.map(setting => (
<ExtensionSettings key={setting.id} setting={setting} size="normal" />
<ExtensionSettings
key={setting.id}
setting={setting}
size="normal"
/>
))}
<section id="update-channel">
@@ -117,7 +145,7 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, us
id="update-channel-input"
options={updateChannelOptions}
value={userStore.updateChannel}
onChange={({ value }) => userStore.updateChannel = value}
onChange={value => userStore.updateChannel = value?.value ?? defaultUpdateChannel}
themeName="lens"
/>
</section>
@@ -130,7 +158,7 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, us
id="timezone-input"
options={timezoneOptions}
value={userStore.localeTimezone}
onChange={({ value }) => userStore.setLocaleTimezone(value)}
onChange={value => userStore.localeTimezone = value?.value ?? defaultLocaleTimezone}
themeName="lens"
/>
</section>
@@ -14,13 +14,11 @@ const closePreferencesInjectable = getInjectable({
const navigateToFrontPage = di.inject(navigateToFrontPageInjectable);
return () => {
if (observableHistory.length === 1) {
if (observableHistory.length <= 1) {
navigateToFrontPage();
return;
} else {
observableHistory.goBack();
}
observableHistory.goBack();
};
},
});
+23 -16
View File
@@ -13,18 +13,28 @@ import { Input, InputValidators } from "../input";
import { Preferences } from "./preferences";
import { withInjectables } from "@ogre-tools/injectable-react";
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
enum EditorLineNumbersStyles {
on = "On",
off = "Off",
relative = "Relative",
interval = "Interval",
}
import { defaultEditorConfig } from "../../../common/user-store/preferences-helpers";
import { capitalize } from "lodash";
interface Dependencies {
userStore: UserStore;
}
const minimapPositionOptions = (["left", "right"] as const)
.map(side => ({
value: side,
label: side,
}));
const lineNumberOptions = ([
"on",
"off",
"relative",
"interval",
] as const).map(lineNumbers => ({
value: lineNumbers,
label: capitalize(lineNumbers),
}));
const NonInjectedEditor = observer(({ userStore }: Dependencies) => {
const editorConfiguration = userStore.editorConfiguration;
@@ -33,7 +43,7 @@ const NonInjectedEditor = observer(({ userStore }: Dependencies) => {
<section id="editor">
<h2 data-testid="editor-configuration-header">Editor configuration</h2>
<SubTitle title="Minimap" />
<SubTitle title="Minimap"/>
<section>
<div className="flex gaps justify-space-between">
<div className="flex gaps align-center">
@@ -49,24 +59,21 @@ const NonInjectedEditor = observer(({ userStore }: Dependencies) => {
<Select
id="minimap-input"
themeName="lens"
options={["left", "right"]}
options={minimapPositionOptions}
value={editorConfiguration.minimap.side}
onChange={({ value }) => editorConfiguration.minimap.side = value}
onChange={option => editorConfiguration.minimap.side = option?.value}
/>
</div>
</div>
</section>
<section>
<SubTitle title="Line numbers" />
<SubTitle title="Line numbers"/>
<Select
id="editor-line-numbers-input"
options={Object.entries(EditorLineNumbersStyles).map(([value, label]) => ({
label,
value,
}))}
options={lineNumberOptions}
value={editorConfiguration.lineNumbers}
onChange={({ value }) => editorConfiguration.lineNumbers = value}
onChange={option => editorConfiguration.lineNumbers = option?.value ?? defaultEditorConfig.lineNumbers}
themeName="lens"
/>
</section>
@@ -14,7 +14,8 @@ const extensionPreferenceItemRegistratorInjectable = getInjectable({
instantiate:
(di) =>
(extension: LensRendererExtension, extensionInstallationCount) => {
(ext, extensionInstallationCount) => {
const extension = ext as LensRendererExtension;
const injectables = pipeline(
extension.appPreferences,
@@ -22,7 +22,11 @@ export function ExtensionSettings({ setting, size, ...props }: ExtensionSettings
return (
<React.Fragment>
<section id={id} className={cssNames(size)} {...props}>
<section
id={id}
className={cssNames(size)}
{...props}
>
<SubTitle title={title} />
<Input />
<div className="hint">
@@ -14,7 +14,8 @@ const extensionTelemetryPreferenceItemRegistratorInjectable = getInjectable({
instantiate:
(di) =>
(extension: LensRendererExtension, extensionInstallationCount) => {
(ext, extensionInstallationCount) => {
const extension = ext as LensRendererExtension;
const injectables = pipeline(
extension.appPreferences,
@@ -6,7 +6,7 @@
import styles from "./helm-charts.module.scss";
import React from "react";
import { computed, observable, makeObservable } from "mobx";
import { observable, makeObservable, computed } from "mobx";
import type { HelmRepo } from "../../../main/helm/helm-repo-manager";
import { HelmRepoManager } from "../../../main/helm/helm-repo-manager";
@@ -21,6 +21,7 @@ import { RemovableItem } from "./removable-item";
import { Notice } from "../+extensions/notice";
import { Spinner } from "../spinner";
import { noop } from "../../utils";
import type { SingleValue } from "react-select";
@observer
export class HelmCharts extends React.Component {
@@ -34,10 +35,11 @@ export class HelmCharts extends React.Component {
makeObservable(this);
}
@computed get options(): SelectOption<HelmRepo>[] {
@computed get repoOptions() {
return this.repos.map(repo => ({
label: repo.name,
value: repo,
label: repo.name,
isSelected: this.addedRepos.has(repo.name),
}));
}
@@ -79,7 +81,14 @@ export class HelmCharts extends React.Component {
await HelmRepoManager.getInstance().addRepo(repo);
this.addedRepos.set(repo.name, repo);
} catch (err) {
Notifications.error(<>Adding helm branch <b>{repo.name}</b> has failed: {String(err)}</>);
Notifications.error((
<>
{"Adding helm branch "}
<b>{repo.name}</b>
{" has failed: "}
{String(err)}
</>
));
}
}
@@ -89,31 +98,45 @@ export class HelmCharts extends React.Component {
this.addedRepos.delete(repo.name);
} catch (err) {
Notifications.error(
<>Removing helm branch <b>{repo.name}</b> has failed: {String(err)}</>,
<>
{"Removing helm branch "}
<b>{repo.name}</b>
{" has failed: "}
{String(err)}
</>,
);
}
}
onRepoSelect = async ({ value: repo }: SelectOption<HelmRepo>): Promise<void> => {
const isAdded = this.addedRepos.has(repo.name);
if (isAdded) {
return void Notifications.ok(<>Helm branch <b>{repo.name}</b> already in use</>);
onRepoSelect = async (option: SingleValue<{ value: HelmRepo }>): Promise<void> => {
if (!option) {
return;
}
await this.addRepo(repo);
if (this.addedRepos.has(option.value.name)) {
return void Notifications.ok((
<>
{"Helm repo "}
<b>{option.value.name}</b>
{" already in use."}
</>
));
}
await this.addRepo(option.value);
};
formatOptionLabel = ({ value: repo }: SelectOption<HelmRepo>) => {
const isAdded = this.addedRepos.has(repo.name);
return (
<div className="flex gaps">
<span>{repo.name}</span>
{isAdded && <Icon small material="check" className="box right"/>}
</div>
);
};
formatOptionLabel = ({ value, isSelected }: SelectOption<HelmRepo>) => (
<div className="flex gaps">
<span>{value.name}</span>
{isSelected && (
<Icon
small
material="check"
className="box right" />
)}
</div>
);
renderRepositories() {
const repos = Array.from(this.addedRepos);
@@ -132,7 +155,11 @@ export class HelmCharts extends React.Component {
return repos.map(([name, repo]) => {
return (
<RemovableItem key={name} onRemove={() => this.removeRepo(repo)} className="mt-3">
<RemovableItem
key={name}
onRemove={() => this.removeRepo(repo)}
className="mt-3"
>
<div>
<div data-testid="repository-name" className={styles.repoName}>{name}</div>
<div className={styles.repoUrl}>{repo.url}</div>
@@ -151,8 +178,9 @@ export class HelmCharts extends React.Component {
placeholder="Repositories"
isLoading={this.loadingAvailableRepos}
isDisabled={this.loadingAvailableRepos}
options={this.options}
options={this.repoOptions}
onChange={this.onRepoSelect}
value={this.repos}
formatOptionLabel={this.formatOptionLabel}
controlShouldRenderValue={false}
className="box grow"
@@ -8,10 +8,9 @@ import { observer } from "mobx-react";
import { Input, InputValidators } from "../input";
import { SubTitle } from "../layout/sub-title";
import type { UserStore } from "../../../common/user-store";
import type { SelectOption } from "../select";
import { Select } from "../select";
import { Switch } from "../switch";
import { packageMirrors } from "../../../common/user-store/preferences-helpers";
import { defaultPackageMirror, packageMirrors } from "../../../common/user-store/preferences-helpers";
import directoryForBinariesInjectable from "../../../common/app-paths/directory-for-binaries/directory-for-binaries.injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
@@ -22,85 +21,80 @@ interface Dependencies {
defaultPathForKubectlBinaries: string;
userStore: UserStore;
}
const downloadMirrorOptions = Array.from(packageMirrors, ([name, mirror]) => ({
value: name,
label: mirror.label,
isDisabled: !mirror.platforms.has(process.platform),
}));
const NonInjectedKubectlBinaries: React.FC<Dependencies> = observer(
({ defaultPathForGeneralBinaries, defaultPathForKubectlBinaries, userStore }) => {
const [downloadPath, setDownloadPath] = useState(
userStore.downloadBinariesPath || "",
);
const NonInjectedKubectlBinaries= observer(({
defaultPathForGeneralBinaries,
defaultPathForKubectlBinaries,
userStore,
}: Dependencies) => {
const [downloadPath, setDownloadPath] = useState(userStore.downloadBinariesPath || "");
const [binariesPath, setBinariesPath] = useState(userStore.kubectlBinariesPath || "");
const pathValidator = downloadPath ? InputValidators.isPath : undefined;
const [binariesPath, setBinariesPath] = useState(
userStore.kubectlBinariesPath || "",
);
const save = () => {
userStore.downloadBinariesPath = downloadPath;
userStore.kubectlBinariesPath = binariesPath;
};
const pathValidator = downloadPath ? InputValidators.isPath : undefined;
const downloadMirrorOptions: SelectOption<string>[] = Array.from(
packageMirrors.entries(),
([value, { label, platforms }]) => ({ value, label, platforms }),
);
return (
<>
<section>
<SubTitle title="Kubectl binary download" />
<Switch
checked={userStore.downloadKubectlBinaries}
onChange={() => userStore.downloadKubectlBinaries = !userStore.downloadKubectlBinaries}
>
Download kubectl binaries matching the Kubernetes cluster version
</Switch>
</section>
const save = () => {
userStore.downloadBinariesPath = downloadPath;
userStore.kubectlBinariesPath = binariesPath;
};
<section>
<SubTitle title="Download mirror" />
<Select
id="download-mirror-input"
placeholder="Download mirror for kubectl"
options={downloadMirrorOptions}
value={userStore.downloadMirror}
onChange={option => userStore.downloadMirror = option?.value ?? defaultPackageMirror}
isDisabled={!userStore.downloadKubectlBinaries}
themeName="lens"
/>
</section>
return (
<>
<section>
<SubTitle title="Kubectl binary download" />
<Switch
checked={userStore.downloadKubectlBinaries}
onChange={() => userStore.downloadKubectlBinaries = !userStore.downloadKubectlBinaries}
>
Download kubectl binaries matching the Kubernetes cluster version
</Switch>
</section>
<section>
<SubTitle title="Directory for binaries" />
<Input
theme="round-black"
value={downloadPath}
placeholder={defaultPathForGeneralBinaries}
validators={pathValidator}
onChange={setDownloadPath}
onBlur={save}
disabled={!userStore.downloadKubectlBinaries}
/>
<div className="hint">The directory to download binaries into.</div>
</section>
<section>
<SubTitle title="Download mirror" />
<Select
id="download-mirror-input"
placeholder="Download mirror for kubectl"
options={downloadMirrorOptions}
value={userStore.downloadMirror}
onChange={({ value }: SelectOption) => userStore.downloadMirror = value}
isDisabled={!userStore.downloadKubectlBinaries}
isOptionDisabled={({ platforms }) =>
!platforms.has(process.platform)
}
themeName="lens"
/>
</section>
<section>
<SubTitle title="Directory for binaries" />
<Input
theme="round-black"
value={downloadPath}
placeholder={defaultPathForGeneralBinaries}
validators={pathValidator}
onChange={setDownloadPath}
onBlur={save}
disabled={!userStore.downloadKubectlBinaries}
/>
<div className="hint">The directory to download binaries into.</div>
</section>
<section>
<SubTitle title="Path to kubectl binary" />
<Input
theme="round-black"
placeholder={defaultPathForKubectlBinaries}
value={binariesPath}
validators={pathValidator}
onChange={setBinariesPath}
onBlur={save}
disabled={userStore.downloadKubectlBinaries}
/>
</section>
</>
);
},
<section>
<SubTitle title="Path to kubectl binary" />
<Input
theme="round-black"
placeholder={defaultPathForKubectlBinaries}
value={binariesPath}
validators={pathValidator}
onChange={setBinariesPath}
onBlur={save}
disabled={userStore.downloadKubectlBinaries}
/>
</section>
</>
);
},
);
export const KubectlBinaries = withInjectables<Dependencies>(
@@ -41,13 +41,17 @@ const NonInjectedLensProxy = observer(({ userStore }: Dependencies) => {
<section className="small">
<SubTitle title="Certificate Trust" />
<Switch checked={userStore.allowUntrustedCAs}
onChange={() => userStore.allowUntrustedCAs = !userStore.allowUntrustedCAs}>
<Switch
checked={userStore.allowUntrustedCAs}
onChange={() => userStore.allowUntrustedCAs = !userStore.allowUntrustedCAs}
>
Allow untrusted Certificate Authorities
</Switch>
<small className="hint">
This will make Lens to trust ANY certificate authority without any validations.{" "}
Needed with some corporate proxies that do certificate re-writing.{" "}
This will make Lens to trust ANY certificate authority without any validations.
{" "}
Needed with some corporate proxies that do certificate re-writing.
{" "}
Does not affect cluster communications!
</small>
</section>
@@ -26,47 +26,47 @@ const NonInjectedTelemetry: React.FC<Dependencies> = ({
telemetryPreferenceItems,
sentryDnsUrl,
userStore,
}) => {
return (
<Preferences data-testid="telemetry-preferences-page">
<section id="telemetry">
<h2 data-testid="telemetry-header">Telemetry</h2>
{telemetryPreferenceItems.get().map((item) => (
<ExtensionSettings
key={item.id}
setting={item}
size="small"
data-testid={`telemetry-preference-item-for-${item.id}`}
/>
))}
{sentryDnsUrl ? (
<React.Fragment key="sentry">
<section id="sentry" className="small" data-testid="telemetry-preferences-for-automatic-error-reporting">
<SubTitle title="Automatic Error Reporting" />
<Checkbox
label="Allow automatic error reporting"
value={userStore.allowErrorReporting}
onChange={(value) => {
userStore.allowErrorReporting = value;
}}
/>
<div className="hint">
<span>
Automatic error reports provide vital information about issues
and application crashes. It is highly recommended to keep this
feature enabled to ensure fast turnaround for issues you might
encounter.
</span>
</div>
</section>
<hr className="small" />
</React.Fragment>
) : // we don't need to shows the checkbox at all if Sentry dsn is not a valid url
null}
</section>
</Preferences>
);
};
}) => (
<Preferences data-testid="telemetry-preferences-page">
<section id="telemetry">
<h2 data-testid="telemetry-header">Telemetry</h2>
{telemetryPreferenceItems.get().map((item) => (
<ExtensionSettings
key={item.id}
setting={item}
size="small"
data-testid={`telemetry-preference-item-for-${item.id}`}
/>
))}
{sentryDnsUrl ? (
<React.Fragment key="sentry">
<section
id="sentry"
className="small"
data-testid="telemetry-preferences-for-automatic-error-reporting"
>
<SubTitle title="Automatic Error Reporting" />
<Checkbox
label="Allow automatic error reporting"
value={userStore.allowErrorReporting}
onChange={(value) => userStore.allowErrorReporting = value}
/>
<div className="hint">
<span>
Automatic error reports provide vital information about issues
and application crashes. It is highly recommended to keep this
feature enabled to ensure fast turnaround for issues you might
encounter.
</span>
</div>
</section>
<hr className="small" />
</React.Fragment>
) : // we don't need to shows the checkbox at all if Sentry dsn is not a valid url
null}
</section>
</Preferences>
);
export const Telemetry = withInjectables<Dependencies>(
observer(NonInjectedTelemetry),
@@ -10,11 +10,11 @@ import { SubTitle } from "../layout/sub-title";
import { Input, InputValidators } from "../input";
import { Switch } from "../switch";
import { Select } from "../select";
import type { ThemeStore } from "../../theme.store";
import type { ThemeStore } from "../../themes/store";
import { Preferences } from "./preferences";
import { withInjectables } from "@ogre-tools/injectable-react";
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
import themeStoreInjectable from "../../theme-store.injectable";
import themeStoreInjectable from "../../themes/store.injectable";
import defaultShellInjectable from "./default-shell.injectable";
interface Dependencies {
@@ -23,7 +23,22 @@ interface Dependencies {
defaultShell: string;
}
const NonInjectedTerminal = observer(({ userStore, themeStore, defaultShell }: Dependencies) => {
const NonInjectedTerminal = observer(({
userStore,
themeStore,
defaultShell,
}: Dependencies) => {
const themeOptions = [
{
value: "", // TODO: replace with a sentinal value that isn't string (and serialize it differently)
label: "Match Lens Theme",
},
...Array.from(themeStore.themes, ([themeId, { name }]) => ({
value: themeId,
label: name,
})),
];
return (
<Preferences data-testid="terminal-preferences-page">
<section>
@@ -54,12 +69,9 @@ const NonInjectedTerminal = observer(({ userStore, themeStore, defaultShell }: D
<Select
id="terminal-theme-input"
themeName="lens"
options={[
{ label: "Match theme", value: "" },
...themeStore.themeOptions,
]}
options={themeOptions}
value={userStore.terminalTheme}
onChange={({ value }) => userStore.terminalTheme = value}
onChange={option => userStore.terminalTheme = option?.value ?? ""}
/>
</section>