Skip to content

Commit

Permalink
chore: rewrite some files with typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
ma-efremoff committed Jul 22, 2024
1 parent 74b4e9f commit 5b50d45
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 141 deletions.
12 changes: 7 additions & 5 deletions packages/ui/src/ui/components/RadioButton/RadioButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ import hammer from '../../common/hammer';
import Icon from '../Icon/Icon';
import {RadioButton, RadioButtonProps} from '@gravity-ui/uikit';

interface Props extends RadioButtonProps {
items: Array<ItemType>;
interface Props<T extends string = string> extends RadioButtonProps<T> {
items: Array<ItemType<T>>;
}

export interface ItemType {
export interface ItemType<T extends string = string> {
icon?: any;
text: string;
value: string;
value: T;
}

const block = cn('elements-radiobutton');

export default class CustomRadioButton extends React.Component<Props> {
export default class CustomRadioButton<T extends string = string> extends React.Component<
Props<T>
> {
static propTypes = {
value: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.shape({value: PropTypes.string})),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const DEFAULT_GROUP = 'other';

export const CLUSTER_GROUPS = {
export const CLUSTER_GROUPS: Record<string, {caption: string; size?: 'l'}> = {
/** !!! the order is important !!! **/

'primary-mrs': {
Expand Down
8 changes: 4 additions & 4 deletions packages/ui/src/ui/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,16 @@ export const MediumType = {
const CLUSTER_MENU_PREFIX = createPrefix('CLUSTER_MENU');

export const FETCH_CLUSTER_VERSIONS = createActionTypes(
CLUSTER_MENU_PREFIX + 'FETCH_CLUSTER_VERSIONS',
`${CLUSTER_MENU_PREFIX}FETCH_CLUSTER_VERSIONS`,
);
export const FETCH_CLUSTER_AVAILABILITY = createActionTypes(
CLUSTER_MENU_PREFIX + 'FETCH_CLUSTER_AVAILABILITY',
`${CLUSTER_MENU_PREFIX}FETCH_CLUSTER_AVAILABILITY`,
);

export const FETCH_CLUSTER_AUTH_STATUS = createActionTypes('FETCH_CLUSTER_AUTH_STATUS');

export const UPDATE_VIEWMODE = CLUSTER_MENU_PREFIX + 'UPDATE_VIEWMODE';
export const UPDATE_FILTER = CLUSTER_MENU_PREFIX + 'UPDATE_FILTER';
export const CLUSTERS_MENU_UPDATE_VIEWMODE = `${CLUSTER_MENU_PREFIX}UPDATE_VIEWMODE` as const;
export const CLUSTERS_MENU_UPDATE_FILTER = `${CLUSTER_MENU_PREFIX}UPDATE_FILTER` as const;

export const SPLIT_PANE_ID = 'split-portal';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import React from 'react';
import {ConnectedProps, connect} from 'react-redux';
import block from 'bem-cn-lite';
import {Link} from 'react-router-dom';
import _ from 'lodash';
import {Lock} from '@gravity-ui/icons';

import {CLUSTER_GROUPS, CLUSTER_GROUPS_ORDER, DEFAULT_GROUP} from '../../constants/cluster-menu';
// @ts-ignore
import format from '@ytsaurus/interface-helpers/lib/hammer/format';

import {CLUSTER_GROUPS, CLUSTER_GROUPS_ORDER, DEFAULT_GROUP} from '../../constants/cluster-menu';
import {utils} from '../../common/hammer/utils';
import ElementsTable from '../../components/ElementsTable/ElementsTable';
import {sortStateType} from '../../components/ElementsTable/ElementsTableHeader';
import {
fetchClusterAuthStatus,
fetchClusterAvailability,
Expand All @@ -20,21 +20,15 @@ import {CLUSTER_MENU_TABLE_ID} from '../../constants/tables';
import {getClusterAppearance} from '../../appearance';
import YT from '../../config/yt-config';
import './ClusterMenuBody.scss';
import {RootState} from '../../store/reducers';
import {ClusterConfigWithStatus} from '../../store/reducers/clusters-menu/clusters-menu';
import {getAppBrowserHistory} from '../../store/window-store';

const b = block('cluster-menu');

class ClustersMenuBody extends Component {
static propTypes = {
// from connect
clusterFilter: PropTypes.string,
viewMode: PropTypes.oneOf(['dashboard', 'table']),
clusters: PropTypes.object,
fetchClusterVersions: PropTypes.func.isRequired,
fetchClusterAuthStatus: PropTypes.func.isRequired,
fetchClusterAvailability: PropTypes.func.isRequired,
sortState: sortStateType.isRequired,
};
type Props = ConnectedProps<typeof connector>;

class ClustersMenuBody extends React.Component<Props> {
componentDidMount() {
const {fetchClusterVersions, fetchClusterAvailability, fetchClusterAuthStatus} = this.props;

Expand All @@ -45,20 +39,20 @@ class ClustersMenuBody extends Component {
}
}

prepareGroups(clusters) {
function sortByClusterName(clusterA, clusterB) {
prepareGroups(clusters: Array<ClusterConfigWithStatus>) {
function sortByClusterName<T extends {name: string}>(clusterA: T, clusterB: T) {
return clusterA.name > clusterB.name ? 1 : -1;
}

const groups = _.reduce(
clusters,
(groups, cluster) => {
(acc, cluster) => {
const currentGroup = cluster.group || DEFAULT_GROUP;
groups[currentGroup] = groups[currentGroup] || [];
groups[currentGroup].push(cluster);
return groups;
acc[currentGroup] = acc[currentGroup] || [];
acc[currentGroup].push(cluster);
return acc;
},
{},
{} as Record<string, Array<ClusterConfigWithStatus>>,
);

_.each(groups, (clusters) => {
Expand All @@ -68,9 +62,9 @@ class ClustersMenuBody extends Component {
return groups;
}

renderVersion({loadState, access, version, status}) {
renderVersion({loadState, access, version, status}: ClusterConfigWithStatus) {
let title;
let text = '—';
let text: typeof version = '—';
if (loadState === 'loaded') {
if (access === 'granted') {
title = `Current cluster version: ${version}`;
Expand All @@ -91,18 +85,8 @@ class ClustersMenuBody extends Component {
);
}

renderCluster(cluster, size) {
const {
status,
access,
id,
name,
environment,
descriptionEnglish,
description,
theme,
authorized,
} = cluster;
renderCluster(cluster: ClusterConfigWithStatus, size?: 'l') {
const {status, access, id, name, environment, description, theme, authorized} = cluster;
const className = b('item', {
state: status,
access: status === 'available' && access,
Expand Down Expand Up @@ -140,14 +124,14 @@ class ClustersMenuBody extends Component {
</div>

<div className={b('item-description', 'elements-multiline-ellipsis')}>
{descriptionEnglish ? descriptionEnglish : description}
{description}
</div>
</div>
</Link>
);
}

renderDashboard(clusters) {
renderDashboard(clusters: Array<ClusterConfigWithStatus>) {
const clusterGroups = this.prepareGroups(clusters);

const unknown = _.filter(
Expand All @@ -156,7 +140,7 @@ class ClustersMenuBody extends Component {
);

return (
<main key="body" className={b(false, 'elements-page__content')}>
<main key="body" className={b(null, 'elements-page__content')}>
{_.map(CLUSTER_GROUPS_ORDER.concat(unknown), (groupName) => {
const clusters = clusterGroups[groupName];
const {caption, size} = CLUSTER_GROUPS[groupName] ?? {caption: groupName};
Expand Down Expand Up @@ -187,19 +171,17 @@ class ClustersMenuBody extends Component {
);
}

renderTable(clusters) {
renderTable(clusters: Array<ClusterConfigWithStatus>) {
const tableSettings = {
css: 'cluster-menu',
theme: 'light',
striped: true,
tableId: CLUSTER_MENU_TABLE_ID,
computeKey: function (item) {
computeKey: function (item: {name: string}) {
return item.name;
},
onItemClick: function (item) {
// FIXME: give back control to react-router once we no longer need to render full page on server
// to get cluster credentials
window.location = `/${item.id}`;
onItemClick: function (item: {id: string}) {
getAppBrowserHistory().push(`/${item.id}`);
},
columns: {
items: {
Expand All @@ -209,35 +191,35 @@ class ClustersMenuBody extends Component {
sort: false,
},
name: {
get: function (cluster) {
get: function (cluster: ClusterConfigWithStatus) {
return cluster.name;
},
sort: true,
align: 'left',
},
environment: {
get: function (cluster) {
get: function (cluster: ClusterConfigWithStatus) {
return cluster.environment;
},
sort: true,
align: 'left',
},
version: {
get: function (cluster) {
get: function (cluster: ClusterConfigWithStatus) {
return [cluster.version, cluster.id];
},
sort: true,
align: 'right',
},
status: {
get: function (cluster) {
get: function (cluster: ClusterConfigWithStatus) {
return [cluster.status, cluster.id];
},
sort: true,
align: 'center',
},
access: {
get: function (cluster) {
get: function (cluster: ClusterConfigWithStatus) {
return [cluster.access, cluster.id];
},
sort: true,
Expand All @@ -264,7 +246,7 @@ class ClustersMenuBody extends Component {
});

return (
<main key="body" className={b(false, 'elements-page__content')}>
<main key="body" className={b(null, 'elements-page__content')}>
<div className={b('table-wrapper')}>
<ElementsTable {...table} />
</div>
Expand All @@ -275,7 +257,7 @@ class ClustersMenuBody extends Component {
renderEmptyContent() {
const className = b('heading', {position: 'center', size: 'l'});
return (
<main key="body" className={b(false, 'elements-page__content')}>
<main key="body" className={b(null, 'elements-page__content')}>
<div className={b('message', className)}>No clusters matching your selection</div>
</main>
);
Expand All @@ -285,7 +267,7 @@ class ClustersMenuBody extends Component {
const {viewMode, clusterFilter, clusters} = this.props;
const regexp = new RegExp(clusterFilter, 'i');

const filterByField = (field) => {
const filterByField = (field?: string) => {
return typeof field === 'string' && field.search(regexp) > -1;
};

Expand All @@ -300,16 +282,17 @@ class ClustersMenuBody extends Component {
} else if (!filteredClusters.length) {
return this.renderEmptyContent();
}
return null;
}
}

function mapStateToProps({clustersMenu, tables}) {
const {viewMode, clusterFilter, clusters} = clustersMenu;
function mapStateToProps(state: RootState) {
const {viewMode, clusterFilter, clusters} = state.clustersMenu;
return {
viewMode,
clusterFilter,
clusters,
sortState: tables[CLUSTER_MENU_TABLE_ID],
sortState: state.tables[CLUSTER_MENU_TABLE_ID],
};
}

Expand All @@ -319,4 +302,6 @@ const mapDispatchToProps = {
fetchClusterAvailability,
};

export default connect(mapStateToProps, mapDispatchToProps)(ClustersMenuBody);
const connector = connect(mapStateToProps, mapDispatchToProps);

export default connector(ClustersMenuBody);
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
import block from 'bem-cn-lite';
import {connect} from 'react-redux';
import {ConnectedProps, connect} from 'react-redux';

import Filter from '../../components/Filter/Filter';
import RadioButton from '../../components/RadioButton/RadioButton';
import {updateFilter, updateViewMode} from '../../store/actions/clusters-menu';
import {HeaderLinks} from '../../containers/ClustersMenu/HeaderLinks';
import {LINKS_ITEM_CLUSTERS} from '../../containers/ClustersMenu/header-links-items';
import {RootState} from '../../store/reducers';

import './ClusterMenuHeader.scss';

Expand All @@ -21,7 +22,9 @@ ClustersMenuHeader.propTypes = {
login: PropTypes.string,
};

function ClustersMenuHeader({viewMode, updateViewMode, clusterFilter, updateFilter}) {
type Props = ConnectedProps<typeof connector>;

function ClustersMenuHeader({viewMode, updateViewMode, clusterFilter, updateFilter}: Props) {
return (
<header className={b('header', 'elements-page__header')}>
<div className={b('header-inner')}>
Expand All @@ -35,11 +38,11 @@ function ClustersMenuHeader({viewMode, updateViewMode, clusterFilter, updateFilt
</div>
</div>
<div className={b('view')}>
<RadioButton
<RadioButton<'table' | 'dashboard'>
size="m"
name="cluster-menu-mode"
value={viewMode}
onChange={(event) => updateViewMode(event.target.value)}
onUpdate={(value) => updateViewMode(value)}
items={[
{
value: 'table',
Expand All @@ -61,9 +64,9 @@ function ClustersMenuHeader({viewMode, updateViewMode, clusterFilter, updateFilt
);
}

function mapStateToProps({clustersMenu, global}) {
const {viewMode, clusterFilter} = clustersMenu;
const {login} = global;
function mapStateToProps(state: RootState) {
const {viewMode, clusterFilter} = state.clustersMenu;
const {login} = state.global;
return {
viewMode,
clusterFilter,
Expand All @@ -76,4 +79,6 @@ const mapDispatchToProps = {
updateFilter,
};

export default connect(mapStateToProps, mapDispatchToProps)(ClustersMenuHeader);
const connector = connect(mapStateToProps, mapDispatchToProps);

export default connector(ClustersMenuHeader);
16 changes: 8 additions & 8 deletions packages/ui/src/ui/pages/odin/odin-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,14 @@ export function currentDate() {

export const fetchClustersAvailability = hasOdinPage()
? () => {
return axios.request({
return axios.request<Array<ClusterAvailability>>({
method: 'get',
url: '/api/odin/clusters/availability',
}) as Promise<
{
id: string;
availability?: 1 | undefined;
}[]
>;
});
}
: () => Promise.resolve([]);
: () => Promise.resolve({data: [] as Array<ClusterAvailability>});

type ClusterAvailability = {
id: string;
availability?: 1;
};
Loading

0 comments on commit 5b50d45

Please # to comment.