fix: Update component && validate
1. Add 'ready' status to State component 2. Add price render in table 3. Support children column in table 4. Fix image/instance name validate 5. Support loading in Label component 6. Fix MagicInput component style 7. Fix role check in layout 8. Update class export 9. Remove useless component Change-Id: I0e5d7e4a23fb0a68e17ae57eba83608be3a3df0e
This commit is contained in:
parent
a6f387d67e
commit
2b68f2a3d7
@ -108,6 +108,7 @@ const DetailCard = ({
|
|||||||
arrowPointAtCenter="true"
|
arrowPointAtCenter="true"
|
||||||
placement="rightTop"
|
placement="rightTop"
|
||||||
content={titleHelp}
|
content={titleHelp}
|
||||||
|
getPopupContainer={(node) => node.parentNode}
|
||||||
>
|
>
|
||||||
<InfoCircleOutlined className={styles['title-help']} />
|
<InfoCircleOutlined className={styles['title-help']} />
|
||||||
</Popover>
|
</Popover>
|
||||||
|
@ -49,6 +49,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import {
|
|||||||
TagOutlined,
|
TagOutlined,
|
||||||
HddOutlined,
|
HddOutlined,
|
||||||
CloudServerOutlined,
|
CloudServerOutlined,
|
||||||
|
LoadingOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
@ -82,14 +83,19 @@ export default class index extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { content, value, iconType, ...rest } = this.props;
|
const { content, value, iconType, showLoading, ...rest } = this.props;
|
||||||
|
const failValues = [undefined, null, ''];
|
||||||
if (content) {
|
if (content) {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span {...rest}>
|
<span {...rest}>
|
||||||
{this.renderIcon()}
|
{this.renderIcon()}
|
||||||
{value}
|
{showLoading && failValues.includes(value) ? (
|
||||||
|
<LoadingOutlined />
|
||||||
|
) : (
|
||||||
|
value
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@ export default class SelectTable extends React.Component {
|
|||||||
defaultSortKey: PropTypes.string,
|
defaultSortKey: PropTypes.string,
|
||||||
defaultSortOrder: PropTypes.string,
|
defaultSortOrder: PropTypes.string,
|
||||||
onRow: PropTypes.func,
|
onRow: PropTypes.func,
|
||||||
|
childrenColumnName: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -105,6 +106,7 @@ export default class SelectTable extends React.Component {
|
|||||||
isSortByBack: false,
|
isSortByBack: false,
|
||||||
defaultSortKey: '',
|
defaultSortKey: '',
|
||||||
defaultSortOrder: '',
|
defaultSortOrder: '',
|
||||||
|
childrenColumnName: 'children',
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -652,6 +654,7 @@ export default class SelectTable extends React.Component {
|
|||||||
filterParams,
|
filterParams,
|
||||||
onRow,
|
onRow,
|
||||||
rowKey,
|
rowKey,
|
||||||
|
childrenColumnName,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { current, pageSize, total, filters } = this.state;
|
const { current, pageSize, total, filters } = this.state;
|
||||||
const defaultPageSizeOptions = [10, 20, 50, 100];
|
const defaultPageSizeOptions = [10, 20, 50, 100];
|
||||||
@ -697,6 +700,7 @@ export default class SelectTable extends React.Component {
|
|||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
footer={footer}
|
footer={footer}
|
||||||
onRow={onRow}
|
onRow={onRow}
|
||||||
|
childrenColumnName={childrenColumnName}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ import TabSelectTable from './TabSelectTable';
|
|||||||
import TreeSelect from './TreeSelect';
|
import TreeSelect from './TreeSelect';
|
||||||
// import styles from './index.less';
|
// import styles from './index.less';
|
||||||
|
|
||||||
const type2component = {
|
export const type2component = {
|
||||||
label: Label,
|
label: Label,
|
||||||
input: Input,
|
input: Input,
|
||||||
select: Select,
|
select: Select,
|
||||||
@ -132,8 +132,8 @@ export default class FormItem extends React.Component {
|
|||||||
getComponentProps(type) {
|
getComponentProps(type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'label': {
|
case 'label': {
|
||||||
const { content, icon, iconType } = this.props;
|
const { content, icon, iconType, showLoading } = this.props;
|
||||||
return { content, icon, iconType };
|
return { content, icon, iconType, showLoading };
|
||||||
}
|
}
|
||||||
case 'divider':
|
case 'divider':
|
||||||
return {
|
return {
|
||||||
@ -319,6 +319,10 @@ export default class FormItem extends React.Component {
|
|||||||
return newRules;
|
return newRules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getComponent(type) {
|
||||||
|
return type2component[type];
|
||||||
|
}
|
||||||
|
|
||||||
renderTip(tip) {
|
renderTip(tip) {
|
||||||
if (!tip) {
|
if (!tip) {
|
||||||
return null;
|
return null;
|
||||||
@ -347,7 +351,7 @@ export default class FormItem extends React.Component {
|
|||||||
if (component) {
|
if (component) {
|
||||||
return <Form.Item {...formItemProps}>{component}</Form.Item>;
|
return <Form.Item {...formItemProps}>{component}</Form.Item>;
|
||||||
}
|
}
|
||||||
const TypeComp = type2component[type];
|
const TypeComp = this.getComponent(type);
|
||||||
const props = this.getComponentProps(type);
|
const props = this.getComponentProps(type);
|
||||||
if (type === 'divider') {
|
if (type === 'divider') {
|
||||||
return <Divider className="form-item-divider" />;
|
return <Divider className="form-item-divider" />;
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
// Copyright 2021 99cloud
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
|
|
||||||
import { trimEnd } from 'lodash';
|
|
||||||
|
|
||||||
import NavItem from './item';
|
|
||||||
|
|
||||||
import styles from './index.less';
|
|
||||||
|
|
||||||
class GlobalNav extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
className: PropTypes.string,
|
|
||||||
navs: PropTypes.array.isRequired,
|
|
||||||
// eslint-disable-next-line react/no-unused-prop-types
|
|
||||||
prefix: PropTypes.string,
|
|
||||||
// eslint-disable-next-line react/no-unused-prop-types
|
|
||||||
checkSelect: PropTypes.func,
|
|
||||||
onItemClick: PropTypes.func,
|
|
||||||
innerRef: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
className: '',
|
|
||||||
prefix: '',
|
|
||||||
checkSelect() {},
|
|
||||||
onItemClick() {},
|
|
||||||
};
|
|
||||||
|
|
||||||
get currentPath() {
|
|
||||||
const {
|
|
||||||
location: { pathname },
|
|
||||||
match: { url },
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const { length } = trimEnd(url, '/');
|
|
||||||
return pathname.slice(length + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { className, navs, innerRef, onItemClick } = this.props;
|
|
||||||
const classNames = classnames(styles.wrapper, className);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={innerRef} className={classNames}>
|
|
||||||
{navs.map((nav) => (
|
|
||||||
<div key={nav.cate} className={styles.subNav}>
|
|
||||||
{nav.title && <p>{t(nav.title)}</p>}
|
|
||||||
<ul>
|
|
||||||
{nav.items.map((item) => (
|
|
||||||
<NavItem
|
|
||||||
key={item.name}
|
|
||||||
item={item}
|
|
||||||
prefix=""
|
|
||||||
current={this.currentPath}
|
|
||||||
onClick={onItemClick}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GlobalNav;
|
|
@ -1,102 +0,0 @@
|
|||||||
@import '~styles/variables';
|
|
||||||
@import '~styles/mixins';
|
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
position: fixed;
|
|
||||||
top: 60px;
|
|
||||||
left: 8px;
|
|
||||||
width: $nav-width;
|
|
||||||
height: calc(100vh - 68px);
|
|
||||||
padding: 40px 20px;
|
|
||||||
border-radius: $border-radius;
|
|
||||||
background-color: $dark;
|
|
||||||
box-shadow: 4px 8px 16px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
transition: left $trans-speed ease-in-out;
|
|
||||||
overflow-y: auto;
|
|
||||||
z-index: 212;
|
|
||||||
|
|
||||||
.subNav > ul > li {
|
|
||||||
&.select {
|
|
||||||
box-shadow: 0 4px 8px 0 rgba(25, 30, 41, 0.2);
|
|
||||||
background-color: #d8dee5;
|
|
||||||
border: solid 1px #404e68;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #d8dee5;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: #d8dee5;
|
|
||||||
border: solid 1px #404e68;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > a {
|
|
||||||
color: $light;
|
|
||||||
transition: color $trans-speed ease-in-out;
|
|
||||||
|
|
||||||
@media (max-width: 1366px) {
|
|
||||||
padding: 7px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global .qicon {
|
|
||||||
color: #b6c2cd;
|
|
||||||
fill: #b6c2cd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.subNav {
|
|
||||||
& > p {
|
|
||||||
color: $light-color02;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > ul {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
& > li {
|
|
||||||
border-radius: 18px;
|
|
||||||
border: solid 1px transparent;
|
|
||||||
transition: all $trans-speed ease-in-out;
|
|
||||||
|
|
||||||
& > a,
|
|
||||||
.title {
|
|
||||||
display: block;
|
|
||||||
padding: 7px 12px;
|
|
||||||
color: #4a5974;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
@media (max-width: 1366px) {
|
|
||||||
padding: 7px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global {
|
|
||||||
.icon {
|
|
||||||
margin-right: 8px;
|
|
||||||
vertical-align: text-bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.select,
|
|
||||||
&:hover,
|
|
||||||
&:active {
|
|
||||||
& > a {
|
|
||||||
color: $primary;
|
|
||||||
|
|
||||||
:global .qicon {
|
|
||||||
color: #1890ff;
|
|
||||||
fill:#6fb4f5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& + li {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
// Copyright 2021 99cloud
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Icon } from 'antd';
|
|
||||||
|
|
||||||
import styles from './index.less';
|
|
||||||
|
|
||||||
export default class NavItem extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
item: PropTypes.object,
|
|
||||||
current: PropTypes.string,
|
|
||||||
prefix: PropTypes.string,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
checkSelect = (item = {}) => {
|
|
||||||
const { current } = this.props;
|
|
||||||
|
|
||||||
return current.startsWith(item.name);
|
|
||||||
};
|
|
||||||
|
|
||||||
renderIcon(icon) {
|
|
||||||
return <Icon name={icon} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { item, prefix, onClick } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li
|
|
||||||
key={item.name}
|
|
||||||
className={classnames({
|
|
||||||
[styles.select]: this.checkSelect(item),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Link to={`${prefix}/${item.name}`} onClick={onClick}>
|
|
||||||
{this.renderIcon(item.icon)} {t(item.title)}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
// Copyright 2021 99cloud
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import { trimEnd } from 'lodash';
|
|
||||||
|
|
||||||
import NavItem from './item';
|
|
||||||
|
|
||||||
import styles from './index.less';
|
|
||||||
|
|
||||||
class Nav extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
className: PropTypes.string,
|
|
||||||
navs: PropTypes.array.isRequired,
|
|
||||||
// eslint-disable-next-line react/no-unused-prop-types
|
|
||||||
prefix: PropTypes.string,
|
|
||||||
// eslint-disable-next-line react/no-unused-prop-types
|
|
||||||
checkSelect: PropTypes.func,
|
|
||||||
onItemClick: PropTypes.func,
|
|
||||||
innerRef: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
className: '',
|
|
||||||
prefix: '',
|
|
||||||
checkSelect() {},
|
|
||||||
onItemClick() {},
|
|
||||||
};
|
|
||||||
|
|
||||||
get currentPath() {
|
|
||||||
const {
|
|
||||||
location: { pathname },
|
|
||||||
match: { url },
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const { length } = trimEnd(url, '/');
|
|
||||||
return pathname.slice(length + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { className, navs, match, innerRef, onItemClick } = this.props;
|
|
||||||
|
|
||||||
const prefix = trimEnd(match.url, '/');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={innerRef} className={className}>
|
|
||||||
{navs.map((nav) => (
|
|
||||||
<div key={nav.cate} className={styles.subNav}>
|
|
||||||
{nav.title && <p>{t(nav.title)}</p>}
|
|
||||||
<ul>
|
|
||||||
{nav.items.map((item) => (
|
|
||||||
<NavItem
|
|
||||||
key={item.name}
|
|
||||||
item={item}
|
|
||||||
prefix={prefix}
|
|
||||||
current={this.currentPath}
|
|
||||||
onClick={onItemClick}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Nav;
|
|
@ -1,134 +0,0 @@
|
|||||||
@import '~styles/variables';
|
|
||||||
|
|
||||||
.subNav {
|
|
||||||
& > p {
|
|
||||||
color: #79879c;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > ul {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
& > li {
|
|
||||||
border-radius: 18px;
|
|
||||||
border: solid 1px transparent;
|
|
||||||
transition: all $trans-speed ease-in-out;
|
|
||||||
|
|
||||||
& > a,
|
|
||||||
.title {
|
|
||||||
display: block;
|
|
||||||
padding: 7px 12px;
|
|
||||||
color: #4a5974;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
@media (max-width: 1366px) {
|
|
||||||
padding: 7px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global {
|
|
||||||
.icon {
|
|
||||||
margin-right: 8px;
|
|
||||||
vertical-align: text-bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qicon-chevron-down {
|
|
||||||
margin-top: 4px;
|
|
||||||
transition: all $trans-speed ease-in-out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.devopsIcon {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
padding: 2px;
|
|
||||||
margin-right: 8px;
|
|
||||||
vertical-align: text-bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.select,
|
|
||||||
&.childSelect,
|
|
||||||
&:hover,
|
|
||||||
&:active {
|
|
||||||
& > a {
|
|
||||||
color: $primary;
|
|
||||||
|
|
||||||
:global .qicon {
|
|
||||||
color: $icon-color;
|
|
||||||
fill: #6fb4f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.devopsIcon {
|
|
||||||
color: $icon-color;
|
|
||||||
fill: #6fb4f5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
:global .qicon-chevron-down {
|
|
||||||
transform: rotate(-180deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.innerNav > li {
|
|
||||||
height: 20px;
|
|
||||||
margin-top: 8px;
|
|
||||||
opacity: 1;
|
|
||||||
transition: height $trans-speed ease-in-out,
|
|
||||||
margin-top $trans-speed ease-in-out,
|
|
||||||
opacity $trans-speed ease-in-out 0.1s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& + li {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.innerNav {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
padding-left: 38px;
|
|
||||||
|
|
||||||
@media (max-width: 1366px) {
|
|
||||||
padding-left: 26px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > li {
|
|
||||||
height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
overflow: auto;
|
|
||||||
transition: height $trans-speed ease-in-out 0.1s,
|
|
||||||
margin-top $trans-speed ease-in-out 0.1s, opacity $trans-speed ease-in-out;
|
|
||||||
|
|
||||||
& > a {
|
|
||||||
color: #4a5974;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.select,
|
|
||||||
&:hover,
|
|
||||||
&:active {
|
|
||||||
& > a {
|
|
||||||
color: $primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.back {
|
|
||||||
margin: 20px 0;
|
|
||||||
padding: 8px 12px;
|
|
||||||
& > a > svg {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-right: 8px;
|
|
||||||
vertical-align: text-top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightIcon {
|
|
||||||
float: right;
|
|
||||||
margin-right: 0 !important;
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
// Copyright 2021 99cloud
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Icon } from 'antd';
|
|
||||||
|
|
||||||
import styles from './index.less';
|
|
||||||
|
|
||||||
export default class NavItem extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
item: PropTypes.object,
|
|
||||||
current: PropTypes.string,
|
|
||||||
prefix: PropTypes.string,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
checkSelect = (item = {}) => {
|
|
||||||
const { current } = this.props;
|
|
||||||
|
|
||||||
if (item.children) {
|
|
||||||
return item.children.some((child) => this.checkSelect(child));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.tabs) {
|
|
||||||
return item.tabs.some((tab) => this.checkSelect(tab));
|
|
||||||
}
|
|
||||||
|
|
||||||
return current.startsWith(item.name);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { item, prefix, onClick } = this.props;
|
|
||||||
|
|
||||||
if (item.children) {
|
|
||||||
return (
|
|
||||||
<li
|
|
||||||
className={classnames({
|
|
||||||
[styles.childSelect]: item.open || this.checkSelect(item),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<div className={styles.title}>
|
|
||||||
<Icon name={item.icon} /> {t(item.title)}
|
|
||||||
<Icon name="chevron-down" className={styles.rightIcon} />
|
|
||||||
</div>
|
|
||||||
<ul className={styles.innerNav}>
|
|
||||||
{item.children.map((child) => (
|
|
||||||
<li
|
|
||||||
key={child.name}
|
|
||||||
className={classnames({
|
|
||||||
[styles.select]: this.checkSelect(child),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Link to={`${prefix}/${child.name}`}>{t(child.title)}</Link>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li
|
|
||||||
key={item.name}
|
|
||||||
className={classnames({
|
|
||||||
[styles.select]: this.checkSelect(item),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Link to={`${prefix}/${item.name}`} onClick={onClick}>
|
|
||||||
<Icon name={item.icon} /> {t(item.title)}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
// Copyright 2021 99cloud
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import { Icon, Dropdown, Spin, Menu } from 'antd';
|
|
||||||
|
|
||||||
import styles from './index.less';
|
|
||||||
|
|
||||||
export default class Selector extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
icon: PropTypes.string,
|
|
||||||
defaultIcon: PropTypes.string,
|
|
||||||
value: PropTypes.string,
|
|
||||||
type: PropTypes.string,
|
|
||||||
loading: PropTypes.bool,
|
|
||||||
options: PropTypes.array,
|
|
||||||
onSelect: PropTypes.func,
|
|
||||||
onScrollBottom: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
icon: '',
|
|
||||||
defaultIcon: '',
|
|
||||||
value: '',
|
|
||||||
type: '',
|
|
||||||
loading: false,
|
|
||||||
options: [],
|
|
||||||
onSelect() {},
|
|
||||||
onScrollBottom() {},
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.contentRef = React.createRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
if (this.contentRef.current) {
|
|
||||||
this.$dropdownContent =
|
|
||||||
this.contentRef.current.querySelector('.dropdown-content');
|
|
||||||
this.$dropdownContent.addEventListener('scroll', this.handleScroll);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
if (this.contentRef.current) {
|
|
||||||
const $menu = this.contentRef.current.querySelector(
|
|
||||||
'.dropdown-content > .menu-wrapper'
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($menu && this.$dropdownContent) {
|
|
||||||
this.threshold =
|
|
||||||
$menu.offsetHeight - this.$dropdownContent.offsetHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
if (this.$dropdownContent) {
|
|
||||||
this.$dropdownContent.removeEventListener('scroll', this.handleScroll);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get isMulti() {
|
|
||||||
return this.props.options.length > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleScroll = (e) => {
|
|
||||||
if (this.threshold && e.target.scrollTop >= this.threshold - 2) {
|
|
||||||
this.props.onScrollBottom();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleMenuClick = (e, key) => {
|
|
||||||
this.props.onSelect(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
renderList() {
|
|
||||||
const { defaultIcon, options, loading } = this.props;
|
|
||||||
|
|
||||||
if (!this.isMulti) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="menu-wrapper">
|
|
||||||
<Menu width={220} onClick={this.handleMenuClick}>
|
|
||||||
{options.map((option) => (
|
|
||||||
<Menu.MenuItem key={option.value}>
|
|
||||||
<img src={defaultIcon} alt="" />
|
|
||||||
{option.label}
|
|
||||||
</Menu.MenuItem>
|
|
||||||
))}
|
|
||||||
</Menu>
|
|
||||||
<div className={styles.bottom}>
|
|
||||||
{loading && <Spin size="small" spinning={loading} />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { icon, defaultIcon, value, type, options } = this.props;
|
|
||||||
|
|
||||||
const option = options.find((item) => item.value === value) || {};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={this.contentRef}>
|
|
||||||
<Dropdown
|
|
||||||
className={classNames('dropdown-default', styles.dropdown)}
|
|
||||||
content={this.renderList()}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={classNames(styles.titleWrapper, {
|
|
||||||
[styles.multi]: this.isMulti,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<div className={styles.icon}>
|
|
||||||
<img src={icon || defaultIcon} alt="" />
|
|
||||||
</div>
|
|
||||||
<div className={styles.text}>
|
|
||||||
<p>{type}</p>
|
|
||||||
<div className="h6">{option.label || value}</div>
|
|
||||||
</div>
|
|
||||||
{this.isMulti && (
|
|
||||||
<div className={styles.arrow}>
|
|
||||||
<Icon name="caret-down" type="light" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Dropdown>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
@import '~styles/variables';
|
|
||||||
@import '~styles/mixins';
|
|
||||||
|
|
||||||
.titleWrapper {
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
padding: 12px;
|
|
||||||
border-radius: $border-radius;
|
|
||||||
background-color: $background-color;
|
|
||||||
box-shadow: 0 8px 16px 0 rgba(36, 46, 66, 0.2);
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
padding: 8px;
|
|
||||||
margin-right: 12px;
|
|
||||||
border-radius: 100px 0 100px 100px;
|
|
||||||
background-color: rgba(239, 244, 249, 0.08);
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 124px;
|
|
||||||
|
|
||||||
:global .h6 {
|
|
||||||
font-family: $font-family-id;
|
|
||||||
line-height: 1.43;
|
|
||||||
color: #ffffff;
|
|
||||||
@include ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: #d8dee5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.arrow {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 12px;
|
|
||||||
right: 12px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
padding: 3px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: rgba(85, 188, 138, 0.1);
|
|
||||||
|
|
||||||
:global .icon {
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
background-color: $primary;
|
|
||||||
border-radius: 50%;
|
|
||||||
vertical-align: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.multi {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown {
|
|
||||||
background-color: $background-color;
|
|
||||||
|
|
||||||
:global {
|
|
||||||
.dropdown-content {
|
|
||||||
max-height: 300px;
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu {
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-item {
|
|
||||||
padding: 6px 20px 6px 14px;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom {
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2021 99cloud
|
|
||||||
//
|
|
||||||
// Licensed 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 { default as Nav } from './Nav';
|
|
||||||
export { default as GlobalNav } from './GlobalNav';
|
|
||||||
export { default as Selector } from './Selector';
|
|
@ -165,4 +165,5 @@
|
|||||||
.magic-input-checks {
|
.magic-input-checks {
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
min-width: 120px;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ const successKeys = [
|
|||||||
'power on',
|
'power on',
|
||||||
'complete',
|
'complete',
|
||||||
'online',
|
'online',
|
||||||
|
'ready',
|
||||||
];
|
];
|
||||||
|
|
||||||
const successKeysContain = ['complete'];
|
const successKeysContain = ['complete'];
|
||||||
@ -90,7 +91,7 @@ const getStatus = (key) => {
|
|||||||
|
|
||||||
export default class index extends Component {
|
export default class index extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: PropTypes.string,
|
status: PropTypes.any,
|
||||||
text: PropTypes.string,
|
text: PropTypes.string,
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
@ -48,6 +48,7 @@ export default class SimpleTable extends React.Component {
|
|||||||
// eslint-disable-next-line react/no-unused-prop-types
|
// eslint-disable-next-line react/no-unused-prop-types
|
||||||
defaultSortOrder: PropTypes.string,
|
defaultSortOrder: PropTypes.string,
|
||||||
onRow: PropTypes.func,
|
onRow: PropTypes.func,
|
||||||
|
childrenColumnName: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -78,6 +79,7 @@ export default class SimpleTable extends React.Component {
|
|||||||
render,
|
render,
|
||||||
isStatus,
|
isStatus,
|
||||||
isName,
|
isName,
|
||||||
|
isPrice,
|
||||||
...rest
|
...rest
|
||||||
} = column;
|
} = column;
|
||||||
if (column.key === 'operation') {
|
if (column.key === 'operation') {
|
||||||
@ -99,6 +101,9 @@ export default class SimpleTable extends React.Component {
|
|||||||
if (dataIndex === 'name' || isName) {
|
if (dataIndex === 'name' || isName) {
|
||||||
newRender = this.getNameRender(newRender, column);
|
newRender = this.getNameRender(newRender, column);
|
||||||
}
|
}
|
||||||
|
if (dataIndex === 'cost' || isPrice) {
|
||||||
|
newRender = this.getPriceRender(newRender, column);
|
||||||
|
}
|
||||||
const newColumn = {
|
const newColumn = {
|
||||||
...rest,
|
...rest,
|
||||||
dataIndex,
|
dataIndex,
|
||||||
@ -196,6 +201,17 @@ export default class SimpleTable extends React.Component {
|
|||||||
return baseColumns;
|
return baseColumns;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
getPriceRender = (render, column) => {
|
||||||
|
if (render) {
|
||||||
|
return render;
|
||||||
|
}
|
||||||
|
return (value) => {
|
||||||
|
const valueStr = isString(value) ? value : (value || 0).toFixed(2);
|
||||||
|
return <span style={{ color: '#f50' }}>{valueStr}</span>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
getDataSource = () => {
|
getDataSource = () => {
|
||||||
const { datas, filters, filterByBackend } = this.props;
|
const { datas, filters, filterByBackend } = this.props;
|
||||||
if (filterByBackend) {
|
if (filterByBackend) {
|
||||||
@ -297,7 +313,8 @@ export default class SimpleTable extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { className, isLoading, rowSelection, footer } = this.props;
|
const { className, isLoading, rowSelection, footer, childrenColumnName } =
|
||||||
|
this.props;
|
||||||
|
|
||||||
const currentColumns = this.getColumns();
|
const currentColumns = this.getColumns();
|
||||||
const dataSource = this.getDataSource();
|
const dataSource = this.getDataSource();
|
||||||
@ -314,6 +331,7 @@ export default class SimpleTable extends React.Component {
|
|||||||
showSorterTooltip={false}
|
showSorterTooltip={false}
|
||||||
footer={footer}
|
footer={footer}
|
||||||
onRow={this.onRow}
|
onRow={this.onRow}
|
||||||
|
childrenColumnName={childrenColumnName}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
// Copyright 2021 99cloud
|
|
||||||
//
|
|
||||||
// Licensed 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.
|
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
|
||||||
|
|
||||||
@observer
|
|
||||||
export default class Observer extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = { visible: !window.IntersectionObserver };
|
|
||||||
this.io = null;
|
|
||||||
this.container = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
(window.IntersectionObserver
|
|
||||||
? Promise.resolve()
|
|
||||||
: import('intersection-observer')
|
|
||||||
).then(() => {
|
|
||||||
this.io = new window.IntersectionObserver((entries) => {
|
|
||||||
entries.forEach((entry) => {
|
|
||||||
this.setState({ visible: entry.isIntersecting });
|
|
||||||
});
|
|
||||||
}, {});
|
|
||||||
this.io.observe(this.container);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
if (this.io) {
|
|
||||||
this.io.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
// 这里也可以使用 findDOMNode 实现,但是不建议
|
|
||||||
<div
|
|
||||||
ref={(div) => {
|
|
||||||
this.container = div;
|
|
||||||
}}
|
|
||||||
{...this.props}
|
|
||||||
>
|
|
||||||
{Array.isArray(this.props.children)
|
|
||||||
? this.props.children.map((child) => child(this.state.visible))
|
|
||||||
: this.props.children(this.state.visible)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,9 +25,7 @@ import styles from './index.less';
|
|||||||
|
|
||||||
const { SubMenu } = Menu;
|
const { SubMenu } = Menu;
|
||||||
|
|
||||||
@inject('rootStore')
|
export class LayoutMenu extends Component {
|
||||||
@observer
|
|
||||||
class LayoutMenu extends Component {
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -57,6 +55,10 @@ class LayoutMenu extends Component {
|
|||||||
this.setState({ collapsed });
|
this.setState({ collapsed });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getImage(isExtend) {
|
||||||
|
return !isExtend ? logoSmall : logoExtend;
|
||||||
|
}
|
||||||
|
|
||||||
changeCollapse = () => {
|
changeCollapse = () => {
|
||||||
const { collapsed } = this.state;
|
const { collapsed } = this.state;
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -200,7 +202,7 @@ class LayoutMenu extends Component {
|
|||||||
renderLogo() {
|
renderLogo() {
|
||||||
const { collapsed, hover } = this.state;
|
const { collapsed, hover } = this.state;
|
||||||
const isExtend = !collapsed || hover;
|
const isExtend = !collapsed || hover;
|
||||||
const imageSvg = !isExtend ? logoSmall : logoExtend;
|
const imageSvg = this.getImage(isExtend);
|
||||||
const homeUrl = this.getUrl('/base/overview');
|
const homeUrl = this.getUrl('/base/overview');
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -240,4 +242,4 @@ class LayoutMenu extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LayoutMenu;
|
export default inject('rootStore')(observer(LayoutMenu));
|
||||||
|
@ -30,9 +30,7 @@ import styles from './index.less';
|
|||||||
|
|
||||||
const { Header } = Layout;
|
const { Header } = Layout;
|
||||||
|
|
||||||
@inject('rootStore')
|
export class BaseLayout extends Component {
|
||||||
@observer
|
|
||||||
class BaseLayout extends Component {
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -204,7 +202,7 @@ class BaseLayout extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
if (this.isAdminPage && !this.hasAdminRole) {
|
if (this.isAdminPage && !this.hasAdminPageRole) {
|
||||||
window.location.href = '/base/overview';
|
window.location.href = '/base/overview';
|
||||||
}
|
}
|
||||||
this.routes = this.props.route.routes;
|
this.routes = this.props.route.routes;
|
||||||
@ -260,4 +258,4 @@ class BaseLayout extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BaseLayout;
|
export default inject('rootStore')(observer(BaseLayout));
|
||||||
|
@ -1572,9 +1572,9 @@
|
|||||||
"The name cannot be modified after creation": "The name cannot be modified after creation",
|
"The name cannot be modified after creation": "The name cannot be modified after creation",
|
||||||
"The name of the physical network to which a port is connected": "The name of the physical network to which a port is connected",
|
"The name of the physical network to which a port is connected": "The name of the physical network to which a port is connected",
|
||||||
"The name should start with upper letter or lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".": "The name should start with upper letter or lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".",
|
"The name should start with upper letter or lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".": "The name should start with upper letter or lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".",
|
||||||
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_().\".": "The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_().\".",
|
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].\".": "The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].\".",
|
||||||
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".": "The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".",
|
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".": "The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".",
|
||||||
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".": "The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".",
|
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_.\".": "The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_.\".",
|
||||||
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 64, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".": "The name should start with upper letter, lower letter or chinese, and be a string of 1 to 64, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".",
|
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 64, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".": "The name should start with upper letter, lower letter or chinese, and be a string of 1 to 64, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".",
|
||||||
"The name should start with upper letter, lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, -, _\".": "The name should start with upper letter, lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, -, _\".",
|
"The name should start with upper letter, lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, -, _\".": "The name should start with upper letter, lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, -, _\".",
|
||||||
"The name should start with upper letter, lower letter, and be a string of 2 to 255, characters can only contain \"0-9, a-z, A-Z, -, ., _\".": "The name should start with upper letter, lower letter, and be a string of 2 to 255, characters can only contain \"0-9, a-z, A-Z, -, ., _\".",
|
"The name should start with upper letter, lower letter, and be a string of 2 to 255, characters can only contain \"0-9, a-z, A-Z, -, ., _\".": "The name should start with upper letter, lower letter, and be a string of 2 to 255, characters can only contain \"0-9, a-z, A-Z, -, ., _\".",
|
||||||
|
@ -869,6 +869,7 @@
|
|||||||
"Invalid: Please input a valid ip": "无效:请输入有效的IP",
|
"Invalid: Please input a valid ip": "无效:请输入有效的IP",
|
||||||
"Invalid: Please input a valid ipv4": "无效:请输入有效的IPV4",
|
"Invalid: Please input a valid ipv4": "无效:请输入有效的IPV4",
|
||||||
"Invalid: Please input a valid ipv6.": "无效:请输入有效的IPV6",
|
"Invalid: Please input a valid ipv6.": "无效:请输入有效的IPV6",
|
||||||
|
"Invalid: Project name can not be chinese": "无效:项目名称不可使用中文",
|
||||||
"Invalid: Project name can not be duplicated": "无效:项目名称不可重复",
|
"Invalid: Project name can not be duplicated": "无效:项目名称不可重复",
|
||||||
"Invalid: Quota value(s) cannot be less than the current usage value(s): { used } used.": "无效:配额必须大于已使用数量{ used }且为整数",
|
"Invalid: Quota value(s) cannot be less than the current usage value(s): { used } used.": "无效:配额必须大于已使用数量{ used }且为整数",
|
||||||
"Invalid: User Group name can not be duplicated": "无效:用户组名称不可重复",
|
"Invalid: User Group name can not be duplicated": "无效:用户组名称不可重复",
|
||||||
@ -1571,9 +1572,9 @@
|
|||||||
"The name cannot be modified after creation": "名称创建后不可修改",
|
"The name cannot be modified after creation": "名称创建后不可修改",
|
||||||
"The name of the physical network to which a port is connected": "端口连接到的物理网络的名称",
|
"The name of the physical network to which a port is connected": "端口连接到的物理网络的名称",
|
||||||
"The name should start with upper letter or lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".": "名称应以大写字母或小写字母开头,最长为128字符,且只包含“0-9, a-z, A-Z, \"'-_()[].:^”。",
|
"The name should start with upper letter or lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".": "名称应以大写字母或小写字母开头,最长为128字符,且只包含“0-9, a-z, A-Z, \"'-_()[].:^”。",
|
||||||
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_().\".": "名称应以大写字母或小写字母开头,最长为128字符,且只包含“0-9, a-z, A-Z, \"'-_().”。",
|
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].\".": "名称应以大写字母,小写字母或中文开头,最长为128字符,且只包含“0-9, a-z, A-Z, \"'-_()[].”。",
|
||||||
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".": "名称应以大写字母,小写字母或中文开头,最长为128字符,且只包含“0-9, a-z, A-Z, \"'-_()[].:^”。",
|
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].:^\".": "名称应以大写字母,小写字母或中文开头,最长为128字符,且只包含“0-9, a-z, A-Z, \"'-_()[].:^”。",
|
||||||
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".": "名称应以大写字母,小写字母或中文开头,最长为128字符,且只包含“0-9, a-z, A-Z, \"'-_()[].^”。",
|
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, \"-'_.\".": "名称应以大写字母,小写字母或中文开头,最长为128字符,且只包含“0-9, a-z, A-Z, \"-'_.”。",
|
||||||
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 64, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".": "名称应以大写字母,小写字母或中文开头,最长为64字符,且只包含“0-9, a-z, A-Z, \"'-_()[].^”。",
|
"The name should start with upper letter, lower letter or chinese, and be a string of 1 to 64, characters can only contain \"0-9, a-z, A-Z, \"-'_()[].^\".": "名称应以大写字母,小写字母或中文开头,最长为64字符,且只包含“0-9, a-z, A-Z, \"'-_()[].^”。",
|
||||||
"The name should start with upper letter, lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, -, _\".": "名称应以大写字母或小写字母开头,最长为128字符,且只包含“0-9, a-z, A-Z, -, _”。",
|
"The name should start with upper letter, lower letter, and be a string of 1 to 128, characters can only contain \"0-9, a-z, A-Z, -, _\".": "名称应以大写字母或小写字母开头,最长为128字符,且只包含“0-9, a-z, A-Z, -, _”。",
|
||||||
"The name should start with upper letter, lower letter, and be a string of 2 to 255, characters can only contain \"0-9, a-z, A-Z, -, ., _\".": "名称应以大写字母或小写字母开头,最长为255字符,且只包含“0-9, a-z, A-Z, -, ., _”。",
|
"The name should start with upper letter, lower letter, and be a string of 2 to 255, characters can only contain \"0-9, a-z, A-Z, -, ., _\".": "名称应以大写字母或小写字母开头,最长为255字符,且只包含“0-9, a-z, A-Z, -, ., _”。",
|
||||||
|
@ -49,9 +49,9 @@ const keypairNameRegex = /^[a-zA-Z][\w_-]{0,127}$/;
|
|||||||
const crontabNameRegex =
|
const crontabNameRegex =
|
||||||
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'\[\]^.:()_-]{0,63}$/; // eslint-disable-line
|
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'\[\]^.:()_-]{0,63}$/; // eslint-disable-line
|
||||||
const imageNameRegex =
|
const imageNameRegex =
|
||||||
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'\[\]^.()_-]{0,127}$/; // eslint-disable-line
|
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'\[\].()_-]{0,127}$/; // eslint-disable-line
|
||||||
const instanceNameRegex =
|
const instanceNameRegex =
|
||||||
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'.()_-]{0,127}$/;
|
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'._-]{0,127}$/;
|
||||||
const ipv6CidrOnly =
|
const ipv6CidrOnly =
|
||||||
/^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*\/(1[01][0-9]|12[0-8]|[0-9]{1,2})$/;
|
/^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*\/(1[01][0-9]|12[0-8]|[0-9]{1,2})$/;
|
||||||
|
|
||||||
@ -307,11 +307,11 @@ const crontabNameMessage = t(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const imageNameMessage = t(
|
const imageNameMessage = t(
|
||||||
'The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain "0-9, a-z, A-Z, "-\'_()[].^".'
|
'The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain "0-9, a-z, A-Z, "-\'_()[].".'
|
||||||
);
|
);
|
||||||
|
|
||||||
const instanceNameMessage = t(
|
const instanceNameMessage = t(
|
||||||
'The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain "0-9, a-z, A-Z, "-\'_().".'
|
'The name should start with upper letter, lower letter or chinese, and be a string of 1 to 128, characters can only contain "0-9, a-z, A-Z, "-\'_.".'
|
||||||
);
|
);
|
||||||
|
|
||||||
export const nameMessageInfo = {
|
export const nameMessageInfo = {
|
||||||
@ -414,7 +414,6 @@ const stackNameValidate = (rule, value) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const crontabNameValidate = (rule, value) => {
|
const crontabNameValidate = (rule, value) => {
|
||||||
console.log(rule, value, isCrontabName(value));
|
|
||||||
if (!rule.required && value === undefined) {
|
if (!rule.required && value === undefined) {
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user