Commit 4f79c3bb authored by nano's avatar nano

update

parent 3d31834a
......@@ -2,11 +2,15 @@
"parser": "babel-eslint",
"extends": "airbnb",
"rules": {
"react/jsx-space-before-closing":[0],
"generator-star-spacing": [0],
"semi":[0],
"no-console":[0],
"consistent-return": [0],
"react/forbid-prop-types": [0],
"react/jsx-filename-extension": [1, { "extensions": [".js"] }],
"global-require": [1],
"react/jsx-closing-bracket-location":[0],
"import/prefer-default-export": [0],
"react/jsx-no-bind": [0],
"react/prop-types": [0],
......@@ -22,11 +26,16 @@
"no-bitwise": [0],
"no-cond-assign": [0],
"import/no-unresolved": [0],
"require-yield": [1]
"require-yield": [1],
"react/react-in-jsx-scope": [0],
"no-extra-semi": [0]
},
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
},
"env": {
"browser": true
}
}
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="JSX" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/moecube-console-web.iml" filepath="$PROJECT_DIR$/.idea/moecube-console-web.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<TaskOptions isEnabled="false">
<option name="arguments" value="--no-color $FileName$" />
<option name="checkSyntaxErrors" value="true" />
<option name="description" />
<option name="exitCodeBehavior" value="ERROR" />
<option name="fileExtension" value="less" />
<option name="immediateSync" value="true" />
<option name="name" value="Less" />
<option name="output" value="$FileNameWithoutExtension$.css" />
<option name="outputFilters">
<array>
<FilterInfo>
<option name="description" value="lessc error format" />
<option name="name" value="lessc" />
<option name="regExp" value="$MESSAGE$\Q in \E$FILE_PATH$\Q on line \E$LINE$\Q, column \E$COLUMN$" />
</FilterInfo>
</array>
</option>
<option name="outputFromStdout" value="true" />
<option name="program" value="" />
<option name="scopeName" value="Project Files" />
<option name="trackOnlyRoot" value="false" />
<option name="workingDir" value="$FileDir$" />
<envs />
</TaskOptions>
</component>
</project>
\ No newline at end of file
This diff is collapsed.
{
export default {
"entry": "src/index.js",
"env": {
"development": {
"extraBabelPlugins": [
"dva-hmr",
"transform-runtime",
"babel-plugin-transform-decorators-legacy",
["import", { "libraryName": "antd", "style": "css" }]
]
},
"production": {
"extraBabelPlugins": [
"transform-runtime",
"babel-plugin-transform-decorators-legacy",
["import", { "libraryName": "antd", "style": "css" }]
]
}
......
......@@ -3,15 +3,14 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dva Demo</title>
<link rel="stylesheet" href="index.css" />
<base href="/">
<link rel="stylesheet" href="index.css"/>
<link rel="icon" href="https://moecube.com/favicon.ico">
</head>
<body>
<div id="root"></div>
<script src="index.js"></script>
<script src="/index.js"></script>
</body>
</html>
import React from 'react';
import styles from './Create.css';
import { Button, Modal, Form, Input, Radio, Select, Spin } from 'antd';
import { connect } from 'dva'
const FormItem = Form.Item;
@connect(
(state, props) => {
const { loading } = state
return {
loading
}
}
)
class Create extends React.Component {
handleSubmit = (e) => {
......@@ -20,11 +29,11 @@ class Create extends React.Component {
}
handleSelectChange = (value) => {
}
render() {
const { visible, onCancel, form, isLoading } = this.props;
const { visible, onCancel, form, loading } = this.props;
const { getFieldDecorator } = form;
return (
......@@ -34,7 +43,7 @@ class Create extends React.Component {
okText="提交"
onCancel={onCancel}
onOk={this.handleSubmit}>
<Spin spinning={isLoading} delay={100} tip="提交中...">
<Spin spinning={loading.global} delay={100} tip="提交中...">
<Form vertical onSubmit={this.handleSubmit}>
<FormItem label="应用 ID (创建应用后无法修改)">
......@@ -56,7 +65,7 @@ class Create extends React.Component {
<FormItem
label="主要语言"
wrapperCol={{ span: 8 }}>
{getFieldDecorator('locale', {
rules: [{ required: true, message: '请至少选择一门主要语言' }],
onChange: this.handleSelectChange,
......@@ -65,13 +74,13 @@ class Create extends React.Component {
<Select.Option value="zh-CN">zh-CN</Select.Option>
<Select.Option value="zh-TW">zh-TW</Select.Option>
<Select.Option value="en-US">en-US</Select.Option>
<Select.Option value="ja-JP">ja-JP</Select.Option>
<Select.Option value="ja-JP">ja-JP</Select.Option>
</Select>
)}
</FormItem>
</Form>
</Spin>
</Spin>
</Modal>
);
}
......
......@@ -2,30 +2,44 @@ import React from 'react';
import styles from './Nav.less';
import { Layout, Menu, Icon, Breadcrumb } from 'antd';
import {Link} from 'dva/router'
import { FormattedMessage } from 'react-intl'
import {connect} from 'dva'
const { Header, Sider, Content, Footer } = Layout;
const SubMenu = Menu.SubMenu
function Nav({ collapsed, mode, dispatch }) {
return (
<Sider
collapsible
collapsed={collapsed}
onCollapse={() => dispatch({ type: 'Common/collapsed' })}>
<div className={styles.logo} />
<Menu theme="dark" mode={mode} defaultSelectedKeys={['0']}>
<Menu.Item key="0">
<Link to="/apps">
<Icon type="windows-o" />
@connect(
(state, props) => {
const {
Common: {collapsed, mode}
} = state
return {
collapsed,
mode
}
}
)
export default class Nav extends React.Component {
render(){
const { collapsed, mode, dispatch } = this.props
return (
<Sider
collapsible
collapsed={collapsed}
onCollapse={() => dispatch({ type: 'Common/collapsed' })}>
<div className={styles.logo} />
<Menu theme="dark" mode={mode} defaultSelectedKeys={['0']}>
<Menu.Item key="0">
<Link to="/apps">
<Icon type="windows-o" />
<span className="nav-next">
<FormattedMessage id="Apps"/>
</span>
</Link>
</Menu.Item>
</Menu>
</Sider>
);
apps
</span>
</Link>
</Menu.Item>
</Menu>
</Sider>
)
}
}
export default Nav;
import React from 'react';
const Example = () => {
return (
<div>
Example
</div>
);
};
Example.propTypes = {
};
export default Example;
import ReactDOM from 'react-dom';
import { browserHistory } from 'dva/router'
import {browserHistory} from 'dva/router'
import createLoading from 'dva-loading'
import {message} from 'antd'
import dva from 'dva';
import './index.less';
import { IntlProvider, addLocaleData } from 'react-intl';
// 1. Initialize
const app = dva({
history: browserHistory
onError: (error) => {
message.destroy();
message.error(error.message);
},
history: browserHistory,
});
app.model(require("./models/Apps"));
......@@ -24,6 +26,7 @@ app.model(require("./models/App"));
// 2. Plugins
// app.use({});
app.use(createLoading())
// 3. Model
// app.model(require('./models/example'));
......@@ -31,24 +34,10 @@ app.model(require("./models/App"));
// 4. Router
app.router(require('./router'));
// 5. Start
import en from 'react-intl/locale-data/en'
import zh from 'react-intl/locale-data/zh'
import localeData from '../i18n.json'
addLocaleData([...en, ...zh])
const language = navigator.language || (navigator.languages && navigator.languages[0]) || navigator.userLanguage;
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
const messages = localeData[languageWithoutRegionCode] || localeData[language] || localeData.zh;
const App = app.start()
ReactDOM.render(
<IntlProvider locale={ language } messages={ messages }>
<App />
</IntlProvider>,
<App />,
document.getElementById("root")
)
import { create } from '../services/Apps'
import {create} from '../services/Apps'
import {message} from 'antd'
export default {
namespace: 'App',
......@@ -23,13 +24,6 @@ export default {
isSubmit: true,
}
},
SubmitSuccess(state, action){
return {
...state,
isSubmit: false,
isCreate: false
}
},
onCancel(state, action) {
return {
...state,
......@@ -49,8 +43,8 @@ export default {
}
},
effects: {
*submit({ payload }, { call, put }){
yield put({ type: 'SubmitRequest', payload })
*submit({payload}, {call, put}){
yield put({type: 'SubmitRequest', payload})
const params = {
id: payload.id,
......@@ -59,13 +53,16 @@ export default {
}
}
const req = yield call(create, params)
if(req.data) {
yield put({ type: 'SubmitSuccess' })
yield put({ type: 'reset' })
// TODO: 成功提示
try {
const {data} = yield call(create, params)
if (data) {
yield put({type: 'SubmitSuccess'})
yield put({type: 'reset'})
message.info("i18n 创建成功")
}
} catch (error) {
message.error(error.message)
}
// TODO: 错误处理
}
},
subscriptions: {},
......
import { fetch, update } from '../services/Apps'
import {fetch, update} from '../services/Apps'
import * as crypto from 'crypto'
import {message} from 'antd'
import config from '../config'
......@@ -10,47 +11,65 @@ export default {
},
reducers: {
save(state, action) {
return {
...state,
return {
...state,
...action.payload
}
},
},
effects: {
*fetch({ payload }, { call, put }) {
const { data } = yield call(fetch, payload)
*fetch({payload}, {call, put}) {
let apps = {}
if(data && data.length > 0) {
data.map(app => {
apps[app["id"]] = app
})
try {
const {data} = yield call(fetch, payload)
let apps = {}
if (data && data.length > 0) {
data.map(app => {
apps[app["id"]] = app
})
}
yield put({type: 'save', payload: {apps}})
} catch (error) {
message.error(error.message)
}
yield put({ type: 'save', payload: { apps } })
},
*update({ payload }, {call, put}){
const { data } = yield call(update, payload)
*update({payload}, {call, put}){
try {
const {data} = yield call(update, payload)
if (data) {
yield put({ type: 'success'})
} else {
yield put({ type: 'faile' })
if (data) {
yield put({type: 'success'})
message.info("i18n success")
}
} catch (error) {
message.error(error.message)
}
},
*success({ payload }, { call, put}) {
yield put({ type: 'fetch' })
*addPackage({payload}, {call, put}){
try {
const {data} = yield call(update, payload)
if (data) {
yield put({type: 'success'})
}
} catch (error) {
message.error(error.message)
}
},
*success({payload}, {call, put}) {
yield put({type: 'fetch'})
}
},
subscriptions: {
setup({ dispatch, history }) {
return history.listen(({ pathname, query}) => {
setup({dispatch, history}) {
dispatch({type: 'fetch'})
if(/^apps/.test(pathname)) {
return history.listen(({pathname, query}) => {
dispatch({ type: 'fetch', payload: query})
} else if(pathname === '/login'){
if (pathname === '/login') {
let params = new URLSearchParams()
params.set('return_sso_url', config.returnSSO)
let payload = Buffer.from(params.toString()).toString('base64')
......@@ -59,7 +78,7 @@ export default {
params.set('sso', payload);
params.set('sig', crypto.createHmac('sha256', 'zsZv6LXHDwwtUAGa').update(payload).digest('hex'))
window.location.href=url
window.location.href = url
}
})
}
......
......@@ -11,11 +11,10 @@ function RouterConfig({ history }) {
return (
<Router history={history}>
<Route path="/" component={Entry} >
<Route path="apps" component={Apps} />
<Route path="apps/:id" component={AppDetail} />
<Route path="/apps/:id" component={AppDetail} />
<Route path="/apps" component={Apps} />
</Route>
<Route path="/loginCallback" component={LoginCallback} />
<Route path="*" component={() => <div>404</div>}/>
</Router>
);
}
......
This diff is collapsed.
:global {
.app-detail-nav{
}
.ant-card {
margin: 2vh 0;
}
.app-detail-nav .ant-tabs-nav-scroll {
display: flex;
justify-content: center;
}
.ant-upload-select-picture-card i {
font-size: 28px;
color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
font-size: 12px;
color: #666;
}
}
.wrapSubmit{
display: flex;
justify-content: center;
}
.form {
align-content: center;
padding: 0 5vw;
display: flex;
justify-content: center;
}
\ No newline at end of file
:global {
.ant-upload {
display: flex !important;
justify-content: center;
align-items:center;
padding: 0 !important;
}
.ant-upload-text {
margin-top: 0 !important;
}
.ant-card {
margin: 2vh 0;
}
.app-detail-nav .ant-tabs-nav-scroll {
display: flex;
justify-content: center;
}
.ant-upload-select-picture-card i {
font-size: 28px;
color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
font-size: 12px;
color: #666;
}
}
.wrapSubmit{
display: flex;
justify-content: center;
}
.form {
align-content: center;
padding: 0 5vw;
display: flex;
justify-content: center;
}
import React from 'react';
import { connect } from 'dva';
import styles from './Entry.less';
import Nav from '../components/Common/Nav'
import { Router, Route, browserHistory } from 'dva/router';
import {Layout} from 'antd'
function Entry({ children, collapsed, mode, dispatch }) {
const NavProps = {
collapsed,
mode,
dispatch
}
function Entry({ children}) {
return (
<Layout style={{ flexDirection: 'row', minHeight: '100%'}}>
<Nav {...NavProps}/>
<Nav />
<Layout style={{ minHeight: '400px'}}>
{children}
</Layout>
......@@ -26,13 +17,7 @@ function Entry({ children, collapsed, mode, dispatch }) {
}
function mapStateToProps(state) {
const {
Common: {collapsed, mode}
} = state
return {
collapsed,
mode
};
return {}
}
export default connect(mapStateToProps)(Entry);
import fetch from 'dva/fetch';
import config from '../config'
import config from '../config';
function parseJSON(response) {
return response.json();
}
function checkStatus(response) {
async function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
let message;
try {
message = (await response.json()).message;
} catch (error) {
message = response.statusText;
}
const error = new Error(message);
error.response = response;
throw error;
}
......@@ -22,17 +29,20 @@ function checkStatus(response) {
* @param {object} [options] The options we want to pass to "fetch"
* @return {object} An object containing either "data" or "err"
*/
export default function request(url, options) {
url = `${config.apiRoot}${url}`
if(options && !options.headers && (options.method == 'POST' || options.method == 'PATCH')) {
options.headers = {
"content-type": "application/json"
}
export default function request(relativeUrl, options) {
const url = `${config.apiRoot}${relativeUrl}`;
if (options && !options.headers) {
Object.assign(options, {
headers: {
'content-type': 'application/json',
},
});
}
console.log(options);
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data => ({ data }))
.catch(err => ({ err }));
}
.then(data => ({data}));
// .catch(err => ({ err }));
};
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment