2 Commits 872776b810 ... f2046b5fa7

Author SHA1 Message Date
  KaysonCui f2046b5fa7 Merge branch 'master' of https://git.proginn.com/zaixianjiaoyu/sourcecode 5 years ago
  KaysonCui 3c1c471b7c add ckeditor 5 years ago
100 changed files with 6278 additions and 250 deletions
  1. 6 24
      front/.eslintrc
  2. 77 6
      front/project/www/components/Answer/index.js
  3. 16 6
      front/project/www/components/AnswerSelect/index.js
  4. 2 2
      front/project/www/components/Button/index.less
  5. 99 98
      front/project/www/components/Card/index.js
  6. 23 0
      front/project/www/components/Editor/index.js
  7. 7 0
      front/project/www/components/Editor/index.less
  8. 1 1
      front/project/www/components/ListTable/index.js
  9. 1 1
      front/project/www/components/Navigation/index.js
  10. 1 8
      front/project/www/components/Table/index.js
  11. 15 11
      front/project/www/components/Tabs/index.js
  12. 5 11
      front/project/www/local.json
  13. 293 31
      front/project/www/routes/page/practise/page.js
  14. 1 1
      front/project/www/routes/page/start/index.js
  15. 139 50
      front/project/www/routes/page/start/page.js
  16. 1703 0
      front/project/www/static/ckeditor/CHANGES.md
  17. 1420 0
      front/project/www/static/ckeditor/LICENSE.md
  18. 39 0
      front/project/www/static/ckeditor/README.md
  19. 10 0
      front/project/www/static/ckeditor/adapters/jquery.js
  20. 97 0
      front/project/www/static/ckeditor/build-config.js
  21. 1237 0
      front/project/www/static/ckeditor/ckeditor.js
  22. 38 0
      front/project/www/static/ckeditor/config.js
  23. 208 0
      front/project/www/static/ckeditor/contents.css
  24. 5 0
      front/project/www/static/ckeditor/lang/en.js
  25. 10 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js
  26. 25 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/_translationstatus.txt
  27. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/af.js
  28. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ar.js
  29. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/az.js
  30. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/bg.js
  31. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ca.js
  32. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/cs.js
  33. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/cy.js
  34. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/da.js
  35. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/de-ch.js
  36. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/de.js
  37. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/el.js
  38. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/en-au.js
  39. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/en-gb.js
  40. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/en.js
  41. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/eo.js
  42. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/es-mx.js
  43. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/es.js
  44. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/et.js
  45. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/eu.js
  46. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fa.js
  47. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fi.js
  48. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fo.js
  49. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fr-ca.js
  50. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fr.js
  51. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/gl.js
  52. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/gu.js
  53. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/he.js
  54. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/hi.js
  55. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/hr.js
  56. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/hu.js
  57. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/id.js
  58. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/it.js
  59. 9 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ja.js
  60. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/km.js
  61. 10 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ko.js
  62. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ku.js
  63. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/lt.js
  64. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/lv.js
  65. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/mk.js
  66. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/mn.js
  67. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/nb.js
  68. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/nl.js
  69. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/no.js
  70. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/oc.js
  71. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/pl.js
  72. 13 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/pt-br.js
  73. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/pt.js
  74. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ro.js
  75. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ru.js
  76. 10 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/si.js
  77. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sk.js
  78. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sl.js
  79. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sq.js
  80. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sr-latn.js
  81. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sr.js
  82. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sv.js
  83. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/th.js
  84. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/tr.js
  85. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/tt.js
  86. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ug.js
  87. 12 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/uk.js
  88. 11 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/vi.js
  89. 9 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/zh-cn.js
  90. 9 0
      front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/zh.js
  91. 8 0
      front/project/www/static/ckeditor/plugins/about/dialogs/about.js
  92. BIN
      front/project/www/static/ckeditor/plugins/about/dialogs/hidpi/logo_ckeditor.png
  93. BIN
      front/project/www/static/ckeditor/plugins/about/dialogs/logo_ckeditor.png
  94. 11 0
      front/project/www/static/ckeditor/plugins/clipboard/dialogs/paste.js
  95. 4 0
      front/project/www/static/ckeditor/plugins/dialog/dialogDefinition.js
  96. BIN
      front/project/www/static/ckeditor/plugins/icons.png
  97. BIN
      front/project/www/static/ckeditor/plugins/icons_hidpi.png
  98. 44 0
      front/project/www/static/ckeditor/plugins/image/dialogs/image.js
  99. BIN
      front/project/www/static/ckeditor/plugins/image/images/noimage.png
  100. 0 0
      front/project/www/static/ckeditor/plugins/link/dialogs/anchor.js

+ 6 - 24
front/.eslintrc

@@ -1,30 +1,11 @@
 {
   "parser": "babel-eslint",
-  "extends": [
-    "standard-react",
-    "airbnb-base"
-  ],
-  "plugins": [
-    "react",
-    "import"
-  ],
+  "extends": ["standard-react", "airbnb-base"],
+  "plugins": ["react", "import"],
   "settings": {
     "import/resolver": {
       "alias": {
-        "map": [
-          [
-            "@src",
-            "./src"
-          ],
-          [
-            "@project",
-            "./project/admin"
-          ],
-          [
-            "@components",
-            "./components"
-          ]
-        ]
+        "map": [["@src", "./src"], ["@project", "./project/admin"], ["@components", "./components"]]
       }
     }
   },
@@ -48,7 +29,8 @@
     "goBack": false,
     "toLink": false,
     "openLink": false,
-    "WxLogin": false
+    "WxLogin": false,
+    "CKEDITOR": false
   },
   "rules": {
     "camelcase": "off",
@@ -73,4 +55,4 @@
     "global-require": "off",
     "import/no-extraneous-dependencies": "off"
   }
-}
+}

+ 77 - 6
front/project/www/components/Answer/index.js

@@ -3,18 +3,88 @@ import './index.less';
 import RadioItem from '../RadioItem';
 
 export default class Answer extends Component {
+  constructor(props) {
+    super(props);
+    const single = [];
+    const double = [];
+    switch (props.type) {
+      case 'single':
+        for (let i = 0; i < props.list.length; i += 1) {
+          single.push(false);
+        }
+        break;
+      case 'double':
+        for (let i = 0; i < props.list.length; i += 1) {
+          double.push([false, false]);
+        }
+        break;
+      default:
+        break;
+    }
+    this.state = { single, double };
+  }
+
+  onChangeSingle(index) {
+    const { single } = this.state;
+    for (let i = 0; i < single.length; i += 1) {
+      single[i] = false;
+    }
+    single[index] = true;
+    this.setState({ single });
+    this.onChange(single);
+  }
+
+  onChangeDouble(index, column) {
+    const { direction } = this.props;
+    let { double } = this.state;
+    switch (direction) {
+      case 'landscape':
+        double[index] = double[index].map(() => false);
+        break;
+      case 'portrait':
+        double = double.map(row => {
+          row[index] = false;
+          return row;
+        });
+        break;
+      default:
+        break;
+    }
+    double[index][column] = true;
+    this.setState({ double });
+    this.onChange(double);
+  }
+
+  onChange(value) {
+    const { onChange } = this.props;
+    if (onChange) onChange(value);
+  }
+
   render() {
-    return <div className="answer">{this.renderTable()}</div>;
+    return <div className="answer">{this.renderDetail()}</div>;
+  }
+
+  renderDetail() {
+    const { type } = this.props;
+    switch (type) {
+      case 'single':
+        return this.renderList();
+      case 'double':
+        return this.renderTable();
+      default:
+        return <div />;
+    }
   }
 
   renderList() {
     const { list = [] } = this.props;
+    const { single = [] } = this.state;
     return (
       <div className="list">
-        {list.map(item => {
+        {list.map((item, index) => {
           return (
             <div className="item">
-              <RadioItem checked onClick={() => {}} />
+              <RadioItem checked={single[index]} onClick={() => this.onChangeSingle(index)} />
               <div className="text">{item}</div>
             </div>
           );
@@ -25,6 +95,7 @@ export default class Answer extends Component {
 
   renderTable() {
     const { list = [] } = this.props;
+    const { double = [] } = this.state;
     return (
       <table border="1" bordercolor="#d8d8d8">
         <thead>
@@ -39,14 +110,14 @@ export default class Answer extends Component {
           </tr>
         </thead>
         <tbody>
-          {list.map(item => {
+          {list.map((item, index) => {
             return (
               <tr>
                 <td align="center" className="bg">
-                  <RadioItem checked onClick={() => {}} />
+                  <RadioItem checked={double[index][0]} onClick={() => this.onChangeDouble(index, 0)} />
                 </td>
                 <td align="center" className="bg">
-                  <RadioItem checked onClick={() => {}} />
+                  <RadioItem checked={double[index][1]} onClick={() => this.onChangeDouble(index, 1)} />
                 </td>
                 <td>{item}</td>
               </tr>

+ 16 - 6
front/project/www/components/AnswerSelect/index.js

@@ -5,12 +5,22 @@ import Assets from '@src/components/Assets';
 export default class AnswerSelect extends Component {
   constructor(props) {
     super(props);
-    this.state = { selecting: false };
+    const select = [];
+    for (let i = 0; i < props.list.length; i += 1) {
+      select[i] = false;
+    }
+    this.state = { selecting: false, select };
   }
 
-  componentWillMount() {}
-
-  componentWillUnmount() {}
+  onChange(index) {
+    const { onChange } = this.props;
+    const { select } = this.state;
+    for (let i = 0; i < select.length; i += 1) {
+      select[i] = false;
+    }
+    select[index] = true;
+    if (onChange) onChange(select);
+  }
 
   open() {
     this.setState({ selecting: true });
@@ -30,7 +40,7 @@ export default class AnswerSelect extends Component {
         break;
       }
     }
-    const title = list.length > 0 ? list[index].title : '';
+    const title = list.length > 0 ? list[index] : '';
     return (
       <div className="answer-select">
         <div hidden={!selecting} className="mask" onClick={() => this.close()} />
@@ -43,7 +53,7 @@ export default class AnswerSelect extends Component {
             {list.map(item => {
               return (
                 <div className="select-option" onClick={() => this.close()}>
-                  {item.title}
+                  {item}
                 </div>
               );
             })}

+ 2 - 2
front/project/www/components/Button/index.less

@@ -51,7 +51,7 @@
 
 .button.default {
   background: #fff;
-  color: @base_color;
+  color: @holder_color;
   border: 1px solid @line_color;
 }
 
@@ -69,5 +69,5 @@
 }
 
 .button.default:hover {
-  border-color: @base_color;
+  border-color: @holder_color;
 }

+ 99 - 98
front/project/www/components/Card/index.js

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Component } from 'react';
 import './index.less';
 import { Link } from 'react-router-dom';
 import { Checkbox } from 'antd';
@@ -7,110 +7,111 @@ import Progress from '../Progress';
 import IconButton from '../IconButton';
 import Button from '../Button';
 
-function getBuyBody(data) {
-  const desc = data.desc || [];
-  return (
-    <div className="body">
-      <div className="desc">
-        {desc.map(item => {
-          return <div className="item">{item}</div>;
-        })}
-      </div>
-      <div className="btn">
-        <Button size="lager" radius>
-          立即购买
-        </Button>
-      </div>
-    </div>
-  );
-}
-function getOpenBody() {
-  return (
-    <div className="body">
-      <div className="title">请开通预习作业</div>
-      <div className="text">
-        <Checkbox />
-        <span>
-          我已阅读并同意<Link to="">《千行 GMAT - Sentence Corretion 课程协议》</Link>
-        </span>
-      </div>
-      <div className="btn">
-        <Button size="lager" radius>
-          立即开通
-        </Button>
+export default class Card extends Component {
+  getBuyBody() {
+    const { data } = this.props;
+    return (
+      <div className="body">
+        <div className="desc" dangerouslySetInnerHTML={{ __html: data.description }} />
+        <div className="btn">
+          <Button size="lager" radius>
+            立即购买
+          </Button>
+        </div>
       </div>
-    </div>
-  );
-}
-function getIngBody(data) {
-  const list = data.list || [];
-  return (
-    <div className="body">
-      <div className="title">近期待完成</div>
-      {list.length === 0 ? (
+    );
+  }
+
+  getOpenBody() {
+    return (
+      <div className="body">
+        <div className="title">请开通预习作业</div>
         <div className="text">
-          <div>好棒!</div>
-          <div>近期的作业都完成啦</div>
+          <Checkbox />
+          <span>
+            我已阅读并同意<Link to="">《千行 GMAT - Sentence Corretion 课程协议》</Link>
+          </span>
+        </div>
+        <div className="btn">
+          <Button size="lager" radius>
+            立即开通
+          </Button>
         </div>
-      ) : (
-        <div className="list">
-          {list.map(item => {
-            return (
-              <div className="item">
-                <div className="top">
-                  <div className="date">{item.date}</div>
-                  <div className="action">
-                    {item.status === 'start' && <IconButton type="start" tip="Start" />}
-                    {item.status === 'ing' && <IconButton type="continue" tip="Continue" />}
-                    {item.status === 'ing' && <IconButton type="restart" tip="Restart" />}
+      </div>
+    );
+  }
+
+  getIngBody() {
+    const { process, previewAction } = this.props;
+    return (
+      <div className="body">
+        <div className="title">近期待完成</div>
+        {process.previews.length === 0 ? (
+          <div className="text">
+            <div>好棒!</div>
+            <div>近期的作业都完成啦</div>
+          </div>
+        ) : (
+          <div className="list">
+            {process.previews.map(item => {
+              return (
+                <div className="item">
+                  <div className="top">
+                    <div className="date">{item.time}</div>
+                    <div className="action">
+                      {!item.repport.id && (
+                        <IconButton
+                          type="start"
+                          tip="Start"
+                          onClick={() => previewAction && previewAction('start', item)}
+                        />
+                      )}
+                      {item.repport.id && (
+                        <IconButton
+                          type="continue"
+                          onClick={() => previewAction && previewAction('continue', item)}
+                          tip="Continue"
+                        />
+                      )}
+                      {item.repport.id && (
+                        <IconButton
+                          type="restart"
+                          onClick={() => previewAction && previewAction('restart', item)}
+                          tip="Restart"
+                        />
+                      )}
+                    </div>
                   </div>
+                  <Progress progress={item.report.id ? item.repport.userNumber / item.report.questionNumber : 0} />
                 </div>
-                <Progress progress={item.progress} />
-              </div>
-            );
-          })}
-        </div>
-      )}
-    </div>
-  );
-}
-function getEndBody() {
-  return (
-    <div className="body">
-      <div className="title">课程已经结束啦</div>
-    </div>
-  );
-}
+              );
+            })}
+          </div>
+        )}
+      </div>
+    );
+  }
 
-function getBody(data) {
-  switch (data.status) {
-    case 'buy':
-      return getBuyBody(data);
-    case 'open':
-      return getOpenBody(data);
-    case 'ing':
-      return getIngBody(data);
-    case 'end':
-      return getEndBody(data);
-    default:
-      return '';
+  getBody() {
+    const { process = {} } = this.props;
+    if (!process.payed && !process.startTime) return this.getBuyBody();
+    if (process.payed) return this.getOpenBody();
+    if (process.startTime) return this.getIngBody();
+    return <div />;
   }
-}
 
-function Card(props) {
-  const { style, data = {}, title } = props;
+  render() {
+    const { style, data = {}, process = {} } = this.props;
 
-  return (
-    <Module style={style} className={`card ${data.status}`}>
-      <div className="header">
-        {title}
-        {data.status === 'buy' && <span className="sub-title">未购买</span>}
-        {data.status === 'open' && <span className="sub-title">已购买</span>}
-      </div>
-      {getBody(data)}
-    </Module>
-  );
+    return (
+      <Module style={style} className={`card ${data.status}`}>
+        <div className="header">
+          {`${data.titleZh} ${data.titleEn}`}
+          {!process.payed && !process.startTime && <span className="sub-title">未购买</span>}
+          {(process.payed || process.startTime) && <span className="sub-title">已购买</span>}
+        </div>
+        {this.getBody()}
+      </Module>
+    );
+  }
 }
-
-Card.propTypes = {};
-export default Card;

+ 23 - 0
front/project/www/components/Editor/index.js

@@ -0,0 +1,23 @@
+import React, { Component } from 'react';
+import './index.less';
+
+export default class Editor extends Component {
+  componentWillMount() {
+    const { onChange } = this.props;
+    setTimeout(() => {
+      const editor = CKEDITOR.replace('editor', {
+        skin: 'moono',
+        toolbarGroups: [{ name: 'clipboard', groups: ['undo', 'clipboard'] }],
+        removePlugins: 'pastetext,pastefromword',
+        language: 'en',
+      });
+      editor.on('change', () => {
+        if (onChange) onChange(editor.getData());
+      });
+    }, 1);
+  }
+
+  render() {
+    return <textarea name="editor" />;
+  }
+}

+ 7 - 0
front/project/www/components/Editor/index.less

@@ -0,0 +1,7 @@
+.cke_button__cut_label,
+.cke_button__copy_label,
+.cke_button__paste_label,
+.cke_button__undo_label,
+.cke_button__redo_label {
+  display: block !important;
+}

+ 1 - 1
front/project/www/components/ListTable/index.js

@@ -20,7 +20,7 @@ function ListTable(props) {
   const { style, title, subTitle, filters = [], columns = [], data = [] } = props;
   return (
     <Module style={style} className="list-table">
-      <div className="header">
+      <div hidden={!title && !subTitle} className="header">
         <span className="title">{title}</span>
         <span className="sub-title">{subTitle}</span>
       </div>

+ 1 - 1
front/project/www/components/Navigation/index.js

@@ -8,7 +8,7 @@ function Navigation(props) {
       {list.map((item, index) => {
         return (
           <div className={`item ${index === active ? 'active' : ''}`}>
-            <span className="text">{item}</span>
+            <span className="text">{item.title}</span>
           </div>
         );
       })}

+ 1 - 8
front/project/www/components/Table/index.js

@@ -19,16 +19,9 @@ function Table(props) {
         return (
           <div className="tr">
             {columns.map(column => {
-              if (column.render) {
-                return (
-                  <div style={{ width: column.width, textAlign: column.align }} className={`td ${column.className}`}>
-                    {column.render(row[column.key], row)}
-                  </div>
-                );
-              }
               return (
                 <div style={{ width: column.width, textAlign: column.align }} className={`td ${column.className}`}>
-                  {row[column.key]}
+                  {column.render ? column.render(row, row[column.key]) : row[column.key]}
                 </div>
               );
             })}

+ 15 - 11
front/project/www/components/Tabs/index.js

@@ -2,21 +2,25 @@ import React from 'react';
 import { Link } from 'react-router-dom';
 import './index.less';
 
+function getItem(props, item, onChange) {
+  const { width, space, active } = props;
+  return (
+    <div
+      onClick={() => active !== item.key && onChange && onChange(item.key)}
+      style={{ width: width || '', marginLeft: space || '', marginRight: space || '' }}
+      className={`tab ${active === item.key ? 'active' : ''}`}
+    >
+      {item.name}
+    </div>
+  );
+}
+
 function Tabs(props) {
-  const { tabs = [], type = 'line', width, space, border, active } = props;
+  const { tabs = [], type = 'line', border, onChange } = props;
   return (
     <div className={`tabs ${type} ${border ? 'border' : ''}`}>
       {tabs.map(item => {
-        return (
-          <Link to={item.path}>
-            <div
-              style={{ width: width || '', marginLeft: space || '', marginRight: space || '' }}
-              className={`tab ${active === item.key ? 'active' : ''}`}
-            >
-              {item.name}
-            </div>
-          </Link>
-        );
+        return item.path ? <Link to={item.path}>{getItem(props, item)}</Link> : getItem(props, item, onChange);
       })}
     </div>
   );

+ 5 - 11
front/project/www/local.json

@@ -1,24 +1,18 @@
 {
   "development": {
-    "scripts": [
-      "http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"
-    ],
+    "scripts": ["/ckeditor/ckeditor.js", "http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"],
     "proxy": [
       {
-        "target": "http://127.0.0.1:8888",
+        "target": "http://qianxing.nuliji.com",
         "from": "/api",
         "to": "/api"
       }
     ]
   },
   "test": {
-    "scripts": [
-      "http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"
-    ]
+    "scripts": ["http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"]
   },
   "production": {
-    "scripts": [
-      "http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"
-    ]
+    "scripts": ["http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"]
   }
-}
+}

+ 293 - 31
front/project/www/routes/page/practise/page.js

@@ -2,51 +2,313 @@ import React from 'react';
 import './index.less';
 import { Link } from 'react-router-dom';
 import Page from '@src/containers/Page';
+import { asyncConfirm } from '@src/services/AsyncTools';
 import Tabs from '../../../components/Tabs';
 import Module from '../../../components/Module';
 import Input from '../../../components/Input';
 import Button from '../../../components/Button';
+import Division from '../../../components/Division';
+import Card from '../../../components/Card';
+import ListTable from '../../../components/ListTable';
+import ProgressText from '../../../components/ProgressText';
+import IconButton from '../../../components/IconButton';
+import { Main } from '../../../stores/main';
+import { Question } from '../../../stores/question';
+
+const HARD = 'HARD';
+const PREVIEW = 'PREVIEW';
+const PREVIEW_CLASS = 'PREVIEW_CLASS';
+const PREVIEW_TASK = 'PREVIEW_TASK';
 
 export default class extends Page {
+  initState() {
+    return {
+      level1Tab: PREVIEW,
+      level2Tab: '',
+      previewType: PREVIEW_CLASS,
+      tabs: [],
+      allClass: [],
+      classProcess: {},
+    };
+  }
+
+  initData() {
+    Main.getExercise().then(result => {
+      const list = result;
+      const map = {};
+      for (let i = 0; i < result.length; i += 1) {
+        const item = result[i];
+        if (!map[item.parentId]) map[item.parentId] = [];
+        map[item.parentId].push(item);
+      }
+      const tabs = [];
+      let allClass = [];
+      tabs.push({ key: HARD, name: '长难句' });
+      if (map[0]) {
+        for (let i = 0; i < map[0].length; i += 1) {
+          const item = map[0][i];
+          tabs.push({ key: item.id, name: `${item.titleZh} ${item.titleEn}` });
+          if (map[item.id]) {
+            allClass = allClass.concat(map[item.id]);
+          }
+        }
+      }
+      tabs.push({ key: PREVIEW, name: '预习作业' });
+      this.setState({ tabs, allClass, list, map });
+    });
+    this.refreshClassProcess();
+  }
+
+  refreshPreview() {
+    const { previewType } = this.state;
+    if (previewType === PREVIEW_CLASS) {
+      this.refreshClassProcess();
+    }
+    if (previewType === PREVIEW_TASK) {
+      this.refreshPreview();
+    }
+  }
+
+  onChangePreviewType(type) {
+    this.setState({ previewType: type });
+    this.refreshPreview();
+  }
+
+  refreshClassProcess() {
+    Question.getClassProcess().then(result => {
+      const classProcess = {};
+      for (let i = 0; i < result.length; i += 1) {
+        const item = result[i];
+        classProcess[item.category].push(item);
+      }
+      this.setState({ classProcess });
+    });
+  }
+
+  refreshListPreview() {
+    Question.listPreview().then(result => {
+      this.setState({ previews: result });
+    });
+  }
+
+  onChangeTab(level, tab) {
+    const state = {};
+    state[`level${level}Tab`] = tab;
+    this.setState(state);
+  }
+
+  previewAction(type, item) {
+    switch (type) {
+      case 'start':
+        this.startPreview(item);
+        break;
+      case 'restart':
+        this.restartPreview(item);
+        break;
+      case 'continue':
+        this.continuePreview(item);
+        break;
+      default:
+        break;
+    }
+  }
+
+  startPreview(item) {
+    linkTo(`/start/${item.id}?type=preview`);
+  }
+
+  restartPreview(item) {
+    asyncConfirm('提示', '是否重置', () => {
+      Question.restart(item.report.id).then(() => {
+        this.refreshPreview();
+      });
+    });
+  }
+
+  continuePreview(item) {
+    linkTo(`/start/${item.id}?type=preview&r=${item.report.id}`);
+  }
+
   renderView() {
+    const { level1Tab, level2Tab, tabs, map } = this.state;
     return (
       <div>
         <div className="content">
           <Module className="m-t-2">
-            <Tabs
-              type="card"
-              active="main"
-              tabs={[
-                { key: 'main', name: '首页', path: '/' },
-                { key: 'ready', name: 'GetReady', path: '/' },
-                { key: 'exercise', name: '练习', path: '/' },
-                { key: 'cat', name: 'CAT模考', path: '/' },
-                { key: 'item', name: '题库', path: '/' },
-                { key: 'machine', name: '换库&机经', path: '/' },
-              ]}
-            />
-          </Module>
-          <Module className="code-module">
-            <div className="title">输入《千行GMAT长难句》专属 Code,解锁在线练习功能。</div>
-            <div className="input-block">
-              <Input size="lager" placeholder="请输入CODE" />
-              <Button size="lager">解锁</Button>
-            </div>
-            <div className="tip">
-              <Link to="/" className="left link">
-                什么是CODE?
-              </Link>
-              <span>没有 CODE?</span>
-              <Link to="/" className="link">
-                去获取 >>
-              </Link>
-              <Link to="/" className="right link">
-                试用 >>
-              </Link>
-            </div>
+            <Tabs type="card" active={level1Tab} tabs={tabs} onChange={key => this.onChangeTab(1, key)} />
+            {(level1Tab !== HARD || level1Tab !== PREVIEW) && (
+              <Tabs active={level2Tab} tabs={map[level2Tab]} onChange={key => this.onChangeTab(2, key)} />
+            )}
           </Module>
+          {(level1Tab !== HARD || level1Tab !== PREVIEW) && this.renderType()}
+          {level1Tab === HARD && this.renderHard()}
+          {level1Tab === PREVIEW && this.renderWork()}
         </div>
       </div>
     );
   }
+
+  renderWork() {
+    const { previewType } = this.state;
+    switch (previewType) {
+      case PREVIEW_CLASS:
+        return this.renderAllClass();
+      case PREVIEW_TASK:
+        return this.renderAllTask();
+      default:
+        return <div />;
+    }
+  }
+
+  renderAllClass() {
+    const { allClass, classProcess } = this.props;
+    return (
+      <Division col="3">
+        {allClass.map(item => {
+          return <Card data={item} process={classProcess[item.id]} previewAction={this.previewAction} />;
+        })}
+      </Division>
+    );
+  }
+
+  renderAllTask() {
+    const { previews } = this.props;
+    return (
+      <ListTable
+        filters={[
+          { type: 'radio', checked: 'first', list: [{ key: 'first', title: 123 }, { key: 'two', title: 321 }] },
+          { type: 'select', checked: 'first', list: [{ key: 'first', title: 123 }, { key: 'two', title: 321 }] },
+        ]}
+        data={previews}
+        columns={[
+          {
+            title: '练习册',
+            width: 250,
+            align: 'left',
+            render: item => {
+              return (
+                <div className="table-row">
+                  <div className="night f-s-16">{item.title}</div>
+                  <div>
+                    <ProgressText
+                      progress={item.report.id ? item.repport.userNumber / item.report.questionNumber : 0}
+                      size="small"
+                    />
+                  </div>
+                </div>
+              );
+            },
+          },
+          {
+            title: '正确率',
+            width: 150,
+            align: 'left',
+            render: item => {
+              return (
+                <div className="table-row">
+                  <div className="night f-s-16 f-w-b">--</div>
+                  <div className="f-s-12">{item.stat.totalCorrect / item.stat.totalNumber}</div>
+                </div>
+              );
+            },
+          },
+          {
+            title: '全站用时',
+            width: 150,
+            align: 'left',
+            render: item => {
+              return (
+                <div className="table-row">
+                  <div className="night f-s-16 f-w-b">--</div>
+                  <div className="f-s-12">全站{item.stat.totalTime / item.stat.totalNumber}s</div>
+                </div>
+              );
+            },
+          },
+          {
+            title: '最近做题',
+            width: 150,
+            align: 'left',
+            render: () => {
+              return (
+                <div className="table-row">
+                  <div>2019-04-28</div>
+                  <div>07:30</div>
+                </div>
+              );
+            },
+          },
+          {
+            title: '操作',
+            width: 180,
+            align: 'left',
+            render: item => {
+              return (
+                <div className="table-row p-t-1">
+                  {!item.repport.id && (
+                    <IconButton type="start" tip="Start" onClick={() => this.previewAction('start', item)} />
+                  )}
+                  {item.repport.id && (
+                    <IconButton
+                      className="m-r-2"
+                      type="continue"
+                      tip="Continue"
+                      onClick={() => this.previewAction('continue', item)}
+                    />
+                  )}
+                  {item.repport.id && (
+                    <IconButton type="restart" tip="Restart" onClick={() => this.previewAction('restart', item)} />
+                  )}
+                </div>
+              );
+            },
+          },
+          {
+            title: '报告',
+            width: 30,
+            align: 'right',
+            render: item => {
+              return (
+                <div className="table-row p-t-1">
+                  {item.report.userNumber === item.report.questionNumber && <IconButton type="report" tip="Report" />}
+                </div>
+              );
+            },
+          },
+        ]}
+      />
+    );
+  }
+
+  renderHard() {
+    return this.renderInputCode();
+  }
+
+  renderType() {
+    return <div />;
+  }
+
+  renderInputCode() {
+    return (
+      <Module className="code-module">
+        <div className="title">输入《千行GMAT长难句》专属 Code,解锁在线练习功能。</div>
+        <div className="input-block">
+          <Input size="lager" placeholder="请输入CODE" />
+          <Button size="lager">解锁</Button>
+        </div>
+        <div className="tip">
+          <Link to="/" className="left link">
+            什么是CODE?
+          </Link>
+          <span>没有 CODE?</span>
+          <Link to="/" className="link">
+            去获取 >>
+          </Link>
+          <Link to="/" className="right link">
+            试用 >>
+          </Link>
+        </div>
+      </Module>
+    );
+  }
 }

+ 1 - 1
front/project/www/routes/page/start/index.js

@@ -1,5 +1,5 @@
 export default {
-  path: '/start',
+  path: '/start/:id',
   key: 'start',
   title: '开始考试',
   needLogin: true,

+ 139 - 50
front/project/www/routes/page/start/page.js

@@ -1,6 +1,7 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
 import './index.less';
+import { Checkbox } from 'antd';
 import Assets from '@src/components/Assets';
 import Page from '@src/containers/Page';
 import Button from '../../../components/Button';
@@ -9,73 +10,156 @@ import Answer from '../../../components/Answer';
 import Calculator from '../../../components/Calculator';
 import AnswerSelect from '../../../components/AnswerSelect';
 import AnswerTable from '../../../components/AnswerTable';
+import { Question } from '../../../stores/question';
+import Editor from '../../../components/Editor';
 
 export default class extends Page {
   initState() {
-    return { showCalculator: false };
+    return {
+      showCalculator: false,
+      start: !this.props.core.query.r,
+      reportId: this.props.core.query.r,
+      type: this.props.core.query.type,
+      disorder: false,
+      step: 0,
+      info: {},
+      reportInfo: {},
+      questionInfo: {},
+      answer: {},
+    };
   }
 
-  renderView() {
-    return this.renderDetail();
+  initData() {
+    const { start } = this.state;
+    Question.getPaper(this.params.id).then(result => {
+      this.setState({ info: result });
+    });
+    if (!start) {
+      this.continue();
+    }
   }
 
-  initData() {
+  onChangeQuestion(index, value) {
+    const { question = {}, answer = {} } = this.state;
+    answer.questions[index] = { [question.type]: value };
+    this.setState({ answer });
+  }
+
+  onChangeAwa(value) {
+    const { answer = {} } = this.state;
+    answer.awa = value;
+    this.setState({ answer });
+  }
+
+  start() {
+    const { type, info, disorder } = this.state;
+    Question.start(type, info.id, disorder).then(result => {
+      this.setState({ reportInfo: result });
+      this.next();
+    });
+  }
+
+  continue() {
+    const { reportId } = this.state;
+    Question.continue(reportId).then(result => {
+      this.setState({ reportInfo: result });
+      this.next();
+    });
+  }
+
+  next() {
+    const { reportInfo } = this.state;
+    Question.next(reportInfo.id).then(result => {
+      this.setState({
+        questionInfo: result,
+        question: result.question,
+        answer: { questions: [], subject: [], predicate: [], object: [], options: [], awa: '' },
+      });
+    });
+  }
+
+  submit() {
+    const { question, answer } = this.state;
+    Question.submit(question.questionNoId, answer).then(() => {
+      this.next();
+    });
+  }
+
+  finish() {
+    const { reportInfo } = this.state;
+    Question.finish(reportInfo.id).then(() => {});
+  }
+
+  formatStrem(text) {
+    if (!text) return '';
+    const { question = { content: {} } } = this.state;
+    const { table = {}, questions = [] } = question.content;
+    text = text.replace(/#select#/g, "<span class='#select#' />");
+    text = text.replace(/#table#/g, "<span class='#table#' />");
     setTimeout(() => {
-      ReactDOM.render(
-        <AnswerSelect list={[{ title: '123' }, { title: '321' }]} />,
-        document.getElementById('#select#'),
-      );
-      ReactDOM.render(
-        <AnswerTable
-          list={[{ title: '123' }, { title: '321' }]}
-          columns={[{ key: 'one', title: 'one' }, { key: 'two', title: 'two' }]}
-          data={[{ one: '123', two: '321' }]}
-        />,
-        document.getElementById('#table#'),
-      );
+      const selectList = document.getElementsByClassName('#select#');
+      const tableList = document.getElementsByClassName('#table#');
+      for (let i = 0; i < selectList.length; i += 1) {
+        ReactDOM.render(
+          <AnswerSelect list={questions[i].select} onChange={v => this.onChangeQuestion(i, v)} />,
+          selectList[i],
+        );
+      }
+      for (let i = 0; i < tableList.length; i += 1) {
+        ReactDOM.render(
+          <AnswerTable list={table.header || []} columns={table.header} data={table.data} />,
+          tableList[i],
+        );
+      }
     }, 1);
+    return text;
+  }
+
+  renderView() {
+    const { start } = this.state;
+    if (!start) return this.renderStart();
+    return this.renderDetail();
   }
 
   renderCotent() {
+    const { question = { content: {} }, step } = this.state;
+    const { steps = [] } = question.content;
     return (
       <div className="block block-content">
-        <Navigation list={['Sports Association', 'News Orgnization', 'News Orgnization']} onChange={() => {}} />
-        <div className="text">
-          For each of the following statements, select Both accept if, based on the information provided, it can be
-          inferred that both the sports association and the news organizations would likely accept that the statement is
-          true. If not, select Otherwise.
-          <span id="#table#" />
-          For each of the following statements, select Both accept if, based on the information provided, it can be
-          inferred <span id="#select#" />
-          that both the sports association and the news organizations would likely accept that the statement is true. If
-          not, select Otherwise.
-        </div>
+        {steps.length > 0 && <Navigation list={question.content.steps} active={step} onChange={() => {}} />}
+        <div className="text">{this.formatStrem(steps.length > 0 ? steps[step].stem : question.stem)}</div>
       </div>
     );
   }
 
   renderAnswer() {
+    const { question = { content: {} } } = this.state;
+    const { questions = [] } = question.content;
+    if (question.type === 'inline') return '';
     return (
       <div className="block block-answer">
-        <div className="text m-b-2">
-          For each of the following statements, select Both accept if, based on the information provided, it can be
-          inferred that both the sports association and the news organizations would likely accept that the statement is
-          true. If not, select Otherwise.{' '}
-        </div>
-        <Answer
-          list={[
-            'Neuroscientists, having amassed a wealth of knowledge',
-            'the past twenty years about the brain and its development from birth to adulthood',
-            'Neuroscientists, having amassed a wealth of knowledge',
-            'the past twenty years about the brain and its development from birth to adulthood, ) the past twenty years about the brain and its development from birth to adulthood',
-          ]}
-        />
+        <Editor onChange={v => this.onChangeAwa(v)} />
+        {question.type === 'awa' && <Editor onChange={v => this.onChangeAwa(v)} />}
+        {questions.map((item, index) => {
+          return (
+            <div>
+              <div className="text m-b-2">{item.description}</div>
+              <Answer
+                list={item.select}
+                type={question.type}
+                direction={question.direction}
+                onChange={v => this.onChangeQuestion(index, v)}
+              />
+            </div>
+          );
+        })}
       </div>
     );
   }
 
   renderDetail() {
-    const { showCalculator } = this.state;
+    const { showCalculator, info, question = { content: {} } } = this.state;
+    const { typeset = 'one' } = question.content;
     return (
       <div className="layout">
         <div className="fixed">
@@ -89,18 +173,19 @@ export default class extends Page {
         </div>
         <Calculator show={showCalculator} />
         <div className="layout-header">
-          <div className="title">OG18:1-20</div>
+          <div className="title">{info.title}</div>
           <div className="right">
             <div className="block">
               <Assets name="timeleft_icon" />
               Time left 00:02
             </div>
             <div className="block">
-              <Assets name="subjectnumber_icon" />1 of 20
+              <Assets name="subjectnumber_icon" />
+              {question.no} of {info.questionNumer}
             </div>
           </div>
         </div>
-        <div className="layout-body two">
+        <div className={`layout-body ${typeset}`}>
           {this.renderCotent()}
           {this.renderAnswer()}
         </div>
@@ -112,7 +197,7 @@ export default class extends Page {
           <div className="full">
             <Assets name="fullscreen_icon" />
           </div>
-          <div className="next">
+          <div className="next" onClick={() => this.next()}>
             Next
             <Assets name="next_icon" />
           </div>
@@ -122,30 +207,34 @@ export default class extends Page {
   }
 
   renderStart() {
+    const { info, disorder } = this.state;
     return (
       <div className="start">
         <div className="bg" />
         <div className="fixed-content">
-          <div className="title">「练习」OG18 综合:第1-20题</div>
+          <div className="title">{info.title}</div>
           <div className="desc">
             <div className="block">
               <div className="desc-title">
                 <Assets name="subject_icon" />
                 题目总数
               </div>
-              <div className="desc-info">20</div>
+              <div className="desc-info">{info.questionNumer}</div>
             </div>
             <div className="block">
               <div className="desc-title">
                 <Assets name="time_icon" />
                 建议用时
               </div>
-              <div className="desc-info">20 min</div>
+              <div className="desc-info">{info.time}</div>
             </div>
           </div>
-          <div className="tip">题目选项乱序显示</div>
+          <div className="tip">
+            <Checkbox className="m-r-1" checked={disorder} onChange={() => this.setState({ disorder: !disorder })} />
+            题目选项乱序显示
+          </div>
           <div className="submit">
-            <Button size="lager" radius>
+            <Button size="lager" radius onClick={() => this.start()}>
               开始练习
             </Button>
           </div>

File diff suppressed because it is too large
+ 1703 - 0
front/project/www/static/ckeditor/CHANGES.md


File diff suppressed because it is too large
+ 1420 - 0
front/project/www/static/ckeditor/LICENSE.md


+ 39 - 0
front/project/www/static/ckeditor/README.md

@@ -0,0 +1,39 @@
+CKEditor 4
+==========
+
+Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+http://ckeditor.com - See LICENSE.md for license information.
+
+CKEditor is a text editor to be used inside web pages. It's not a replacement
+for desktop text editors like Word or OpenOffice, but a component to be used as
+part of web applications and websites.
+
+## Documentation
+
+The full editor documentation is available online at the following address:
+http://docs.ckeditor.com
+
+## Installation
+
+Installing CKEditor is an easy task. Just follow these simple steps:
+
+ 1. **Download** the latest version from the CKEditor website:
+    http://ckeditor.com. You should have already completed this step, but be
+    sure you have the very latest version.
+ 2. **Extract** (decompress) the downloaded file into the root of your website.
+
+**Note:** CKEditor is by default installed in the `ckeditor` folder. You can
+place the files in whichever you want though.
+
+## Checking Your Installation
+
+The editor comes with a few sample pages that can be used to verify that
+installation proceeded properly. Take a look at the `samples` directory.
+
+To test your installation, just call the following page at your website:
+
+	http://<your site>/<CKEditor installation path>/samples/index.html
+
+For example:
+
+	http://www.example.com/ckeditor/samples/index.html

File diff suppressed because it is too large
+ 10 - 0
front/project/www/static/ckeditor/adapters/jquery.js


+ 97 - 0
front/project/www/static/ckeditor/build-config.js

@@ -0,0 +1,97 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/license
+ */
+
+/**
+ * This file was added automatically by CKEditor builder.
+ * You may re-use it at any time to build CKEditor again.
+ *
+ * If you would like to build CKEditor online again
+ * (for example to upgrade), visit one the following links:
+ *
+ * (1) https://ckeditor.com/cke4/builder
+ *     Visit online builder to build CKEditor from scratch.
+ *
+ * (2) https://ckeditor.com/cke4/builder/4f63382572985d622b9d98e28e170aeb
+ *     Visit online builder to build CKEditor, starting with the same setup as before.
+ *
+ * (3) https://ckeditor.com/cke4/builder/download/4f63382572985d622b9d98e28e170aeb
+ *     Straight download link to the latest version of CKEditor (Optimized) with the same setup as before.
+ *
+ * NOTE:
+ *    This file is not used by CKEditor, you may remove it.
+ *    Changing this file will not change your CKEditor configuration.
+ */
+
+var CKBUILDER_CONFIG = {
+	skin: 'moono',
+	preset: 'standard',
+	ignore: [
+		'.DS_Store',
+		'.bender',
+		'.editorconfig',
+		'.gitattributes',
+		'.gitignore',
+		'.idea',
+		'.jscsrc',
+		'.jshintignore',
+		'.jshintrc',
+		'.mailmap',
+		'.npm',
+		'.travis.yml',
+		'bender-err.log',
+		'bender-out.log',
+		'bender.ci.js',
+		'bender.js',
+		'dev',
+		'gruntfile.js',
+		'less',
+		'node_modules',
+		'package.json',
+		'tests'
+	],
+	plugins : {
+		'a11yhelp' : 1,
+		'about' : 1,
+		'basicstyles' : 1,
+		'blockquote' : 1,
+		'clipboard' : 1,
+		'contextmenu' : 1,
+		'elementspath' : 1,
+		'enterkey' : 1,
+		'entities' : 1,
+		'filebrowser' : 1,
+		'floatingspace' : 1,
+		'format' : 1,
+		'horizontalrule' : 1,
+		'htmlwriter' : 1,
+		'image' : 1,
+		'indentlist' : 1,
+		'link' : 1,
+		'list' : 1,
+		'magicline' : 1,
+		'maximize' : 1,
+		'pastefromword' : 1,
+		'pastetext' : 1,
+		'removeformat' : 1,
+		'resize' : 1,
+		'scayt' : 1,
+		'showborders' : 1,
+		'sourcearea' : 1,
+		'specialchar' : 1,
+		'stylescombo' : 1,
+		'tab' : 1,
+		'table' : 1,
+		'tableselection' : 1,
+		'tabletools' : 1,
+		'toolbar' : 1,
+		'undo' : 1,
+		'uploadimage' : 1,
+		'wsc' : 1,
+		'wysiwygarea' : 1
+	},
+	languages : {
+		'en' : 1
+	}
+};

File diff suppressed because it is too large
+ 1237 - 0
front/project/www/static/ckeditor/ckeditor.js


+ 38 - 0
front/project/www/static/ckeditor/config.js

@@ -0,0 +1,38 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+CKEDITOR.editorConfig = function( config ) {
+	// Define changes to default configuration here.
+	// For complete reference see:
+	// https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html
+
+	// The toolbar groups arrangement, optimized for two toolbar rows.
+	config.toolbarGroups = [
+		{ name: 'clipboard',   groups: [ 'clipboard', 'undo' ] },
+		{ name: 'editing',     groups: [ 'find', 'selection', 'spellchecker' ] },
+		{ name: 'links' },
+		{ name: 'insert' },
+		{ name: 'forms' },
+		{ name: 'tools' },
+		{ name: 'document',	   groups: [ 'mode', 'document', 'doctools' ] },
+		{ name: 'others' },
+		'/',
+		{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
+		{ name: 'paragraph',   groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
+		{ name: 'styles' },
+		{ name: 'colors' },
+		{ name: 'about' }
+	];
+
+	// Remove some buttons provided by the standard plugins, which are
+	// not needed in the Standard(s) toolbar.
+	config.removeButtons = 'Underline,Subscript,Superscript';
+
+	// Set the most common block elements.
+	config.format_tags = 'p;h1;h2;h3;pre';
+
+	// Simplify the dialog windows.
+	config.removeDialogTabs = 'image:advanced;link:advanced';
+};

+ 208 - 0
front/project/www/static/ckeditor/contents.css

@@ -0,0 +1,208 @@
+/*
+Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+*/
+
+body
+{
+	/* Font */
+	/* Emoji fonts are added to visualise them nicely in Internet Explorer. */
+	font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+	font-size: 12px;
+
+	/* Text color */
+	color: #333;
+
+	/* Remove the background color to make it transparent. */
+	background-color: #fff;
+
+	margin: 20px;
+}
+
+.cke_editable
+{
+	font-size: 13px;
+	line-height: 1.6;
+
+	/* Fix for missing scrollbars with RTL texts. (#10488) */
+	word-wrap: break-word;
+}
+
+blockquote
+{
+	font-style: italic;
+	font-family: Georgia, Times, "Times New Roman", serif;
+	padding: 2px 0;
+	border-style: solid;
+	border-color: #ccc;
+	border-width: 0;
+}
+
+.cke_contents_ltr blockquote
+{
+	padding-left: 20px;
+	padding-right: 8px;
+	border-left-width: 5px;
+}
+
+.cke_contents_rtl blockquote
+{
+	padding-left: 8px;
+	padding-right: 20px;
+	border-right-width: 5px;
+}
+
+a
+{
+	color: #0782C1;
+}
+
+ol,ul,dl
+{
+	/* IE7: reset rtl list margin. (#7334) */
+	*margin-right: 0px;
+	/* Preserved spaces for list items with text direction different than the list. (#6249,#8049)*/
+	padding: 0 40px;
+}
+
+h1,h2,h3,h4,h5,h6
+{
+	font-weight: normal;
+	line-height: 1.2;
+}
+
+hr
+{
+	border: 0px;
+	border-top: 1px solid #ccc;
+}
+
+img.right
+{
+	border: 1px solid #ccc;
+	float: right;
+	margin-left: 15px;
+	padding: 5px;
+}
+
+img.left
+{
+	border: 1px solid #ccc;
+	float: left;
+	margin-right: 15px;
+	padding: 5px;
+}
+
+pre
+{
+	white-space: pre-wrap; /* CSS 2.1 */
+	word-wrap: break-word; /* IE7 */
+	-moz-tab-size: 4;
+	tab-size: 4;
+}
+
+.marker
+{
+	background-color: Yellow;
+}
+
+span[lang]
+{
+	font-style: italic;
+}
+
+figure
+{
+	text-align: center;
+	outline: solid 1px #ccc;
+	background: rgba(0,0,0,0.05);
+	padding: 10px;
+	margin: 10px 20px;
+	display: inline-block;
+}
+
+figure > figcaption
+{
+	text-align: center;
+	display: block; /* For IE8 */
+}
+
+a > img {
+	padding: 1px;
+	margin: 1px;
+	border: none;
+	outline: 1px solid #0782C1;
+}
+
+/* Widget Styles */
+.code-featured
+{
+	border: 5px solid red;
+}
+
+.math-featured
+{
+	padding: 20px;
+	box-shadow: 0 0 2px rgba(200, 0, 0, 1);
+	background-color: rgba(255, 0, 0, 0.05);
+	margin: 10px;
+}
+
+.image-clean
+{
+	border: 0;
+	background: none;
+	padding: 0;
+}
+
+.image-clean > figcaption
+{
+	font-size: .9em;
+	text-align: right;
+}
+
+.image-grayscale
+{
+	background-color: white;
+	color: #666;
+}
+
+.image-grayscale img, img.image-grayscale
+{
+	filter: grayscale(100%);
+}
+
+.embed-240p
+{
+	max-width: 426px;
+	max-height: 240px;
+	margin:0 auto;
+}
+
+.embed-360p
+{
+	max-width: 640px;
+	max-height: 360px;
+	margin:0 auto;
+}
+
+.embed-480p
+{
+	max-width: 854px;
+	max-height: 480px;
+	margin:0 auto;
+}
+
+.embed-720p
+{
+	max-width: 1280px;
+	max-height: 720px;
+	margin:0 auto;
+}
+
+.embed-1080p
+{
+	max-width: 1920px;
+	max-height: 1080px;
+	margin:0 auto;
+}

File diff suppressed because it is too large
+ 5 - 0
front/project/www/static/ckeditor/lang/en.js


File diff suppressed because it is too large
+ 10 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js


+ 25 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/_translationstatus.txt

@@ -0,0 +1,25 @@
+Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+
+cs.js      Found: 30 Missing: 0
+cy.js      Found: 30 Missing: 0
+da.js      Found: 12 Missing: 18
+de.js      Found: 30 Missing: 0
+el.js      Found: 25 Missing: 5
+eo.js      Found: 30 Missing: 0
+fa.js      Found: 30 Missing: 0
+fi.js      Found: 30 Missing: 0
+fr.js      Found: 30 Missing: 0
+gu.js      Found: 12 Missing: 18
+he.js      Found: 30 Missing: 0
+it.js      Found: 30 Missing: 0
+mk.js      Found: 5 Missing: 25
+nb.js      Found: 30 Missing: 0
+nl.js      Found: 30 Missing: 0
+no.js      Found: 30 Missing: 0
+pt-br.js   Found: 30 Missing: 0
+ro.js      Found: 6 Missing: 24
+tr.js      Found: 30 Missing: 0
+ug.js      Found: 27 Missing: 3
+vi.js      Found: 6 Missing: 24
+zh-cn.js   Found: 30 Missing: 0

File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/af.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ar.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/az.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/bg.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ca.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/cs.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/cy.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/da.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/de-ch.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/de.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/el.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/en-au.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/en-gb.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/en.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/eo.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/es-mx.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/es.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/et.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/eu.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fa.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fi.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fo.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fr-ca.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/fr.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/gl.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/gu.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/he.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/hi.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/hr.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/hu.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/id.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/it.js


File diff suppressed because it is too large
+ 9 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ja.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/km.js


File diff suppressed because it is too large
+ 10 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ko.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ku.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/lt.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/lv.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/mk.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/mn.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/nb.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/nl.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/no.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/oc.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/pl.js


File diff suppressed because it is too large
+ 13 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/pt-br.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/pt.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ro.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ru.js


File diff suppressed because it is too large
+ 10 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/si.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sk.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sl.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sq.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sr-latn.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sr.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/sv.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/th.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/tr.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/tt.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/ug.js


File diff suppressed because it is too large
+ 12 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/uk.js


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/vi.js


File diff suppressed because it is too large
+ 9 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/zh-cn.js


File diff suppressed because it is too large
+ 9 - 0
front/project/www/static/ckeditor/plugins/a11yhelp/dialogs/lang/zh.js


File diff suppressed because it is too large
+ 8 - 0
front/project/www/static/ckeditor/plugins/about/dialogs/about.js


BIN
front/project/www/static/ckeditor/plugins/about/dialogs/hidpi/logo_ckeditor.png


BIN
front/project/www/static/ckeditor/plugins/about/dialogs/logo_ckeditor.png


File diff suppressed because it is too large
+ 11 - 0
front/project/www/static/ckeditor/plugins/clipboard/dialogs/paste.js


+ 4 - 0
front/project/www/static/ckeditor/plugins/dialog/dialogDefinition.js

@@ -0,0 +1,4 @@
+/*
+ Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+*/

BIN
front/project/www/static/ckeditor/plugins/icons.png


BIN
front/project/www/static/ckeditor/plugins/icons_hidpi.png


File diff suppressed because it is too large
+ 44 - 0
front/project/www/static/ckeditor/plugins/image/dialogs/image.js


BIN
front/project/www/static/ckeditor/plugins/image/images/noimage.png


+ 0 - 0
front/project/www/static/ckeditor/plugins/link/dialogs/anchor.js


Some files were not shown because too many files changed in this diff