Skip to content
Permalink
Browse files
[fix] fix manager1.0.0 frontend bugs (#13)
[fix] fix manager1.0.0 frontend bugs
  • Loading branch information
zhengbowen01 committed Mar 23, 2022
1 parent 90278d0 commit 4987e024dadb60808f184b8eadd484cdf5fc218a
Showing 16 changed files with 374 additions and 162 deletions.
@@ -25,14 +25,14 @@ import {
TableOutlined,
AppstoreOutlined,
} from '@ant-design/icons';
import { Link, useHistory } from 'react-router-dom';
import React, { useState, useEffect, useContext } from 'react';
import { Link, useHistory, useLocation } from 'react-router-dom';
import React, { useState, useEffect, useContext, useMemo } from 'react';

import { useTranslation } from 'react-i18next';
import styles from './sidebar.less';
import { UserInfoContext } from '@src/common/common.context';

const GLOBAL_PATHS = ['/settings', '/space'];
const GLOBAL_PATHS = ['/settings', '/space', '/user-setting'];

export function Sidebar(props: any) {
const { t } = useTranslation();
@@ -42,9 +42,14 @@ export function Sidebar(props: any) {
const user = useContext(UserInfoContext);

const history = useHistory();
const { pathname } = useLocation();
const isSuperAdmin = user?.is_super_admin;
const isSpaceAdmin = user?.is_admin;
const isInSpace = !GLOBAL_PATHS.includes(selectedKeys);
const logoRoute = useMemo(
() => (GLOBAL_PATHS.some(path => pathname.startsWith(path)) ? '/space' : '/cluster'),
[pathname],
);
useEffect(() => {
if (history.location.pathname.includes('configuration')) {
setSelectedKeys('/configuration');
@@ -130,10 +135,9 @@ export function Sidebar(props: any) {
alignItems: 'center',
}}
key="/logo"
onClick={() => history.push(logoRoute)}
>
<div
className={collapsed ? styles['logo-collapsed'] : styles['logo']}
/>
<div className={collapsed ? styles['logo-collapsed'] : styles['logo']} />
</Menu.Item>
{isInSpace && (
<>
@@ -0,0 +1,22 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

export function transformHostToIp(host: string) {
if (!host.includes(':')) return host;
const sliceIndex = host.indexOf(':');
return host.slice(0, sliceIndex);
}
@@ -15,10 +15,11 @@
// specific language governing permissions and limitations
// under the License.

import React, { useState } from 'react';
import React from 'react';
import { Button, Modal, Table } from 'antd';
import { useTranslation } from 'react-i18next';
import { ConfigurationItem } from '.';
import { transformHostToIp } from '../cluster.utils';

interface CheckModalProps {
visible: boolean;
@@ -38,6 +39,7 @@ export default function CheckModal(props: CheckModalProps) {
{
title: t`hostIp`,
dataIndex: 'host',
render: (host: string) => transformHostToIp(host),
},
{
title: t`currentValue`,
@@ -21,6 +21,7 @@ import { useTranslation } from 'react-i18next';
import { ConfigurationItem } from '.';
import { useAsync } from '@src/hooks/use-async';
import * as ClusterAPI from '../cluster.api';
import { transformHostToIp } from '../cluster.utils';

interface EditModalProps {
visible: boolean;
@@ -33,12 +34,18 @@ interface FormInstanceProps {
value: string;
persist: boolean;
range: 'all' | 'part';
nodes: number[];
nodes: string[];
}

const enum RangeEnum {
ALL = 'ALL',
PART = 'PART',
}

export default function EditModal(props: EditModalProps) {
const { t } = useTranslation();
const { visible, currentParameter, onOk, onCancel } = props;
const [range, setRange] = useState<RangeEnum>(RangeEnum.ALL);
const { loading: confirmLoading, run: runChangeConfiguration } = useAsync();
const [form] = Form.useForm<FormInstanceProps>();

@@ -48,7 +55,7 @@ export default function EditModal(props: EditModalProps) {
runChangeConfiguration(
ClusterAPI.changeConfiguration(currentParameter.type === 'Frontend' ? 'fe' : 'be', {
[currentParameter.name]: {
node: [...currentParameter.nodes],
node: [...(range === RangeEnum.ALL ? currentParameter.nodes : values.nodes)],
value: values.value,
persist: values.persist ? 'true' : 'false',
},
@@ -68,7 +75,7 @@ export default function EditModal(props: EditModalProps) {

const handleCancel = () => {
form.resetFields();
// setRange('all');
setRange(RangeEnum.ALL);
onCancel();
};

@@ -99,7 +106,7 @@ export default function EditModal(props: EditModalProps) {
<Radio value={false}>{t`onceEffective`}</Radio>
</Radio.Group>
</Form.Item>
{/* <Form.Item
<Form.Item
name="range"
label={t`effectiveRange`}
rules={[{ required: true, message: t`effectiveRangeRequiredMessage` }]}
@@ -109,21 +116,25 @@ export default function EditModal(props: EditModalProps) {
setRange(e.target.value);
}}
>
<Radio value="all">{t`allNodes`}</Radio>
<Radio value="part">{t`certainNodes`}</Radio>
<Radio value={RangeEnum.ALL}>{t`allNodes`}</Radio>
<Radio value={RangeEnum.PART}>{t`certainNodes`}</Radio>
</Radio.Group>
</Form.Item> */}
{/* {range === 'part' && (
</Form.Item>
{range === RangeEnum.PART && (
<Form.Item
name="nodes"
label={t`effectiveNodes`}
rules={[{ required: true, message: t`effectiveNodesPlaceholder` }]}
>
<Select mode="multiple" placeholder={t`effectiveNodesPlaceholder`}>
<Select.Option value="1">127.0.0.1</Select.Option>
{currentParameter.nodes.map(nodeHost => (
<Select.Option key={nodeHost} value={nodeHost}>
{transformHostToIp(nodeHost)}
</Select.Option>
))}
</Select>
</Form.Item>
)} */}
)}
</Form>
</Modal>
);
@@ -35,16 +35,22 @@ import { useRecoilState, useRecoilValue } from 'recoil';
import { requestInfoState, stepDisabledState } from './access-cluster.recoil';
import { ClusterVerify } from './steps/cluster-verify/cluster-verify';
import { SpaceAccessFinish } from './steps/finish/finish';
import { checkParam } from '../space.utils';
const { Step } = Steps;

export function AccessCluster(props: any) {
const match = useRouteMatch<{requestId: string}>();
const match = useRouteMatch<{ requestId: string }>();
const history = useHistory();
const [step, setStep] = React.useState(0);
const [loading, setLoading] = useState(false);
const [requestInfo, setRequestInfo] = useRecoilState(requestInfoState);
const [stepDisabled, setStepDisabled] = useRecoilState(stepDisabledState);
const hidePrevSteps = [AccessClusterStepsEnum['space-register'], AccessClusterStepsEnum['node-verify'], AccessClusterStepsEnum['cluster-verify'], AccessClusterStepsEnum.finish];
const hidePrevSteps = [
AccessClusterStepsEnum['space-register'],
AccessClusterStepsEnum['node-verify'],
AccessClusterStepsEnum['cluster-verify'],
AccessClusterStepsEnum.finish,
];

useEffect(() => {
if (history.location.pathname === '/space/list') {
@@ -55,9 +61,9 @@ export function AccessCluster(props: any) {
const step = (paths as string[])[2];
setStep(AccessClusterStepsEnum[step]);

setStepDisabled({...stepDisabled, next: false});
setStepDisabled({ ...stepDisabled, next: false });

if (match.params.requestId && +match.params.requestId !== 0) {
if (match.params.requestId && +match.params.requestId !== 0) {
getRequestInfo();
}
}, [history.location.pathname]);
@@ -74,20 +80,23 @@ export function AccessCluster(props: any) {

async function nextStep() {
const value = form.getFieldsValue();
let isParamsValid = true;
const newStep = step + 1;
setLoading(true);
const params: ClusterAccessParams = {
...requestInfo.reqInfo,
cluster_id: requestInfo.clusterId,
request_id: requestInfo.requestId,
event_type: (step + 1).toString(),
}
if (value && step === AccessClusterStepsEnum['space-register']) {
};
if (value && step === AccessClusterStepsEnum['space-register']) {
params.spaceInfo = {
describe: value.describe,
name: value.name,
spaceAdminUsers: value.spaceAdminUsers,
}
};
isParamsValid =
checkParam(params.spaceInfo.name, '请填写空间名称') &&
checkParam(params.spaceInfo.spaceAdminUsers, '请填写管理员姓名');
}
if (value && step === AccessClusterStepsEnum['connect-cluster']) {
params.clusterAccessInfo = {
@@ -97,38 +106,47 @@ export function AccessCluster(props: any) {
queryPort: value.queryPort,
type: value.type,
user: value.user,
}
};
isParamsValid =
checkParam(params.clusterAccessInfo.address, '请填写集群地址') &&
checkParam(params.clusterAccessInfo.httpPort, '请填写HTTP端口') &&
checkParam(params.clusterAccessInfo.queryPort, '请填写JDBC端口') &&
checkParam(params.clusterAccessInfo.user, '请填写集群用户名');
}

if (value && step === AccessClusterStepsEnum['managed-options']) {
params.authInfo = {
sshKey: value.sshKey,
sshPort: value.sshPort,
sshUser: value.sshUser,
}
params.installInfo = value.installInfo
};
params.installInfo = value.installInfo;
isParamsValid =
checkParam(params.authInfo.sshUser, '请填写SSH用户') &&
checkParam(params.authInfo.sshPort, '请填写SSH端口') &&
checkParam(params.authInfo.sshKey, '请填写SSH私钥') &&
checkParam(params.installInfo, '请填写安装路径')
}

if (!isParamsValid) return;
setLoading(true);
const res = await SpaceAPI.accessCluster(params);
setLoading(false);
if (isSuccess(res)) {
setRequestInfo(res.data);
setStep(newStep);
setStepDisabled({...stepDisabled, next: false});
setStepDisabled({ ...stepDisabled, next: false });
setTimeout(() => {
history.push(`/space/access/${res.data.requestId}/${AccessClusterStepsEnum[newStep]}`);
}, 0)

}, 0);
} else {
message.error(res.msg);
}
}


function prevStep() {
const newStep = step - 1;
setStep(newStep);
setStepDisabled({...stepDisabled, prev: false});
setStepDisabled({ ...stepDisabled, prev: false });
history.push(`/space/access/${requestInfo.requestId}/${AccessClusterStepsEnum[newStep]}`);
}

@@ -138,11 +156,13 @@ export function AccessCluster(props: any) {

return (
<>
<NewSpaceInfoContext.Provider value={{
step,
form,
reqInfo: requestInfo.reqInfo || {authInfo: {}, spaceInfo: {}, clusterAccessInfo: {} }
}}>
<NewSpaceInfoContext.Provider
value={{
step,
form,
reqInfo: requestInfo.reqInfo || { authInfo: {}, spaceInfo: {}, clusterAccessInfo: {} },
}}
>
<ProCard style={{ marginTop: 20 }}>
<div style={{ position: 'fixed', top: 80, right: 80 }}>
<Steps direction="vertical" current={step} style={{ padding: '20px 0 40px 0' }}>
@@ -157,11 +177,20 @@ export function AccessCluster(props: any) {
<div style={{ marginRight: 240 }}>
<CacheSwitch>
<CacheRoute path={`${match.path}/${AccessClusterStepsEnum[0]}`} component={SpaceRegister} />
<CacheRoute path={`${match.path}/${AccessClusterStepsEnum[1]}`} component={ConnectCluster} />
<CacheRoute path={`${match.path}/${AccessClusterStepsEnum[2]}`} component={ManagedOptions} />
<CacheRoute
path={`${match.path}/${AccessClusterStepsEnum[1]}`}
component={ConnectCluster}
/>
<CacheRoute
path={`${match.path}/${AccessClusterStepsEnum[2]}`}
component={ManagedOptions}
/>
<CacheRoute path={`${match.path}/${AccessClusterStepsEnum[3]}`} component={NodeVerify} />
<CacheRoute path={`${match.path}/${AccessClusterStepsEnum[4]}`} component={ClusterVerify} />
<CacheRoute path={`${match.path}/${AccessClusterStepsEnum[5]}`} component={SpaceAccessFinish} />
<CacheRoute
path={`${match.path}/${AccessClusterStepsEnum[5]}`}
component={SpaceAccessFinish}
/>
<Redirect to={`${match.path}/${AccessClusterStepsEnum[0]}`} />
</CacheSwitch>
<Row justify="end" style={{ marginTop: 20 }}>

0 comments on commit 4987e02

Please sign in to comment.