mirror of
https://github.com/skooner-k8s/skooner.git
synced 2026-08-28 19:27:15 +00:00
Merge pull request #118 from tianni4104/typescript
extra components into ts
This commit is contained in:
+5
-4
@@ -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;
|
||||
@@ -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];
|
||||
}
|
||||
+4
-3
@@ -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 ? (
|
||||
@@ -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'>
|
||||
|
||||
@@ -30,6 +30,9 @@ interface Metadata {
|
||||
}
|
||||
|
||||
interface Container {
|
||||
name?: string;
|
||||
image?: string;
|
||||
args?: string[];
|
||||
resources?: {
|
||||
requests?: {
|
||||
cpu?: string;
|
||||
|
||||
Reference in New Issue
Block a user