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

Using RemovableItem for items in Kubernetes page

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2021-08-12 16:27:48 +03:00
parent e4c393244a
commit 89b2c79fe2
7 changed files with 136 additions and 68 deletions

View File

@ -0,0 +1,33 @@
/**
* 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.
*/
.repos {
@apply mt-6 flex flex-col;
}
.repoName {
font-weight: 500;
margin-bottom: 8px;
}
.repoUrl {
color: var(--textColorDimmed);
}

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import "./helm-charts.scss";
import styles from "./helm-charts.module.css";
import React from "react";
import { action, computed, observable, makeObservable } from "mobx";
@ -31,6 +31,7 @@ import { Notifications } from "../notifications";
import { Select, SelectOption } from "../select";
import { AddHelmRepoDialog } from "./add-helm-repo-dialog";
import { observer } from "mobx-react";
import { RemovableItem } from "./removable-item";
@observer
export class HelmCharts extends React.Component {
@ -119,7 +120,7 @@ export class HelmCharts extends React.Component {
render() {
return (
<div className="HelmCharts">
<div>
<div className="flex gaps">
<Select id="HelmRepoSelect"
placeholder="Repositories"
@ -139,20 +140,15 @@ export class HelmCharts extends React.Component {
/>
</div>
<AddHelmRepoDialog onAddRepo={() => this.loadRepos()}/>
<div className="repos flex gaps column">
<div className={styles.repos}>
{Array.from(this.addedRepos).map(([name, repo]) => {
return (
<div key={name} className="repo flex gaps align-center justify-space-between">
<RemovableItem key={name} onRemove={() => this.removeRepo(repo)} className="mt-3">
<div>
<div className="repoName">{name}</div>
<div className="repoUrl">{repo.url}</div>
<div className={styles.repoName}>{name}</div>
<div className={styles.repoUrl}>{repo.url}</div>
</div>
<Icon
material="delete"
onClick={() => this.removeRepo(repo)}
tooltip="Remove"
/>
</div>
</RemovableItem>
);
})}
</div>

View File

@ -18,19 +18,19 @@
* 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 React from "react";
import { Avatar, IconButton, List, ListItem, ListItemAvatar, ListItemSecondaryAction, ListItemText, Paper } from "@material-ui/core";
import { Description, Folder, Delete, HelpOutline } from "@material-ui/icons";
import { action, computed, observable, reaction, makeObservable } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import fse from "fs-extra";
import { action, computed, makeObservable, observable, reaction } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import React from "react";
import { KubeconfigSyncEntry, KubeconfigSyncValue, UserStore } from "../../../common/user-store";
import { Spinner } from "../spinner";
import { isWindows } from "../../../common/vars";
import logger from "../../../main/logger";
import { iter, multiSet } from "../../utils";
import { isWindows } from "../../../common/vars";
import { SubTitle } from "../layout/sub-title";
import { PathPicker } from "../path-picker/path-picker";
import { Spinner } from "../spinner";
import { RemovableItem } from "./removable-item";
interface SyncInfo {
type: "file" | "folder" | "unknown";
@ -111,41 +111,29 @@ export class KubeconfigSyncs extends React.Component {
@action
onPick = async (filePaths: string[]) => multiSet(this.syncs, await getAllEntries(filePaths));
renderEntryIcon(entry: Entry) {
getIconName(entry: Entry) {
switch (entry.info.type) {
case "file":
return <Description />;
return "description";
case "folder":
return <Folder />;
return "folder";
case "unknown":
return <HelpOutline />;
return "help_outline";
}
}
renderEntry = (entry: Entry) => {
return (
<Paper className="entry" key={entry.filePath} elevation={3}>
<ListItem>
<ListItemAvatar>
<Avatar>
{this.renderEntryIcon(entry)}
</Avatar>
</ListItemAvatar>
<ListItemText
primary={entry.filePath}
className="description"
/>
<ListItemSecondaryAction className="action">
<IconButton
edge="end"
aria-label="delete"
onClick={() => this.syncs.delete(entry.filePath)}
>
<Delete />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
</Paper>
<RemovableItem
key={entry.filePath}
onRemove={() => this.syncs.delete(entry.filePath)}
className="mt-3"
icon={this.getIconName(entry)}
>
<div className="flex-grow break-all">
{entry.filePath}
</div>
</RemovableItem>
);
};
@ -161,26 +149,25 @@ export class KubeconfigSyncs extends React.Component {
}
return (
<List className="kubeconfig-sync-list">
<div>
{entries.map(this.renderEntry)}
</List>
</div>
);
}
renderSyncButtons() {
if (isWindows) {
return (
<div className="flex gaps align-center">
<div className="flex gaps align-center mb-5">
<PathPicker
label="Sync file(s)"
className="box grow"
onPick={this.onPick}
buttonLabel="Sync"
properties={["showHiddenFiles", "multiSelections", "openFile"]}
/>
<span>or</span>
<PathPicker
label="Sync folder(s)"
className="box grow"
onPick={this.onPick}
buttonLabel="Sync"
properties={["showHiddenFiles", "multiSelections", "openDirectory"]}
@ -190,12 +177,14 @@ export class KubeconfigSyncs extends React.Component {
}
return (
<PathPicker
label="Sync file(s) and folder(s)"
onPick={this.onPick}
buttonLabel="Sync"
properties={["showHiddenFiles", "multiSelections", "openFile", "openDirectory"]}
/>
<div className="self-start mb-5">
<PathPicker
label="Sync Files and Folders"
onPick={this.onPick}
buttonLabel="Sync"
properties={["showHiddenFiles", "multiSelections", "openFile", "openDirectory"]}
/>
</div>
);
}
@ -203,6 +192,7 @@ export class KubeconfigSyncs extends React.Component {
return (
<>
{this.renderSyncButtons()}
<SubTitle title="Synced Items" className="pt-5"/>
{this.renderEntries()}
</>
);

View File

@ -46,7 +46,7 @@ export const KubectlBinaries = observer(() => {
return (
<>
<section className="small">
<section>
<SubTitle title="Kubectl binary download"/>
<FormSwitch
control={
@ -60,9 +60,7 @@ export const KubectlBinaries = observer(() => {
/>
</section>
<hr className="small"/>
<section className="small">
<section>
<SubTitle title="Download mirror" />
<Select
placeholder="Download mirror for kubectl"
@ -74,9 +72,7 @@ export const KubectlBinaries = observer(() => {
/>
</section>
<hr className="small"/>
<section className="small">
<section>
<SubTitle title="Directory for binaries" />
<Input
theme="round-black"
@ -92,9 +88,7 @@ export const KubectlBinaries = observer(() => {
</div>
</section>
<hr className="small"/>
<section className="small">
<section>
<SubTitle title="Path to kubectl binary" />
<Input
theme="round-black"

View File

@ -0,0 +1,7 @@
.item {
--flex-gap: 1.2rem;
@apply rounded-md px-7 py-5 shadow-sm;
background: var(--inputControlBackground);
min-height: 65px;
}

View File

@ -0,0 +1,48 @@
/**
* 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 styles from "./removable-item.module.css";
import React, { DOMAttributes } from "react";
import { cssNames } from "../../utils";
import { Icon } from "../icon";
interface Props extends DOMAttributes<any>{
icon?: string;
onRemove: () => void;
className?: string;
}
export function RemovableItem({icon, onRemove, children, className, ...rest}: Props) {
return (
<div className={cssNames(styles.item, "flex gaps align-center justify-space-between", className)} {...rest}>
{icon && (
<Icon material={icon}/>
)}
{children}
<Icon
material="delete"
onClick={onRemove}
tooltip="Remove"
/>
</div>
);
}

View File

@ -228,7 +228,7 @@
margin-top: 0;
margin-bottom: 8px;
padding-bottom: 0;
font-size: 12px;
font-size: 13px;
line-height: 1;
}