miqro 6.1.2 → 6.1.3

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 (157) hide show
  1. package/build/esm/editor/auth.d.ts +6 -0
  2. package/build/esm/editor/auth.js +41 -0
  3. package/build/esm/editor/common/admin-interface.d.ts +36 -0
  4. package/build/esm/editor/common/admin-interface.js +44 -0
  5. package/build/esm/editor/common/constants.d.ts +4 -0
  6. package/build/esm/editor/common/constants.js +20 -0
  7. package/build/esm/editor/common/constants.server.d.ts +2 -0
  8. package/build/esm/editor/common/constants.server.js +4 -0
  9. package/build/esm/editor/common/editor-index.d.ts +2 -0
  10. package/build/esm/editor/common/editor-index.js +14 -0
  11. package/build/esm/editor/common/html-encode.d.ts +1 -0
  12. package/build/esm/editor/common/html-encode.js +14 -0
  13. package/build/esm/editor/common/log-socket.d.ts +15 -0
  14. package/build/esm/editor/common/log-socket.js +70 -0
  15. package/build/esm/editor/common/templates.d.ts +11 -0
  16. package/build/esm/editor/common/templates.js +461 -0
  17. package/build/esm/editor/components/api-preview.d.ts +11 -0
  18. package/build/esm/editor/components/api-preview.js +90 -0
  19. package/build/esm/editor/components/editor.d.ts +16 -0
  20. package/build/esm/editor/components/editor.js +357 -0
  21. package/build/esm/editor/components/file-browser.d.ts +37 -0
  22. package/build/esm/editor/components/file-browser.js +126 -0
  23. package/build/esm/editor/components/file-editor-toolbar.d.ts +22 -0
  24. package/build/esm/editor/components/file-editor-toolbar.js +93 -0
  25. package/build/esm/editor/components/file-editor.d.ts +32 -0
  26. package/build/esm/editor/components/file-editor.js +59 -0
  27. package/build/esm/editor/components/filter-query.d.ts +1 -0
  28. package/build/esm/editor/components/filter-query.js +22 -0
  29. package/build/esm/editor/components/highlight-text-area.d.ts +11 -0
  30. package/build/esm/editor/components/highlight-text-area.js +124 -0
  31. package/build/esm/editor/components/log-viewer.d.ts +6 -0
  32. package/build/esm/editor/components/log-viewer.js +69 -0
  33. package/build/esm/editor/components/new-file.d.ts +10 -0
  34. package/build/esm/editor/components/new-file.js +117 -0
  35. package/build/esm/editor/components/scroll-query.d.ts +7 -0
  36. package/build/esm/editor/components/scroll-query.js +21 -0
  37. package/build/esm/editor/components/start-page.d.ts +13 -0
  38. package/build/esm/editor/components/start-page.js +30 -0
  39. package/build/esm/editor/http/admin/editor/api/fs/delete.api.d.ts +3 -0
  40. package/build/esm/editor/http/admin/editor/api/fs/delete.api.js +29 -0
  41. package/build/esm/editor/http/admin/editor/api/fs/read.api.d.ts +5 -0
  42. package/build/esm/editor/http/admin/editor/api/fs/read.api.js +49 -0
  43. package/build/esm/editor/http/admin/editor/api/fs/rename.api.d.ts +4 -0
  44. package/build/esm/editor/http/admin/editor/api/fs/rename.api.js +39 -0
  45. package/build/esm/editor/http/admin/editor/api/fs/scan.api.d.ts +26 -0
  46. package/build/esm/editor/http/admin/editor/api/fs/scan.api.js +149 -0
  47. package/build/esm/editor/http/admin/editor/api/fs/write.api.d.ts +3 -0
  48. package/build/esm/editor/http/admin/editor/api/fs/write.api.js +38 -0
  49. package/build/esm/editor/http/admin/editor/api/server/reload.api.d.ts +10 -0
  50. package/build/esm/editor/http/admin/editor/api/server/reload.api.js +46 -0
  51. package/build/esm/editor/http/admin/editor/api/server/restart.api.d.ts +10 -0
  52. package/build/esm/editor/http/admin/editor/api/server/restart.api.js +45 -0
  53. package/build/esm/editor/http/admin/editor/editor.d.ts +1 -0
  54. package/build/esm/editor/http/admin/editor/editor.js +7 -0
  55. package/build/esm/editor/http/admin/editor/index.api.d.ts +3 -0
  56. package/build/esm/editor/http/admin/editor/index.api.js +21 -0
  57. package/build/esm/editor/server.d.ts +3 -0
  58. package/build/esm/editor/server.js +49 -0
  59. package/build/esm/editor/ws.d.ts +3 -0
  60. package/build/esm/editor/ws.js +11 -0
  61. package/editor/auth.ts +51 -0
  62. package/editor/common/admin-interface.ts +84 -0
  63. package/editor/common/constants.server.ts +5 -0
  64. package/editor/common/constants.ts +21 -0
  65. package/editor/common/editor-index.tsx +17 -0
  66. package/editor/common/html-encode.ts +14 -0
  67. package/editor/common/log-socket.tsx +85 -0
  68. package/editor/common/templates.ts +466 -0
  69. package/editor/components/api-preview.tsx +116 -0
  70. package/editor/components/editor.tsx +486 -0
  71. package/editor/components/file-browser.tsx +308 -0
  72. package/editor/components/file-editor-toolbar.tsx +191 -0
  73. package/editor/components/file-editor.tsx +122 -0
  74. package/editor/components/filter-query.tsx +22 -0
  75. package/editor/components/highlight-text-area.tsx +144 -0
  76. package/editor/components/log-viewer.tsx +110 -0
  77. package/editor/components/new-file.tsx +169 -0
  78. package/editor/components/scroll-query.tsx +22 -0
  79. package/editor/components/start-page.tsx +49 -0
  80. package/editor/http/admin/editor/api/fs/delete.api.tsx +32 -0
  81. package/editor/http/admin/editor/api/fs/read.api.tsx +55 -0
  82. package/editor/http/admin/editor/api/fs/rename.api.tsx +41 -0
  83. package/editor/http/admin/editor/api/fs/scan.api.tsx +181 -0
  84. package/editor/http/admin/editor/api/fs/write.api.tsx +41 -0
  85. package/editor/http/admin/editor/api/server/reload.api.ts +53 -0
  86. package/editor/http/admin/editor/api/server/restart.api.tsx +52 -0
  87. package/editor/http/admin/editor/editor.tsx +8 -0
  88. package/editor/http/admin/editor/index.api.tsx +39 -0
  89. package/editor/server.ts +57 -0
  90. package/editor/ws.ts +15 -0
  91. package/package.json +1 -1
  92. package/src/bin/compile.ts +35 -0
  93. package/src/bin/doc-md.ts +210 -0
  94. package/src/bin/generate-doc.ts +64 -0
  95. package/src/bin/test.ts +92 -0
  96. package/src/bin/types.ts +22 -0
  97. package/src/cluster.ts +27 -0
  98. package/src/common/arguments.ts +503 -0
  99. package/src/common/assets.ts +128 -0
  100. package/src/common/checksum.ts +58 -0
  101. package/src/common/constants.ts +18 -0
  102. package/src/common/content-type.ts +84 -0
  103. package/src/common/esbuild.ts +94 -0
  104. package/src/common/exit.ts +91 -0
  105. package/src/common/fs.ts +17 -0
  106. package/src/common/help.ts +51 -0
  107. package/src/common/jsx.ts +512 -0
  108. package/src/common/paths.ts +158 -0
  109. package/src/common/watch.ts +85 -0
  110. package/src/inflate/inflate-sea.ts +206 -0
  111. package/src/inflate/inflate.ts +99 -0
  112. package/src/inflate/md.ts +25 -0
  113. package/src/inflate/setup-auth.ts +40 -0
  114. package/src/inflate/setup-cors.ts +40 -0
  115. package/src/inflate/setup-db.ts +113 -0
  116. package/src/inflate/setup-error.ts +43 -0
  117. package/src/inflate/setup-http.ts +655 -0
  118. package/src/inflate/setup-log.ts +44 -0
  119. package/src/inflate/setup-middleware.ts +46 -0
  120. package/src/inflate/setup-server-config.ts +47 -0
  121. package/src/inflate/setup-test.ts +23 -0
  122. package/src/inflate/setup-ws.ts +48 -0
  123. package/src/inflate/setup.doc.ts +68 -0
  124. package/src/inflate/utils/sea-utils.ts +14 -0
  125. package/src/lib.ts +19 -0
  126. package/src/main.ts +87 -0
  127. package/src/services/app.ts +658 -0
  128. package/src/services/editor.tsx +101 -0
  129. package/src/services/globals.ts +143 -0
  130. package/src/services/hot-reload.ts +48 -0
  131. package/src/services/migrations.ts +66 -0
  132. package/src/services/utils/admin-interface.ts +37 -0
  133. package/src/services/utils/cache.ts +88 -0
  134. package/src/services/utils/cluster-cache.ts +230 -0
  135. package/src/services/utils/cluster-ws.ts +197 -0
  136. package/src/services/utils/db-manager.ts +92 -0
  137. package/src/services/utils/get-route.ts +70 -0
  138. package/src/services/utils/log-transport.ts +75 -0
  139. package/src/services/utils/log.ts +92 -0
  140. package/src/services/utils/server-interface.ts +172 -0
  141. package/src/services/utils/websocketmanager.ts +149 -0
  142. package/src/types/@esbuild.d.ts +1 -0
  143. package/src/types/@miqro/core.d.ts +2 -0
  144. package/src/types/@miqro/jsx.d.ts +2 -0
  145. package/src/types/@miqro/parser.d.ts +2 -0
  146. package/src/types/@miqro/query.d.ts +2 -0
  147. package/src/types/@miqro/request.d.ts +2 -0
  148. package/src/types/@miqro/test.d.ts +2 -0
  149. package/src/types/@miqro.d.ts +1 -0
  150. package/src/types/@types.d.ts +1 -0
  151. package/src/types/browser.globals.d.ts +9 -0
  152. package/src/types/globals.d.ts +2 -0
  153. package/src/types/jsx.globals.d.ts +37 -0
  154. package/src/types/miqro.d.ts +129 -0
  155. package/src/types/postject.d.ts +1 -0
  156. package/src/types/server.globals.d.ts +72 -0
  157. package/src/types.ts +222 -0
@@ -0,0 +1,308 @@
1
+ interface FileBrowserFile {
2
+ filePath: string;
3
+ fileName: string;
4
+ language: string;
5
+ content?: string;
6
+ dirs: string[];
7
+ }
8
+
9
+ interface FileBrowserProps {
10
+ filter: string;
11
+ migrations: string[];
12
+ current: string;
13
+ isDirCollapsed: (dir: string) => boolean;
14
+ toggleCollapseDir: (dir: string) => void;
15
+ saveAll: () => void;
16
+ isOpen: (file: string) => boolean;
17
+ openFile: (file: string) => void;
18
+ setfilter: (newFilter) => void;
19
+ showNewFile: () => void;
20
+ scanFiles: () => void;
21
+ closeAll: () => void;
22
+ closeFile: (file: string) => void;
23
+ reloadServer: () => void;
24
+ hasFileContentChanged: (file: string) => boolean;
25
+ hasErrors: (file: string) => boolean;
26
+ files: FileBrowserFile[];
27
+ opened: {
28
+ fileName: string;
29
+ filePath: string;
30
+ }[];
31
+ isPanelVisible: (panel: string) => boolean;
32
+ togglePanel: (panel: string) => void;
33
+ disableLog?: boolean; disablePreview?: boolean; disableReload?: boolean;
34
+ }
35
+
36
+ export function FileBrowser(props: FileBrowserProps) {
37
+ return <div class="file-browser" style={`${!props.isPanelVisible("left") ? "display: none;" : ""}`}>
38
+ <div class="file-browser-toolbar">
39
+ <div class="row">
40
+ <button
41
+ class="file-editor-button btn"
42
+ style={`width: 10%;${props.disableReload ? "width: 30%;" : ""}`}
43
+ onclick={ev => {
44
+ ev.preventDefault();
45
+ props.togglePanel("left");
46
+ }}>{"<<"}</button>
47
+ {props.disableLog ? <></> :
48
+ <button
49
+ id="log-btn"
50
+ class="file-editor-button btn"
51
+ style={`width: 30%;${props.disableLog ? "display: none;" : ""}`}
52
+ onclick={ev => {
53
+ ev.preventDefault();
54
+ props.togglePanel("bottom");
55
+ }}>log</button>}
56
+ {props.disableReload ? <></> :
57
+ <button
58
+ id="scan-btn"
59
+ class="file-editor-button btn active"
60
+ style={`width: 30%;${props.disableReload ? "display: none;" : ""}`}
61
+ onclick={ev => {
62
+ ev.preventDefault();
63
+ props.scanFiles();
64
+ }}>scan</button>}
65
+ {props.disableReload ? <></> :
66
+ <button
67
+ id="reload-btn"
68
+ class="file-editor-button btn warning"
69
+ style={`width: 30%;${props.disableReload ? "display: none;" : ""}`}
70
+ onclick={ev => {
71
+ ev.preventDefault();
72
+ props.reloadServer();
73
+ }}>reload</button>}
74
+ </div>
75
+ <div class="row">
76
+ <input
77
+ type="text"
78
+ style="width: 100%;"
79
+ value={props.filter}
80
+ oninput={ev => {
81
+ ev.preventDefault();
82
+ const text = ev.target.value;
83
+ props.setfilter(text);
84
+ }}
85
+ placeholder={"..filter.."} />
86
+ </div>
87
+ <div class="row">
88
+ {props.disablePreview ? <></> :
89
+ <button
90
+ id="preview-btn"
91
+ class="file-editor-button btn"
92
+ style={`width: 30%;${props.disablePreview ? "display: none;" : ""}`}
93
+ onclick={ev => {
94
+ ev.preventDefault();
95
+ props.togglePanel("right");
96
+ }}>preview</button>}
97
+ <button
98
+ id="new-btn"
99
+ class="file-editor-button btn info"
100
+ style="width: 20%;"
101
+ onclick={ev => {
102
+ ev.preventDefault();
103
+ props.showNewFile();
104
+ }}>new</button>
105
+ {props.disableReload ? <></> :
106
+ <button
107
+ id="scan-btn"
108
+ class="file-editor-button btn active"
109
+ style={`width: 30%;${!props.disableReload ? "display: none;" : ""}`}
110
+ onclick={ev => {
111
+ ev.preventDefault();
112
+ props.scanFiles();
113
+ }}>scan</button>}
114
+ <button
115
+ id="saveall-btn"
116
+ class="file-editor-button btn success"
117
+ style="width: 25%;"
118
+ onclick={ev => {
119
+ ev.preventDefault();
120
+ props.saveAll();
121
+
122
+ }}>save</button>
123
+ <button
124
+ id="closeall-btn"
125
+ class="file-editor-button btn danger"
126
+ style="width: 25%;"
127
+ onclick={ev => {
128
+ ev.preventDefault();
129
+ props.closeAll();
130
+ }}>close</button>
131
+ </div>
132
+ </div>
133
+
134
+ <div class="file-browser-files">
135
+ {props.opened.length > 0 ? <div class="file-browser-opened-files" style="padding: var(--file-browser-separation);">
136
+ {/*<p style="padding: 0; margin: 0;">opened</p>*/}
137
+ <ul style="padding: 0; margin: 0;">
138
+ {props.opened.map(file => <File
139
+ closeFile={props.closeFile}
140
+ current={props.current}
141
+ fileName={file.fileName}
142
+ filePath={file.filePath}
143
+ hasErrors={props.hasErrors}
144
+ hasFileContentChanged={props.hasFileContentChanged}
145
+ isOpen={props.isOpen}
146
+ openFile={props.openFile} />)}
147
+ </ul></div> : <></>}
148
+ <FileTree
149
+ isDirCollapsed={props.isDirCollapsed}
150
+ toggleCollapseDir={props.toggleCollapseDir}
151
+ closeFile={props.closeFile}
152
+ current={props.current}
153
+ files={props.files}
154
+ filter={props.filter}
155
+ hasErrors={props.hasErrors}
156
+ hasFileContentChanged={props.hasFileContentChanged}
157
+ isOpen={props.isOpen}
158
+ openFile={props.openFile} />
159
+ </div>
160
+ </div>
161
+ }
162
+
163
+ interface FileTreeProps {
164
+ isDirCollapsed: (dir: string) => boolean;
165
+ toggleCollapseDir: (dir: string) => void;
166
+ current: string;
167
+ files: FileBrowserFile[];
168
+ filter: string;
169
+ isOpen: (file: string) => boolean;
170
+ openFile: (file: string) => void;
171
+ closeFile: (file: string) => void;
172
+ hasErrors: (file: string) => boolean;
173
+ hasFileContentChanged: (file: string) => boolean;
174
+ }
175
+
176
+ interface FileTreeDir {
177
+ dirs: {
178
+ [name: string]: FileTreeDir
179
+ };
180
+ files: FileBrowserFile[];
181
+ name: string;
182
+ fullName: string;
183
+ }
184
+
185
+ function FileTree(props: FileTreeProps) {
186
+ const ret: FileTreeDir = {
187
+ dirs: {},
188
+ files: [],
189
+ name: "",
190
+ fullName: ""
191
+ };
192
+
193
+ props.files.forEach((file) => {
194
+ let cDir = ret;
195
+ let fullName = "";
196
+ for (const dir of file.dirs) {
197
+ fullName += dir + "/";
198
+ if (cDir.dirs[dir] === undefined) {
199
+ const newDir: FileTreeDir = {
200
+ dirs: {},
201
+ files: [],
202
+ name: dir,
203
+ fullName: `${fullName}`
204
+ };
205
+ cDir.dirs[dir] = newDir;
206
+ cDir = newDir;
207
+ } else {
208
+ cDir = cDir.dirs[dir];
209
+ }
210
+ }
211
+ cDir.files.push(file);
212
+ });
213
+
214
+ //console.dir(ret);
215
+
216
+ return <FileTreeFolder {...props} tree={ret} level={0} />
217
+ }
218
+
219
+ interface FileTreeFolderProps {
220
+ isDirCollapsed: (dir: string) => boolean;
221
+ toggleCollapseDir: (dir: string) => void;
222
+ tree: FileTreeDir;
223
+ current: string;
224
+ filter: string;
225
+ level: number;
226
+ isOpen: (file: string) => boolean;
227
+ openFile: (file: string) => void;
228
+ closeFile: (file: string) => void;
229
+ hasErrors: (file: string) => boolean;
230
+ hasFileContentChanged: (file: string) => boolean;
231
+ }
232
+
233
+ function FileTreeFolder(props: FileTreeFolderProps) {
234
+
235
+ //console.dir(props.tree);
236
+
237
+ const dirs = Object.keys(props.tree.dirs).map(k => props.tree.dirs[k]);
238
+
239
+ const files = props.tree.files.filter(file => props.filter ? file.filePath.includes(props.filter) : true);
240
+
241
+
242
+ return <ul style={`margin-left: calc(2 * var(--file-browser-separation-file));${props.level === 0 ? " padding: var(--file-browser-separation);" : ""}`}>
243
+ <>
244
+ {props.tree.name !== "" ? <div class="file-browser-dir" style="padding: 0;">
245
+ <p style="margin: 0;">{props.tree.name}/</p>
246
+ <button
247
+ onclick={ev => {
248
+ ev.preventDefault();
249
+ ev.stopPropagation();
250
+ props.toggleCollapseDir(props.tree.fullName);
251
+ }}
252
+ class="btn-small"
253
+ style={"margin: 0; margin-left: calc(2 * var(--file-browser-separation));"}>{props.isDirCollapsed(props.tree.fullName) ? "+" : "-"}</button>
254
+ </div> : <></>}
255
+ {props.isDirCollapsed(props.tree.fullName) ? <></> :
256
+ <>
257
+ {dirs.map(dir => {
258
+ return <FileTreeFolder {...props} tree={dir} level={props.level + 1} />
259
+ })}
260
+ {files.map(file => <File
261
+ closeFile={props.closeFile}
262
+ current={props.current}
263
+ fileName={file.fileName}
264
+ filePath={file.filePath}
265
+ hasErrors={props.hasErrors}
266
+ hasFileContentChanged={props.hasFileContentChanged}
267
+ isOpen={props.isOpen}
268
+ openFile={props.openFile} />)
269
+ }
270
+ </>}
271
+ </>
272
+ </ul>
273
+ }
274
+
275
+ interface FileProps {
276
+ fileName: string;
277
+ filePath: string;
278
+ current: string;
279
+ isOpen: (file: string) => boolean;
280
+ openFile: (file: string) => void;
281
+ closeFile: (file: string) => void;
282
+ hasErrors: (file: string) => boolean;
283
+ hasFileContentChanged: (file: string) => boolean;
284
+ }
285
+
286
+ function File(props: FileProps) {
287
+ const isOpen = props.isOpen(props.filePath);
288
+
289
+ return <li
290
+ class={`file-browser-file${props.hasErrors(props.filePath) ? " error" : ""}${props.hasFileContentChanged(props.filePath) ? " changed" : ""}${props.current === props.filePath ? " active" : ""}${isOpen ? " open" : ""}`}
291
+ style={"display: flex; justify-content: flex-start; align-items: center; margin-left: calc(2 * var(--file-browser-separation-file));"}
292
+ onclick={ev => {
293
+ ev.preventDefault();
294
+ ev.stopPropagation();
295
+ props.openFile(props.filePath);
296
+ }}>
297
+ <p style="margin: 0; padding: 0;">{props.fileName}{props.hasFileContentChanged(props.filePath) ? "(*)" : ""}</p>
298
+ <button
299
+ onclick={ev => {
300
+ ev.preventDefault();
301
+ ev.stopPropagation();
302
+ props.closeFile(props.filePath);
303
+ }}
304
+ class="btn-small"
305
+ style={props.isOpen(props.filePath) ? "margin-left: calc(2 * var(--file-browser-separation-file));" : "display: none;"}
306
+ disabled={!props.isOpen(props.filePath)}>X</button>
307
+ </li>
308
+ }
@@ -0,0 +1,191 @@
1
+ import { SUPPORTED_LANGUAGES } from "../common/constants.js";
2
+
3
+ interface FileEditorToolbar {
4
+ path: string;
5
+ language: string;
6
+ changed: boolean;
7
+ renameFile: (newName: string) => void;
8
+ deleteFile: () => void;
9
+ setlanguage: (newLang: string) => void;
10
+ saveFile: (reload?: boolean) => void;
11
+ revertFile: () => void;
12
+ closeFile: () => void;
13
+ togglePanel: (panel: string) => void;
14
+ isPanelVisible: (panel: string) => boolean;
15
+ disableLog?: boolean; disablePreview?: boolean; disableReload?: boolean;
16
+ }
17
+
18
+ export function FileEditorToolbar(props: FileEditorToolbar) {
19
+
20
+ const renamingRef = jsx.useRef();
21
+ const refresh = jsx.useRefresh();
22
+ const [renaming, setrenaming] = jsx.useState<boolean>(false);
23
+
24
+ jsx.useEffect(() => {
25
+ if (renamingRef.current) {
26
+ renamingRef.current.value = props.path;
27
+ renamingRef.current.focus();
28
+ refresh();
29
+ }
30
+ }, [renamingRef.current]);
31
+
32
+ jsx.useEffect(() => {
33
+ setrenaming(false);
34
+ }, [props.path]);
35
+
36
+ return <div class="file-editor-toolbar">
37
+ <div class="file-editor-toolbar-row">
38
+ <button
39
+ class="file-editor-button btn"
40
+ style={`${props.isPanelVisible("left") ? "display: none;" : "margin-right: var(--file-browser-separation);"}`}
41
+ onclick={ev => {
42
+ ev.preventDefault();
43
+ props.togglePanel("left");
44
+ }}>{">>"}</button>
45
+ <button
46
+ id="save-btn"
47
+ disabled={!props.changed}
48
+ class={`btn success`}
49
+ onclick={ev => {
50
+ ev.preventDefault();
51
+ props.saveFile();
52
+ }}>save</button>
53
+ {props.disableReload ? <></> : <button
54
+ id="savereload-btn"
55
+ disabled={!props.changed}
56
+ class={`btn info`}
57
+ style="margin-left: var(--file-browser-separation);"
58
+ onclick={ev => {
59
+ ev.preventDefault();
60
+ props.saveFile(true);
61
+ }}>save/reload</button>}
62
+ <button
63
+ id="revert-btn"
64
+ disabled={!props.changed}
65
+ style="margin-left: var(--file-browser-separation);"
66
+ class={`btn warning`}
67
+ onclick={ev => {
68
+ ev.preventDefault();
69
+ props.revertFile();
70
+ }}>revert</button>
71
+ <button
72
+ id="close-btn"
73
+ class={`btn danger`}
74
+ style="margin-left: var(--file-browser-separation);"
75
+ onclick={ev => {
76
+ ev.preventDefault();
77
+ props.closeFile();
78
+
79
+ }}>close</button>
80
+ {SUPPORTED_LANGUAGES.includes(props.language) ?
81
+ <select
82
+ value={props.language}
83
+ oninput={ev => {
84
+ ev.preventDefault();
85
+ props.setlanguage(ev.target.value);
86
+ }}
87
+ style="margin: 0; padding: 0; margin-left: calc(2*var(--file-browser-separation-file));">
88
+ {SUPPORTED_LANGUAGES.map(language => <option value={language}>{language}</option>)}
89
+ </select> : <></>}
90
+ {/*<div
91
+ style="margin-left: calc(2*var(--file-browser-separation));"
92
+ class={`toggle-panel-button left-side-panel-button ${props.isPanelVisible("left") ? "active" : ""}`}
93
+ onclick={ev => {
94
+ ev.preventDefault();
95
+ props.togglePanel("left");
96
+ }}
97
+ ></div>
98
+ <br />
99
+ <div
100
+ style="margin-left: calc(2*var(--file-browser-separation-file));"
101
+ class={`toggle-panel-button bottom-side-panel-button ${props.isPanelVisible("bottom") ? "active" : ""}`}
102
+ onclick={ev => {
103
+ ev.preventDefault();
104
+ props.togglePanel("bottom");
105
+ }}
106
+ ></div>
107
+ <br />
108
+ <div class={`toggle-panel-button right-side-panel-button ${props.isPanelVisible("right") ? "active" : ""}`}
109
+ onclick={ev => {
110
+ ev.preventDefault();
111
+ props.togglePanel("right");
112
+ }}
113
+ ></div>*/}
114
+
115
+
116
+ </div>
117
+ <div class="file-editor-toolbar-row">
118
+ {!renaming ?
119
+ <><p
120
+ style="margin-left:20px;"
121
+ onclick={ev => {
122
+ ev.preventDefault();
123
+ setrenaming(true);
124
+ }}>{props.path}</p>
125
+ </> :
126
+ <>
127
+ <form
128
+ style="width: 100%; height: 100%; margin-right: calc(2 * var(--file-browser-separation));"
129
+ onsubmit={ev => {
130
+ ev.preventDefault();
131
+ setrenaming(false);
132
+ if (renamingRef.current && renamingRef.current.value !== props.path) {
133
+ setrenaming(false);
134
+ props.renameFile(renamingRef.current.value);
135
+ }
136
+ }}>
137
+ <input
138
+ style="width: 100%; height: 100%;"
139
+ onfocusout={ev => {
140
+ ev.preventDefault();
141
+ //setrenaming(false);
142
+ }}
143
+ ref={renamingRef}
144
+ onkeydown={(ev) => {
145
+ if (ev.keyCode === 27) {
146
+ // catch esc
147
+ ev.preventDefault();
148
+ setrenaming(false);
149
+ } else {
150
+ refresh();
151
+ }
152
+ }}
153
+ type="text" />
154
+ </form>
155
+ {renamingRef.current && renamingRef.current.value !== props.path && renamingRef.current.value !== "" ?
156
+ <button
157
+ style="margin-left: var(--file-browser-separation);"
158
+ class="btn info"
159
+ onclick={ev => {
160
+ ev.preventDefault();
161
+ if (renamingRef.current) {
162
+ setrenaming(false);
163
+ props.renameFile(renamingRef.current.value);
164
+ }
165
+ }}>rename file</button>
166
+ : <></>}
167
+ <button
168
+ style="margin-left: var(--file-browser-separation);"
169
+ class="btn danger"
170
+ onclick={ev => {
171
+ ev.preventDefault();
172
+ if (renamingRef.current) {
173
+ setrenaming(false);
174
+ props.deleteFile();
175
+ }
176
+ }}>delete file</button>
177
+ <button
178
+ style="margin-left: var(--file-browser-separation);"
179
+ class="btn"
180
+ onclick={ev => {
181
+ ev.preventDefault();
182
+ setrenaming(false);
183
+ }}>cancel</button>
184
+ </>
185
+ }
186
+ </div>
187
+ </div>
188
+ }
189
+
190
+ FileEditorToolbar.asFragment = true;
191
+ FileEditorToolbar.shadowInit = false;
@@ -0,0 +1,122 @@
1
+ import { APIPReview } from "./api-preview.js";
2
+ import { FileEditorToolbar } from "./file-editor-toolbar.js";
3
+ import { HighlightTextArea } from "./highlight-text-area.js";
4
+ import { useScroll } from "./scroll-query.js";
5
+
6
+ interface FileEditorProps {
7
+ current: boolean;
8
+ error: string;
9
+ path: string;
10
+ previewPath: string | undefined;
11
+ apiPreview: undefined | {
12
+ path: string;
13
+ method: string;
14
+ }[];
15
+ content: string | null;
16
+ contentchange: (content: string) => void;
17
+ closeFile: () => void;
18
+ saveFile: (reload?: boolean) => void;
19
+ revertFile: () => void;
20
+ deleteFile: () => void;
21
+ renameFile: (newName) => void;
22
+ setlanguage: (newLanguage) => void;
23
+ language: string;
24
+ changed: boolean;
25
+ reloadString: string;
26
+ togglePanel: (panel: string) => void;
27
+ isPanelVisible: (panel: string) => boolean;
28
+ disableLog?: boolean; disablePreview?: boolean; disableReload?: boolean;
29
+ }
30
+
31
+ export function FileEditor({ disableLog, disablePreview, disableReload, togglePanel, isPanelVisible, apiPreview, reloadString, error, revertFile, changed, setlanguage, saveFile, deleteFile, renameFile, current, path, previewPath, content, contentchange, closeFile, language }: FileEditorProps) {
32
+ //console.log("FileEditor [%s]", path);
33
+ const iFrameRef = jsx.useRef();
34
+ const scrollRef = jsx.useRef();
35
+ const [scroll, setScroll] = useScroll();
36
+
37
+ jsx.useEffect(() => {
38
+ if (scrollRef.current) {
39
+ (scrollRef.current as any).scrollLeft = scroll.scrollLeft;
40
+ (scrollRef.current as any).scrollTop = scroll.scrollTop;
41
+ }
42
+ }, [scrollRef.current]);
43
+
44
+ jsx.useEffect(() => {
45
+ if (current && scrollRef.current) {
46
+ setScroll({
47
+ scrollLeft: (scrollRef.current as any).scrollLeft,
48
+ scrollTop: (scrollRef.current as any).scrollTop
49
+ }, true);
50
+ }
51
+ }, [current]);
52
+
53
+ jsx.useEffect(() => {
54
+ if (iFrameRef.current) {
55
+ (iFrameRef.current as any).src = "";
56
+ (iFrameRef.current as any).src = previewPath;
57
+ }
58
+ }, [iFrameRef.current, previewPath, reloadString]);
59
+
60
+ return <div class="file-editor">
61
+ {content === null ? <p>loading</p> : <>
62
+ <FileEditorToolbar
63
+ disableLog={disableLog}
64
+ disablePreview={disablePreview}
65
+ disableReload={disableReload}
66
+ isPanelVisible={isPanelVisible}
67
+ togglePanel={togglePanel}
68
+ revertFile={revertFile}
69
+ closeFile={closeFile}
70
+ language={language}
71
+ path={path}
72
+ changed={changed}
73
+ saveFile={saveFile}
74
+ setlanguage={setlanguage}
75
+ deleteFile={deleteFile}
76
+ renameFile={renameFile} />
77
+ <div
78
+ //class={`file-editor-content${previewPath || apiPreview ? " split" : ""}`}
79
+ class="file-editor-content">
80
+ <div ref={scrollRef}
81
+ class={`file-editor-text-editor${previewPath || (apiPreview && apiPreview.length > 0) && isPanelVisible("right") ? " split" : ""}`}
82
+ //class={`file-editor-text-editor`}
83
+ onscroll={ev => {
84
+ setScroll({
85
+ scrollLeft: ev.target.scrollLeft,
86
+ scrollTop: ev.target.scrollTop
87
+ });
88
+ }}>
89
+ {error ?
90
+ <p class="file-editor-content-error">{error}</p>
91
+ : <></>}
92
+ {language !== "binary" ?
93
+ <HighlightTextArea
94
+ tabChar=" "
95
+ oncontentchange={(args: CustomEvent) => {
96
+ if (contentchange) {
97
+ contentchange(args.detail);
98
+ }
99
+ }}
100
+ content={content}
101
+ language={language} /> : <p>binary data not supported</p>
102
+ }
103
+ </div>
104
+ {apiPreview && apiPreview.length > 0 ? <APIPReview
105
+ isPanelVisible={isPanelVisible}
106
+ apiPreview={apiPreview} /> : <></>}
107
+ {previewPath ? <div
108
+ class={`file-editor-preview`}
109
+ style={`${!isPanelVisible("right") ? "display: none;" : ""}`}>
110
+ <div class="file-editor-preview-path"><a href={previewPath} target="_blank">open in new window</a></div>
111
+ <iframe
112
+ ref={iFrameRef}
113
+ src={previewPath} sandbox="allow-scripts allow-same-origin"></iframe>
114
+ </div> : <></>}
115
+ </div>
116
+ </>}
117
+ </div>
118
+ }
119
+
120
+ FileEditor.asFragment = true;
121
+ FileEditor.shadowInit = false;
122
+
@@ -0,0 +1,22 @@
1
+ let queryTimeout2: any = null;
2
+
3
+ export function useFilterQuery(): [string, (newFilter: string, inmediate?: boolean) => void] {
4
+ const [filterQuery, setfilterQuery] = jsx.useQuery("filter", "");
5
+ const [filter, setfilter] = jsx.useState<string>(typeof filterQuery === "string" ? filterQuery : "");
6
+
7
+ return [
8
+ filter,
9
+ (newFilter: string, inmediate?: boolean) => {
10
+ clearTimeout(queryTimeout2);
11
+ if (inmediate) {
12
+ setfilter(newFilter);
13
+ setfilterQuery(newFilter);
14
+ } else {
15
+ setfilter(newFilter);
16
+ queryTimeout2 = setTimeout(() => {
17
+ setfilter(newFilter);
18
+ setfilterQuery(newFilter);
19
+ }, 1000);
20
+ }
21
+ }]
22
+ }