diff --git a/.stylelintrc.json b/.stylelintrc.json
index 6b966ac3..943d5b62 100644
--- a/.stylelintrc.json
+++ b/.stylelintrc.json
@@ -14,7 +14,7 @@
"property-no-unknown": [
true,
{
- "ignoreProperties": ["/Color$/", "/Height$/"]
+ "ignoreProperties": ["/Color$/", "/Height$/", "productsColumnWidth"]
}
]
}
diff --git a/config/config.yaml b/config/config.yaml
index aa5b1344..653164f9 100644
--- a/config/config.yaml
+++ b/config/config.yaml
@@ -2,6 +2,8 @@ host: 0.0.0.0
port: 8088
server: http://localhost
+theme: default
+
globalVariables:
defaultLanguage: en
supportLanguages: # use value in i18n.js
diff --git a/config/js-string-replace-loader.js b/config/js-string-replace-loader.js
new file mode 100644
index 00000000..293f9fdd
--- /dev/null
+++ b/config/js-string-replace-loader.js
@@ -0,0 +1,20 @@
+const { getOptions } = require('loader-utils');
+
+module.exports = function (source) {
+ const { search, change } = getOptions(this) || {}; // getOptions用于获取配置
+ if (!search || !change) {
+ return source;
+ }
+ if (source.includes(search)) {
+ // eslint-disable-next-line no-console
+ console.log(
+ 'has-search',
+ search,
+ 'in',
+ this.resource,
+ 'replace to',
+ change
+ );
+ }
+ return source.replace(search, change);
+};
diff --git a/config/less-replace-loader.js b/config/less-replace-loader.js
new file mode 100644
index 00000000..94ee737b
--- /dev/null
+++ b/config/less-replace-loader.js
@@ -0,0 +1,17 @@
+const { getOptions } = require('loader-utils');
+
+module.exports = function (source) {
+ const { variableFile } = getOptions(this) || {}; // getOptions用于获取配置
+ if (!variableFile) {
+ return source;
+ }
+
+ // 将 @import "styles/variables"; 变更为 @import "styles/variables";
+ const consoleReg = /~styles\/variables/g;
+ if (consoleReg.test(source)) {
+ // eslint-disable-next-line no-console
+ console.log(this.resourcePath, 'match ~styles/variables');
+ return source.replace(consoleReg, `~${variableFile}`);
+ }
+ return source;
+};
diff --git a/config/theme-custom.js b/config/theme-custom.js
new file mode 100644
index 00000000..3a30a6a7
--- /dev/null
+++ b/config/theme-custom.js
@@ -0,0 +1,26 @@
+// 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.
+
+module.exports = {
+ 'primary-color': '#0C63FA',
+ 'link-color': '#0C63FA',
+ 'success-color': '#52C41A',
+ 'warning-color': '#FAAD14',
+ 'error-color': '#D40000',
+ 'btn-default-color': '#0C63FA',
+ 'btn-default-border': '#0C63FA',
+ 'border-color-base': '#E8E8EA',
+ 'border-radius-base': '2px',
+ 'font-size-base': '12px',
+};
diff --git a/config/utils.js b/config/utils.js
index 8a67e75b..aa56dcba 100644
--- a/config/utils.js
+++ b/config/utils.js
@@ -7,6 +7,12 @@ const { merge, extend, has } = require('lodash');
const root = (dir) =>
`${path.resolve(__dirname, './')}/${dir}`.replace(/(\/+)/g, '/');
+const configRoot = (dir) =>
+ `${path.resolve(__dirname, '../config')}/${dir}`.replace(/(\/+)/g, '/');
+
+const srcRoot = (dir) =>
+ `${path.resolve(__dirname, '../src')}/${dir}`.replace(/(\/+)/g, '/');
+
const loadYaml = (filePath) => {
try {
return yaml.load(fs.readFileSync(filePath), 'utf8');
@@ -50,15 +56,101 @@ const getObjectConfig = (key) => {
return result;
};
+const getConfig = (key) => {
+ // parse config yaml
+ const config = loadYaml(root('./config.yaml')) || {};
+
+ const tryFile = root('./local_config.yaml');
+ if (fs.existsSync(tryFile)) {
+ // merge local_config
+ const local_config = loadYaml(tryFile);
+ if (typeof local_config === 'object') {
+ merge(config, local_config);
+ }
+ }
+
+ return key ? config[key] : config;
+};
+
+const THEMES = {
+ default: {
+ themeFile: 'theme.js',
+ lessVariablesName: 'styles/variables',
+ globalVariables: {
+ menuTheme: 'dark',
+ skylineThemeName: 'default',
+ },
+ },
+ custom: {
+ themeFile: 'theme-custom.js',
+ lessVariablesName: 'styles/variables-custom',
+ globalVariables: {
+ menuTheme: 'light',
+ skylineThemeName: 'custom',
+ },
+ },
+};
+
+const getThemeConfig = () => {
+ // parse config yaml
+ const themeName = getConfig('theme') || 'default';
+
+ const themeInfo = THEMES[themeName] || THEMES.default;
+
+ const themeFile = configRoot(themeInfo.themeFile);
+
+ // eslint-disable-next-line no-console
+ console.log('themeFile', themeFile);
+
+ if (fs.existsSync(themeFile)) {
+ // eslint-disable-next-line import/no-dynamic-require
+ const config = require(themeFile);
+ return config;
+ }
+
+ // eslint-disable-next-line no-console
+ console.error('the theme file not exist');
+ return {};
+};
+
+const getCustomStyleVariables = () => {
+ const themeName = getConfig('theme') || 'default';
+ const themeInfo = THEMES[themeName] || THEMES.default;
+ const lessFileName = themeInfo.lessVariablesName;
+ const defaultLessFile = THEMES.default.lessVariablesName;
+
+ if (defaultLessFile === lessFileName) {
+ return false;
+ }
+
+ const customFile = srcRoot(`${lessFileName}.less`);
+ // eslint-disable-next-line no-console
+ console.log('customFile', customFile);
+ const exist = fs.existsSync(customFile) && lessFileName;
+ // eslint-disable-next-line no-console
+ console.log('exist', exist);
+ return exist;
+};
+
+const getGlobalVariablesForTheme = () => {
+ const themeName = getConfig('theme') || 'default';
+ const themeInfo = THEMES[themeName] || THEMES.default;
+ return themeInfo.globalVariables || {};
+};
+
const getGlobalVariables = () => {
const variables = getObjectConfig('globalVariables') || {};
+ const themeVariables = getGlobalVariablesForTheme();
+ const allVariables = { ...variables, ...themeVariables };
// eslint-disable-next-line no-console
- console.log('globalVariables', variables, JSON.stringify(variables));
- return JSON.stringify(variables);
+ console.log('globalVariables', allVariables, JSON.stringify(allVariables));
+ return JSON.stringify(allVariables);
};
module.exports = {
getServerConfig,
root,
getGlobalVariables,
+ getThemeConfig,
+ getCustomStyleVariables,
};
diff --git a/config/webpack.common.js b/config/webpack.common.js
index 1b503288..ca3b39f1 100644
--- a/config/webpack.common.js
+++ b/config/webpack.common.js
@@ -17,7 +17,7 @@ const { normalize, resolve } = require('path');
// const path = require("path");
// const CleanWebpackPlugin = require('clean-webpack-plugin');
const moment = require('moment');
-const { getGlobalVariables } = require('./utils');
+const { getGlobalVariables, getCustomStyleVariables } = require('./utils');
const root = (path) => resolve(__dirname, `../${path}`);
const version = moment().unix();
@@ -25,9 +25,18 @@ const version = moment().unix();
module.exports = {
module: {
rules: [
+ {
+ test: /\.jsx$/,
+ loader: resolve('config/js-string-replace-loader'),
+ include: [root('src/core')],
+ options: {
+ search: 'styles/variables',
+ change: getCustomStyleVariables(),
+ },
+ },
{
test: /\.jsx?$/,
- include: root('node_modules'),
+ include: [root('src'), root('node_modules')],
use: ['thread-loader', 'cache-loader'],
},
{
@@ -73,7 +82,10 @@ module.exports = {
},
},
],
- include: [root('src/asset/image/cloud-logo.svg')],
+ include: [
+ root('src/asset/image/cloud-logo.svg'),
+ root('src/asset/image/cloud-logo-white.svg'),
+ ],
},
{
test: /\.(woff|woff2|ttf|eot|svg)$/,
@@ -86,7 +98,10 @@ module.exports = {
},
},
],
- exclude: [root('src/asset/image/cloud-logo.svg')],
+ exclude: [
+ root('src/asset/image/cloud-logo.svg'),
+ root('src/asset/image/cloud-logo-white.svg'),
+ ],
},
],
},
diff --git a/config/webpack.dev.js b/config/webpack.dev.js
index abb58200..bff16d61 100644
--- a/config/webpack.dev.js
+++ b/config/webpack.dev.js
@@ -21,10 +21,15 @@ const HtmlWebPackPlugin = require('html-webpack-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const common = require('./webpack.common');
-const theme = require('./theme');
const server = require('./server.dev');
+const { getThemeConfig, getCustomStyleVariables } = require('./utils');
+
+const theme = getThemeConfig();
+
+console.log('theme', theme);
+
const root = (path) => resolve(__dirname, `../${path}`);
const { host, port, proxy } = server;
@@ -129,7 +134,12 @@ module.exports = (env) => {
options: {
importLoaders: true,
javascriptEnabled: true,
- modifyVars: theme,
+ },
+ },
+ {
+ loader: resolve('config/less-replace-loader'),
+ options: {
+ variableFile: getCustomStyleVariables(),
},
},
],
diff --git a/config/webpack.e2e.js b/config/webpack.e2e.js
index 4578d129..e70c692f 100644
--- a/config/webpack.e2e.js
+++ b/config/webpack.e2e.js
@@ -21,7 +21,10 @@ const autoprefixer = require('autoprefixer');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const common = require('./webpack.common');
-const theme = require('./theme');
+
+const { getThemeConfig, getCustomStyleVariables } = require('./utils');
+
+const theme = getThemeConfig();
const root = (path) => resolve(__dirname, `../${path}`);
@@ -102,7 +105,12 @@ module.exports = (env) => {
options: {
importLoaders: true,
javascriptEnabled: true,
- modifyVars: theme,
+ },
+ },
+ {
+ loader: resolve('config/less-replace-loader'),
+ options: {
+ variableFile: getCustomStyleVariables(),
},
},
],
diff --git a/config/webpack.prod.js b/config/webpack.prod.js
index aabf38f0..38c76b6a 100644
--- a/config/webpack.prod.js
+++ b/config/webpack.prod.js
@@ -22,7 +22,10 @@ const CleanWebpackPlugin = require('clean-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const common = require('./webpack.common');
-const theme = require('./theme');
+
+const { getThemeConfig, getCustomStyleVariables } = require('./utils');
+
+const theme = getThemeConfig();
const root = (path) => resolve(__dirname, `../${path}`);
@@ -91,7 +94,12 @@ module.exports = (env) => {
options: {
importLoaders: true,
javascriptEnabled: true,
- modifyVars: theme,
+ },
+ },
+ {
+ loader: resolve('config/less-replace-loader'),
+ options: {
+ variableFile: getCustomStyleVariables(),
},
},
],
diff --git a/releasenotes/notes/Support-A-Custom-Theme-fe56c9dc8d3bfe03.yaml b/releasenotes/notes/Support-A-Custom-Theme-fe56c9dc8d3bfe03.yaml
new file mode 100644
index 00000000..b36cc890
--- /dev/null
+++ b/releasenotes/notes/Support-A-Custom-Theme-fe56c9dc8d3bfe03.yaml
@@ -0,0 +1,11 @@
+---
+features:
+ - |
+ Support a custom UI theme
+
+ * Support theme setting in the config.yaml file, optional values: default, custom.
+ The default value represents the old theme, the custom value represents the new theme,
+ and the color is light.
+
+ * When you want to use the customized new theme, you can set `theme: custom` in config.yaml
+ or local_config.yaml.
diff --git a/src/asset/image/cloud-logo-white.svg b/src/asset/image/cloud-logo-white.svg
new file mode 100644
index 00000000..2335b730
--- /dev/null
+++ b/src/asset/image/cloud-logo-white.svg
@@ -0,0 +1,21 @@
+
+
diff --git a/src/components/Layout/GlobalHeader/AvatarDropdown.jsx b/src/components/Layout/GlobalHeader/AvatarDropdown.jsx
index 3a501cfe..41bf750b 100644
--- a/src/components/Layout/GlobalHeader/AvatarDropdown.jsx
+++ b/src/components/Layout/GlobalHeader/AvatarDropdown.jsx
@@ -145,12 +145,12 @@ export class AvatarDropdown extends React.Component {
-
+
{this.renderLanguageMenuItem()}
{
const homeUrl = getRoutePath('overview');
+ const logoSrc =
+ GLOBAL_VARIABLES.skylineThemeName === 'default'
+ ? cloudLogo
+ : cloudLogoWhite;
return (
-
+
);
diff --git a/src/components/Layout/GlobalHeader/index.less b/src/components/Layout/GlobalHeader/index.less
index f14d660f..ec26222b 100644
--- a/src/components/Layout/GlobalHeader/index.less
+++ b/src/components/Layout/GlobalHeader/index.less
@@ -1,29 +1,40 @@
@import '~styles/variables';
.menu {
+ color: @avatar-dropdown-text-color;
+ background-color: @avatar-dropdown-background-color;
+
:global(.anticon) {
margin-right: 8px;
}
- :global(.ant-dropdown-menu-item) {
- min-width: 245px;
+ :global {
+ .ant-dropdown-menu-item {
+ min-width: 245px;
+ color: @avatar-dropdown-text-color;
+
+ &:hover {
+ color: @avatar-dropdown-hover-text-color;
+ background-color: @avatar-dropdown-hover-background-color;
+ }
+ }
}
.no-hover {
overflow: hidden;
&:hover {
- background-color: #fff;
+ background-color: @avatar-dropdown-hover-background-color;
}
}
.name-item {
padding: 0 12px;
+ font-weight: bold;
line-height: 40px;
.user-label {
margin-right: 8px;
- font-weight: 'bold';
}
span {
@@ -33,6 +44,24 @@
.menu-item {
line-height: 30px;
+
+ :global {
+ .ant-btn {
+ color: @avatar-dropdown-button-color;
+ }
+
+ .ant-btn-link[disabled] {
+ color: @avatar-dropdown-button-disabled-color;
+ }
+ }
+ }
+
+ .menu-btn {
+ color: @avatar-dropdown-button-color;
+ }
+
+ .menu-divider {
+ background-color: @avatar-dropdown-divider-color;
}
}
@@ -110,15 +139,15 @@
height: 100%;
padding-left: 0;
overflow: hidden;
- color: @title-color;
- background-color: #fff;
+ color: @layout-text-color;
+ background-color: @layout-header-color;
box-shadow: 0 2px 20px 0 rgba(0, 0, 0, 9%);
}
.avatar {
width: 30px;
height: 30px;
- color: #bfbfbf;
+ color: @avatar-color;
border: none;
box-shadow: 0 2px 20px 0 rgba(0, 0, 0, 9%);
}
@@ -162,7 +191,11 @@
.single-link {
margin-right: 5px;
- color: @primary-color;
+ color: @layout-link-color;
+
+ &:hover {
+ color: @layout-link-color;
+ }
}
.token {
@@ -178,12 +211,12 @@
.logo {
float: left;
- width: 190px;
+ width: @layout-header-logo-wrapper-width;
height: @header-height;
line-height: @header-height;
text-align: center;
img {
- height: 30px;
+ height: @layout-header-logo-image-height;
}
}
diff --git a/src/components/Layout/GlobalNav/Left/index.jsx b/src/components/Layout/GlobalNav/Left/index.jsx
index e5dd7a26..b9923794 100644
--- a/src/components/Layout/GlobalNav/Left/index.jsx
+++ b/src/components/Layout/GlobalNav/Left/index.jsx
@@ -48,6 +48,10 @@ export default class Left extends React.Component {
render() {
const { items } = this.props;
- return {items.map(this.renderItem)}
;
+ return (
+
+ {items.map(this.renderItem)}
+
+ );
}
}
diff --git a/src/components/Layout/GlobalNav/Left/index.less b/src/components/Layout/GlobalNav/Left/index.less
index e5fe8563..21021b39 100644
--- a/src/components/Layout/GlobalNav/Left/index.less
+++ b/src/components/Layout/GlobalNav/Left/index.less
@@ -1,18 +1,23 @@
+@import '~styles/variables';
+
+// .left {}
+
.item {
padding: 12px 24px;
cursor: pointer;
&:hover {
- background-color: rgba(0, 0, 0, 5%);
+ background-color: @products-drawer-hover-background-1;
}
}
.item-label {
display: block;
width: 100%;
- color: #000;
+ color: @products-title-color;
+ font-size: 13px;
&:hover {
- color: #000;
+ color: @products-title-color;
}
}
diff --git a/src/components/Layout/GlobalNav/Right/index.jsx b/src/components/Layout/GlobalNav/Right/index.jsx
index 1be888e2..893ed59d 100644
--- a/src/components/Layout/GlobalNav/Right/index.jsx
+++ b/src/components/Layout/GlobalNav/Right/index.jsx
@@ -15,13 +15,12 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Input } from 'antd';
+import { SearchOutlined } from '@ant-design/icons';
import PropTypes from 'prop-types';
import { navItemPropType } from '../common';
import styles from './index.less';
-const { Search } = Input;
-
export default class Right extends React.Component {
static propTypes = {
items: PropTypes.oneOfType([
@@ -113,11 +112,11 @@ export default class Right extends React.Component {
renderSearch() {
return (
- }
placeholder={t('Search')}
allowClear
onChange={this.onInputChange}
- onSearch={this.onSearch}
/>
);
diff --git a/src/components/Layout/GlobalNav/Right/index.less b/src/components/Layout/GlobalNav/Right/index.less
index a4dd302b..581a3ad3 100644
--- a/src/components/Layout/GlobalNav/Right/index.less
+++ b/src/components/Layout/GlobalNav/Right/index.less
@@ -1,3 +1,5 @@
+@import '~styles/variables';
+
.right {
columns: 200px 3;
column-gap: 12px;
@@ -13,7 +15,7 @@
box-sizing: border-box;
height: 32px;
margin-bottom: 4px;
- color: #000;
+ color: @products-title-color;
font-weight: 600;
font-size: 14px;
line-height: 22px;
@@ -33,17 +35,53 @@
}
&:hover {
- background-color: rgba(0, 0, 0, 5%);
+ color: @products-drawer-sub-title-hover-color;
+ background-color: @products-drawer-sub-title-hover-background;
+
+ .link-name {
+ color: @products-drawer-sub-title-hover-color;
+ }
}
.link-name {
- color: #000;
+ color: @products-sub-title-color;
}
}
.search {
- width: 90%;
+ width: 60%;
margin-top: -8px;
margin-bottom: 16px;
margin-left: 0;
+
+ :global {
+ .ant-input-affix-wrapper {
+ background-color: @products-drawer-search-background;
+ border: @products-drawer-search-border;
+ border-color: @products-drawer-search-border-color;
+ box-shadow: none;
+ }
+
+ .anticon-search {
+ color: @products-drawer-search-icon !important;
+ }
+
+ .ant-input {
+ color: @products-drawer-search-input-color;
+ background-color: @products-drawer-search-background;
+
+ &:hover {
+ border: @products-drawer-search-hover-border-color;
+ }
+ }
+
+ .ant-input-affix-wrapper:not(.ant-input-affix-wrapper-disabled):hover {
+ border-color: @products-drawer-search-hover-border-color;
+ }
+
+ .ant-input-clear-icon,
+ .ant-input-clear-icon:active {
+ color: @products-drawer-search-input-color;
+ }
+ }
}
diff --git a/src/components/Layout/GlobalNav/index.jsx b/src/components/Layout/GlobalNav/index.jsx
index f5eacdc8..2df0386d 100644
--- a/src/components/Layout/GlobalNav/index.jsx
+++ b/src/components/Layout/GlobalNav/index.jsx
@@ -64,6 +64,10 @@ export class GlobalNav extends React.Component {
height: `calc(100% - ${globalCSS.headerHeight})`,
};
+ const productsColumnWidth = Number(
+ globalCSS.productsColumnWidth.replace('px', '')
+ );
+
return (
<>
@@ -75,30 +79,32 @@ export class GlobalNav extends React.Component {
}
>
diff --git a/src/components/Layout/GlobalNav/index.less b/src/components/Layout/GlobalNav/index.less
index 438d8241..2723b406 100644
--- a/src/components/Layout/GlobalNav/index.less
+++ b/src/components/Layout/GlobalNav/index.less
@@ -9,8 +9,12 @@
font-size: 16px;
line-height: @header-height;
text-align: center;
- background-color: @primary-color;
+ background-color: @products-icon-background;
cursor: pointer;
+
+ &:hover {
+ background-color: @products-icon-hover-background;
+ }
}
.global-nav-icon-icon {
@@ -20,3 +24,33 @@
.main {
padding: 32px 32px 0;
}
+
+.drawer-left {
+ :global {
+ .ant-drawer-header {
+ background-color: @products-drawer-background-1;
+
+ .ant-drawer-title {
+ color: @products-header-title-color;
+ }
+
+ border-bottom-color: @products-drawer-divider-color-1;
+ }
+
+ .ant-drawer-body {
+ background-color: @products-drawer-background-2;
+ }
+ }
+}
+
+.drawer-right {
+ :global {
+ .ant-drawer-body {
+ background-color: @products-drawer-background-1;
+ }
+
+ .ant-drawer-close {
+ color: @products-drawer-close-icon;
+ }
+ }
+}
diff --git a/src/components/MagicInput/index.jsx b/src/components/MagicInput/index.jsx
index 90803c47..b4964222 100644
--- a/src/components/MagicInput/index.jsx
+++ b/src/components/MagicInput/index.jsx
@@ -565,7 +565,8 @@ class MagicInput extends PureComponent {
className={classnames(
'magic-input-wrapper',
styles['magic-input-wrapper'],
- isFocus ? styles['magic-input-wrapper-active'] : ''
+ isFocus ? styles['magic-input-wrapper-active'] : '',
+ isFocus ? 'magic-input-wrapper-active' : ''
)}
>
{this.renderTags()}
diff --git a/src/components/MagicInput/index.less b/src/components/MagicInput/index.less
index f1e5e0d4..686f604b 100644
--- a/src/components/MagicInput/index.less
+++ b/src/components/MagicInput/index.less
@@ -11,8 +11,8 @@
width: 100%;
min-width: 200px;
padding: 3px 0 3px 8px;
- background-color: #fff;
- border: 1px solid rgb(217, 217, 217);
+ background-color: @table-header-search-input-background;
+ border: 1px solid @table-header-search-input-border-color;
border-radius: @border-radius;
:global {
@@ -22,7 +22,7 @@
margin-bottom: 1px;
padding: 0 4px;
color: #fff;
- font-size: 10px;
+ font-size: @table-header-search-input-font-size;
line-height: 24px;
background-color: @primary-color;
border: none;
@@ -69,7 +69,7 @@
}
input::placeholder {
- font-size: 10px;
+ font-size: @table-header-search-input-font-size;
}
.ant-menu-vertical > .ant-menu-item {
@@ -80,7 +80,7 @@
.ant-menu-vertical .ant-menu-item {
margin-top: 0;
margin-bottom: 0;
- font-size: 10px;
+ font-size: @table-header-search-input-font-size;
}
}
}
@@ -101,7 +101,7 @@
}
.key {
- font-size: 10px;
+ font-size: @table-header-search-input-font-size;
line-height: 24px;
:global {
@@ -156,6 +156,7 @@
.close-btn {
height: 28px !important;
padding: 0;
+ background-color: @table-header-default-button-background;
border: none;
}
}
diff --git a/src/components/Tables/Base/index.less b/src/components/Tables/Base/index.less
index b2e7594d..d6b69b35 100644
--- a/src/components/Tables/Base/index.less
+++ b/src/components/Tables/Base/index.less
@@ -81,6 +81,35 @@
.ant-btn[disabled] {
box-shadow: 0 2px 0 rgba(0, 0, 0, 4.5%);
}
+
+ .ant-btn-default {
+ color: @table-header-default-button-color;
+ background-color: @table-header-default-button-background;
+ border-color: @table-header-default-button-border;
+ }
+
+ .ant-btn-default:hover {
+ color: @primary-color;
+ border-color: @primary-color;
+ }
+
+ .ant-btn-dangerous {
+ color: @table-header-danger-button-color;
+ }
+
+ .ant-btn-dangerous:hover {
+ color: @error-color;
+ border-color: @error-color;
+ }
+
+ .ant-btn[disabled],
+ .ant-btn[disabled]:hover,
+ .ant-btn[disabled]:focus,
+ .ant-btn[disabled]:active {
+ color: @table-header-disable-button-color !important;
+ background: @table-header-disable-button-background !important;
+ border-color: @table-header-disable-button-border !important;
+ }
}
}
diff --git a/src/components/Tables/SimpleTable/index.jsx b/src/components/Tables/SimpleTable/index.jsx
index 36fd6be9..3a89c0cc 100644
--- a/src/components/Tables/SimpleTable/index.jsx
+++ b/src/components/Tables/SimpleTable/index.jsx
@@ -283,7 +283,11 @@ export default class SimpleTable extends React.Component {
const dataSource = this.getDataSource();
return (
1) {
return null;
}
- if (!item.children || item.children.length === 0 || item.level) {
+ const { showChildren = true } = item;
+ if (
+ !showChildren ||
+ !item.children ||
+ item.children.length === 0 ||
+ item.level
+ ) {
return (
{/* */}
{item.icon}
-
+
{item.name.length >= this.maxTitleLength ? (
{item.name}
@@ -224,7 +236,7 @@ export class LayoutMenu extends Component {
const newSelectedKeys = this.getSelectedKeysForMenu(selectedKeys);
return (