@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,450 @@
1
+ import React, { Suspense, useEffect, useState } from 'react';
2
+ import { lazy } from '@loadable/component';
3
+ import { useOT } from '~/hooks';
4
+ // import * as ot from 'ot';
5
+ import styled from '@emotion/styled';
6
+ // import { animated, useSpring } from 'react-spring';
7
+ import Terminal from '~/components/Terminal';
8
+ import Tabs from '~/components/Tabs';
9
+ import create from 'zustand';
10
+ import { css } from '@emotion/css';
11
+ import { Avatar } from '~/components';
12
+ import Skeleton from '~/components/Skeleton';
13
+ import { oTStore } from '~/stores';
14
+ // import { FileTree } from '~/components/FileTree';
15
+ import Console from '~/components/Console';
16
+ import ToolBar from '~/components/ToolBar';
17
+ // import { TreeItemIndex } from 'react-complex-tree/lib/esm/types';
18
+ import OutputBrowser from '~/components/OutputBrowser';
19
+ import { ITerminalOptions } from 'xterm';
20
+ import { replay } from '~/helpers/collections/replay';
21
+ import LiveContent from '~/components/LiveContent';
22
+ import { userListStore, userStore } from '~/stores/oTStore';
23
+
24
+ export enum LanguageIcon {
25
+ js = 'javascript',
26
+ ts = 'typescript',
27
+ typescript = 'typescript',
28
+ tsx = 'typescript',
29
+ python = 'python',
30
+ json = 'json',
31
+ ruby = 'ruby',
32
+ rb = 'ruby',
33
+ java = 'java',
34
+ md = 'markdown',
35
+ erb = 'erb',
36
+ css = 'css',
37
+ ru = 'ruby',
38
+ ejs = 'html',
39
+ html = 'html',
40
+ }
41
+ const useIndexState = create<{
42
+ isFolded: boolean;
43
+ setFold: (arg: boolean) => void;
44
+ }>((set) => ({
45
+ isFolded: false,
46
+ setFold: (arg) => set({ isFolded: arg }),
47
+ }));
48
+
49
+ const LazyEditorComponent = lazy(
50
+ async () => (await import('../components/Editor')).Editor,
51
+ );
52
+ const LazyTreeComponent = lazy(
53
+ async () => (await import('../components/FileTree')).FileTree,
54
+ );
55
+
56
+ /*! purgecss start ignore */
57
+
58
+ const MainLayout = styled.div`
59
+ width: 100vw;
60
+ height: 100vh;
61
+ overflow: hidden;
62
+ background: #202327;
63
+ .lan-iconfont {
64
+ font-size: 40px;
65
+ }
66
+ .replay-button {
67
+ margin-left: 20px;
68
+ box-shadow: 0 0 5px aliceblue;
69
+ padding: 7px;
70
+ border-radius: 5px;
71
+ font-size: 12px;
72
+ background: #fff;
73
+ color: #000;
74
+ transition: 0.2s all;
75
+ &:active {
76
+ box-shadow: 0 0 0 aliceblue;
77
+ margin-right: 8px;
78
+ margin-top: 5px;
79
+ }
80
+ }
81
+ `;
82
+ /*! purgecss end ignore */
83
+
84
+ const PreviewWrapper = styled.div`
85
+ height: 40vh;
86
+ color: #333333;
87
+ background-color: #eaeaea;
88
+ `;
89
+
90
+ const TermWrapper = styled.div`
91
+ height: calc(100% - 40vh - 51px);
92
+ width: 100%;
93
+ `;
94
+
95
+ const HeaderLayout = styled.header`
96
+ width: 100%;
97
+ `;
98
+
99
+ const ContainerLayout = styled.div`
100
+ height: calc(100% - 4.625rem);
101
+ section {
102
+ height: calc(100% - 0.625rem);
103
+ }
104
+ `;
105
+
106
+ const IDELayout = styled.div`
107
+ height: 100%;
108
+ `;
109
+
110
+ const RunnerLayout = styled.section`
111
+ background: #202327;
112
+ width: 500px;
113
+ `;
114
+
115
+ const Index = (props) => {
116
+ const tabItems = [
117
+ {
118
+ eventKey: 'console',
119
+ itemName: 'Console',
120
+ },
121
+ {
122
+ eventKey: 'shell',
123
+ itemName: 'Shell',
124
+ },
125
+ ];
126
+ const defaultOptions: ITerminalOptions = {
127
+ convertEol: true,
128
+ fontSize: 12,
129
+ fontFamily: 'Monaco, Menlo, monospace',
130
+ lineHeight: 1,
131
+ cursorBlink: true,
132
+ cursorWidth: 1,
133
+ cursorStyle: 'block',
134
+ rightClickSelectsWord: true,
135
+ theme: {
136
+ background: '#1E1E1E',
137
+ },
138
+ };
139
+
140
+ // console.log(props);
141
+ const isFolded = useIndexState.getState().isFolded;
142
+ const playgroundInfo = oTStore((state) => state.playgroundInfo);
143
+
144
+ const [active, setActive] = useState('shell');
145
+ const [url, setUrl] = useState(playgroundInfo.url);
146
+ const { socket } = useOT.getState();
147
+ let terminalTabsTimer = 1;
148
+ const [consoleComp, setConsoleComp] = useState(<></>);
149
+ useEffect(() => {
150
+ if (terminalTabsTimer && active === 'console') {
151
+ terminalTabsTimer--;
152
+ setConsoleComp(<Console options={defaultOptions} fitHook={isFolded} />);
153
+ }
154
+ }, [active]);
155
+
156
+ useEffect(() => {
157
+ props.replay && replay();
158
+ }, [props.replay]);
159
+
160
+ useEffect(() => {
161
+ setUrl(playgroundInfo.url);
162
+ }, [playgroundInfo]);
163
+ useEffect(() => {
164
+ props.playgroundId &&
165
+ socket?.emit(
166
+ 'playgroundInfo',
167
+ JSON.stringify({
168
+ messageId: '1',
169
+ playgroundId: props.playgroundId,
170
+ }),
171
+ );
172
+ // temp code
173
+ }, [props.playgroundId]);
174
+ // useEffect(() => {
175
+ // // fetch('http://smb.dev.paas.dao42.com:9998/PaaS/users')
176
+ // // fetch('/paas/users')
177
+ // // .then((d) => d.json())
178
+ // // .then((d) => {
179
+ // // console.log(d);
180
+ // // });
181
+ // }, [props.users]);
182
+
183
+ return (
184
+ <>
185
+ <MainLayout className="flex flex-col">
186
+ {/* 头部 */}
187
+ <HeaderComponent />
188
+ {/* 内容区 */}
189
+ <ContainerLayout className="flex flex-1 mt-2.5 flex-row">
190
+ {/* 左侧栏 */}
191
+
192
+ <section className="flex flex-row">
193
+ <SliderComponent />
194
+ <TreeComponent />
195
+ {/* 文件树 */}
196
+ </section>
197
+ {/* 编辑器与终端 */}
198
+ <section className="bg-codezone-black rounded-sm mx-3.5 flex-1 flex flex-col">
199
+ <IDELayout>
200
+ {/* <Skeleton count={10} /> */}
201
+ <Suspense fallback={<Skeleton count={10} />}>
202
+ <LazyEditorComponent />
203
+ </Suspense>
204
+ </IDELayout>
205
+ </section>
206
+
207
+ {/* 运行框 */}
208
+ <RunnerLayout
209
+ // className={`rounded-sm mr-2.5 ${!isFolded ? 'max-w-5/12' : 'w-0'}`}
210
+ className={`rounded-sm mr-2.5`}
211
+ >
212
+ {/* <PreviewWrapper className="mb-2.5 relative">
213
+ <OutputBrowser url={url} />
214
+ </PreviewWrapper> */}
215
+
216
+ <Tabs
217
+ className="mb-1"
218
+ appearance="tabs"
219
+ activeKey={active}
220
+ onSelect={setActive}
221
+ tabItems={tabItems}
222
+ />
223
+ <Suspense fallback={<Skeleton />}>
224
+ <TermWrapper>
225
+ <div
226
+ key="console"
227
+ className=""
228
+ style={{
229
+ display: active === 'console' ? 'block' : 'none',
230
+ height: '100%',
231
+ width: '100%',
232
+ }}
233
+ >
234
+ {consoleComp}
235
+ </div>
236
+ <div
237
+ key="terminal"
238
+ style={{
239
+ display: active === 'console' ? 'none' : 'block',
240
+ height: '100%',
241
+ width: '100%',
242
+ }}
243
+ >
244
+ <Terminal options={defaultOptions} fitHook={isFolded} />
245
+ </div>
246
+ </TermWrapper>
247
+ </Suspense>
248
+ </RunnerLayout>
249
+ </ContainerLayout>
250
+ </MainLayout>
251
+ </>
252
+ );
253
+ };
254
+
255
+ const HeaderComponent = () => {
256
+ // const { userList } = userListStore.getState();
257
+ const userList = userListStore((state) => state.userList);
258
+ const appStatus = oTStore((state) => state.appStatus);
259
+ const globalData = oTStore((state) => state.globalData);
260
+ const { setAppStatus } = oTStore.getState();
261
+ const user = userStore.getState().userInfo;
262
+ // const [isRecording, setIsRecording] = useState<boolean>(false);
263
+ // console.log(userList);
264
+ return userList ? (
265
+ <HeaderLayout className="relative bg-codezone-black h-16 flex px-9 flex-shrink-0 justify-between">
266
+ <div className="flex">
267
+ <Avatar
268
+ user={user}
269
+ onClick={() => {
270
+ const minePage = window.open(
271
+ '//github.com/login/oauth/authorize?client_id=7333fa72cf5753ba016e&redirect_uri=http://localhost:3000/auth/github',
272
+ 'targetWindow',
273
+ `toolbar=no,
274
+ location=no,
275
+ status=no,
276
+ menubar=no,
277
+ scrollbars=yes,
278
+ resizable=yes,
279
+ width=500,
280
+ height=500`,
281
+ );
282
+ minePage.addEventListener(
283
+ 'load',
284
+ () => {
285
+ minePage.close();
286
+ },
287
+ false,
288
+ );
289
+ }}
290
+ />
291
+ {/* playgroundInfo */}
292
+ <div className="flex" style={{ color: '#fff', marginLeft: 20 }}>
293
+ <span className="self-center">{user.name}</span>
294
+ <i className="self-center" style={{ margin: '0 10px' }} />
295
+ <i
296
+ className={`self-center
297
+
298
+ devicon-${oTStore
299
+ .getState()
300
+ .playgroundInfo?.language?.toLowerCase()}-plain
301
+ lan-iconfont
302
+ colored`}
303
+ />
304
+
305
+ {/* <span className="self-center mr-2.5">{'{ playground_info }'}</span> */}
306
+ {/* <span className="self-center mr-2.5">{'{ playground_info }'}</span> */}
307
+ <ToolBar />
308
+ {!globalData.isRecording ? (
309
+ <button
310
+ className="replay-button self-center"
311
+ style={{
312
+ color: appStatus === 'replay' ? 'rgb(48, 89, 182)' : '#000',
313
+ }}
314
+ onClick={() => {
315
+ if (appStatus !== 'replay') {
316
+ replay();
317
+ }
318
+
319
+ if (appStatus === 'replay') {
320
+ replay('pause');
321
+ }
322
+ }}
323
+ >
324
+ {appStatus === 'replay'
325
+ ? '暂停播放'
326
+ : appStatus === 'pause'
327
+ ? '继续播放'
328
+ : '播放'}
329
+ </button>
330
+ ) : null}
331
+
332
+ {appStatus === 'replay' ? (
333
+ <button
334
+ className="replay-button self-center"
335
+ onClick={() => {
336
+ replay('stop');
337
+ }}
338
+ >
339
+ {appStatus === 'replay' ? '停止播放' : null}
340
+ </button>
341
+ ) : null}
342
+
343
+ {appStatus !== 'replay' ? (
344
+ <button
345
+ className="replay-button self-center"
346
+ // style={{
347
+ // color: appStatus === 'replay' ? 'rgb(48, 89, 182)' : '#000',
348
+ // }}
349
+ onClick={() => {
350
+ if (!globalData.isRecording) {
351
+ oTStore.getState().setGlobalData({
352
+ isRecording: true,
353
+ });
354
+ useOT.getState().socket.emit('globalData', {
355
+ isRecording: true,
356
+ });
357
+ return;
358
+ }
359
+ // oTStore.getState().setGlobalData({
360
+ // isRecording: false,
361
+ // });
362
+ // useOT.getState().socket.emit('globalData', {
363
+ // isRecording: false,
364
+ // });
365
+ }}
366
+ >
367
+ {globalData.isRecording ? '重新录制' : '开始录制'}
368
+ </button>
369
+ ) : null}
370
+
371
+ {globalData.isRecording ? (
372
+ <button
373
+ className="replay-button self-center"
374
+ onClick={() => {
375
+ oTStore.getState().setGlobalData({
376
+ isRecording: false,
377
+ });
378
+ useOT.getState().socket.emit('globalData', {
379
+ isRecording: false,
380
+ });
381
+ setAppStatus('code');
382
+ // replay('stop');
383
+ }}
384
+ >
385
+ 停止录制
386
+ </button>
387
+ ) : null}
388
+ </div>
389
+ </div>
390
+ <LiveContent />
391
+
392
+ <div className="items-center flex relative">
393
+ {userListStore.getState().userList.map((item, index) => {
394
+ return (
395
+ <div className="-ml-2.5 z-0 avatar-hover" key={index}>
396
+ <Avatar user={item} />
397
+ </div>
398
+ );
399
+ })}
400
+ </div>
401
+ </HeaderLayout>
402
+ ) : null;
403
+ };
404
+
405
+ const SliderComponent = () => {
406
+ const setFold = useIndexState((state) => state.setFold);
407
+ const isFolded = useIndexState((state) => state.isFolded);
408
+
409
+ return (
410
+ <section className="bg-codezone-black rounded-sm w-14 ml-2.5 flex flex-col pt-5 flex-shrink-0">
411
+ <i
412
+ onClick={() => setFold(!isFolded)}
413
+ className="cursor-pointer text-2xl text-gray-50 self-center mb-6 flex-center d42 snippets"
414
+ />
415
+ {/* <i className="cursor-pointer text-2xl text-gray-50 self-center mb-6 flex-center d42 Field-time"></i>
416
+ <i className="cursor-pointer text-2xl text-gray-50 self-center mb-6 flex-center d42 CodeSandbox"></i>
417
+ <i className="cursor-pointer text-2xl text-gray-50 self-center mb-6 flex-center d42 database"></i>
418
+ <i className="cursor-pointer text-2xl text-gray-50 self-center mb-6 flex-center d42 cloud-upload"></i>
419
+ <i className="cursor-pointer text-2xl text-gray-50 self-center mb-6 flex-center d42 setting"></i> */}
420
+ </section>
421
+ );
422
+ };
423
+
424
+ const TreeComponent = () => {
425
+ const isFolded = useIndexState.getState().isFolded;
426
+ return (
427
+ <section
428
+ className={`bg-codezone-black rounded-sm ml-2.5 transition-all flex-shrink-0 min-w-52 ${
429
+ !isFolded ? 'visible' : 'invisible'
430
+ } ${!isFolded ? 'w-52' : 'w-0'}`}
431
+ // } ${!isFolded ? 'w-52' : 'w-0'}`}
432
+ >
433
+ <header
434
+ className={css`
435
+ margin: 15px;
436
+ color: #fff;
437
+ visibility: ${!isFolded ? 'visible' : 'hidden'};
438
+ `}
439
+ >
440
+ 文件
441
+ </header>
442
+ <div style={{ height: 'calc(100% - 52px)' }}>
443
+ <Suspense fallback={<Skeleton count={5} />}>
444
+ <LazyTreeComponent />
445
+ </Suspense>
446
+ </div>
447
+ </section>
448
+ );
449
+ };
450
+ export default Index;
@@ -0,0 +1,35 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>DaoPaaS</title>
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.14.0/devicon.min.css" crossorigin="anonymous" />
9
+
10
+ </head>
11
+ <body>
12
+ <main>
13
+ <div class="edit-container"></div>
14
+ </main>
15
+ <script>
16
+ window.onload = () => {
17
+ var qs = new URLSearchParams(document.location.search.substring(1));
18
+ window.daopaas = new DaoPaaS({
19
+ ticket: qs.get('ticket'),
20
+ playgroundId: qs.get('playgroundId'),
21
+ userId: qs.get('userId'),
22
+ tenantId: qs.get('tenantId'),
23
+ username: qs.get('username')
24
+ });
25
+ daopaas.Page({
26
+ container: document.querySelector('main'),
27
+ // props: {
28
+ // playgroundId: search,
29
+ // }
30
+ }
31
+ )
32
+ }
33
+ </script>
34
+ </body>
35
+ </html>
@@ -0,0 +1,45 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>DaoPaaS</title>
8
+ <style>
9
+ main {
10
+ width: 100%;
11
+ height: 100vh;
12
+ overflow: hidden;
13
+ }
14
+ .edit-container {
15
+ height: 100%;
16
+ }
17
+ </style>
18
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.14.0/devicon.min.css" crossorigin="anonymous" />
19
+ </head>
20
+ <body>
21
+ <main>
22
+ <div class="edit-container"></div>
23
+ </main>
24
+ <script src="/dist/daoPaaS.js"></script>
25
+ <script>
26
+ window.onload = () => {
27
+ var qs = new URLSearchParams(document.location.search.substring(1));
28
+ window.daopaas = new DaoPaaS({
29
+ ticket: qs.get('ticket'),
30
+ playgroundId: qs.get('playgroundId'),
31
+ userId: qs.get('userId'),
32
+ tenantId: qs.get('tenantId'),
33
+ username: qs.get('username')
34
+ });
35
+ daopaas.Page({
36
+ container: document.querySelector('main'),
37
+ // props: {
38
+ // playgroundId: search,
39
+ // }
40
+ }
41
+ )
42
+ }
43
+ </script>
44
+ </body>
45
+ </html>
@@ -0,0 +1,35 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>DaoPaaS</title>
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.14.0/devicon.min.css" crossorigin="anonymous" />
9
+
10
+ </head>
11
+ <body>
12
+ <main></main>
13
+ <script>
14
+ window.onload = () => {
15
+ var qs = new URLSearchParams(document.location.search.substring(1));
16
+ console.log(DaoPaaS);
17
+ var daopaas = new DaoPaaS({
18
+ ticket: qs.get('ticket'),
19
+ playgroundId: qs.get('playgroundId'),
20
+ userId: qs.get('userId'),
21
+ tenantId: qs.get('tenantId'),
22
+ username: qs.get('username')
23
+ });
24
+ daopaas.Page({
25
+ container: document.querySelector('main'),
26
+ // props: {
27
+ // playgroundId: search,
28
+ // }
29
+ }
30
+ )
31
+ }
32
+
33
+ </script>
34
+ </body>
35
+ </html>
@@ -0,0 +1 @@
1
+ export { oTStore } from './oTStore';