@dao42/d42paas-front 0.4.5 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/package.json +3 -2
  2. package/src/app.tsx +250 -0
  3. package/src/assets/code-brackets.svg +1 -0
  4. package/src/assets/colors.svg +1 -0
  5. package/src/assets/comments.svg +1 -0
  6. package/src/assets/direction.svg +1 -0
  7. package/src/assets/flow.svg +1 -0
  8. package/src/assets/plugin.svg +1 -0
  9. package/src/assets/repo.svg +1 -0
  10. package/src/assets/stackalt.svg +1 -0
  11. package/src/components/Avatar/index.tsx +27 -0
  12. package/src/components/CanvasHelper/index.tsx +89 -0
  13. package/src/components/Console/index.tsx +88 -0
  14. package/src/components/Editor/index.tsx +979 -0
  15. package/src/components/FileTree/index.tsx +477 -0
  16. package/src/components/LiveContent/index.tsx +221 -0
  17. package/src/components/LiveContent/video.tsx +213 -0
  18. package/src/components/LottieAnim/index.tsx +41 -0
  19. package/src/components/Message/index.tsx +64 -0
  20. package/src/components/Model/index.tsx +42 -0
  21. package/src/components/OutputBrowser/index.tsx +180 -0
  22. package/src/components/Skeleton/index.tsx +41 -0
  23. package/src/components/Tabs/index.tsx +23 -0
  24. package/src/components/Terminal/index.tsx +127 -0
  25. package/src/components/ToolBar/index.tsx +169 -0
  26. package/src/components/XTerm/index.tsx +113 -0
  27. package/src/components/index.tsx +4 -0
  28. package/src/components/loading/index.tsx +282 -0
  29. package/src/enum/FExtension.ts +168 -0
  30. package/src/helpers/collections/IoClient.tsx +314 -0
  31. package/src/helpers/collections/errorCatcher.tsx +0 -0
  32. package/src/helpers/collections/idb.tsx +186 -0
  33. package/src/helpers/collections/localStorage.tsx +13 -0
  34. package/src/helpers/collections/mock.tsx +30 -0
  35. package/src/helpers/collections/playgroundInit.tsx +311 -0
  36. package/src/helpers/collections/replay.tsx +168 -0
  37. package/src/helpers/collections/socket.tsx +6 -0
  38. package/src/helpers/collections/toast.tsx +19 -0
  39. package/src/helpers/collections/userTool.tsx +12 -0
  40. package/src/helpers/collections/util.tsx +4 -0
  41. package/src/helpers/index.tsx +6 -0
  42. package/src/helpers/monaco/monaco-ot-adapter.tsx +476 -0
  43. package/src/hooks/collections/useOT.tsx +38 -0
  44. package/src/hooks/index.tsx +1 -0
  45. package/src/pages/index.tsx +450 -0
  46. package/src/public/dev.html +35 -0
  47. package/src/public/index.html +45 -0
  48. package/src/public/sdkserver.html +35 -0
  49. package/src/stores/index.tsx +1 -0
  50. package/src/stores/oTStore.tsx +288 -0
  51. package/src/stories/BrowserWindow.tsx +30 -0
  52. package/src/stories/Console.tsx +46 -0
  53. package/src/stories/Editor.tsx +37 -0
  54. package/src/stories/FileTree.tsx +50 -0
  55. package/src/stories/Shell.tsx +53 -0
  56. package/src/stories/introduction.stories.mdx +193 -0
  57. package/src/stories/page.tsx +71 -0
  58. package/src/styles/collections/iconfont.scss +1 -0
  59. package/src/styles/collections/tabs-costumers.scss +20 -0
  60. package/src/styles/collections/tailwind.scss +3 -0
  61. package/src/styles/collections/tree-costumers.scss +53 -0
  62. package/src/styles/collections/utility.scss +10 -0
  63. package/src/styles/collections/xterm-costumers.scss +47 -0
  64. package/src/styles/index.scss +19 -0
  65. package/src/types/editor.d.ts +31 -0
  66. package/src/types/index.d.ts +158 -0
@@ -0,0 +1,127 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { Terminal, ITerminalOptions } from 'xterm';
3
+ import XTerm from '~/components/XTerm';
4
+ import { oTStore, userListStore, userStore } from '~/stores/oTStore';
5
+ import { useOT } from '~/hooks';
6
+ import { pick } from 'lodash';
7
+ import { IsMe } from '~/helpers';
8
+
9
+ type TerminalProps = {
10
+ options?: ITerminalOptions;
11
+ height?: number | string;
12
+ width?: number | string;
13
+ fitHook?: boolean;
14
+ };
15
+
16
+ const TerminalComponent: React.FC<TerminalProps> = ({ options, ...props }) => {
17
+ const defaultOptions: ITerminalOptions = {
18
+ ...options,
19
+ };
20
+ const userLabel = document.createElement('div');
21
+ userLabel.classList.add('xterm-helper-user-label');
22
+
23
+ const [terminal, setTerminal] = useState<Terminal>(null);
24
+ const io = useOT((state) => state.socket);
25
+ const { CRDTInfo } = oTStore((state) => state);
26
+
27
+ const initTerminalText = (terminal: Terminal, text: string) => {
28
+ // terminal.clear() 会留下最后一行代码,因此使用 write: \r\n 空置一行
29
+ terminal.write('\r\n');
30
+ terminal.clear();
31
+ writeText(terminal, text);
32
+ };
33
+
34
+ const writeText = (terminal: Terminal, text: string) => {
35
+ terminal.write(text);
36
+ };
37
+
38
+ const onKey = (char: string) => {
39
+ if (oTStore.getState().appStatus === 'replay') {
40
+ return;
41
+ }
42
+ const crdt: D42_FrontType.CRDT = {
43
+ timestamp: Date.now().toString(),
44
+ userInfo: pick(userStore.getState().userInfo, 'uuid'),
45
+ terminal: {
46
+ doc: {
47
+ action: 'Edit',
48
+ value: char,
49
+ },
50
+ },
51
+ };
52
+ io.emit('terminal', JSON.stringify(crdt));
53
+ };
54
+
55
+ useEffect(() => {
56
+ if (!terminal) {
57
+ const term = new Terminal(defaultOptions);
58
+ setTerminal(term);
59
+ }
60
+ }, []);
61
+ useEffect(() => {
62
+ if (!terminal) return;
63
+ if (CRDTInfo.terminal) {
64
+ initTerminalText(
65
+ terminal,
66
+ oTStore.getState().CRDTInfo.terminal.doc?.value || '',
67
+ );
68
+ }
69
+ }, [terminal]);
70
+
71
+ useEffect(() => {
72
+ const crdt = CRDTInfo.terminal;
73
+ if (terminal && crdt) {
74
+ if (crdt.doc.action === 'Get') {
75
+ initTerminalText(terminal, crdt.doc.value);
76
+ return;
77
+ }
78
+ writeText(terminal, crdt.doc.value || '');
79
+
80
+ const postUser = userListStore.getState().userList[
81
+ CRDTInfo.userInfo.uuid
82
+ ];
83
+ if (postUser && !IsMe(CRDTInfo.userInfo)) {
84
+ const helperContainer = terminal._core._helperContainer;
85
+
86
+ userLabel.innerText = postUser.name;
87
+ userLabel.style.backgroundColor = postUser.color;
88
+ userLabel.style.top = helperContainer.firstChild.style.top;
89
+ userLabel.style.left = helperContainer.firstChild.style.left;
90
+
91
+ helperContainer?.appendChild(userLabel);
92
+ terminal.setOption('theme', {
93
+ ...terminal.getOption('theme'),
94
+ cursor: postUser.color,
95
+ });
96
+
97
+ const timer = setTimeout(() => {
98
+ helperContainer?.removeChild(userLabel);
99
+ terminal.setOption('theme', {
100
+ ...terminal.getOption('theme'),
101
+ cursor: '#ffffff',
102
+ });
103
+ }, 6000);
104
+ return () => {
105
+ try {
106
+ helperContainer?.removeChild(userLabel);
107
+ } catch (_) {
108
+ console.log('There isn\'t any "userLabel", please try again.');
109
+ }
110
+ terminal.setOption('theme', {
111
+ ...terminal.getOption('theme'),
112
+ cursor: '#ffffff',
113
+ });
114
+ clearTimeout(timer);
115
+ };
116
+ }
117
+ }
118
+ }, [CRDTInfo.terminal]);
119
+
120
+ return (
121
+ <div id="terminal" style={{ height: '100%', width: '100%' }}>
122
+ <XTerm terminal={terminal} onKey={onKey} {...props} />
123
+ </div>
124
+ );
125
+ };
126
+
127
+ export default TerminalComponent;
@@ -0,0 +1,169 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { oTStore } from '~/stores/oTStore';
3
+ import styled from '@emotion/styled';
4
+ import { useOT } from '~/hooks';
5
+
6
+ type ToolBarProps = {
7
+ className?: string;
8
+ };
9
+
10
+ const ToolBarWrapper = styled.div`
11
+ position: relative;
12
+ display: flex;
13
+ align-items: center;
14
+ margin-left: 50px;
15
+ padding-right: 30px;
16
+ `;
17
+
18
+ const ButtonWrapper = styled.div`
19
+ align-self: center;
20
+ color: white;
21
+ width: auto;
22
+ height: 40px;
23
+ padding-left: 8px;
24
+ padding-right: 8px;
25
+ border-radius: 4px;
26
+ display: flex;
27
+ justify-content: space-around;
28
+ align-items: center;
29
+ cursor: pointer;
30
+ background-color: rgb(48, 89, 182);
31
+ &.disabled {
32
+ background-color: #524e4e;
33
+ cursor: not-allowed;
34
+ }
35
+
36
+ &.pro-running {
37
+ background-color: red;
38
+ }
39
+ `;
40
+
41
+ const ButtonContent = ({ playgroundStatus, dockerStatus }) => {
42
+ return (
43
+ <>
44
+ {(() => {
45
+ switch (playgroundStatus) {
46
+ case 'EMPTY':
47
+ return (
48
+ <>
49
+ <i className="w-5 h-5 mr-2.5 text-xl d42 loading text-white animate-spin flex justify-center items-center" />
50
+ <div>加载中...</div>
51
+ </>
52
+ );
53
+ case 'ACTIVE':
54
+ return dockerStatus === 'STOP' ? (
55
+ <>
56
+ <i className="w-5 h-5 mr-2.5 text-xl d42 run-solid text-white flex justify-center items-center" />
57
+ <div>运行</div>
58
+ </>
59
+ ) : (
60
+ dockerStatus === 'RUNNING' && (
61
+ <>
62
+ <i className="w-5 h-5 mr-2.5 text-xl d42 stop text-white flex justify-center items-center" />
63
+ <div>停止运行</div>
64
+ </>
65
+ )
66
+ );
67
+ case 'INACTIVE':
68
+ return (
69
+ <>
70
+ <i className="w-5 h-5 mr-2.5 self-center text-xl d42 cloud-offline-outline flex justify-center items-center" />
71
+ <div>激活</div>
72
+ </>
73
+ );
74
+ default:
75
+ return <></>;
76
+ }
77
+ })()}
78
+ </>
79
+ );
80
+ };
81
+
82
+ const ToolBar: React.FC<ToolBarProps> = ({ ...props }) => {
83
+ const io = useOT((state) => state.socket);
84
+
85
+ const pStatus = oTStore((state) => state.playgroundStatus);
86
+ const dStatus = oTStore((state) => state.dockerStatus);
87
+
88
+ const [playgroundStatus, setPlaygroundStatus] = useState('EMPTY');
89
+ const [dockerStatus, setDockerStatus] = useState('STOP');
90
+
91
+ useEffect(() => {
92
+ setPlaygroundStatus(pStatus);
93
+ }, [pStatus]);
94
+ useEffect(() => {
95
+ setDockerStatus(dStatus);
96
+ }, [dStatus]);
97
+
98
+ const onRun = () => {
99
+ if (oTStore.getState().playgroundStatus === 'ACTIVE') {
100
+ io.emit('run');
101
+ } else if (oTStore.getState().playgroundStatus === 'INACTIVE') {
102
+ io.emit('active');
103
+ }
104
+ };
105
+ const onStop = () => {
106
+ io.emit('stop');
107
+ };
108
+
109
+ const [netStatus, setNetStatus] = useState<'WEAK_NET' | 'ONLINE' | 'OFFLINE'>(
110
+ 'ONLINE',
111
+ );
112
+ useEffect(() => {
113
+ window.addEventListener('online', () => {
114
+ setNetStatus('ONLINE');
115
+ });
116
+ window.addEventListener('offline', () => {
117
+ setNetStatus('OFFLINE');
118
+ });
119
+ setInterval(() => {
120
+ if (getSpeedWithDownlink() <= 300) {
121
+ setNetStatus('WEAK_NET');
122
+ } else {
123
+ setNetStatus('ONLINE');
124
+ }
125
+ }, 300000);
126
+ }, []);
127
+
128
+ const getSpeedWithDownlink = () => {
129
+ // downlink 测算网速: kb/s
130
+ const connection = window.navigator.connection;
131
+ if (connection && connection.downlink) {
132
+ return (connection.downlink * 1024) / 8;
133
+ }
134
+ };
135
+
136
+ return (
137
+ <ToolBarWrapper>
138
+ <ButtonWrapper
139
+ onClick={
140
+ playgroundStatus === 'INACTIVE' || dockerStatus === 'STOP'
141
+ ? onRun
142
+ : onStop
143
+ }
144
+ className={[
145
+ playgroundStatus === 'EMPTY' ? 'disabled' : '',
146
+ playgroundStatus === 'ACTIVE' && dockerStatus === 'RUNNING'
147
+ ? 'pro-running'
148
+ : '',
149
+ ].join(' ')}
150
+ {...props}
151
+ >
152
+ <ButtonContent
153
+ playgroundStatus={playgroundStatus}
154
+ dockerStatus={dockerStatus}
155
+ />
156
+ </ButtonWrapper>
157
+ <i
158
+ className="d42 offline text-xl text-white absolute animate-pulse -right-2"
159
+ style={{ display: netStatus === 'OFFLINE' ? 'block' : 'none' }}
160
+ />
161
+ <i
162
+ className="d42 loading text-xl text-white animate-spin absolute -right-2"
163
+ style={{ display: netStatus === 'WEAK_NET' ? 'block' : 'none' }}
164
+ />
165
+ </ToolBarWrapper>
166
+ );
167
+ };
168
+
169
+ export default ToolBar;
@@ -0,0 +1,113 @@
1
+ import React, { FC, useEffect, useRef } from 'react';
2
+ import { Terminal } from 'xterm';
3
+ import { FitAddon } from 'xterm-addon-fit';
4
+
5
+ /**
6
+ * 特殊字符表
7
+ * "\x1b[K",//清除光标至行末字符,包括光标位置,行属性不受影响。
8
+ "\x1b[0K",//清除光标至行末字符,包括光标位置,行属性不受影响。
9
+ "\x1b[1K",//清除行首至光标位置字符,包括光标位置,行属性不受影响。
10
+ "\x1b[2K",//清除光标所在行的所有字符
11
+ "\x1b[A",//光标上移
12
+ "\x1b[B",//光标下移
13
+ "\x1b[C",//光标右移
14
+ "\x1b[D",//光标左移
15
+ "\u00003", //Ctrl-C
16
+ */
17
+
18
+ export interface XTermProps {
19
+ terminal: Terminal;
20
+ userLabel?: HTMLDivElement;
21
+ height?: number | string;
22
+ width?: number | string;
23
+ fitHook?: boolean;
24
+ onKey?: (character: string) => void;
25
+ }
26
+
27
+ const XTerm: FC<XTermProps> = ({ terminal, onKey, fitHook, ...props }) => {
28
+ const stateStyle = {
29
+ height: '100%',
30
+ width: '100%',
31
+ padding: '5px 20px',
32
+ backgroundColor: '#1e1e1e',
33
+ ...props,
34
+ };
35
+
36
+ const xtermFitAddon = new FitAddon();
37
+
38
+ const terminalRef = useRef<HTMLDivElement>(null);
39
+
40
+ const initTerminalEvents = (term: Terminal) => {
41
+ term.onKey(({ key, domEvent }) => {
42
+ let character: string = key;
43
+
44
+ switch (key.charCodeAt(0)) {
45
+ case 13:
46
+ break;
47
+ case 27:
48
+ switch (domEvent.key) {
49
+ case 'ArrowLeft':
50
+ if (term.buffer.active.cursorX <= 2) {
51
+ return;
52
+ }
53
+ break;
54
+ case 'ArrowRight':
55
+ break;
56
+ case 'ArrowUp':
57
+ case 'ArrowDown':
58
+ break;
59
+ default:
60
+ break;
61
+ }
62
+ break;
63
+ case 8: // backspace key: delete char on the left of the cursor
64
+ case 127:
65
+ if (term.buffer.active.cursorX > 2) {
66
+ character = '\b';
67
+ }
68
+ break;
69
+ case 27: // delete key: delete char on the right of the cursor
70
+ character = '[3~';
71
+ break;
72
+ default:
73
+ break;
74
+ }
75
+
76
+ onKey(character);
77
+ });
78
+ };
79
+
80
+ const fitTerminal = () => {
81
+ try {
82
+ setTimeout(() => {
83
+ xtermFitAddon.fit();
84
+ }, 0);
85
+ } catch (_) {}
86
+ };
87
+
88
+ useEffect(() => {
89
+ if (terminal) {
90
+ terminal.loadAddon(xtermFitAddon);
91
+ initTerminalEvents(terminal);
92
+ terminal.open(terminalRef.current);
93
+ fitTerminal();
94
+ }
95
+ }, [terminal]);
96
+
97
+ useEffect(() => {
98
+ fitTerminal();
99
+ }, [fitHook]);
100
+
101
+ return (
102
+ <>
103
+ <div
104
+ style={{
105
+ ...stateStyle,
106
+ }}
107
+ ref={terminalRef}
108
+ ></div>
109
+ </>
110
+ );
111
+ };
112
+
113
+ export default XTerm;
@@ -0,0 +1,4 @@
1
+ export { Editor } from './Editor';
2
+ export { Avatar } from './Avatar';
3
+ export { FileTree } from './FileTree';
4
+ // export * as FileTree from './FileTree';
@@ -0,0 +1,282 @@
1
+ import styled from '@emotion/styled';
2
+ import React from 'react';
3
+
4
+ const LoadingLayout = styled.div`
5
+ position: fixed;
6
+ width: 100%;
7
+ height: 100%;
8
+ top: 0;
9
+ left: 0;
10
+ z-index: 999;
11
+ .preloader {
12
+ opacity: 1;
13
+ position: absolute;
14
+ margin-left: -55px;
15
+ margin-top: -100px;
16
+ height: 110px;
17
+ width: 110px;
18
+ left: 50%;
19
+ top: 50%;
20
+ }
21
+
22
+ .first-svg {
23
+ opacity: 1;
24
+ margin-left: 0px;
25
+ margin-top: 0px;
26
+ }
27
+
28
+ svg {
29
+ width: 110px;
30
+ height: 110px;
31
+ }
32
+
33
+ path {
34
+ stroke: #9ea1a4;
35
+ stroke-width: 0.25;
36
+ fill: #241e20;
37
+ }
38
+
39
+ #cloud {
40
+ position: relative;
41
+ z-index: 2;
42
+ }
43
+
44
+ #cloud path {
45
+ fill: #efefef;
46
+ }
47
+
48
+ #sun {
49
+ margin-left: -10px;
50
+ margin-top: 6px;
51
+ opacity: 0;
52
+ width: 60px;
53
+ height: 60px;
54
+ position: absolute;
55
+ left: 45px;
56
+ top: 15px;
57
+ z-index: 1;
58
+
59
+ animation-name: rotate;
60
+ animation-duration: 16000ms;
61
+ animation-iteration-count: infinite;
62
+ animation-timing-function: linear;
63
+ }
64
+
65
+ #sun path {
66
+ stroke-width: 0.18;
67
+ fill: #9ea1a4;
68
+ }
69
+
70
+ @keyframes rotate {
71
+ 0% {
72
+ transform: rotateZ(0deg);
73
+ }
74
+
75
+ 100% {
76
+ transform: rotateZ(360deg);
77
+ }
78
+ }
79
+
80
+ /* Rain */
81
+ .rain {
82
+ position: absolute;
83
+ width: 70px;
84
+ height: 70px;
85
+ margin-top: -32px;
86
+ margin-left: 19px;
87
+ }
88
+
89
+ .drop {
90
+ opacity: 1;
91
+ background: #9ea1a4;
92
+ display: block;
93
+ float: left;
94
+ width: 3px;
95
+ height: 10px;
96
+ margin-left: 4px;
97
+ border-radius: 0px 0px 6px 6px;
98
+
99
+ animation-name: drop;
100
+ animation-duration: 350ms;
101
+ animation-iteration-count: infinite;
102
+ }
103
+
104
+ .drop:nth-of-type(1) {
105
+ animation-delay: -130ms;
106
+ }
107
+
108
+ .drop:nth-of-type(2) {
109
+ animation-delay: -240ms;
110
+ }
111
+
112
+ .drop:nth-of-type(3) {
113
+ animation-delay: -390ms;
114
+ }
115
+
116
+ .drop:nth-of-type(4) {
117
+ animation-delay: -525ms;
118
+ }
119
+
120
+ .drop:nth-of-type(5) {
121
+ animation-delay: -640ms;
122
+ }
123
+
124
+ .drop:nth-of-type(6) {
125
+ animation-delay: -790ms;
126
+ }
127
+
128
+ .drop:nth-of-type(7) {
129
+ animation-delay: -900ms;
130
+ }
131
+
132
+ .drop:nth-of-type(8) {
133
+ animation-delay: -1050ms;
134
+ }
135
+
136
+ .drop:nth-of-type(9) {
137
+ animation-delay: -1130ms;
138
+ }
139
+
140
+ .drop:nth-of-type(10) {
141
+ animation-delay: -1300ms;
142
+ }
143
+
144
+ @keyframes drop {
145
+ 50% {
146
+ height: 45px;
147
+ opacity: 0;
148
+ }
149
+
150
+ 51% {
151
+ opacity: 0;
152
+ }
153
+
154
+ 100% {
155
+ height: 1px;
156
+ opacity: 0;
157
+ }
158
+ }
159
+
160
+ .text {
161
+ font-family: Helvetica, 'Helvetica Neue', sans-serif;
162
+ letter-spacing: 1px;
163
+ text-align: center;
164
+ margin-left: -43px;
165
+ font-weight: bold;
166
+ margin-top: 20px;
167
+ font-size: 11px;
168
+ color: #a0a0a0;
169
+ width: 200px;
170
+ }
171
+ `;
172
+ export const Loading = () => {
173
+ return (
174
+ <LoadingLayout>
175
+ <div className="preloader">
176
+ <svg
177
+ className="first-svg"
178
+ version="1.1"
179
+ id="sun"
180
+ xmlns="http://www.w3.org/2000/svg"
181
+ xmlnsXlink="http://www.w3.org/1999/xlink"
182
+ x="0px"
183
+ y="0px"
184
+ width="10px"
185
+ height="10px"
186
+ viewBox="0 0 10 10"
187
+ enableBackground="new 0 0 10 10"
188
+ xmlSpace="preserve"
189
+ >
190
+ <g>
191
+ <path
192
+ fill="none"
193
+ d="M6.942,3.876c-0.4-0.692-1.146-1.123-1.946-1.123c-0.392,0-0.779,0.104-1.121,0.301c-1.072,0.619-1.44,1.994-0.821,3.067C3.454,6.815,4.2,7.245,5,7.245c0.392,0,0.779-0.104,1.121-0.301C6.64,6.644,7.013,6.159,7.167,5.581C7.321,5,7.243,4.396,6.942,3.876z M6.88,5.505C6.745,6.007,6.423,6.427,5.973,6.688C5.676,6.858,5.34,6.948,5,6.948c-0.695,0-1.343-0.373-1.69-0.975C2.774,5.043,3.093,3.849,4.024,3.312C4.32,3.14,4.656,3.05,4.996,3.05c0.695,0,1.342,0.374,1.69,0.975C6.946,4.476,7.015,5,6.88,5.505z"
194
+ ></path>
195
+ <path
196
+ fill="none"
197
+ d="M8.759,2.828C8.718,2.757,8.626,2.732,8.556,2.774L7.345,3.473c-0.07,0.041-0.094,0.132-0.053,0.202C7.319,3.723,7.368,3.75,7.419,3.75c0.025,0,0.053-0.007,0.074-0.02l1.211-0.699C8.774,2.989,8.8,2.899,8.759,2.828z"
198
+ ></path>
199
+ <path
200
+ fill="none"
201
+ d="M1.238,7.171c0.027,0.047,0.077,0.074,0.128,0.074c0.025,0,0.051-0.008,0.074-0.02l1.211-0.699c0.071-0.041,0.095-0.133,0.054-0.203S2.574,6.228,2.503,6.269l-1.21,0.699C1.221,7.009,1.197,7.101,1.238,7.171z"
202
+ ></path>
203
+ <path
204
+ fill="none"
205
+ d="M6.396,2.726c0.052,0,0.102-0.026,0.13-0.075l0.349-0.605C6.915,1.976,6.89,1.885,6.819,1.844c-0.07-0.042-0.162-0.017-0.202,0.054L6.269,2.503C6.228,2.574,6.251,2.666,6.322,2.706C6.346,2.719,6.371,2.726,6.396,2.726z"
206
+ ></path>
207
+ <path
208
+ fill="none"
209
+ d="M3.472,7.347L3.123,7.952c-0.041,0.07-0.017,0.162,0.054,0.203C3.2,8.169,3.226,8.175,3.25,8.175c0.052,0,0.102-0.027,0.129-0.074l0.349-0.605c0.041-0.07,0.017-0.16-0.054-0.203C3.603,7.251,3.513,7.276,3.472,7.347z"
210
+ ></path>
211
+ <path
212
+ fill="none"
213
+ d="M3.601,2.726c0.025,0,0.051-0.007,0.074-0.02C3.746,2.666,3.77,2.574,3.729,2.503l-0.35-0.604C3.338,1.828,3.248,1.804,3.177,1.844C3.106,1.886,3.082,1.976,3.123,2.047l0.35,0.604C3.5,2.7,3.549,2.726,3.601,2.726z"
214
+ ></path>
215
+ <path
216
+ fill="none"
217
+ d="M6.321,7.292c-0.07,0.043-0.094,0.133-0.054,0.203l0.351,0.605c0.026,0.047,0.076,0.074,0.127,0.074c0.025,0,0.051-0.006,0.074-0.02c0.072-0.041,0.096-0.133,0.055-0.203l-0.35-0.605C6.483,7.276,6.393,7.253,6.321,7.292z"
218
+ ></path>
219
+ <path
220
+ fill="none"
221
+ d="M2.202,5.146c0.082,0,0.149-0.065,0.149-0.147S2.284,4.851,2.202,4.851H1.503c-0.082,0-0.148,0.066-0.148,0.148s0.066,0.147,0.148,0.147H2.202z"
222
+ ></path>
223
+ <path
224
+ fill="none"
225
+ d="M8.493,4.851H7.794c-0.082,0-0.148,0.066-0.148,0.148s0.066,0.147,0.148,0.147l0,0h0.699c0.082,0,0.148-0.065,0.148-0.147S8.575,4.851,8.493,4.851L8.493,4.851z"
226
+ ></path>
227
+ <path
228
+ fill="none"
229
+ d="M5.146,2.203V0.805c0-0.082-0.066-0.148-0.148-0.148c-0.082,0-0.148,0.066-0.148,0.148v1.398c0,0.082,0.066,0.149,0.148,0.149C5.08,2.352,5.146,2.285,5.146,2.203z"
230
+ ></path>
231
+ <path
232
+ fill="none"
233
+ d="M4.85,7.796v1.396c0,0.082,0.066,0.15,0.148,0.15c0.082,0,0.148-0.068,0.148-0.15V7.796c0-0.082-0.066-0.148-0.148-0.148C4.917,7.647,4.85,7.714,4.85,7.796z"
234
+ ></path>
235
+ <path
236
+ fill="none"
237
+ d="M2.651,3.473L1.44,2.774C1.369,2.732,1.279,2.757,1.238,2.828C1.197,2.899,1.221,2.989,1.292,3.031l1.21,0.699c0.023,0.013,0.049,0.02,0.074,0.02c0.051,0,0.101-0.026,0.129-0.075C2.747,3.604,2.722,3.514,2.651,3.473z"
238
+ ></path>
239
+ <path
240
+ fill="none"
241
+ d="M8.704,6.968L7.493,6.269c-0.07-0.041-0.162-0.016-0.201,0.055c-0.041,0.07-0.018,0.162,0.053,0.203l1.211,0.699c0.023,0.012,0.049,0.02,0.074,0.02c0.051,0,0.102-0.027,0.129-0.074C8.8,7.101,8.776,7.009,8.704,6.968z"
242
+ ></path>
243
+ </g>
244
+ </svg>
245
+
246
+ <svg
247
+ version="1.1"
248
+ id="cloud"
249
+ xmlns="http://www.w3.org/2000/svg"
250
+ xmlnsXlink="http://www.w3.org/1999/xlink"
251
+ x="0px"
252
+ y="0px"
253
+ width="10px"
254
+ height="10px"
255
+ viewBox="0 0 10 10"
256
+ enableBackground="new 0 0 10 10"
257
+ xmlSpace="preserve"
258
+ >
259
+ <path
260
+ fill="none"
261
+ d="M8.528,5.624H8.247c-0.085,0-0.156-0.068-0.156-0.154c0-0.694-0.563-1.257-1.257-1.257c-0.098,0-0.197,0.013-0.3,0.038C6.493,4.259,6.45,4.252,6.415,4.229C6.38,4.208,6.356,4.172,6.348,4.131C6.117,3.032,5.135,2.235,4.01,2.235c-1.252,0-2.297,0.979-2.379,2.23c-0.004,0.056-0.039,0.108-0.093,0.13C1.076,4.793,0.776,5.249,0.776,5.752c0,0.693,0.564,1.257,1.257,1.257h6.495c0.383,0,0.695-0.31,0.695-0.692S8.911,5.624,8.528,5.624z"
262
+ ></path>
263
+ </svg>
264
+
265
+ <div className="rain">
266
+ <span className="drop"></span>
267
+ <span className="drop"></span>
268
+ <span className="drop"></span>
269
+ <span className="drop"></span>
270
+ <span className="drop"></span>
271
+ <span className="drop"></span>
272
+ <span className="drop"></span>
273
+ <span className="drop"></span>
274
+ <span className="drop"></span>
275
+ <span className="drop"></span>
276
+ </div>
277
+
278
+ <div className="text">Loading......</div>
279
+ </div>
280
+ </LoadingLayout>
281
+ );
282
+ };