Commit 15c4b1c3 authored by nano's avatar nano

awesome

parent 4b82338e
......@@ -12,9 +12,13 @@
"dependencies": {
"antd": "^2.7.4",
"babel-runtime": "^6.9.2",
"crypto": "^0.0.3",
"dva": "^1.2.1",
"qs": "^6.4.0",
"react": "^15.4.0",
"react-dom": "^15.4.0"
"react-dom": "^15.4.0",
"react-intl": "^2.2.3",
"uuid": "^3.0.1"
},
"devDependencies": {
"babel-eslint": "^7.1.1",
......
......@@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dva Demo</title>
<link rel="stylesheet" href="index.css" />
<base href="/">
</head>
<body>
......
......@@ -20,7 +20,7 @@ class Create extends React.Component {
}
handleSelectChange = (value) => {
}
render() {
......
import React from 'react';
import styles from './Items.css';
function Items() {
return (
<div className={styles.normal}>
Component: Items
</div>
);
}
export default Items;
import { Table, Input, Popconfirm } from 'antd';
class EditableCell extends React.Component {
state = {
value: this.props.value,
editable: this.props.editable || false,
}
componentWillReceiveProps(nextProps) {
if (nextProps.editable !== this.state.editable) {
this.setState({ editable: nextProps.editable });
if (nextProps.editable) {
this.cacheValue = this.state.value;
}
}
if (nextProps.status && nextProps.status !== this.props.status) {
if (nextProps.status === 'save') {
this.props.onChange(this.state.value);
} else if (nextProps.status === 'cancel') {
this.setState({ value: this.cacheValue });
this.props.onChange(this.cacheValue);
}
}
}
shouldComponentUpdate(nextProps, nextState) {
return nextProps.editable !== this.state.editable ||
nextState.value !== this.state.value;
}
handleChange(e) {
const value = e.target.value;
this.setState({ value });
}
render() {
const { value, editable } = this.state;
return (
<div>
{
editable ?
<div>
<Input
value={value}
onChange={e => this.handleChange(e)}
/>
</div>
:
<div className="editable-row-text">
{value.toString() || ' '}
</div>
}
</div>
);
}
}
export default EditableCell
\ No newline at end of file
export default {
apiRoot: 'http://localhost:8001'
apiRoot: 'http://localhost:8001',
imgRoot: 'http://node:7888',
returnSSO: 'http://localhost:8000/loginCallback',
SSOProvider: 'https://ygobbs.com/session/sso_provider'
// SSOProvider: 'http://localhost:8081'
}
\ No newline at end of file
import ReactDOM from 'react-dom';
import { browserHistory } from 'dva/router'
import dva from 'dva';
import './index.css';
import './index.less';
import { IntlProvider, addLocaleData } from 'react-intl';
// 1. Initialize
const app = dva();
const app = dva({
history: browserHistory
});
app.model(require("./models/Apps"));
app.model(require("./models/user"));
app.model(require("./models/Common"));
app.model(require("./models/App"));
......
html, body, :global(#root) {
height: 100%;
}
\ No newline at end of file
import { fetch } from '../services/Apps'
import { fetch, update } from '../services/Apps'
import * as crypto from 'crypto'
import config from '../config'
export default {
namespace: 'Apps',
state: {
list: [],
apps: {},
},
reducers: {
save(state, action) {
......@@ -16,14 +19,44 @@ export default {
effects: {
*fetch({ payload }, { call, put }) {
const { data } = yield call(fetch, payload)
yield put({ type: 'save', payload: { list: data }})
let apps = {}
if(data && data.length > 0) {
data.map(app => {
apps[app["id"]] = app
})
}
yield put({ type: 'save', payload: { apps } })
},
*update({ payload }, {call, put}){
const { data } = yield call(update, payload)
if (data) {
yield put({ type: 'success'})
} else {
yield put({ type: 'faile' })
}
}
},
subscriptions: {
setup({ dispatch, history }) {
return history.listen(({ pathname, query}) => {
if(pathname === '/apps') {
if(/^apps/.test(pathname)) {
dispatch({ type: 'fetch', payload: query})
} else if(pathname === '/login'){
let params = new URLSearchParams()
params.set('return_sso_url', config.returnSSO)
let payload = Buffer.from(params.toString()).toString('base64')
let url = new URL(config.SSOProvider)
params = url['searchParams'];
params.set('sso', payload);
params.set('sig', crypto.createHmac('sha256', 'zsZv6LXHDwwtUAGa').update(payload).digest('hex'))
window.location.href=url
}
})
}
......
export default {
namespace: 'user',
state: {
},
reducers: {
change(state, action){
return {
...state, ...action.payload
}
}
},
effects: {},
subscriptions: {},
};
......@@ -4,14 +4,19 @@ import IndexPage from './routes/IndexPage';
import Apps from "./routes/Apps.js";
import AppDetail from './routes/AppDetail.js'
import Entry from "./routes/Entry.js";
import LoginCallback from "./routes/LoginCallback.js";
function RouterConfig({ history }) {
return (
<Router history={history}>
<Route path="/" component={Entry} >
<Route path="apps" component={Apps} />
<Route path="apps/:id" component={AppDetail} />
</Route>
<Route path="/loginCallback" component={LoginCallback} />
<Route path="*" component={() => <div>404</div>}/>
</Router>
);
}
......
This diff is collapsed.
:global {
.app-detail-nav{
width: 100%;
}
.ant-card {
margin: 2vh 0;
}
.app-detail-nav .ant-tabs-nav-scroll {
widows: 100%;
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{
width: 100%;
display: flex;
justify-content: center;
}
.form {
flex: 1;
align-content: center;
padding: 0 5vw;
display: flex;
justify-content: center;
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'dva';
import styles from './Apps.less';
import { Link } from 'dva/router';
import { Button, Affix, Icon, Table } from 'antd'
import { Button, Affix, Icon, Table, Tag } from 'antd'
import Create from '../components/App/Create'
......@@ -17,15 +17,28 @@ const columns = [
}, {
title: 'Name',
dataIndex: 'name',
render: name => `${Object.values(name)[0]}`,
render: name => name && name["zh-CN"],
width: '10%',
key: 'name'
},{
title: "Created_At",
dataIndex: 'created_at',
title: "author",
dataIndex: 'author',
width: '10%',
},{
title: "category",
dataIndex: 'category',
width: '10%',
},{
title: "homepage",
dataIndex: 'homepage',
render: homepage => <a href={homepage} target="_blank">{homepage}</a>,
width: '10%',
},{
title: "released_at",
dataIndex: 'released_at',
sorter: true,
width: '10%',
key:'created_at'
key:'released_at'
}, {
title: "Updated_at",
dataIndex: 'updated_at',
......@@ -35,7 +48,7 @@ const columns = [
},
]
function Apps({children, dispatch, isCreate, isSubmit, list}) {
function Apps({children, dispatch, isCreate, isSubmit, apps}) {
const CreateProps = {
visible: isCreate,
......@@ -55,11 +68,10 @@ function Apps({children, dispatch, isCreate, isSubmit, list}) {
const TableProps = {
columns,
dataSource: list
dataSource: Object.values(apps)
}
return (
<div className={styles.normal}>
......@@ -78,11 +90,11 @@ function Apps({children, dispatch, isCreate, isSubmit, list}) {
function mapStateToProps(state) {
const {
Apps: { list },
Apps: { apps },
App: { isCreate, isSubmit }
} = state
return {
list,
apps,
isCreate,
isSubmit
};
......
......@@ -2,6 +2,8 @@ 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'
......@@ -14,12 +16,12 @@ function Entry({ children, collapsed, mode, dispatch }) {
}
return (
<Layout style={{ flexDirection: 'row', height: '100%'}}>
<Nav {...NavProps}/>
<Layout style={{ minHeight: '400px'}}>
{children}
</Layout>
<Layout style={{ flexDirection: 'row', minHeight: '100%'}}>
<Nav {...NavProps}/>
<Layout style={{ minHeight: '400px'}}>
{children}
</Layout>
</Layout>
);
}
......
import React from 'react';
import { connect } from 'dva';
import styles from './LoginCallback.css';
class LoginCallback extends React.Component{
componentDidMount() {
const { location: { query: { sso }}, dispatch } = this.props
console.log(this.props)
const data = toObject(new URLSearchParams(Buffer.from(sso, 'base64').toString()))
if (data) {
dispatch({type: "user/change", payload:{ data }})
localStorage.setItem("user", JSON.stringify(data))
}
}
render(){
const {dispatch, location} = this.props
return (
<div className={styles.normal}>
</div>
)
}
}
function LoginCallback({ }) {
return (
<div className={styles.normal}>
{JSON.stringify(data)}
</div>
);
}
function mapStateToProps({ }) {
return {
};
}
function toObject(entries){
let result = {};
for (let [key, value] of entries) {
result[key] = value;
}
return result;
}
export default connect(mapStateToProps)(LoginCallback);
......@@ -6,7 +6,14 @@ export async function fetch() {
export async function create(params) {
return request(`/apps/${params.id}`, {
method: 'post',
method: 'POST',
body: JSON.stringify(params)
})
}
export async function update(params) {
return request(`/apps/${params.id}`, {
method: 'PATCH',
body: JSON.stringify(params)
})
}
\ No newline at end of file
......@@ -24,7 +24,7 @@ function checkStatus(response) {
*/
export default function request(url, options) {
url = `${config.apiRoot}${url}`
if(options && !options.headers && options.method == 'post') {
if(options && !options.headers && (options.method == 'POST' || options.method == 'PATCH')) {
options.headers = {
"content-type": "application/json"
}
......
......@@ -1444,6 +1444,10 @@ crypto-browserify@3.3.0:
ripemd160 "0.2.0"
sha.js "2.2.6"
crypto@^0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/crypto/-/crypto-0.0.3.tgz#470a81b86be4c5ee17acc8207a1f5315ae20dbb0"
css-animation@1.x, css-animation@^1.2.5, css-animation@^1.3.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/css-animation/-/css-animation-1.3.2.tgz#df515820ef5903733ad2db0999403b3037b8b880"
......@@ -2701,7 +2705,27 @@ interpret@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c"
invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1:
intl-format-cache@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-2.0.5.tgz#b484cefcb9353f374f25de389a3ceea1af18d7c9"
intl-messageformat-parser@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-1.2.0.tgz#5906b7f953ab7470e0dc8549097b648b991892ff"
intl-messageformat@1.3.0, intl-messageformat@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-1.3.0.tgz#f7d926aded7a3ab19b2dc601efd54e99a4bd4eae"
dependencies:
intl-messageformat-parser "1.2.0"
intl-relativeformat@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/intl-relativeformat/-/intl-relativeformat-1.3.0.tgz#893dc7076fccd380cf091a2300c380fa57ace45b"
dependencies:
intl-messageformat "1.3.0"
invariant@^2.0.0, invariant@^2.1.1, invariant@^2.2.0, invariant@^2.2.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
dependencies:
......@@ -4102,6 +4126,10 @@ qs@6.3.1, qs@~6.3.0:
version "6.3.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.1.tgz#918c0b3bcd36679772baf135b1acb4c1651ed79d"
qs@^6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
query-string@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-3.0.3.tgz#ae2e14b4d05071d4e9b9eb4873c35b0dcd42e638"
......@@ -4459,6 +4487,15 @@ react-hammerjs@~0.5.0:
dependencies:
hammerjs "^2.0.8"
react-intl@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-2.2.3.tgz#8eebb03cddc38b337ed22fab78037ab53a594270"
dependencies:
intl-format-cache "^2.0.5"
intl-messageformat "^1.3.0"
intl-relativeformat "^1.3.0"
invariant "^2.1.1"
react-lazy-load@^3.0.10:
version "3.0.11"
resolved "https://registry.yarnpkg.com/react-lazy-load/-/react-lazy-load-3.0.11.tgz#1d27e4e1f6dc77daaf9236db707aaf2bbbfabafe"
......@@ -5371,7 +5408,7 @@ uuid@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
uuid@^3.0.0:
uuid@^3.0.0, uuid@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
......
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