1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Attempt to use MuiCheckbox for 3-state checkbox

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-08-03 16:08:19 -04:00
parent 9b4ca7f0ce
commit cdb2d35e12
6 changed files with 171 additions and 10 deletions

View File

@ -200,6 +200,19 @@ const openAtLogin: PreferenceDescription<boolean> = {
}, },
}; };
const extensionRegistryUrl: PreferenceDescription<boolean | string> = {
fromStore(val) {
return val ?? false;
},
toStore(val) {
if (val === false) {
return undefined;
}
return val;
}
};
const hiddenTableColumns: PreferenceDescription<[string, string[]][], Map<string, ObservableToggleSet<string>>> = { const hiddenTableColumns: PreferenceDescription<[string, string[]][], Map<string, ObservableToggleSet<string>>> = {
fromStore(val) { fromStore(val) {
return new Map( return new Map(
@ -271,6 +284,7 @@ export const DESCRIPTORS = {
downloadBinariesPath, downloadBinariesPath,
kubectlBinariesPath, kubectlBinariesPath,
openAtLogin, openAtLogin,
extensionRegistryUrl,
hiddenTableColumns, hiddenTableColumns,
syncKubeconfigEntries, syncKubeconfigEntries,
editorConfiguration, editorConfiguration,

View File

@ -71,6 +71,22 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
@observable downloadBinariesPath?: string; @observable downloadBinariesPath?: string;
@observable kubectlBinariesPath?: string; @observable kubectlBinariesPath?: string;
/**
* The extension registry URL
* - If `true` then used the registry configured in the `~/.npmrc`
* - If `false` then the default location
* - If a string, then use that
*/
@observable extensionRegistryUrl: boolean | string;
@computed get getUseConfiguredExtensionRegistryUrl(): boolean {
if (typeof this.extensionRegistryUrl === "boolean") {
return this.extensionRegistryUrl;
}
return false;
}
/** /**
* Download kubectl binaries matching cluster version * Download kubectl binaries matching cluster version
*/ */
@ -209,6 +225,7 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
this.downloadBinariesPath = DESCRIPTORS.downloadBinariesPath.fromStore(preferences?.downloadBinariesPath); this.downloadBinariesPath = DESCRIPTORS.downloadBinariesPath.fromStore(preferences?.downloadBinariesPath);
this.kubectlBinariesPath = DESCRIPTORS.kubectlBinariesPath.fromStore(preferences?.kubectlBinariesPath); this.kubectlBinariesPath = DESCRIPTORS.kubectlBinariesPath.fromStore(preferences?.kubectlBinariesPath);
this.openAtLogin = DESCRIPTORS.openAtLogin.fromStore(preferences?.openAtLogin); this.openAtLogin = DESCRIPTORS.openAtLogin.fromStore(preferences?.openAtLogin);
this.extensionRegistryUrl = DESCRIPTORS.extensionRegistryUrl.fromStore(preferences?.extensionRegistryUrl);
this.hiddenTableColumns.replace(DESCRIPTORS.hiddenTableColumns.fromStore(preferences?.hiddenTableColumns)); this.hiddenTableColumns.replace(DESCRIPTORS.hiddenTableColumns.fromStore(preferences?.hiddenTableColumns));
this.syncKubeconfigEntries.replace(DESCRIPTORS.syncKubeconfigEntries.fromStore(preferences?.syncKubeconfigEntries)); this.syncKubeconfigEntries.replace(DESCRIPTORS.syncKubeconfigEntries.fromStore(preferences?.syncKubeconfigEntries));
this.editorConfiguration = DESCRIPTORS.editorConfiguration.fromStore(preferences?.editorConfiguration); this.editorConfiguration = DESCRIPTORS.editorConfiguration.fromStore(preferences?.editorConfiguration);
@ -230,6 +247,7 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
downloadBinariesPath: DESCRIPTORS.downloadBinariesPath.toStore(this.downloadBinariesPath), downloadBinariesPath: DESCRIPTORS.downloadBinariesPath.toStore(this.downloadBinariesPath),
kubectlBinariesPath: DESCRIPTORS.kubectlBinariesPath.toStore(this.kubectlBinariesPath), kubectlBinariesPath: DESCRIPTORS.kubectlBinariesPath.toStore(this.kubectlBinariesPath),
openAtLogin: DESCRIPTORS.openAtLogin.toStore(this.openAtLogin), openAtLogin: DESCRIPTORS.openAtLogin.toStore(this.openAtLogin),
extensionRegistryUrl: DESCRIPTORS.extensionRegistryUrl.toStore(this.extensionRegistryUrl),
hiddenTableColumns: DESCRIPTORS.hiddenTableColumns.toStore(this.hiddenTableColumns), hiddenTableColumns: DESCRIPTORS.hiddenTableColumns.toStore(this.hiddenTableColumns),
syncKubeconfigEntries: DESCRIPTORS.syncKubeconfigEntries.toStore(this.syncKubeconfigEntries), syncKubeconfigEntries: DESCRIPTORS.syncKubeconfigEntries.toStore(this.syncKubeconfigEntries),
editorConfiguration: DESCRIPTORS.editorConfiguration.toStore(this.editorConfiguration), editorConfiguration: DESCRIPTORS.editorConfiguration.toStore(this.editorConfiguration),

View File

@ -47,6 +47,7 @@ import { Notice } from "./notice";
import { SettingLayout } from "../layout/setting-layout"; import { SettingLayout } from "../layout/setting-layout";
import { docsUrl } from "../../../common/vars"; import { docsUrl } from "../../../common/vars";
import { dialog } from "../../remote-helpers"; import { dialog } from "../../remote-helpers";
import { UserStore } from "../../../common/user-store";
function getMessageFromError(error: any): string { function getMessageFromError(error: any): string {
if (!error || typeof error !== "object") { if (!error || typeof error !== "object") {
@ -299,9 +300,19 @@ async function unpackExtension(request: InstallRequestValidated, disposeDownload
} }
} }
const defaultBaseRegistryUrl = "https://registry.npmjs.com"; export const defaultBaseRegistryUrl = "https://registry.npmjs.com";
async function getBaseRegistryUrl(): Promise<string> { async function getBaseRegistryUrl(): Promise<string> {
const userStore = UserStore.getInstance();
if (userStore.extensionRegistryUrl === false) {
return defaultBaseRegistryUrl;
}
if (typeof userStore.extensionRegistryUrl === "string") {
return userStore.extensionRegistryUrl;
}
try { try {
const filteredEnv = Object.fromEntries( const filteredEnv = Object.fromEntries(
Object.entries(process.env) Object.entries(process.env)

View File

@ -29,6 +29,8 @@ import { Input } from "../input";
import { isWindows } from "../../../common/vars"; import { isWindows } from "../../../common/vars";
import { FormSwitch, Switcher } from "../switch"; import { FormSwitch, Switcher } from "../switch";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { defaultBaseRegistryUrl } from "../+extensions";
import { Checkbox } from "../mui/checkbox";
const timezoneOptions: SelectOption<string>[] = moment.tz.names().map(zone => ({ const timezoneOptions: SelectOption<string>[] = moment.tz.names().map(zone => ({
label: zone, label: zone,
@ -43,8 +45,13 @@ export const Application = observer(() => {
? "powershell.exe" ? "powershell.exe"
: "System default shell" : "System default shell"
); );
const userStore = UserStore.getInstance();
const [shell, setShell] = React.useState(UserStore.getInstance().shell || ""); const [shell, setShell] = React.useState(userStore.shell || "");
const [extensionRegistryUrl, setExtensionRegistryUrl] = React.useState(
typeof userStore.extensionRegistryUrl === "string"
? userStore.extensionRegistryUrl
: ""
);
return ( return (
<section id="application"> <section id="application">
@ -53,8 +60,8 @@ export const Application = observer(() => {
<SubTitle title="Theme"/> <SubTitle title="Theme"/>
<Select <Select
options={ThemeStore.getInstance().themeOptions} options={ThemeStore.getInstance().themeOptions}
value={UserStore.getInstance().colorTheme} value={userStore.colorTheme}
onChange={({ value }: SelectOption) => UserStore.getInstance().colorTheme = value} onChange={({ value }: SelectOption) => userStore.colorTheme = value}
themeName="lens" themeName="lens"
/> />
</section> </section>
@ -68,8 +75,35 @@ export const Application = observer(() => {
placeholder={defaultShell} placeholder={defaultShell}
value={shell} value={shell}
onChange={v => setShell(v)} onChange={v => setShell(v)}
onBlur={() => UserStore.getInstance().shell = shell} onBlur={() => userStore.shell = shell}
/> />
</section><hr />
<section id="registry">
<SubTitle title="Extension registry" />
<FormSwitch
control={
<Checkbox
checked={userStore.getUseConfiguredExtensionRegistryUrl}
indeterminate={typeof userStore.extensionRegistryUrl === "string"}
onChange={(event, checked) => {
userStore.extensionRegistryUrl = checked;
setExtensionRegistryUrl("");
}}
/>
}
label="Use .npmrc configuration"
/>
<Input
theme="round-black"
placeholder={defaultBaseRegistryUrl}
value={extensionRegistryUrl}
onChange={setExtensionRegistryUrl}
onBlur={() => userStore.extensionRegistryUrl = extensionRegistryUrl}
/>
<small className="hint">
The registry URL for installing extensions by name.
</small>
</section> </section>
<hr/> <hr/>
@ -79,8 +113,8 @@ export const Application = observer(() => {
<FormSwitch <FormSwitch
control={ control={
<Switcher <Switcher
checked={UserStore.getInstance().openAtLogin} checked={userStore.openAtLogin}
onChange={v => UserStore.getInstance().openAtLogin = v.target.checked} onChange={v => userStore.openAtLogin = v.target.checked}
name="startup" name="startup"
/> />
} }
@ -94,8 +128,8 @@ export const Application = observer(() => {
<SubTitle title="Locale Timezone" /> <SubTitle title="Locale Timezone" />
<Select <Select
options={timezoneOptions} options={timezoneOptions}
value={UserStore.getInstance().localeTimezone} value={userStore.localeTimezone}
onChange={({ value }: SelectOption) => UserStore.getInstance().setLocaleTimezone(value)} onChange={({ value }: SelectOption) => userStore.setLocaleTimezone(value)}
themeName="lens" themeName="lens"
/> />
</section> </section>

View File

@ -0,0 +1,62 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { Checkbox as MuiCheckbox, CheckboxClassKey, CheckboxProps, createStyles, Theme, withStyles } from "@material-ui/core";
import React from "react";
interface Styles extends Partial<Record<CheckboxClassKey, string>> {
}
interface Props extends CheckboxProps {
classes: Styles;
}
export const Checkbox = withStyles((theme: Theme) =>
createStyles({
root: {
width: 40,
height: 24,
padding: 0,
margin: "0 0 0 8px",
},
colorPrimary: { },
colorSecondary: { },
checked: {},
disabled: {},
indeterminate: {},
input: {},
}),
)(({ classes, ...props }: Props) => {
return (
<MuiCheckbox
classes={{
root: classes.root,
colorPrimary: classes.colorPrimary,
colorSecondary: classes.colorSecondary,
checked: classes.checked,
disabled: classes.disabled,
indeterminate: classes.indeterminate,
input: classes.input,
}}
{...props}
/>
);
});

View File

@ -0,0 +1,22 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
export * from "./checkbox";