diff --git a/.eslintignore b/.eslintignore index 1670a42..f29e7db 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ coverage view app/controller/app.js docs_dist +public/ diff --git a/.gitignore b/.gitignore index e5a7a7e..7c0d85e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,14 @@ logs/ npm-debug.log -yarn-error.log node_modules/ package-lock.json -yarn.lock -coverage/ .nyc_output docs_dist/ .idea/ .vscode/ app/public/**/*.js app/public/**/*.css +view/public/ run/ .DS_Store *.sw* diff --git a/app/controller/home.js b/app/controller/home.js index 5b33764..152999a 100644 --- a/app/controller/home.js +++ b/app/controller/home.js @@ -9,6 +9,7 @@ class HomeController extends Controller { const ctx = this.ctx; const user = ctx.session.user; const { appid, callbackUrl } = ctx.app.config.authorize.dingtalkAuth; + const { data: configRes } = await this.ctx.model.Config.findOne({ raw: true }); ctx.body = await this.app.render({ dingtalkAuth: { appid, @@ -19,7 +20,7 @@ class HomeController extends Controller { title: 'Reliable Suites for Macaca', pageId: 'home', SERVER_ADDRESS: this.config.reliableView.serverUrl, - assetsUrl: this.config.reliableView.assetsUrl, + assetsUrl: configRes.site.assetsUrl || this.config.reliableView.assetsUrl, version: this.app.config.pkg.version, }); } diff --git a/test/fixtures/config-data.json b/test/fixtures/config-data.json index 9fff414..18cc180 100644 --- a/test/fixtures/config-data.json +++ b/test/fixtures/config-data.json @@ -1,9 +1,11 @@ { - "type": "webhooks", "webhooks": [ { "tag": "build", "url": "https://localhost" } - ] + ], + "site": { + "assetsUrl": "" + } } diff --git a/view/.eslintignore b/view/.eslintignore index cb32de6..8904517 100644 --- a/view/.eslintignore +++ b/view/.eslintignore @@ -1,7 +1,6 @@ **/.* **/node_modules -**/dist +**/public **/assets **/coverage **/reports - diff --git a/view/package.json b/view/package.json index 3e94b2c..746dfa3 100644 --- a/view/package.json +++ b/view/package.json @@ -1,12 +1,10 @@ { "name": "reliable-view", - "version": "", + "version": "1.0.1", "description": "view layer for Reliable", "files": [ - "dist/*.js", - "dist/*.css", - "lib/*.js", - "index.html" + "public/*.js", + "public/*.css" ], "links": { "issues": "https://github.com/macacajs/reliable/issues?utf8=%E2%9C%93&q=", @@ -19,8 +17,9 @@ "test": "macaca run -d ./test", "lint": "eslint --fix . --ext jsx,js && stylelint --fix assets/**/*.less -s less", "build": "NODE_ENV=production webpack -p --mode production", + "build:local": "DIST_DIR=./public npm run build", "build:report": "npm run build --report", - "prepublishOnly": "npm run build", + "prepublishOnly": "npm run build:local", "ci": "npm run lint && npm run build && npm run serve && npm test" }, "precommit": [ diff --git a/view/src/components/DingdingSetting.js b/view/src/components/DingdingSetting.js index a098b4e..fc5db36 100644 --- a/view/src/components/DingdingSetting.js +++ b/view/src/components/DingdingSetting.js @@ -65,7 +65,6 @@ class DingdingSetting extends React.Component { postWebhooks = async (webhooks) => { const res = await request('postWebhooks', 'POST', { - type: 'webhooks', webhooks, }); if (res.success) { diff --git a/view/src/components/SiteSetting.js b/view/src/components/SiteSetting.js new file mode 100644 index 0000000..a1ae0ae --- /dev/null +++ b/view/src/components/SiteSetting.js @@ -0,0 +1,114 @@ +'use strict'; + +import React from 'react'; +import safeGet from 'lodash.get'; +import { FormattedMessage } from 'react-intl'; +import { + Form, + Icon, + Spin, + Input, + Button, + Select, + message, +} from 'antd'; + +import request from '../util/request'; + +const FormItem = Form.Item; +const Option = Select.Option; + +const siteConfigFormItemLayout = { + wrapperCol: { + xs: { span: 24 }, + sm: { offset: 4, span: 16 }, + }, +}; +const buttonFormItemLayout = { + wrapperCol: { + xs: { span: 24 }, + sm: { offset: 10, span: 4 }, + }, +}; + +class SiteSetting extends React.Component { + state = { + } + + componentDidMount () { + this.fetchSite(); + } + + fetchSite = async () => { + this.setState({ loading: true }); + const res = await request('getSite', 'GET'); + this.setState({ loading: false }); + if (!res.success) return; + + const siteConfig = safeGet(res, 'data.site'); + this.setState({ + siteConfig, + }); + } + + postSite = async (siteConfig) => { + const res = await request('postSite', 'POST', { + site: siteConfig, + }); + if (res.success) { + await this.fetchSite(); + message.success('Update siteConfig successfully!'); + } else { + message.error('Update siteConfig failed.'); + console.error('postSite', res); + } + } + + updateSite = () => { + this.props.form.validateFields((err, values) => { + if (err) return; + this.postSite(values); + }); + } + + renderSiteConfig = () => { + const { getFieldDecorator } = this.props.form; + const assetsUrl = safeGet(this.state, 'siteConfig.assetsUrl'); + return ( +
+ + {getFieldDecorator('assetsUrl', { + initialValue: assetsUrl, + })( + + )} + + + + +
+ ); + } + + render () { + return ( +
+ + {this.renderSiteConfig()} + +
+ ); + } +} + +export default Form.create()(SiteSetting); + diff --git a/view/src/i18n/en_US.js b/view/src/i18n/en_US.js index 9368af9..20a721e 100644 --- a/view/src/i18n/en_US.js +++ b/view/src/i18n/en_US.js @@ -18,6 +18,7 @@ export default { 'setting.submit': 'Update', 'setting.versioning': 'Version Info', 'setting.notification.build': 'Build', + 'setting.site': 'Site Config', 'builds.buildNumber': 'Build Number', 'builds.buildLog': 'Build Log', diff --git a/view/src/i18n/zh_CN.js b/view/src/i18n/zh_CN.js index 174f979..ecda93d 100644 --- a/view/src/i18n/zh_CN.js +++ b/view/src/i18n/zh_CN.js @@ -18,6 +18,7 @@ export default { 'setting.submit': '更新设置', 'setting.versioning': '版本信息', 'setting.notification.build': '构建', + 'setting.site': '站点设置', 'builds.buildNumber': '构建号', 'builds.buildLog': '构建日志', diff --git a/view/src/page/Setting.js b/view/src/page/Setting.js index a3e5715..5e6f69d 100644 --- a/view/src/page/Setting.js +++ b/view/src/page/Setting.js @@ -11,6 +11,7 @@ import { } from 'antd'; import ReliableLayout from '../components/ReliableLayout'; +import SiteSetting from '../components/SiteSetting'; import DingdingSetting from '../components/DingdingSetting'; import pkg from '../../package.json'; @@ -38,6 +39,13 @@ export default class Setting extends React.Component { + }> + + + + + + }> diff --git a/view/src/util/getServer.js b/view/src/util/getServer.js index e5806e4..904467c 100644 --- a/view/src/util/getServer.js +++ b/view/src/util/getServer.js @@ -35,5 +35,9 @@ export const getServer = (url, param) => { return `${SERVER_ADDRESS}/api/config`; } + if (url === 'getSite' || url === 'postSite') { + return `${SERVER_ADDRESS}/api/config`; + } + return `${SERVER_ADDRESS}/api/delegate/message`; }; diff --git a/view/webpack.config.js b/view/webpack.config.js index ea5f912..4dacf99 100644 --- a/view/webpack.config.js +++ b/view/webpack.config.js @@ -7,6 +7,10 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl const pkg = require('./package'); +const { + DIST_DIR, +} = process.env; + module.exports = (env, argv) => { const isProduction = argv.mode === 'production'; @@ -27,7 +31,7 @@ module.exports = (env, argv) => { }, output: { - path: path.join(__dirname, '..', 'app', 'public'), + path: DIST_DIR ? path.resolve(DIST_DIR) : path.join(__dirname, '..', 'app', 'public'), publicPath: 'public', filename: '[name].js', },