DevelopVersion.jsx 32 KB

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