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"
|
||||
placement="rightTop"
|
||||
content={titleHelp}
|
||||
getPopupContainer={(node) => node.parentNode}
|
||||
>
|
||||
<InfoCircleOutlined className={styles['title-help']} />
|
||||
</Popover>
|
||||
|
@ -49,6 +49,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -31,6 +31,7 @@ import {
|
||||
TagOutlined,
|
||||
HddOutlined,
|
||||
CloudServerOutlined,
|
||||
LoadingOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import styles from './index.less';
|
||||
|
||||
@ -82,14 +83,19 @@ export default class index extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { content, value, iconType, ...rest } = this.props;
|
||||
const { content, value, iconType, showLoading, ...rest } = this.props;
|
||||
const failValues = [undefined, null, ''];
|
||||
if (content) {
|
||||
return content;
|
||||
}
|
||||
return (
|
||||
<span {...rest}>
|
||||
{this.renderIcon()}
|
||||
{value}
|
||||
{showLoading && failValues.includes(value) ? (
|
||||
<LoadingOutlined />
|
||||
) : (
|
||||
value
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ export default class SelectTable extends React.Component {
|
||||
defaultSortKey: PropTypes.string,
|
||||
defaultSortOrder: PropTypes.string,
|
||||
onRow: PropTypes.func,
|
||||
childrenColumnName: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@ -105,6 +106,7 @@ export default class SelectTable extends React.Component {
|
||||
isSortByBack: false,
|
||||
defaultSortKey: '',
|
||||
defaultSortOrder: '',
|
||||
childrenColumnName: 'children',
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@ -652,6 +654,7 @@ export default class SelectTable extends React.Component {
|
||||
filterParams,
|
||||
onRow,
|
||||
rowKey,
|
||||
childrenColumnName,
|
||||
} = this.props;
|
||||
const { current, pageSize, total, filters } = this.state;
|
||||
const defaultPageSizeOptions = [10, 20, 50, 100];
|
||||
@ -697,6 +700,7 @@ export default class SelectTable extends React.Component {
|
||||
onChange={this.handleChange}
|
||||
footer={footer}
|
||||
onRow={onRow}
|
||||
childrenColumnName={childrenColumnName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ import TabSelectTable from './TabSelectTable';
|
||||
import TreeSelect from './TreeSelect';
|
||||
// import styles from './index.less';
|
||||
|
||||
const type2component = {
|
||||
export const type2component = {
|
||||
label: Label,
|
||||
input: Input,
|
||||
select: Select,
|
||||
@ -132,8 +132,8 @@ export default class FormItem extends React.Component {
|
||||
getComponentProps(type) {
|
||||
switch (type) {
|
||||
case 'label': {
|
||||
const { content, icon, iconType } = this.props;
|
||||
return { content, icon, iconType };
|
||||
const { content, icon, iconType, showLoading } = this.props;
|
||||
return { content, icon, iconType, showLoading };
|
||||
}
|
||||
case 'divider':
|
||||
return {
|
||||
@ -319,6 +319,10 @@ export default class FormItem extends React.Component {
|
||||
return newRules;
|
||||
}
|
||||
|
||||
getComponent(type) {
|
||||
return type2component[type];
|
||||
}
|
||||
|
||||
renderTip(tip) {
|
||||
if (!tip) {
|
||||
return null;
|
||||
@ -347,7 +351,7 @@ export default class FormItem extends React.Component {
|
||||
if (component) {
|
||||
return <Form.Item {...formItemProps}>{component}</Form.Item>;
|
||||
}
|
||||
const TypeComp = type2component[type];
|
||||
const TypeComp = this.getComponent(type);
|
||||
const props = this.getComponentProps(type);
|
||||
if (type === '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 {
|
||||
line-height: 32px;
|
||||
margin-left: 8px;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ const successKeys = [
|
||||
'power on',
|
||||
'complete',
|
||||
'online',
|
||||
'ready',
|
||||
];
|
||||
|
||||
const successKeysContain = ['complete'];
|
||||
@ -90,7 +91,7 @@ const getStatus = (key) => {
|
||||
|
||||
export default class index extends Component {
|
||||
static propTypes = {
|
||||
status: PropTypes.string,
|
||||
status: PropTypes.any,
|
||||
text: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
};
|
||||
|
@ -48,6 +48,7 @@ export default class SimpleTable extends React.Component {
|
||||
// eslint-disable-next-line react/no-unused-prop-types
|
||||
defaultSortOrder: PropTypes.string,
|
||||
onRow: PropTypes.func,
|
||||
childrenColumnName: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@ -78,6 +79,7 @@ export default class SimpleTable extends React.Component {
|
||||
render,
|
||||
isStatus,
|
||||
isName,
|
||||
isPrice,
|
||||
...rest
|
||||
} = column;
|
||||
if (column.key === 'operation') {
|
||||
@ -99,6 +101,9 @@ export default class SimpleTable extends React.Component {
|
||||
if (dataIndex === 'name' || isName) {
|
||||
newRender = this.getNameRender(newRender, column);
|
||||
}
|
||||
if (dataIndex === 'cost' || isPrice) {
|
||||
newRender = this.getPriceRender(newRender, column);
|
||||
}
|
||||
const newColumn = {
|
||||
...rest,
|
||||
dataIndex,
|
||||
@ -196,6 +201,17 @@ export default class SimpleTable extends React.Component {
|
||||
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 = () => {
|
||||
const { datas, filters, filterByBackend } = this.props;
|
||||
if (filterByBackend) {
|
||||
@ -297,7 +313,8 @@ export default class SimpleTable extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { className, isLoading, rowSelection, footer } = this.props;
|
||||
const { className, isLoading, rowSelection, footer, childrenColumnName } =
|
||||
this.props;
|
||||
|
||||
const currentColumns = this.getColumns();
|
||||
const dataSource = this.getDataSource();
|
||||
@ -314,6 +331,7 @@ export default class SimpleTable extends React.Component {
|
||||
showSorterTooltip={false}
|
||||
footer={footer}
|
||||
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;
|
||||
|
||||
@inject('rootStore')
|
||||
@observer
|
||||
class LayoutMenu extends Component {
|
||||
export class LayoutMenu extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -57,6 +55,10 @@ class LayoutMenu extends Component {
|
||||
this.setState({ collapsed });
|
||||
};
|
||||
|
||||
getImage(isExtend) {
|
||||
return !isExtend ? logoSmall : logoExtend;
|
||||
}
|
||||
|
||||
changeCollapse = () => {
|
||||
const { collapsed } = this.state;
|
||||
this.setState({
|
||||
@ -200,7 +202,7 @@ class LayoutMenu extends Component {
|
||||
renderLogo() {
|
||||
const { collapsed, hover } = this.state;
|
||||
const isExtend = !collapsed || hover;
|
||||
const imageSvg = !isExtend ? logoSmall : logoExtend;
|
||||
const imageSvg = this.getImage(isExtend);
|
||||
const homeUrl = this.getUrl('/base/overview');
|
||||
return (
|
||||
<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;
|
||||
|
||||
@inject('rootStore')
|
||||
@observer
|
||||
class BaseLayout extends Component {
|
||||
export class BaseLayout extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -204,7 +202,7 @@ class BaseLayout extends Component {
|
||||
};
|
||||
|
||||
init() {
|
||||
if (this.isAdminPage && !this.hasAdminRole) {
|
||||
if (this.isAdminPage && !this.hasAdminPageRole) {
|
||||
window.location.href = '/base/overview';
|
||||
}
|
||||
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 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, 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, 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, -, ., _\".",
|
||||
|
@ -869,6 +869,7 @@
|
||||
"Invalid: Please input a valid ip": "无效:请输入有效的IP",
|
||||
"Invalid: Please input a valid ipv4": "无效:请输入有效的IPV4",
|
||||
"Invalid: Please input a valid ipv6.": "无效:请输入有效的IPV6",
|
||||
"Invalid: Project name can not be chinese": "无效:项目名称不可使用中文",
|
||||
"Invalid: Project name can not be duplicated": "无效:项目名称不可重复",
|
||||
"Invalid: Quota value(s) cannot be less than the current usage value(s): { used } used.": "无效:配额必须大于已使用数量{ used }且为整数",
|
||||
"Invalid: User Group name can not be duplicated": "无效:用户组名称不可重复",
|
||||
@ -1571,9 +1572,9 @@
|
||||
"The name cannot be modified after creation": "名称创建后不可修改",
|
||||
"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, 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, 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, -, ., _”。",
|
||||
|
@ -49,9 +49,9 @@ const keypairNameRegex = /^[a-zA-Z][\w_-]{0,127}$/;
|
||||
const crontabNameRegex =
|
||||
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'\[\]^.:()_-]{0,63}$/; // eslint-disable-line
|
||||
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 =
|
||||
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'.()_-]{0,127}$/;
|
||||
/^[a-zA-Z\u4e00-\u9fa5][\u4e00-\u9fa5\w"'._-]{0,127}$/;
|
||||
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})$/;
|
||||
|
||||
@ -307,11 +307,11 @@ const crontabNameMessage = 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(
|
||||
'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 = {
|
||||
@ -414,7 +414,6 @@ const stackNameValidate = (rule, value) => {
|
||||
};
|
||||
|
||||
const crontabNameValidate = (rule, value) => {
|
||||
console.log(rule, value, isCrontabName(value));
|
||||
if (!rule.required && value === undefined) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user