mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
1 parent
c70ed87da9
commit
117ad584d3
10 files changed
+363
-470
No files matched your search
@@ -1,3 +1,14 @@
|
||||
.Workspaces {
|
||||
.workspace {
|
||||
--flex-gap: #{$padding};
|
||||
padding: $padding / 2;
|
||||
|
||||
&.default {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
> .description {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,173 @@
|
||||
import "./workspaces.scss"
|
||||
import React, { Fragment } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { computed, observable, toJS } from "mobx";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import { WizardLayout } from "../layout/wizard-layout";
|
||||
import { workspaceStore } from "../../../common/workspace-store";
|
||||
import { Workspace, WorkspaceId, workspaceStore } from "../../../common/workspace-store";
|
||||
import { v4 as uuid } from "uuid"
|
||||
import { _i18n } from "../../i18n";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { Icon } from "../icon";
|
||||
import { Input } from "../input";
|
||||
import { cssNames, prevDefault } from "../../utils";
|
||||
import { Button } from "../button";
|
||||
|
||||
@observer
|
||||
export class Workspaces extends React.Component {
|
||||
@observable editingWorkspaces = observable.map<WorkspaceId, Workspace>();
|
||||
|
||||
@computed get workspaces(): Workspace[] {
|
||||
const allWorkspaces = new Map([
|
||||
...workspaceStore.workspaces,
|
||||
...this.editingWorkspaces,
|
||||
]);
|
||||
return Array.from(allWorkspaces.values());
|
||||
}
|
||||
|
||||
renderInfo() {
|
||||
return (
|
||||
<Fragment>
|
||||
<h2><Trans>What is a Workspace?</Trans></h2>
|
||||
<p><Trans>Workspaces are used to organize number of clusters into logical groups.</Trans></p>
|
||||
<p><Trans>A single workspaces contains a list of clusters and their full configuration.</Trans></p>
|
||||
<p className="info">
|
||||
<Trans>Workspaces are used to organize number of clusters into logical groups.</Trans>
|
||||
</p>
|
||||
<p>
|
||||
<Trans>A single workspaces contains a list of clusters and their full configuration.</Trans>
|
||||
</p>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
saveWorkspace = (id: WorkspaceId) => {
|
||||
const draft = toJS(this.editingWorkspaces.get(id));
|
||||
if (draft) {
|
||||
this.clearEditing(id);
|
||||
workspaceStore.saveWorkspace(draft);
|
||||
}
|
||||
}
|
||||
|
||||
addWorkspace = () => {
|
||||
console.log('add workspace')
|
||||
const workspaceId = uuid();
|
||||
this.editingWorkspaces.set(workspaceId, {
|
||||
id: workspaceId,
|
||||
name: _i18n._(t`My Workspace`),
|
||||
description: "",
|
||||
})
|
||||
}
|
||||
|
||||
editWorkspace = (id: WorkspaceId) => {
|
||||
const workspace = workspaceStore.getById(id);
|
||||
this.editingWorkspaces.set(id, toJS(workspace));
|
||||
}
|
||||
|
||||
clearEditing = (id: WorkspaceId) => {
|
||||
this.editingWorkspaces.delete(id);
|
||||
}
|
||||
|
||||
removeWorkspace = (id: WorkspaceId) => {
|
||||
const workspace = workspaceStore.getById(id);
|
||||
ConfirmDialog.open({
|
||||
okButtonProps: {
|
||||
label: _i18n._(t`Remove Workspace`),
|
||||
primary: false,
|
||||
accent: true,
|
||||
},
|
||||
ok: () => {
|
||||
this.clearEditing(id);
|
||||
workspaceStore.removeWorkspace(id);
|
||||
},
|
||||
message: (
|
||||
<div className="confirm flex column gaps">
|
||||
<p>
|
||||
<Trans>Are you sure you want remove workspace <b>{workspace.name}</b>?</Trans>
|
||||
</p>
|
||||
<p className="info">
|
||||
<Trans>All clusters within workspace will be cleared as well</Trans>
|
||||
</p>
|
||||
</div>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { workspacesList, currentWorkspace } = workspaceStore;
|
||||
return (
|
||||
<WizardLayout className="Workspaces" infoPanel={this.renderInfo()}>
|
||||
<h2>
|
||||
<Trans>Workspaces</Trans>
|
||||
</h2>
|
||||
<div className="workspaces">
|
||||
{workspacesList.map(({ id: workspaceId, name, description }) => {
|
||||
<div className="items flex column gaps">
|
||||
{this.workspaces.map(({ id: workspaceId, name, description }) => {
|
||||
const isActive = workspaceStore.currentWorkspaceId === workspaceId;
|
||||
const isDefault = workspaceStore.isDefault(workspaceId);
|
||||
const isEditing = this.editingWorkspaces.has(workspaceId);
|
||||
const editingWorkspace = this.editingWorkspaces.get(workspaceId);
|
||||
const className = cssNames("workspace flex gaps align-center", {
|
||||
active: isActive,
|
||||
editing: isEditing,
|
||||
default: isDefault,
|
||||
});
|
||||
return (
|
||||
<div key={workspaceId} className="workspace flex gaps">
|
||||
<span className="name">{name}</span>
|
||||
<span className="description">{description}</span>
|
||||
<div key={workspaceId} className={className}>
|
||||
{!isEditing && (
|
||||
<Fragment>
|
||||
<span className="name flex gaps align-center">
|
||||
<a href="#" onClick={prevDefault(() => workspaceStore.setActive(workspaceId))}>{name}</a>
|
||||
{isActive && <span> <Trans>(current)</Trans></span>}
|
||||
</span>
|
||||
<span className="description">{description}</span>
|
||||
{!isDefault && (
|
||||
<Fragment>
|
||||
<Icon
|
||||
material="edit"
|
||||
tooltip={<Trans>Edit</Trans>}
|
||||
onClick={() => this.editWorkspace(workspaceId)}
|
||||
/>
|
||||
<Icon
|
||||
material="delete"
|
||||
tooltip={<Trans>Delete</Trans>}
|
||||
onClick={() => this.removeWorkspace(workspaceId)}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
{isEditing && (
|
||||
<Fragment>
|
||||
<Input
|
||||
className="name"
|
||||
placeholder={_i18n._(t`Name`)}
|
||||
value={editingWorkspace.name}
|
||||
onChange={v => editingWorkspace.name = v}
|
||||
/>
|
||||
<Input
|
||||
className="description"
|
||||
placeholder={_i18n._(t`Description`)}
|
||||
value={editingWorkspace.description}
|
||||
onChange={v => editingWorkspace.description = v}
|
||||
/>
|
||||
<Icon
|
||||
material="cancel"
|
||||
tooltip={<Trans>Cancel</Trans>}
|
||||
onClick={() => this.clearEditing(workspaceId)}
|
||||
/>
|
||||
<Icon
|
||||
material="save"
|
||||
tooltip={<Trans>Save</Trans>}
|
||||
onClick={() => this.saveWorkspace(workspaceId)}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<Button
|
||||
primary
|
||||
className="box left"
|
||||
label={<Trans>Add Workspace</Trans>}
|
||||
onClick={this.addWorkspace}
|
||||
/>
|
||||
</WizardLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { cssNames, noop, prevDefault } from "../../utils";
|
||||
import { Button } from "../button";
|
||||
import { Button, ButtonProps } from "../button";
|
||||
import { Dialog, DialogProps } from "../dialog";
|
||||
import { Icon } from "../icon";
|
||||
|
||||
@@ -14,7 +14,9 @@ export interface IConfirmDialogParams {
|
||||
labelOk?: ReactNode;
|
||||
labelCancel?: ReactNode;
|
||||
message?: ReactNode;
|
||||
icon?: string;
|
||||
icon?: ReactNode;
|
||||
okButtonProps?: Partial<ButtonProps>
|
||||
cancelButtonProps?: Partial<ButtonProps>
|
||||
}
|
||||
|
||||
interface Props extends Partial<DialogProps> {
|
||||
@@ -40,7 +42,7 @@ export class ConfirmDialog extends React.Component<Props> {
|
||||
ok: noop,
|
||||
labelOk: <Trans>Ok</Trans>,
|
||||
labelCancel: <Trans>Cancel</Trans>,
|
||||
icon: "warning",
|
||||
icon: <Icon big material="warning"/>,
|
||||
};
|
||||
|
||||
get params(): IConfirmDialogParams {
|
||||
@@ -67,18 +69,21 @@ export class ConfirmDialog extends React.Component<Props> {
|
||||
|
||||
render() {
|
||||
const { className, ...dialogProps } = this.props;
|
||||
const { icon, labelOk, labelCancel, message } = this.params;
|
||||
const {
|
||||
icon, labelOk, labelCancel, message,
|
||||
okButtonProps = {},
|
||||
cancelButtonProps = {},
|
||||
} = this.params;
|
||||
return (
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className={cssNames("ConfirmDialog", className, icon)}
|
||||
className={cssNames("ConfirmDialog", className)}
|
||||
isOpen={ConfirmDialog.isOpen}
|
||||
onClose={this.onClose}
|
||||
close={this.close}
|
||||
>
|
||||
<div className="confirm-content">
|
||||
<Icon big material={icon}/>
|
||||
{message}
|
||||
{icon} {message}
|
||||
</div>
|
||||
<div className="confirm-buttons">
|
||||
<Button
|
||||
@@ -86,6 +91,7 @@ export class ConfirmDialog extends React.Component<Props> {
|
||||
className="cancel"
|
||||
label={labelCancel}
|
||||
onClick={prevDefault(this.close)}
|
||||
{...cancelButtonProps}
|
||||
/>
|
||||
<Button
|
||||
autoFocus primary
|
||||
@@ -93,6 +99,7 @@ export class ConfirmDialog extends React.Component<Props> {
|
||||
label={labelOk}
|
||||
onClick={prevDefault(this.ok)}
|
||||
waiting={this.isSaving}
|
||||
{...okButtonProps}
|
||||
/>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
Reference in new issue
Block a user