mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Extension support page (#1112)
Signed-off-by: Roman <ixrock@gmail.com> Co-authored-by: Jim Ehrismann <40840436+jim-docker@users.noreply.github.com>
This commit is contained in:
1 parent
ce995f3deb
commit
f3a0059355
67 files changed
+4511
-553
No files matched your search
@@ -0,0 +1,64 @@
|
||||
.PageLayout {
|
||||
$spacing: $padding * 2;
|
||||
|
||||
position: relative;
|
||||
height: 100%;
|
||||
display: grid !important;
|
||||
grid-template-rows: min-content 1fr;
|
||||
|
||||
// covers whole app view area
|
||||
&.top {
|
||||
position: fixed !important; // allow to cover ClustersMenu
|
||||
z-index: 1;
|
||||
|
||||
// adds extra space for traffic-light top buttons (mac only)
|
||||
.is-mac & > .header {
|
||||
padding-top: $spacing * 2;
|
||||
}
|
||||
}
|
||||
|
||||
> .header {
|
||||
position: sticky;
|
||||
padding: $spacing;
|
||||
background-color: $layoutTabsBackground;
|
||||
}
|
||||
|
||||
> .content-wrapper {
|
||||
@include custom-scrollbar-themed;
|
||||
padding: $spacing * 2;
|
||||
|
||||
> .content {
|
||||
margin: 0 auto;
|
||||
width: 60%;
|
||||
min-width: 570px;
|
||||
max-width: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
h2:not(:first-of-type) {
|
||||
margin-top: $spacing;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $colorInfo;
|
||||
}
|
||||
|
||||
.SubTitle {
|
||||
text-transform: none;
|
||||
margin-bottom: 0 !important;
|
||||
|
||||
+ * + .hint {
|
||||
margin-top: -$padding / 2;
|
||||
}
|
||||
}
|
||||
|
||||
.Select {
|
||||
&__control {
|
||||
box-shadow: 0 0 0 1px $borderFaintColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import "./page-layout.scss"
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { autobind, cssNames, IClassName } from "../../utils";
|
||||
import { Icon } from "../icon";
|
||||
import { navigation } from "../../navigation";
|
||||
|
||||
export interface PageLayoutProps extends React.DOMAttributes<any> {
|
||||
className?: IClassName;
|
||||
header: React.ReactNode;
|
||||
headerClass?: IClassName;
|
||||
contentClass?: IClassName;
|
||||
provideBackButtonNavigation?: boolean;
|
||||
contentGaps?: boolean;
|
||||
showOnTop?: boolean; // covers whole app view
|
||||
back?: (evt: React.MouseEvent | KeyboardEvent) => void;
|
||||
}
|
||||
|
||||
const defaultProps: Partial<PageLayoutProps> = {
|
||||
provideBackButtonNavigation: true,
|
||||
contentGaps: true,
|
||||
}
|
||||
|
||||
@observer
|
||||
export class PageLayout extends React.Component<PageLayoutProps> {
|
||||
static defaultProps = defaultProps as object;
|
||||
|
||||
@autobind()
|
||||
back(evt?: React.MouseEvent | KeyboardEvent) {
|
||||
if (this.props.back) {
|
||||
this.props.back(evt);
|
||||
} else {
|
||||
navigation.goBack();
|
||||
}
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
window.addEventListener('keydown', this.onEscapeKey);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.onEscapeKey);
|
||||
}
|
||||
|
||||
onEscapeKey = (evt: KeyboardEvent) => {
|
||||
if (!this.props.provideBackButtonNavigation) {
|
||||
return;
|
||||
}
|
||||
if (evt.code === "Escape") {
|
||||
evt.stopPropagation();
|
||||
this.back(evt);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
contentClass, header, headerClass, provideBackButtonNavigation,
|
||||
contentGaps, showOnTop, children, ...elemProps
|
||||
} = this.props;
|
||||
const className = cssNames("PageLayout", { top: showOnTop }, this.props.className);
|
||||
return (
|
||||
<div {...elemProps} className={className}>
|
||||
<div className={cssNames("header flex gaps align-center", headerClass)}>
|
||||
{header}
|
||||
{provideBackButtonNavigation && (
|
||||
<Icon
|
||||
big material="close"
|
||||
className="back box right"
|
||||
onClick={this.back}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="content-wrapper">
|
||||
<div className={cssNames("content", contentGaps && "flex column gaps", contentClass)}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import { CrdList, crdResourcesRoute, crdRoute, crdURL } from "../+custom-resourc
|
||||
import { CustomResources } from "../+custom-resources/custom-resources";
|
||||
import { navigation } from "../../navigation";
|
||||
import { isAllowedResource } from "../../../common/rbac"
|
||||
import { pageRegistry } from "../../../extensions/page-registry";
|
||||
import { pageRegistry } from "../../../extensions/registries/page-registry";
|
||||
|
||||
const SidebarContext = React.createContext<SidebarContextValue>({ pinned: false });
|
||||
type SidebarContextValue = {
|
||||
@@ -80,7 +80,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
<div className={cssNames("Sidebar flex column", className, { pinned: isPinned })}>
|
||||
<div className="header flex align-center">
|
||||
<NavLink exact to="/" className="box grow">
|
||||
<Icon svg="logo-full" className="logo-icon" />
|
||||
<Icon svg="logo-full" className="logo-icon"/>
|
||||
<div className="logo-text">Lens</div>
|
||||
</NavLink>
|
||||
<Icon
|
||||
@@ -97,14 +97,14 @@ export class Sidebar extends React.Component<Props> {
|
||||
isHidden={!isAllowedResource("nodes")}
|
||||
url={clusterURL()}
|
||||
text={<Trans>Cluster</Trans>}
|
||||
icon={<Icon svg="kube" />}
|
||||
icon={<Icon svg="kube"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="nodes"
|
||||
isHidden={!isAllowedResource("nodes")}
|
||||
url={nodesURL()}
|
||||
text={<Trans>Nodes</Trans>}
|
||||
icon={<Icon svg="nodes" />}
|
||||
icon={<Icon svg="nodes"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="workloads"
|
||||
@@ -113,7 +113,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={workloadsRoute.path}
|
||||
subMenus={Workloads.tabRoutes}
|
||||
text={<Trans>Workloads</Trans>}
|
||||
icon={<Icon svg="workloads" />}
|
||||
icon={<Icon svg="workloads"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="config"
|
||||
@@ -122,7 +122,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={configRoute.path}
|
||||
subMenus={Config.tabRoutes}
|
||||
text={<Trans>Configuration</Trans>}
|
||||
icon={<Icon material="list" />}
|
||||
icon={<Icon material="list"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="networks"
|
||||
@@ -131,7 +131,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={networkRoute.path}
|
||||
subMenus={Network.tabRoutes}
|
||||
text={<Trans>Network</Trans>}
|
||||
icon={<Icon material="device_hub" />}
|
||||
icon={<Icon material="device_hub"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="storage"
|
||||
@@ -139,14 +139,14 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={storageURL({ query })}
|
||||
routePath={storageRoute.path}
|
||||
subMenus={Storage.tabRoutes}
|
||||
icon={<Icon svg="storage" />}
|
||||
icon={<Icon svg="storage"/>}
|
||||
text={<Trans>Storage</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="namespaces"
|
||||
isHidden={!isAllowedResource("namespaces")}
|
||||
url={namespacesURL()}
|
||||
icon={<Icon material="layers" />}
|
||||
icon={<Icon material="layers"/>}
|
||||
text={<Trans>Namespaces</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@@ -154,7 +154,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
isHidden={!isAllowedResource("events")}
|
||||
url={eventsURL({ query })}
|
||||
routePath={eventRoute.path}
|
||||
icon={<Icon material="access_time" />}
|
||||
icon={<Icon material="access_time"/>}
|
||||
text={<Trans>Events</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@@ -162,7 +162,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={appsURL({ query })}
|
||||
subMenus={Apps.tabRoutes}
|
||||
routePath={appsRoute.path}
|
||||
icon={<Icon material="apps" />}
|
||||
icon={<Icon material="apps"/>}
|
||||
text={<Trans>Apps</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@@ -170,7 +170,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={usersManagementURL({ query })}
|
||||
routePath={usersManagementRoute.path}
|
||||
subMenus={UserManagement.tabRoutes}
|
||||
icon={<Icon material="security" />}
|
||||
icon={<Icon material="security"/>}
|
||||
text={<Trans>Access Control</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@@ -179,17 +179,17 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={crdURL()}
|
||||
subMenus={CustomResources.tabRoutes}
|
||||
routePath={crdRoute.path}
|
||||
icon={<Icon material="extension" />}
|
||||
icon={<Icon material="extension"/>}
|
||||
text={<Trans>Custom Resources</Trans>}
|
||||
>
|
||||
{this.renderCustomResources()}
|
||||
</SidebarNavItem>
|
||||
{pageRegistry.clusterPages.map(({ path, title, components: { MenuIcon } }) => {
|
||||
{pageRegistry.clusterPages.map(({ path, title, url = String(path), components: { MenuIcon } }) => {
|
||||
if (!MenuIcon) return;
|
||||
return (
|
||||
<SidebarNavItem
|
||||
key={path}
|
||||
id={`extension-${path}`}
|
||||
url={path}
|
||||
key={url} id={`sidebar_item_${url}`}
|
||||
url={url}
|
||||
routePath={path}
|
||||
text={title}
|
||||
icon={<MenuIcon/>}
|
||||
@@ -255,7 +255,7 @@ class SidebarNavItem extends React.Component<SidebarNavItemProps> {
|
||||
<div className={cssNames("nav-item", { active: isActive })} onClick={this.toggleSubMenu}>
|
||||
{icon}
|
||||
<span className="link-text">{text}</span>
|
||||
<Icon className="expand-icon" material={this.isExpanded ? "keyboard_arrow_up" : "keyboard_arrow_down"} />
|
||||
<Icon className="expand-icon" material={this.isExpanded ? "keyboard_arrow_up" : "keyboard_arrow_down"}/>
|
||||
</div>
|
||||
<ul className={cssNames("sub-menu", { active: isActive })}>
|
||||
{subMenus.map(({ title, url }) => (
|
||||
|
||||
@@ -8,13 +8,9 @@
|
||||
grid-template-columns: 1fr 40%;
|
||||
|
||||
> * {
|
||||
@include custom-scrollbar;
|
||||
@include custom-scrollbar-themed;
|
||||
--flex-gap: #{$spacing};
|
||||
padding: $spacing;
|
||||
|
||||
.theme-light & {
|
||||
@include custom-scrollbar(dark);
|
||||
}
|
||||
}
|
||||
|
||||
> .head-col {
|
||||
|
||||
Reference in new issue
Block a user