Merge pull request #118 from tianni4104/typescript

extra components into ts
This commit is contained in:
Eric Herbrandson
2020-08-10 10:53:30 -05:00
committed by GitHub
10 changed files with 130 additions and 65 deletions
@@ -1,8 +1,9 @@
import _ from 'lodash';
import React, {Fragment} from 'react';
import Field from './field';
import {TODO} from "../utils/types";
const ContainersPanel = ({spec}) => (
const ContainersPanel = ({spec}: {spec: TODO}) => (
<>
{spec && _.map(spec.containers, item => (
<Fragment key={item.name}>
@@ -18,7 +19,7 @@ const ContainersPanel = ({spec}) => (
{item.env && (
<Field name='Env'>
{item.env.map(x => (
{item.env.map((x: TODO) => (
<div key={x.name}>
{x.name}: {getVariableValue(x)}
</div>
@@ -42,7 +43,7 @@ const ContainersPanel = ({spec}) => (
{item.ports && (
<Field name='Ports'>
{item.ports.map((x, i) => (
{item.ports.map((x: TODO, i: number) => (
<div key={i}>
{[x.name, x.containerPort, x.hostPort, x.protocol].filter(y => !!y).join(' • ')}
</div>
@@ -55,7 +56,7 @@ const ContainersPanel = ({spec}) => (
</>
);
function getVariableValue(item) {
function getVariableValue(item: TODO) {
if (item.value) return item.value;
if (!item.valueFrom) return null;
if (item.valueFrom.secretKeyRef) return item.valueFrom.secretKeyRef.key;
+3 -3
View File
@@ -63,9 +63,9 @@ export default class Donut extends Base<Props, State> {
return (
<svg className='donut' xmlns='http://www.w3.org/2000/svg' viewBox="0 0 42 42" width='100%' height='100%'>
<circle className='donut_background' cx='21' cy='21' r='16'></circle>
<circle className='donut_layer1' cx='21' cy='21' r='16' strokeDasharray={`${percent} ${100 - percent}`} strokeDashoffset="25"></circle>
<circle className='donut_layer2' cx='21' cy='21' r='16' strokeDasharray={`${percent2} ${100 - percent2}`} strokeDashoffset={25 + (100 - percent)}></circle>
<circle className='donut_background' cx='21' cy='21' r='16' />
<circle className='donut_layer1' cx='21' cy='21' r='16' strokeDasharray={`${percent} ${100 - percent}`} strokeDashoffset="25" />
<circle className='donut_layer2' cx='21' cy='21' r='16' strokeDasharray={`${percent2} ${100 - percent2}`} strokeDashoffset={25 + (100 - percent)} />
</svg>
);
}
@@ -7,9 +7,27 @@ import api from '../services/api';
import {addHandler} from '../services/auth';
import ResourceSvg from '../art/resourceSvg';
import AddSvg from '../art/addSvg';
import {TODO} from "../utils/types";
interface MenuProps {
onClick: TODO;
toggled: boolean;
}
export default class Menu extends Base {
interface MenuStates {
rules: TODO[];
showAdd: boolean;
}
interface MenuItemProps {
path: string;
title: string;
resource: string;
onClick: TODO;
additionalPaths?: string[];
}
export default class Menu extends Base<MenuProps, MenuStates> {
componentDidMount() {
this.getRules();
@@ -29,7 +47,7 @@ export default class Menu extends Base {
return (
<>
<div className={toggled ? 'menu_background menu_backgroundToggled' : 'menu_background'} onClick={onClick}></div>
<div className={toggled ? 'menu_background menu_backgroundToggled' : 'menu_background'} onClick={onClick} />
<div id='menu' className={toggled ? 'menu_toggled' : undefined}>
@@ -122,7 +140,7 @@ export default class Menu extends Base {
{showAdd && (
<EditorModal
onSave={x => api.apply(x)}
onSave={(x: TODO) => api.apply(x)}
onRequestClose={() => this.setState({showAdd: false})}
/>
)}
@@ -133,13 +151,13 @@ export default class Menu extends Base {
}
}
function canView(resourcesRules, ...args) {
function canView(resourcesRules: TODO[], ...args: TODO) {
if (!resourcesRules) return false;
return args.some(x => canViewResource(resourcesRules, x.resource));
return args.some((x: TODO) => canViewResource(resourcesRules, x.resource));
}
function canViewResource(resourcesRules, {group, resource}) {
function canViewResource(resourcesRules: TODO[], {group, resource}: {group: TODO, resource: string}) {
return resourcesRules.some((x) => {
const hasVerb = (x.verbs.includes('list') || x.verbs.includes('*'));
const hasGroup = (x.apiGroups.includes(group) || x.apiGroups.includes('*'));
@@ -148,7 +166,7 @@ function canViewResource(resourcesRules, {group, resource}) {
});
}
function MenuItem(props) {
function MenuItem(props: MenuItemProps) {
const currentPath = getRootPath();
const paths = getPaths(props);
const className = paths.includes(currentPath) ? 'menu_item menu_itemSelected' : 'menu_item';
@@ -162,16 +180,16 @@ function MenuItem(props) {
);
}
function Group({children = []}) {
function Group({children = []}: TODO) {
if (!Array.isArray(children)) children = [children]; // eslint-disable-line no-param-reassign
children = children.filter(Boolean); // eslint-disable-line no-param-reassign
if (children.length === 0) return null;
const paths = children.flatMap(x => getPaths(x.props));
const paths = children.flatMap((x: TODO) => getPaths(x.props));
const currentPath = getRootPath();
const isSelected = paths.some(x => x === currentPath);
const isSelected = paths.some((x: TODO) => x === currentPath);
return (
<div className='menu_group'>
@@ -186,6 +204,6 @@ function Group({children = []}) {
);
}
function getPaths({path, additionalPaths = []}) {
function getPaths({path, additionalPaths = []}: MenuItemProps) {
return [path, ...additionalPaths];
}
@@ -2,8 +2,9 @@ import _ from 'lodash';
import React from 'react';
import Chart from './chart';
import LoadingChart from './loadingChart';
import {TODO, Node} from "../utils/types";
export default function NodeStatusChart({items}) {
export default function NodeStatusChart({items}: {items: Node[]}) {
const readyCount = _.sumBy(items, x => getReadyStatus(x) === 'True' ? 1 : 0); // eslint-disable-line no-confusing-arrow
return (
@@ -19,9 +20,9 @@ export default function NodeStatusChart({items}) {
);
}
function getReadyStatus({status}) {
function getReadyStatus({status}: {status?: TODO}) {
if (!status.conditions) return null;
const ready = status.conditions.find(y => y.type === 'Ready');
const ready = status.conditions.find((y: TODO) => y.type === 'Ready');
return ready && ready.status;
}
@@ -7,18 +7,38 @@ import {MetadataHeaders, MetadataColumns, TableBody, objectMap} from './listView
import {unparseCpu, unparseRam} from '../utils/unitHelpers';
import {getNodeResourceValue, getNodeResourcePercent, getNodeUsagePercent, getNodeUsage, getNodeResourcesAvailable} from '../utils/metricsHelpers';
import getReadyStatus from '../utils/nodeHelpers';
import {TODO} from "../utils/types";
export default class NodesPanel extends Base {
constructor(props) {
interface NodesPanelProps {
metrics: TODO;
pods: TODO[];
items: TODO[];
sort: TODO;
filter: TODO;
}
interface NodesPanelStates {
show: {}
}
export default class NodesPanel extends Base<NodesPanelProps, NodesPanelStates> {
private sortByCpuUsage: TODO;
private sortByCpuRequest: TODO;
private sortByCpuLimit: TODO;
private sortByRamUsage: TODO;
private sortByRamRequest: TODO;
private sortByRamLimit: TODO;
constructor(props: TODO) {
super(props);
this.sortByCpuUsage = x => getNodeUsagePercent(x, this.props.metrics, 'cpu');
this.sortByCpuRequest = x => getNodeResourcePercent(x, this.props.pods, 'cpu', 'requests');
this.sortByCpuLimit = x => getNodeResourcePercent(x, this.props.pods, 'cpu', 'limits');
this.sortByCpuUsage = (x: TODO) => getNodeUsagePercent(x, this.props.metrics, 'cpu');
this.sortByCpuRequest = (x: TODO) => getNodeResourcePercent(x, this.props.pods, 'cpu', 'requests');
this.sortByCpuLimit = (x: TODO) => getNodeResourcePercent(x, this.props.pods, 'cpu', 'limits');
this.sortByRamUsage = x => getNodeUsagePercent(x, this.props.metrics, 'memory');
this.sortByRamRequest = x => getNodeResourcePercent(x, this.props.pods, 'memory', 'requests');
this.sortByRamLimit = x => getNodeResourcePercent(x, this.props.pods, 'memory', 'limits');
this.sortByRamUsage = (x: TODO) => getNodeUsagePercent(x, this.props.metrics, 'memory');
this.sortByRamRequest = (x: TODO) => getNodeResourcePercent(x, this.props.pods, 'memory', 'requests');
this.sortByRamLimit = (x: TODO) => getNodeResourcePercent(x, this.props.pods, 'memory', 'limits');
}
render() {
@@ -73,7 +93,7 @@ export default class NodesPanel extends Base {
</tr>
</thead>
<TableBody items={items} filter={filter} sort={sort} colSpan='11' row={x => (
<TableBody items={items} filter={filter} sort={sort} colSpan={11} row={(x: TODO) => (
<tr key={x.metadata.uid}>
<MetadataColumns item={x} href={`#!node/${x.metadata.name}`} />
<td className='smallText optional_medium'>{objectMap(x.metadata.labels)}</td>
@@ -94,39 +114,39 @@ export default class NodesPanel extends Base {
/** Simple mapping between ready statuses and an UTF-8 symbol character */
const statusesToUtf8 = {True: '\u2713', False: '\uD83D\uDEC7', Unknown: '\u003F'};
const statusesToUtf8: {[key: string]: string} = {True: '\u2713', False: '\uD83D\uDEC7', Unknown: '\u003F'};
/**
*
* @param {*statusTxt a status text (as returned by getReadyStatus for example) }
* @param statusTxt {*statusTxt a status text (as returned by getReadyStatus for example) }
* @returns a dedicated span element with an UTF-8 symbol representing the status
*/
function statusSymbol(statusTxt) {
function statusSymbol(statusTxt: string) {
const cssClass = `node-ready-status-${statusTxt}`;
const utf8Symbol = statusesToUtf8[statusTxt] || statusesToUtf8.Unknown;
return <span className={cssClass} title={statusTxt}>{utf8Symbol}</span>;
}
function getPercentDisplay(node, metrics, resource) {
function getPercentDisplay(node: TODO, metrics: TODO, resource: string) {
const used = getNodeUsage(node, metrics, resource);
return percent(node, used, resource);
}
function getResourcePercentDisplay(node, pods, resource, type) {
function getResourcePercentDisplay(node: TODO, pods: TODO[], resource: string, type: TODO) {
const used = getNodeResourceValue(node, pods, resource, type, ['Running']);
return percent(node, used, resource);
}
function percent(node, used, resource) {
function percent(node: TODO, used: number | string | null, resource: string) {
if (used == null) return <LoadingEllipsis />;
if (!used) return <span className='smallText'>-</span>;
const unparser = resource === 'cpu' ? unparseCpu : unparseRam;
const unparser: TODO = resource === 'cpu' ? unparseCpu : unparseRam;
const result = unparser(used);
const available = getNodeResourcesAvailable(node, resource);
const displayPercent = _.round(used / available * 100, 1);
const displayPercent = available? _.round(Number(used) / available * 100, 1): "";
const className = displayPercent >= 85 ? 'contentPanel_warn' : undefined;
return (
@@ -2,14 +2,15 @@ import _ from 'lodash';
import React from 'react';
import Chart from './chart';
import LoadingChart from './loadingChart';
import {Pod} from "../utils/types";
export default function PodStatusChart({items}) {
export default function PodStatusChart({items}: {items?: Pod[]}) {
const available = items && items.length;
const count = _.sumBy(items, x => x.status.phase === 'Running' ? 1 : 0); // eslint-disable-line no-confusing-arrow
return (
<div className='charts_item'>
{items ? (
{items && available ? (
<Chart used={count} pending={available - count} available={available} />
) : (
<LoadingChart />
@@ -6,23 +6,43 @@ import LoadingEllipsis from './loadingEllipsis';
import {MetadataHeaders, MetadataColumns, TableBody} from './listViewHelpers';
import {unparseRam, unparseCpu} from '../utils/unitHelpers';
import {getPodResourcePercent, getPodUsage, getPodResourceValue} from '../utils/metricsHelpers';
import {Pod, TODO} from "../utils/types";
export default class PodsPanel extends Base {
constructor(props) {
interface PodsPanelProps {
metrics: TODO;
pods?: TODO[];
items?: Pod[];
sort?: TODO;
filter?: TODO;
skipNamespace: boolean;
}
interface PodsPanelStates {
}
export default class PodsPanel extends Base<PodsPanelProps, PodsPanelStates> {
private sortByCpuUsage: TODO;
private sortByCpuRequest: TODO;
private sortByCpuLimit: TODO;
private sortByRamUsage: TODO;
private sortByRamRequest: TODO;
private sortByRamLimit: TODO;
constructor(props: TODO) {
super(props);
this.sortByCpuUsage = x => getPodUsage(x, this.props.metrics, 'cpu');
this.sortByCpuRequest = x => sortBy(x, this.props.metrics, 'cpu', 'requests');
this.sortByCpuLimit = x => sortBy(x, this.props.metrics, 'cpu', 'limits');
this.sortByCpuUsage = (x: TODO) => getPodUsage(x, this.props.metrics, 'cpu');
this.sortByCpuRequest = (x: TODO) => sortBy(x, this.props.metrics, 'cpu', 'requests');
this.sortByCpuLimit = (x: TODO) => sortBy(x, this.props.metrics, 'cpu', 'limits');
this.sortByRamUsage = x => getPodUsage(x, this.props.metrics, 'memory');
this.sortByRamRequest = x => sortBy(x, this.props.metrics, 'memory', 'requests');
this.sortByRamLimit = x => sortBy(x, this.props.metrics, 'memory', 'limits');
this.sortByRamUsage = (x: TODO) => getPodUsage(x, this.props.metrics, 'memory');
this.sortByRamRequest = (x: TODO) => sortBy(x, this.props.metrics, 'memory', 'requests');
this.sortByRamLimit = (x: TODO) => sortBy(x, this.props.metrics, 'memory', 'limits');
}
render() {
const {items, metrics, sort, filter, skipNamespace} = this.props;
const col = 10 + !skipNamespace;
const col = 10 + Number(!skipNamespace);
return (
<div className='contentPanel'>
@@ -70,7 +90,7 @@ export default class PodsPanel extends Base {
</tr>
</thead>
<TableBody items={items} filter={filter} sort={sort} colSpan={col} row={x => (
<TableBody items={items} filter={filter} sort={sort} colSpan={col} row={(x: TODO) => (
<tr key={x.metadata.uid}>
<MetadataColumns
item={x}
@@ -89,7 +109,7 @@ export default class PodsPanel extends Base {
}
}
function getPhaseStyle(phase) {
function getPhaseStyle(phase: string) {
switch (phase) {
case 'Pending':
return 'svg_warn';
@@ -108,31 +128,31 @@ function getPhaseStyle(phase) {
}
}
function sortBy(item, metrics, resource, type) {
function sortBy(item: TODO, metrics: TODO, resource: string, type: string) {
const result = getPodResourcePercent(item, metrics, resource, type);
return Number.isFinite(result) ? result : -1;
return result && Number.isFinite(result) ? result : -1;
}
function getRestartCount({status}) {
function getRestartCount({status}: {status: TODO}) {
return _.sumBy(status.containerStatuses, 'restartCount');
}
function getChart(item, metrics, resource) {
function getChart(item: TODO, metrics: TODO, resource: string) {
const actual = getPodUsage(item, metrics, resource);
return (
<>
{getRawDisplay(item, metrics, actual, resource)}
{getPercentDisplay(item, metrics, actual, resource, 'requests')}
{getPercentDisplay(item, metrics, actual, resource, 'limits')}
{actual && getRawDisplay(item, metrics, actual, resource)}
{actual && getPercentDisplay(item, metrics, actual, resource, 'requests')}
{actual && getPercentDisplay(item, metrics, actual, resource, 'limits')}
</>
);
}
function getRawDisplay(item, metrics, actual, resource) {
function getRawDisplay(item: TODO, metrics: TODO, actual: number | string | null, resource: string) {
if (!item || !metrics) return <td><LoadingEllipsis /></td>;
const unparser = resource === 'cpu' ? unparseCpu : unparseRam;
const unparser: TODO = resource === 'cpu' ? unparseCpu : unparseRam;
const actualResult = unparser(actual);
return (
@@ -143,13 +163,13 @@ function getRawDisplay(item, metrics, actual, resource) {
);
}
function getPercentDisplay(item, metrics, actual, resource, type) {
function getPercentDisplay(item: TODO, metrics: TODO, actual: number, resource: string, type: TODO) {
if (!item || !metrics) return <td className='optional_xsmall'><LoadingEllipsis /></td>;
const request = getPodResourceValue(item, resource, type);
if (!request) return <td className='smallText optional_xsmall'>-</td>;
const unparser = resource === 'cpu' ? unparseCpu : unparseRam;
const unparser: TODO = resource === 'cpu' ? unparseCpu : unparseRam;
const result = unparser(request);
const percent = request ? _.round(actual / request * 100, 1) : 0;
const className = percent > 85 ? 'optional_xsmall contentPanel_warn' : 'optional_xsmall';
@@ -1,8 +1,9 @@
import React from 'react';
import Chart from './chart';
import LoadingChart from './loadingChart';
import {TODO} from "../utils/types";
export default function ReplicasChart({item}) {
export default function ReplicasChart({item}: {item: TODO}) {
return (
<div className='charts_item'>
{item ? (
+2 -2
View File
@@ -15,13 +15,13 @@ interface SecretValueStates {
export default class SecretValue extends Base<SecretValueProps, SecretValueStates> {
toggle() {
const {show = {}} = this.state || {};
const {show = null} = this.state || {};
this.setState({show: !show});
}
render() {
const {text} = this.props;
const {show = {}} = this.state || {};
const {show = null} = this.state || {};
return (
<div className='secretValue'>
+3
View File
@@ -30,6 +30,9 @@ interface Metadata {
}
interface Container {
name?: string;
image?: string;
args?: string[];
resources?: {
requests?: {
cpu?: string;