App.jsx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. import React, {Component} from 'react';
  2. import {Layout, Menu, Button, Spin, Icon, LocaleProvider} from 'antd';
  3. import {BrowserRouter as Router, Route, Link, Switch, Redirect} from "react-router-dom";
  4. import {Query} from "react-apollo";
  5. import gql from "graphql-tag";
  6. import moment from 'moment';
  7. import 'moment/locale/zh-cn';
  8. import {FormattedMessage} from 'react-intl';
  9. import zhCN from 'antd/lib/locale-provider/zh_CN';
  10. import QuantService from "./quantService/QuantService";
  11. import TrialCase from "./graphqlService/TrialCase";
  12. import UserCreate from "./graphqlService/UserCreate";
  13. import WxTrialCase from "./wechatService/WxTrialCase";
  14. import WxUserCreate from "./wechatService/WxUserCreate";
  15. import Login from "../login/Login";
  16. import './graphqlService/component/graphql/index.css';
  17. import './index.css'
  18. import Create from "./graphqlService/component/schema/Create";
  19. import WxCreate from "./wechatService/wxCreate/WxCreate";
  20. import {SHOW_ALL_SCHEMA, SHOW_CASE_SCHEMA, SHOW_PROJECT, CASE_AND_PROJECT} from "../gql";
  21. import axios from 'axios';
  22. import {getCookie, setCookie} from "../cookie";
  23. axios.defaults.withCredentials = true;
  24. const {SubMenu} = Menu;
  25. const {Header, Sider} = Layout;
  26. moment.locale('en');
  27. class App extends Component {
  28. constructor(props) {
  29. super(props);
  30. this.state = {
  31. menuLevel1: "graphql-service",
  32. sideBar: "ecommerce",
  33. collapsed: false,
  34. inlineCollapsed: false,
  35. language: props.language,
  36. locale: props.language === "中文" ? zhCN : undefined,
  37. languageButton: props.language === "中文" ? "English" : "中文",
  38. visible: false,
  39. wxVisible: false
  40. };
  41. }
  42. componentWillMount() {
  43. let urlList = window.location.pathname.split("/");
  44. let urlListLength = urlList.length;
  45. if (urlListLength > 2) {
  46. this.setState({menuLevel1: urlList[1]});
  47. if (urlList[3] !== 'index') {
  48. this.setState({sideBar: urlList[3]});
  49. }
  50. }
  51. let userID = getCookie('user_id');
  52. if (userID === undefined || '') {
  53. axios.get(this.state.getIdUrl)
  54. .then((res) => {
  55. if (res.data !== '') {
  56. setCookie("user_id", res.data);
  57. }
  58. })
  59. .catch(function (err) {
  60. console.log(err);
  61. });
  62. }
  63. }
  64. onCollapse = (collapsed) => {
  65. this.setState({collapsed});
  66. };
  67. switchMenu = (menuName, e) => {
  68. this.setState({
  69. [menuName]: e.key,
  70. });
  71. };
  72. switchMenuTab = (menuName, e) => {
  73. this.setState({
  74. [menuName]: e.key,
  75. });
  76. if (e.key === "graphql-service") {
  77. this.setState({sideBar: "ecommerce"});
  78. }
  79. };
  80. switchSidebar = (value) => {
  81. this.setState({
  82. sideBar: value,
  83. });
  84. };
  85. switchMenuLevel = (menuName, value) => {
  86. this.setState({
  87. [menuName]: value,
  88. });
  89. };
  90. showModal = () => {
  91. this.setState({
  92. visible: true,
  93. });
  94. };
  95. wxShowModal = () => {
  96. this.setState({
  97. wxVisible: true,
  98. });
  99. };
  100. hideModal = () => {
  101. this.setState({
  102. visible: false,
  103. });
  104. };
  105. wxHideModal = () => {
  106. this.setState({
  107. wxVisible: false,
  108. });
  109. };
  110. changeLocale = (e) => {
  111. e.stopPropagation();
  112. let {language} = this.state;
  113. // console.log('app language',language);
  114. let changeLanguage = language === "中文" ? "English" : "中文";
  115. let local = language === "中文" ? undefined : zhCN;
  116. let languageButton = language === "中文" ? "中文" : "English";
  117. sessionStorage.setItem("language", changeLanguage);
  118. this.props.changeLanguage(changeLanguage);
  119. this.setState({
  120. language: changeLanguage,
  121. locale: local,
  122. languageButton: languageButton
  123. });
  124. if (!local) {
  125. moment.locale('en');
  126. } else {
  127. moment.locale('zh-cn');
  128. }
  129. };
  130. render() {
  131. const {locale, languageButton, visible, wxVisible} = this.state;
  132. return (
  133. <Router>
  134. <Layout style={{minHeight: '100vh'}}>
  135. <Header className="header" style={{position: 'fixed', zIndex: 1, width: '100%'}}>
  136. <Link to="/"
  137. onClick={() => this.setState({menuLevel1: "graphql-service", sideBar: "ecommerce"})}>
  138. <div className="logo-wrapper">
  139. <div className='logo'/>
  140. </div>
  141. </Link>
  142. <Menu
  143. theme="dark"
  144. mode="horizontal"
  145. selectedKeys={[this.state.menuLevel1]}
  146. style={{lineHeight: '64px'}}
  147. onClick={(e) => this.switchMenuTab('menuLevel1', e)}
  148. >
  149. <Menu.Item key="graphql-service">
  150. <Link to="/graphql-service/trial-case/index"><FormattedMessage
  151. id="Graphql Service"/></Link>
  152. </Menu.Item>
  153. <Menu.Item key="wechat-service">
  154. <Link to="/wechat-service/trial-case/index"><FormattedMessage
  155. id="Wechat Service"/></Link>
  156. </Menu.Item>
  157. <Menu.Item key="quant-service">
  158. <Link to="/quant-service/trial-case/index"><FormattedMessage id="Quantization Service"/></Link>
  159. </Menu.Item>
  160. </Menu>
  161. <Link to="/login">
  162. <Button className='login-button' type='primary'
  163. onClick={() => this.switchMenuLevel('menuLevel1', 'user')}>
  164. <FormattedMessage id="Login"/></Button>
  165. </Link>
  166. <div className="change-locale">
  167. <Button size="small" onClick={(e) => this.changeLocale(e)}>{languageButton}</Button>
  168. </div>
  169. </Header>
  170. {(() => {
  171. switch (this.state.menuLevel1) {
  172. case 'graphql-service':
  173. return (
  174. <Sider
  175. width={200}
  176. style={{background: '#fff', marginTop: '64px', zIndex: '0'}}
  177. collapsible
  178. collapsed={this.state.collapsed}
  179. onCollapse={this.onCollapse}
  180. >
  181. <GraphqlSidebar inlineCollapsed={this.state.inlineCollapsed}
  182. sideBar={this.state.sideBar} switchMenu={this.switchMenu}
  183. showModal={this.showModal}/>
  184. </Sider>
  185. );
  186. case 'wechat-service':
  187. return (
  188. <Sider
  189. width={200}
  190. style={{background: '#fff', marginTop: '64px', zIndex: '0'}}
  191. collapsible
  192. collapsed={this.state.collapsed}
  193. onCollapse={this.onCollapse}
  194. >
  195. <WxConfigSiderbar inlineCollapsed={this.state.inlineCollapsed}
  196. sideBar={this.state.sideBar} switchMenu={this.switchMenu}
  197. wxShowModal={this.wxShowModal}/>
  198. </Sider>
  199. );
  200. case 'quant-service':
  201. return (
  202. <Sider
  203. width={200}
  204. style={{background: '#fff', marginTop: '64px', zIndex: '0'}}
  205. collapsible
  206. collapsed={this.state.collapsed}
  207. onCollapse={this.onCollapse}
  208. >
  209. <Menu
  210. theme="dark"
  211. mode="inline"
  212. inlineCollapsed={this.state.inlineCollapsed}
  213. defaultSelectedKeys={['quant-service']}
  214. defaultOpenKeys={['trial-case']}
  215. // openKeys={['cloud-function']}
  216. onClick={(e) => this.switchMenu('sideBar', e)}
  217. selectedKeys={['quant-service']}
  218. style={{
  219. borderRight: 0,
  220. overflow: 'auto',
  221. height: '100vh',
  222. left: '0',
  223. width: '200px',
  224. position: 'fixed'
  225. }}
  226. >
  227. <SubMenu key="trial-case"
  228. title={<span><Icon type="appstore" theme="twoTone"/>
  229. <span><FormattedMessage id="Case Show"/></span></span>}>
  230. <Menu.Item key="quant-service">
  231. <Link to="/quant-service/trial-case/quant case">quant case</Link>
  232. </Menu.Item>
  233. </SubMenu>
  234. <Menu.Item key="instructions">
  235. <a href="https://ioobot-document.netlify.com/" title="instructions"
  236. target="instructions">
  237. <Icon type="file-text" theme="twoTone"/>
  238. <span><FormattedMessage id="Instructions"/></span>
  239. </a>
  240. </Menu.Item>
  241. </Menu>
  242. </Sider>
  243. );
  244. case 'user':
  245. return (
  246. <Sider
  247. width={200}
  248. style={{background: '#fff', marginTop: '64px', zIndex: '0'}}
  249. collapsible
  250. collapsed={this.state.collapsed}
  251. onCollapse={this.onCollapse}
  252. >
  253. <Menu
  254. theme="dark"
  255. defaultSelectedKeys={['cloud-settings']}
  256. onClick={(e) => this.switchMenu('sideBar', e)}
  257. selectedKeys={[this.state.sideBar]}
  258. style={{
  259. borderRight: 0,
  260. overflow: 'auto',
  261. height: '100vh',
  262. left: '0',
  263. width: '200px',
  264. position: 'fixed'
  265. }}
  266. >
  267. <Menu.Item key="account">
  268. <Icon type="setting" theme="twoTone"/>
  269. <span><FormattedMessage id="Account center"/></span>
  270. <Link to="/login/account"/>
  271. </Menu.Item>
  272. <Menu.Item key="cloud-settings">
  273. <Icon type="cloud" theme="twoTone"/>
  274. <span><FormattedMessage id="Cloud settings"/></span>
  275. <Link to="/login/cloud"/>
  276. </Menu.Item>
  277. </Menu>
  278. </Sider>
  279. );
  280. default:
  281. return (
  282. <Sider
  283. width={200}
  284. style={{background: '#fff', marginTop: '64px', zIndex: '0'}}
  285. collapsible
  286. collapsed={this.state.collapsed}
  287. onCollapse={this.onCollapse}
  288. >
  289. <GraphqlSidebar inlineCollapsed={this.state.inlineCollapsed}
  290. sideBar={this.state.sideBar} switchMenu={this.switchMenu}
  291. showModal={this.showModal}/>
  292. </Sider>
  293. );
  294. }
  295. })()}
  296. <Create visible={visible} hideModal={this.hideModal} switchSidebar={this.switchSidebar}/>
  297. <WxCreate visible={wxVisible} hideModal={this.wxHideModal} switchSidebar={this.switchSidebar}/>
  298. <LocaleProvider locale={locale}>
  299. <Layout style={{marginTop: '64px', zIndex: '0'}}
  300. key={locale ? locale.locale : 'en'/* Have to refresh for production environment */}>
  301. <Switch>
  302. <Route path="/" exact component={TrialCase}/>
  303. <Route path="/graphql-service/trial-case/:case" component={TrialCase}/>
  304. <Route path="/graphql-service/my-create/:case" component={UserCreate}/>
  305. <Route path="/wechat-service/trial-case/:case" component={WxTrialCase}/>
  306. <Route path="/wechat-service/my-create/:case" component={WxUserCreate}/>
  307. <Route path="/quant-service/:sidebar/:case" component={QuantService}/>
  308. <Route path="/login/:setting" component={Login}/>
  309. <Route path="/login" component={Login}/>
  310. <Redirect path="*" to="/"/>
  311. </Switch>
  312. </Layout>
  313. </LocaleProvider>
  314. </Layout>
  315. </Router>
  316. );
  317. }
  318. }
  319. export default App;
  320. class GraphqlSidebar extends Component {
  321. constructor(props) {
  322. super(props);
  323. this.state = {
  324. userID: getCookie('user_id'),
  325. }
  326. }
  327. render() {
  328. return (
  329. <Query query={gql(CASE_AND_PROJECT)} variables={{projectType: 'graphql', user_id: this.state.userID}}>
  330. {
  331. ({loading, error, data}) => {
  332. if (loading) return <Spin style={{marginLeft: 3}}/>;
  333. if (error) return 'error!';
  334. // console.log('CASE_AND_PROJECT data', data);
  335. data.caseProject.forEach((project) => {
  336. switch (project.schema_id.schemaName) {
  337. case 'ecommerce' :
  338. localStorage.setItem('ecommerce', project.schema_id.schemaData);
  339. break;
  340. case 'subscribe':
  341. localStorage.setItem('subscribe', project.schema_id.schemaData);
  342. break;
  343. case 'bills':
  344. localStorage.setItem('bills', project.schema_id.schemaData);
  345. break;
  346. default:
  347. break;
  348. }
  349. });
  350. return (
  351. <Menu
  352. theme="dark"
  353. mode="inline"
  354. inlineCollapsed={this.props.inlineCollapsed}
  355. defaultSelectedKeys={['ecommerce']}
  356. defaultOpenKeys={['trial-case', 'my-create']}
  357. // openKeys={['trial-case', 'my-create']}
  358. onClick={(e) => this.props.switchMenu('sideBar', e)}
  359. selectedKeys={[this.props.sideBar]}
  360. style={{
  361. borderRight: 0,
  362. overflow: 'auto',
  363. height: '100vh',
  364. left: '0',
  365. width: '200px',
  366. position: 'fixed'
  367. }}
  368. >
  369. <SubMenu
  370. key="trial-case"
  371. title={<span><Icon type="appstore" theme="twoTone"/><span><FormattedMessage
  372. id="Case Show"/></span></span>}>
  373. {
  374. data.caseProject.map((project) =>
  375. <Menu.Item key={project.schema_id.schemaName}>
  376. <Link to={{
  377. pathname: `/graphql-service/trial-case/${project.schema_id.schemaName}`,
  378. state: {
  379. schemaName: project.schema_id.schemaName,
  380. schemaID: project.schema_id.id,
  381. projectID: project.id
  382. }
  383. }}>{project.schema_id.schemaName}</Link>
  384. </Menu.Item>)
  385. }
  386. </SubMenu>
  387. <Menu.Item key="create-graphql" onClick={this.props.showModal}>
  388. <Icon type="edit" theme="twoTone"/>
  389. <span><FormattedMessage id="Create"/></span>
  390. <Icon type="plus" style={{
  391. position: 'absolute',
  392. top: '35%',
  393. right: '6px',
  394. color: 'white'
  395. }}/>
  396. </Menu.Item>
  397. <SubMenu
  398. key="my-create"
  399. title={<span><Icon type="user" theme="outlined"/><span><FormattedMessage
  400. id="My Create"/></span></span>}>
  401. {
  402. data.project.map((project) =>
  403. <Menu.Item key={project.projectName}>
  404. <Link to={{
  405. pathname: `/graphql-service/my-create/${project.projectName}`,
  406. state: {
  407. schemaName: project.projectName,
  408. schemaID: project.schema_id.id,
  409. projectID: project.id
  410. }
  411. }}>{project.projectName}</Link>
  412. </Menu.Item>)
  413. }
  414. </SubMenu>
  415. <Menu.Item key="instructions">
  416. <a href="https://ioobot-document.netlify.com/" title="instructions" target="_blank"
  417. rel="noopener noreferrer">
  418. <Icon type="file-text" theme="twoTone"/>
  419. <span><FormattedMessage id="Instructions"/></span>
  420. </a>
  421. </Menu.Item>
  422. </Menu>
  423. )
  424. }
  425. }
  426. </Query>
  427. )
  428. }
  429. }
  430. class WxConfigSiderbar extends Component {
  431. constructor(props) {
  432. super(props);
  433. this.state = {
  434. userID: getCookie('user_id'),
  435. }
  436. }
  437. render() {
  438. return (
  439. <Query query={gql(CASE_AND_PROJECT)} variables={{projectType: 'wx', user_id: this.state.userID}}>
  440. {
  441. ({loading, error, data}) => {
  442. // console.log('CASE_WXCONFIG_AND_PROJECT data', data);
  443. if (loading) return <Spin style={{marginLeft: 3}}/>;
  444. if (error) return 'error!';
  445. return (
  446. <Menu
  447. theme="dark"
  448. mode="inline"
  449. inlineCollapsed={this.props.inlineCollapsed}
  450. // defaultSelectedKeys={['my-wechat']}
  451. defaultOpenKeys={['trial-case', 'my-create']}
  452. // openKeys={['trial-case', 'my-create']}
  453. onClick={(e) => this.props.switchMenu('sideBar', e)}
  454. selectedKeys={[this.props.sideBar]}
  455. style={{
  456. borderRight: 0,
  457. overflow: 'auto',
  458. height: '100vh',
  459. left: '0',
  460. width: '200px',
  461. position: 'fixed'
  462. }}
  463. >
  464. <SubMenu key="trial-case" title={<span><Icon type="appstore" theme="twoTone"/>
  465. <span><FormattedMessage id="Case Show"/></span>
  466. </span>}>
  467. {
  468. data.caseProject.map((project) => {
  469. if (project) {
  470. let appName = project.wxConfig_id.appName;
  471. let configID = project.wxConfig_id.id;
  472. let projectID = project.id;
  473. return (
  474. <Menu.Item key={appName}>
  475. <Link to={{
  476. pathname: `/wechat-service/trial-case/${appName}`,
  477. state: {
  478. appName,
  479. configID,
  480. projectID
  481. }
  482. }}>{appName}</Link>
  483. </Menu.Item>
  484. )
  485. }
  486. return false;
  487. })
  488. }
  489. </SubMenu>
  490. <Menu.Item key="create-config" onClick={this.props.wxShowModal}>
  491. <Icon type="edit" theme="twoTone"/>
  492. <span><FormattedMessage id="Create"/></span>
  493. <Icon type="plus" style={{
  494. position: 'absolute',
  495. top: '35%',
  496. right: '6px',
  497. color: 'white'
  498. }}/>
  499. </Menu.Item>
  500. <SubMenu key="my-create" title={<span><Icon type="user" theme="outlined"/>
  501. <span><FormattedMessage id="My Create"/></span>
  502. </span>}>
  503. {
  504. data.project.map((project) => {
  505. if (project) {
  506. let appName = project.wxConfig_id.appName;
  507. let configID = project.wxConfig_id.id;
  508. let projectID = project.id;
  509. return (
  510. <Menu.Item key={appName}>
  511. <Link to={{
  512. pathname: `/wechat-service/my-create/${appName}`,
  513. state: {
  514. appName,
  515. configID,
  516. projectID
  517. }
  518. }}>{appName}</Link>
  519. </Menu.Item>
  520. )
  521. }
  522. return false;
  523. })
  524. }
  525. </SubMenu>
  526. <Menu.Item key="instructions">
  527. <a href="https://ioobot-document.netlify.com/" title="instructions" target="_blank"
  528. rel="noopener noreferrer">
  529. <Icon type="file-text" theme="twoTone"/>
  530. <span><FormattedMessage id="Instructions"/></span>
  531. </a>
  532. </Menu.Item>
  533. </Menu>
  534. )
  535. }
  536. }
  537. </Query>
  538. )
  539. }
  540. }