mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
added workspace overview as details page (WIP)
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>
This commit is contained in:
parent
a0c19eb3c5
commit
f6058d73d1
@ -0,0 +1,2 @@
|
|||||||
|
.AddWorkspaceDialog {
|
||||||
|
}
|
||||||
84
src/renderer/components/+workspaces/add-workspace-dialog.tsx
Normal file
84
src/renderer/components/+workspaces/add-workspace-dialog.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import "./add-workspace-dialog.scss";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { observable } from "mobx";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Dialog, DialogProps } from "../dialog";
|
||||||
|
import { Wizard, WizardStep } from "../wizard";
|
||||||
|
//import { namespaceStore } from "./namespace.store";
|
||||||
|
import { Workspace, WorkspaceId } from "../../../common/workspace-store";
|
||||||
|
import { Input } from "../input";
|
||||||
|
import { systemName } from "../input/input_validators";
|
||||||
|
import { Notifications } from "../notifications";
|
||||||
|
|
||||||
|
interface Props extends DialogProps {
|
||||||
|
onSuccess?(ws: Workspace): void;
|
||||||
|
onError?(error: any): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class AddWorkspaceDialog extends React.Component<Props> {
|
||||||
|
@observable static isOpen = false;
|
||||||
|
@observable workspace = "";
|
||||||
|
|
||||||
|
static open() {
|
||||||
|
AddWorkspaceDialog.isOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static close() {
|
||||||
|
AddWorkspaceDialog.isOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset = () => {
|
||||||
|
this.workspace = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
close = () => {
|
||||||
|
AddWorkspaceDialog.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
addWorkspace = async () => {
|
||||||
|
const { workspace } = this;
|
||||||
|
const { onSuccess, onError } = this.props;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// await namespaceStore.create({ name: workspace }).then(onSuccess);
|
||||||
|
this.close();
|
||||||
|
} catch (err) {
|
||||||
|
Notifications.error(err);
|
||||||
|
onError && onError(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { ...dialogProps } = this.props;
|
||||||
|
const { workspace } = this;
|
||||||
|
const header = <h5>Create Workspace</h5>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
{...dialogProps}
|
||||||
|
className="AddWorkspaceDialog"
|
||||||
|
isOpen={AddWorkspaceDialog.isOpen}
|
||||||
|
onOpen={this.reset}
|
||||||
|
close={this.close}
|
||||||
|
>
|
||||||
|
<Wizard header={header} done={this.close}>
|
||||||
|
<WizardStep
|
||||||
|
contentClass="flex gaps column"
|
||||||
|
nextLabel="Create"
|
||||||
|
next={this.addWorkspace}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
required autoFocus
|
||||||
|
iconLeft="layers"
|
||||||
|
placeholder={`Workspace`}
|
||||||
|
validators={systemName}
|
||||||
|
value={workspace} onChange={v => this.workspace = v.toLowerCase()}
|
||||||
|
/>
|
||||||
|
</WizardStep>
|
||||||
|
</Wizard>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
export * from "./workspaces.route";
|
export * from "./workspaces.route";
|
||||||
|
export * from "./workspace-list.route";
|
||||||
export * from "./workspaces";
|
export * from "./workspaces";
|
||||||
export * from "./workspace-list";
|
export * from "./workspace-list";
|
||||||
|
|||||||
52
src/renderer/components/+workspaces/workspace-details.scss
Normal file
52
src/renderer/components/+workspaces/workspace-details.scss
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
.WorkspaceDetails {
|
||||||
|
.intro-logo {
|
||||||
|
margin-right: $margin * 2;
|
||||||
|
background: $helmLogoBackground;
|
||||||
|
border-radius: $radius;
|
||||||
|
max-width: 150px;
|
||||||
|
max-height: 100px;
|
||||||
|
padding: $padding;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-contents {
|
||||||
|
.description {
|
||||||
|
font-weight: bold;
|
||||||
|
color: $textColorAccent;
|
||||||
|
padding-bottom: $padding;
|
||||||
|
|
||||||
|
.Button {
|
||||||
|
padding-left: $padding * 3;
|
||||||
|
padding-right: $padding * 3;
|
||||||
|
margin-left: $margin * 2;
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
.Select {
|
||||||
|
min-width: 80px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Icon {
|
||||||
|
margin-right: $margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.maintainers {
|
||||||
|
a {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: $margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.DrawerItem {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-description {
|
||||||
|
margin-top: $margin * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/renderer/components/+workspaces/workspace-details.tsx
Normal file
62
src/renderer/components/+workspaces/workspace-details.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import "./workspace-details.scss";
|
||||||
|
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { WorkspaceItem } from "./workspace-list.store";
|
||||||
|
import { clusterStore } from "../../../common/cluster-store";
|
||||||
|
import { Cluster } from "../../../main/cluster";
|
||||||
|
import { observable, autorun } from "mobx";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Drawer, DrawerItem, DrawerTitle } from "../drawer";
|
||||||
|
import { autobind, stopPropagation } from "../../utils";
|
||||||
|
import { MarkdownViewer } from "../markdown-viewer";
|
||||||
|
import { Spinner } from "../spinner";
|
||||||
|
import { Button } from "../button";
|
||||||
|
import { Select, SelectOption } from "../select";
|
||||||
|
import { Badge } from "../badge";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
workspace: WorkspaceItem;
|
||||||
|
hideDetails(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class WorkspaceDetails extends Component<Props> {
|
||||||
|
|
||||||
|
renderClusters() {
|
||||||
|
const { workspace } = this.props;
|
||||||
|
const clusters = clusterStore.getByWorkspaceId(workspace.getId());
|
||||||
|
return <div>
|
||||||
|
{clusters.map(cluster => <div>{cluster.contextName}</div>)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { workspace, hideDetails } = this.props;
|
||||||
|
const title = workspace ? <>Workspace: {workspace.getName()}</> : "";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Drawer
|
||||||
|
className="WorkspaceDetails"
|
||||||
|
usePortal={true}
|
||||||
|
open={!!workspace}
|
||||||
|
title={title}
|
||||||
|
onClose={hideDetails}
|
||||||
|
>
|
||||||
|
<DrawerItem name={"Description"}>
|
||||||
|
{workspace.getDescription()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name={"Id"}>
|
||||||
|
{workspace.getId()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name={"Owner Ref"}>
|
||||||
|
{workspace.getOwnerRef()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name={"Enabled"} renderBoolean={true}>
|
||||||
|
{workspace.getEnabled()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerTitle title={"Clusters"}/>
|
||||||
|
{this.renderClusters()}
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/renderer/components/+workspaces/workspace-list.route.ts
Normal file
12
src/renderer/components/+workspaces/workspace-list.route.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import type { RouteProps } from "react-router";
|
||||||
|
import { buildURL } from "../../../common/utils/buildUrl";
|
||||||
|
|
||||||
|
export const workspaceListRoute: RouteProps = {
|
||||||
|
path: `/workspaces/:workspaceName?`
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IWorkspaceListRouteParams {
|
||||||
|
workspaceName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const workspaceListURL = buildURL<IWorkspaceListRouteParams>(workspaceListRoute.path);
|
||||||
@ -8,9 +8,21 @@ export class WorkspaceItem {
|
|||||||
return this.workspace.name;
|
return this.workspace.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDescription() {
|
||||||
|
return this.workspace.description;
|
||||||
|
}
|
||||||
|
|
||||||
getId() {
|
getId() {
|
||||||
return this.workspace.id;
|
return this.workspace.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getOwnerRef() {
|
||||||
|
return this.workspace.ownerRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEnabled() {
|
||||||
|
return this.workspace.enabled ? "True" : "False";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WorkspaceListStore extends ItemStore<WorkspaceItem> {
|
export class WorkspaceListStore extends ItemStore<WorkspaceItem> {
|
||||||
|
|||||||
@ -1,22 +1,55 @@
|
|||||||
import "./workspaces.scss";
|
import "./workspaces.scss";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { RouteComponentProps } from "react-router";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { navigation } from "../../navigation";
|
||||||
|
import { workspaceListURL, IWorkspaceListRouteParams } from "./workspace-list.route";
|
||||||
import { TabLayout } from "../layout/tab-layout";
|
import { TabLayout } from "../layout/tab-layout";
|
||||||
import { Badge } from "../badge";
|
import { Badge } from "../badge";
|
||||||
import { ItemListLayout, ItemListLayoutProps } from "../item-object-list/item-list-layout";
|
import { ItemListLayout, ItemListLayoutProps } from "../item-object-list/item-list-layout";
|
||||||
|
import { AddWorkspaceDialog } from "./add-workspace-dialog";
|
||||||
import { Workspace, WorkspaceId } from "../../../common/workspace-store";
|
import { Workspace, WorkspaceId } from "../../../common/workspace-store";
|
||||||
import { WorkspaceItem, workspaceListStore } from "./workspace-list.store";
|
import { WorkspaceItem, workspaceListStore } from "./workspace-list.store";
|
||||||
|
import { WorkspaceDetails } from "./workspace-details";
|
||||||
|
|
||||||
enum sortBy {
|
enum sortBy {
|
||||||
name = "name",
|
name = "name",
|
||||||
id = "id",
|
description = "description",
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WorkspaceList extends React.Component {
|
interface Props extends RouteComponentProps<IWorkspaceListRouteParams> {
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class WorkspaceList extends React.Component<Props> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
workspaceListStore.loadAll();
|
workspaceListStore.loadAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get selectedWorkspace() {
|
||||||
|
const { match: { params: { workspaceName } } } = this.props;
|
||||||
|
|
||||||
|
return workspaceListStore.getByName(workspaceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
showDetails = (workspace: WorkspaceItem) => {
|
||||||
|
if (!workspace) {
|
||||||
|
navigation.merge(workspaceListURL());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
navigation.merge(workspaceListURL({
|
||||||
|
params: {
|
||||||
|
workspaceName: workspace.getName(),
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
hideDetails = () => {
|
||||||
|
this.showDetails(null);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<TabLayout>
|
<TabLayout>
|
||||||
@ -25,19 +58,32 @@ export class WorkspaceList extends React.Component {
|
|||||||
className="Workspaces" store={workspaceListStore}
|
className="Workspaces" store={workspaceListStore}
|
||||||
sortingCallbacks={{
|
sortingCallbacks={{
|
||||||
[sortBy.name]: (ws: WorkspaceItem) => ws.getName(),
|
[sortBy.name]: (ws: WorkspaceItem) => ws.getName(),
|
||||||
[sortBy.id]: (ws: WorkspaceItem) => ws.getId(),
|
[sortBy.description]: (ws: WorkspaceItem) => ws.getDescription(),
|
||||||
}}
|
}}
|
||||||
searchFilters={[]}
|
searchFilters={[]}
|
||||||
renderHeaderTitle="Workspaces"
|
renderHeaderTitle="Workspaces"
|
||||||
renderTableHeader={[
|
renderTableHeader={[
|
||||||
{ title: "Name", className: "name", sortBy: sortBy.name },
|
{ title: "Name", className: "name", sortBy: sortBy.name },
|
||||||
{ title: "Id", className: "id", sortBy: sortBy.id },
|
{ title: "Description", className: "description", sortBy: sortBy.description },
|
||||||
]}
|
]}
|
||||||
renderTableContents={(item: WorkspaceItem) => [
|
renderTableContents={(item: WorkspaceItem) => [
|
||||||
item.getName(),
|
item.getName(),
|
||||||
item.getId(),
|
item.getDescription(),
|
||||||
]}
|
]}
|
||||||
|
addRemoveButtons={{
|
||||||
|
addTooltip: "Add Workspace",
|
||||||
|
onAdd: () => AddWorkspaceDialog.open(),
|
||||||
|
}}
|
||||||
|
detailsItem={this.selectedWorkspace}
|
||||||
|
onDetails={this.showDetails}
|
||||||
/>
|
/>
|
||||||
|
{this.selectedWorkspace && (
|
||||||
|
<WorkspaceDetails
|
||||||
|
workspace={this.selectedWorkspace}
|
||||||
|
hideDetails={this.hideDetails}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<AddWorkspaceDialog/>
|
||||||
</TabLayout>
|
</TabLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { ClustersMenu } from "./clusters-menu";
|
|||||||
import { BottomBar } from "./bottom-bar";
|
import { BottomBar } from "./bottom-bar";
|
||||||
import { LandingPage, landingRoute, landingURL } from "../+landing-page";
|
import { LandingPage, landingRoute, landingURL } from "../+landing-page";
|
||||||
import { Preferences, preferencesRoute } from "../+preferences";
|
import { Preferences, preferencesRoute } from "../+preferences";
|
||||||
import { WorkspaceList, workspacesRoute } from "../+workspaces";
|
import { WorkspaceList, workspaceListRoute } from "../+workspaces";
|
||||||
import { AddCluster, addClusterRoute } from "../+add-cluster";
|
import { AddCluster, addClusterRoute } from "../+add-cluster";
|
||||||
import { ClusterView } from "./cluster-view";
|
import { ClusterView } from "./cluster-view";
|
||||||
import { ClusterSettings, clusterSettingsRoute } from "../+cluster-settings";
|
import { ClusterSettings, clusterSettingsRoute } from "../+cluster-settings";
|
||||||
@ -67,7 +67,7 @@ export class ClusterManager extends React.Component {
|
|||||||
<Route component={LandingPage} {...landingRoute} />
|
<Route component={LandingPage} {...landingRoute} />
|
||||||
<Route component={Preferences} {...preferencesRoute} />
|
<Route component={Preferences} {...preferencesRoute} />
|
||||||
<Route component={Extensions} {...extensionsRoute} />
|
<Route component={Extensions} {...extensionsRoute} />
|
||||||
<Route component={WorkspaceList} {...workspacesRoute} />
|
<Route component={WorkspaceList} {...workspaceListRoute} />
|
||||||
<Route component={AddCluster} {...addClusterRoute} />
|
<Route component={AddCluster} {...addClusterRoute} />
|
||||||
<Route component={ClusterView} {...clusterViewRoute} />
|
<Route component={ClusterView} {...clusterViewRoute} />
|
||||||
<Route component={ClusterSettings} {...clusterSettingsRoute} />
|
<Route component={ClusterSettings} {...clusterSettingsRoute} />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user