lupine.api 1.1.58 → 1.1.60

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 (137) hide show
  1. package/README.md +3 -3
  2. package/admin/admin-about.tsx +12 -16
  3. package/admin/admin-config.tsx +47 -44
  4. package/admin/admin-css.tsx +3 -3
  5. package/admin/admin-db.tsx +75 -75
  6. package/admin/admin-frame-helper.tsx +364 -364
  7. package/admin/admin-frame.tsx +164 -164
  8. package/admin/admin-index.tsx +65 -65
  9. package/admin/admin-login.tsx +111 -111
  10. package/admin/admin-menu-edit.tsx +637 -637
  11. package/admin/admin-menu-list.tsx +87 -87
  12. package/admin/admin-page-edit.tsx +564 -564
  13. package/admin/admin-page-list.tsx +83 -83
  14. package/admin/admin-performance.tsx +28 -28
  15. package/admin/admin-release.tsx +427 -426
  16. package/admin/admin-resources.tsx +382 -382
  17. package/admin/admin-shell.tsx +89 -89
  18. package/admin/admin-table-data.tsx +146 -146
  19. package/admin/admin-table-list.tsx +230 -230
  20. package/admin/admin-test-animations.tsx +395 -395
  21. package/admin/admin-test-component.tsx +823 -808
  22. package/admin/admin-test-edit.tsx +319 -319
  23. package/admin/admin-test-themes.tsx +56 -56
  24. package/admin/admin-tokens.tsx +338 -338
  25. package/admin/design/admin-design.tsx +174 -174
  26. package/admin/design/block-grid.tsx +36 -36
  27. package/admin/design/block-grid1.tsx +21 -21
  28. package/admin/design/block-paragraph.tsx +19 -19
  29. package/admin/design/block-title.tsx +19 -19
  30. package/admin/design/design-block-box.tsx +140 -140
  31. package/admin/design/drag-data.tsx +24 -24
  32. package/admin/index.ts +9 -9
  33. package/admin/package.json +15 -15
  34. package/admin/tsconfig.json +127 -127
  35. package/dev/copy-folder.js +32 -32
  36. package/dev/cp-index-html.js +69 -69
  37. package/dev/file-utils.js +12 -12
  38. package/dev/index.js +18 -19
  39. package/dev/package.json +12 -12
  40. package/dev/plugin-ifelse.js +168 -168
  41. package/dev/plugin-ifelse.test.js +37 -37
  42. package/dev/run-cmd.js +14 -14
  43. package/dev/send-request.js +12 -12
  44. package/package.json +55 -55
  45. package/src/admin-api/admin-api-helper.ts +210 -205
  46. package/src/admin-api/admin-api.ts +65 -65
  47. package/src/admin-api/admin-auth.ts +152 -146
  48. package/src/admin-api/admin-config.ts +94 -84
  49. package/src/admin-api/admin-csv.ts +94 -94
  50. package/src/admin-api/admin-db.ts +269 -269
  51. package/src/admin-api/admin-menu.ts +135 -135
  52. package/src/admin-api/admin-page.ts +135 -135
  53. package/src/admin-api/admin-performance.ts +128 -128
  54. package/src/admin-api/admin-release.ts +706 -700
  55. package/src/admin-api/admin-resources.ts +318 -318
  56. package/src/admin-api/admin-token-helper.ts +82 -79
  57. package/src/admin-api/admin-tokens.ts +90 -90
  58. package/src/admin-api/index.ts +2 -2
  59. package/src/admin-api/web-config-api.ts +19 -19
  60. package/src/api/api-cache.ts +103 -103
  61. package/src/api/api-helper.ts +44 -44
  62. package/src/api/api-module.ts +67 -60
  63. package/src/api/api-router.ts +177 -177
  64. package/src/api/api-shared-storage.ts +64 -64
  65. package/src/api/async-storage.ts +5 -5
  66. package/src/api/debug-service.ts +56 -56
  67. package/src/api/encode-html.ts +27 -27
  68. package/src/api/handle-status.ts +75 -75
  69. package/src/api/index.ts +15 -16
  70. package/src/api/mini-web-socket.ts +270 -270
  71. package/src/api/server-content-type.ts +82 -82
  72. package/src/api/server-render.ts +235 -215
  73. package/src/api/shell-service.ts +74 -74
  74. package/src/api/simple-storage.ts +80 -80
  75. package/src/api/static-server.ts +128 -125
  76. package/src/api/to-client-delivery.ts +26 -26
  77. package/src/app/app-cache.ts +55 -55
  78. package/src/app/app-helper.ts +62 -62
  79. package/src/app/app-message.ts +109 -109
  80. package/src/app/app-shared-storage.ts +363 -363
  81. package/src/app/app-start.ts +136 -136
  82. package/src/app/cleanup-exit.ts +16 -16
  83. package/src/app/host-to-path.ts +38 -38
  84. package/src/app/index.ts +11 -11
  85. package/src/app/process-dev-requests.ts +130 -130
  86. package/src/app/web-listener.ts +294 -294
  87. package/src/app/web-processor.ts +47 -42
  88. package/src/app/web-server.ts +100 -100
  89. package/src/common-js/web-env.js +104 -104
  90. package/src/index.ts +7 -7
  91. package/src/lang/api-lang-en.ts +26 -26
  92. package/src/lang/api-lang-zh-cn.ts +27 -27
  93. package/src/lang/index.ts +2 -2
  94. package/src/lang/lang-helper.ts +76 -76
  95. package/src/lang/lang-props.ts +6 -6
  96. package/src/lib/db/db-helper.ts +23 -23
  97. package/src/lib/db/db-mysql.ts +249 -250
  98. package/src/lib/db/db-sqlite.ts +101 -101
  99. package/src/lib/db/db.spec.ts +28 -28
  100. package/src/lib/db/db.ts +325 -325
  101. package/src/lib/db/index.ts +5 -5
  102. package/src/lib/index.ts +3 -3
  103. package/src/lib/logger.spec.ts +214 -214
  104. package/src/lib/logger.ts +281 -281
  105. package/src/lib/runtime-require.ts +37 -37
  106. package/src/lib/utils/cookie-util.ts +34 -34
  107. package/src/lib/utils/crypto.ts +58 -58
  108. package/src/lib/utils/date-utils.ts +317 -317
  109. package/src/lib/utils/deep-merge.ts +37 -37
  110. package/src/lib/utils/delay.ts +12 -12
  111. package/src/lib/utils/file-setting.ts +55 -55
  112. package/src/lib/utils/format-bytes.ts +11 -11
  113. package/src/lib/utils/fs-utils.ts +158 -158
  114. package/src/lib/utils/get-env.ts +27 -27
  115. package/src/lib/utils/index.ts +12 -12
  116. package/src/lib/utils/is-type.ts +48 -48
  117. package/src/lib/utils/load-env.ts +14 -14
  118. package/src/lib/utils/pad.ts +6 -6
  119. package/src/models/api-base.ts +5 -5
  120. package/src/models/api-module-props.ts +10 -11
  121. package/src/models/api-router-props.ts +26 -26
  122. package/src/models/app-cache-props.ts +33 -33
  123. package/src/models/app-data-props.ts +10 -10
  124. package/src/models/app-helper-props.ts +6 -6
  125. package/src/models/app-shared-storage-props.ts +38 -38
  126. package/src/models/app-start-props.ts +18 -18
  127. package/src/models/async-storage-props.ts +13 -13
  128. package/src/models/db-config.ts +30 -30
  129. package/src/models/host-to-path-props.ts +12 -12
  130. package/src/models/index.ts +16 -16
  131. package/src/models/json-object.ts +8 -8
  132. package/src/models/locals-props.ts +36 -36
  133. package/src/models/logger-props.ts +84 -84
  134. package/src/models/simple-storage-props.ts +13 -14
  135. package/src/models/to-client-delivery-props.ts +6 -6
  136. package/tsconfig.json +115 -115
  137. package/dev/plugin-gen-versions.js +0 -20
@@ -1,637 +1,637 @@
1
- import { CssProps, getRenderPageProps, RefProps, DomUtils, ModalWindow, NotificationMessage } from 'lupine.components';
2
-
3
- const fetchTableList = async () => {
4
- const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/db/tables');
5
- return data.json;
6
- };
7
- const fetchTableDrop = async (tableName: string) => {
8
- const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/db/table-drop', {
9
- table: tableName,
10
- });
11
- return data.json;
12
- };
13
- const fetchTableTruncate = async (tableName: string) => {
14
- const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/db/table-truncate', {
15
- table: tableName,
16
- });
17
- return data.json;
18
- };
19
-
20
- export const SaveMenu = (props: {
21
- menuIdReadonly?: boolean;
22
- menuId: string;
23
- title: string;
24
- note: string;
25
- package: string;
26
- }) => {
27
- return (
28
- <div class='save-menu'>
29
- <div class='row-box mb-s'>
30
- <div class='w-7'>Menu Id:</div>
31
- <input type='text' id='s_menuId' value={props.menuId} class='input-base w-20' readonly={props.menuIdReadonly} />
32
- </div>
33
- <div class='row-box mb-s'>
34
- <div class='w-7'>Menu Title:</div>
35
- <input type='text' id='s_menuTitle' value={props.title} class='input-base w-20' />
36
- </div>
37
- <div class='row-box mb-s'>
38
- <div class='w-7'>Menu Description:</div>
39
- <input type='text' id='s_menuNote' value={props.note} class='input-base w-20' />
40
- </div>
41
- <div class='row-box mb-s'>
42
- <div class='w-7'>Package id:</div>
43
- <input type='text' id='s_menuPackage' value={props.package} class='input-base w-20' />
44
- </div>
45
- </div>
46
- );
47
- };
48
-
49
- export const AdminMenuEditPage = (menuId: string) => {
50
- let savedMenuId = '';
51
- let savedMenuTitle = '';
52
- let savedMenuNote = '';
53
- let savedPackage = '';
54
- const onDelete = async (tableName: string) => {
55
- if (!confirm(`Are you really Deleting ${tableName}?`)) {
56
- return;
57
- }
58
- const json = await fetchTableDrop(tableName);
59
- console.log('====fetchTableDelete', json);
60
- NotificationMessage.sendMessage('Deleted: ' + tableName);
61
- onClick();
62
- };
63
-
64
- // const onDownload = async (tableName: string) => {
65
- // DomUtils.download('/api/admin/db/table-download?table=' + tableName);
66
- // };
67
-
68
- const onClick = async () => {
69
- const json = await fetchTableList();
70
- console.log('====fetchTableList', json);
71
- };
72
-
73
- const doLoad = (results: any) => {
74
- oMenu.length = 0;
75
- savedMenuId = results.menuid;
76
- savedMenuTitle = results.title;
77
- savedMenuNote = results.note;
78
- savedPackage = results.package;
79
- for (const i in results.items) {
80
- const item = results.items[i];
81
- const lev = Number.parseInt(item[0]);
82
- var pre = new Array(lev * 4 + 1).join('-');
83
- oMenu.options[oMenu.length] = new Option(pre + item[4], item.join('\t'));
84
- }
85
- oMenu.selectedIndex = 0;
86
- doListChg();
87
- };
88
- const onSave = () => {
89
- doSave(false);
90
- };
91
- const onSaveAs = () => {
92
- doSave(true);
93
- };
94
- const doSave = async (isSaveAs = false) => {
95
- const handleClicked = async (index: number) => {
96
- if (index === 0) {
97
- // Save
98
- const id = DomUtils.getValue('#s_menuId');
99
- const title = DomUtils.getValue('#s_menuTitle');
100
- const note = DomUtils.getValue('#s_menuNote');
101
- const pkg = DomUtils.getValue('#s_menuPackage');
102
- let regex = /^[a-zA-Z0-9]+$/;
103
- if (!id || !regex.test(id)) {
104
- alert('menuId is not valid!');
105
- return;
106
- }
107
- const menuIdReadonly = !isSaveAs && !!savedMenuId;
108
- const items = getAllItems();
109
- const post: any = {
110
- id,
111
- title,
112
- note,
113
- items,
114
- idReadonly: menuIdReadonly,
115
- package: pkg,
116
- };
117
-
118
- const updateIds = () => {
119
- savedMenuId = id;
120
- savedMenuTitle = title;
121
- savedMenuNote = note;
122
- savedPackage = pkg;
123
- ref.$('.admin-sub-title').innerHTML = `Edit Menu: ${savedMenuId}`;
124
- };
125
- const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/menu/save', post);
126
- if (data.json && data.json.status !== 'ok') {
127
- if (!post.idReadonly && data.json.status === 'ID_EXISTS') {
128
- if (!confirm(`${data.json.message}\r\n\r\nDo you want to override the same menu id?`)) {
129
- return;
130
- }
131
- post.idReadonly = true;
132
- const data2 = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/menu/save', post);
133
- if (data2.json && data2.json.status !== 'ok') {
134
- alert(`Error happened: ${data2.json.message}`);
135
- } else {
136
- updateIds();
137
- NotificationMessage.sendMessage('Menu is saved.');
138
- }
139
- } else {
140
- alert(`Error happened: ${data.json.message}`);
141
- return;
142
- }
143
- } else {
144
- updateIds();
145
- NotificationMessage.sendMessage('Menu is saved.');
146
- }
147
- }
148
-
149
- modalClose();
150
- };
151
- const modalClose = await ModalWindow.show({
152
- title: 'Save Menu',
153
- buttons: ['Save', 'Cancel'],
154
- // contentMaxHeight: '400px',
155
- handleClicked,
156
- children: (
157
- <SaveMenu
158
- menuIdReadonly={!!savedMenuId && !isSaveAs}
159
- menuId={savedMenuId}
160
- title={savedMenuTitle}
161
- note={savedMenuNote}
162
- package={savedPackage}
163
- ></SaveMenu>
164
- ),
165
- });
166
- };
167
-
168
- let oMenu: HTMLSelectElement;
169
- const ref: RefProps = {
170
- onLoad: async () => {
171
- oMenu = document.querySelector('#menulist')!;
172
- if (menuId) {
173
- const response = await getRenderPageProps().renderPageFunctions.fetchData(`/api/admin/menu/get/${menuId}`);
174
- doLoad(response.json.result);
175
- }
176
- },
177
- };
178
- function getSel(ismsg = true) {
179
- if (oMenu.selectedIndex < 0 && ismsg) {
180
- if (oMenu.length == 0) {
181
- NotificationMessage.sendMessage('No item in menu item list.');
182
- } else {
183
- NotificationMessage.sendMessage('Please select one item.');
184
- }
185
- }
186
- return oMenu.selectedIndex;
187
- }
188
- function getLevel(ind: number) {
189
- var t = oMenu.options[ind].value.split('\t');
190
- return Number.parseInt(t[0]);
191
- }
192
- function getNav(ind: number) {
193
- var t = oMenu.options[ind].value.split('\t');
194
- return t[1];
195
- }
196
- function getAcc(ind: number) {
197
- var t = oMenu.options[ind].value.split('\t');
198
- return t[2];
199
- }
200
- function getLnk(ind: number) {
201
- var t = oMenu.options[ind].value.split('\t');
202
- return t[3];
203
- }
204
- function getTxt(ind: number) {
205
- var t = oMenu.options[ind].value.split('\t');
206
- return t[4];
207
- }
208
-
209
- function getAllItems() {
210
- const ret = [];
211
- for (var i = 0; i < oMenu.length; i++) {
212
- // ret.push(oMenu.options[i].value);
213
- ret.push([getLevel(i), getNav(i), getAcc(i), getLnk(i), getTxt(i)]);
214
- }
215
- return ret;
216
- }
217
- async function doDelete() {
218
- if (!savedMenuId) {
219
- alert('Current menu is not on DB yet.');
220
- return;
221
- }
222
- if (!confirm('Do you delete this menu from the system?')) return;
223
- await getRenderPageProps().renderPageFunctions.fetchData(`/api/admin/menu/delete/${savedMenuId}`);
224
- doNew();
225
- NotificationMessage.sendMessage('Menu is deleted.');
226
- }
227
- function doNew() {
228
- savedMenuId = '';
229
- for (var i = oMenu.length - 1; i >= 0; i--) {
230
- oMenu.options[i].remove();
231
- }
232
- }
233
- function byId(id: string) {
234
- return document.getElementById(id)! as HTMLElement;
235
- }
236
- function doListChg() {
237
- var ind = getSel(false);
238
- var tt = getTxt(ind);
239
-
240
- var ty = '0';
241
- DomUtils.setValue('#menuimageout', '');
242
- DomUtils.setValue('#menuimageon', '');
243
- DomUtils.setValue('#menupanel', '');
244
- if (tt.substring(0, 4) == '[::]') {
245
- var t = tt.split('[::]');
246
- if (t.length == 6) {
247
- DomUtils.setValue('#menuimg1', t[3]);
248
- DomUtils.setValue('#menuimg2', t[4]);
249
- ty = t[1];
250
- tt = t[2];
251
- DomUtils.setValue('#menupanel', t[5]);
252
- }
253
- }
254
-
255
- var lev = getLevel(ind);
256
- if (lev > 0) {
257
- byId('img_p0').style.display = 'none';
258
- byId('img_p1').style.display = 'none';
259
- byId('img_p2').style.display = 'none';
260
- byId('img_panel').style.display = 'none';
261
- } else {
262
- byId('img_p0').style.display = '';
263
- byId('img_p1').style.display = '';
264
- byId('img_p2').style.display = '';
265
- byId('img_panel').style.display = '';
266
- }
267
-
268
- DomUtils.setChecked('#itemtype1', ty == '' || ty == '0');
269
- DomUtils.setChecked('#itemtype2', ty == '1');
270
- DomUtils.setValue('#menutitle', tt);
271
- DomUtils.setValue('#menulink', getLnk(ind));
272
- DomUtils.setValue('#menutarget', getNav(ind));
273
- DomUtils.setValue('#menuaccess', getAcc(ind));
274
- }
275
-
276
- function doReplace(ind2?: number) {
277
- var ind = typeof ind2 === 'number' && ind2 >= 0 ? ind2 : getSel(true);
278
- if (ind < 0) return;
279
- var menutxt = DomUtils.getValue('#menutitle').trim();
280
- if (menutxt == '') {
281
- alert('Please input menu text.');
282
- return;
283
- }
284
- if (menutxt.indexOf('[::]') >= 0) {
285
- alert('Cannot include "[::]" in menu text.');
286
- return;
287
- }
288
-
289
- var lev = getLevel(ind);
290
- var acc = DomUtils.getValue('#menuaccess');
291
- var nav = DomUtils.getValue('#menutarget');
292
- if (!nav || nav == '' || !acc || acc == '') {
293
- alert('Please select browsernav and access.');
294
- return;
295
- }
296
-
297
- var itemty = '0';
298
- if (DomUtils.getChecked('#itemtype2')) {
299
- itemty = '1';
300
- }
301
- var img1 = DomUtils.getValue('#menuimageout').trim();
302
- var img2 = DomUtils.getValue('#menuimageon').trim();
303
- var panel = DomUtils.getValue('#menupanel').trim();
304
- if (itemty == '1' && img1 == '') {
305
- alert('For selected Image, need input image path.');
306
- return;
307
- }
308
-
309
- if (img1 != '' || panel != '') {
310
- menutxt = '[::]' + itemty + '[::]' + menutxt + '[::]' + img1 + '[::]' + img2 + '[::]' + panel;
311
- }
312
-
313
- var pre = new Array(lev * 4 + 1).join('-');
314
- oMenu.options[ind].value = lev + ' ' + nav + ' ' + acc + ' XX ' + DomUtils.getValue('#menulink').trim() + ' ' + menutxt;
315
- oMenu.options[ind].text = pre + DomUtils.getValue('#menutitle').trim();
316
- }
317
- function doAppend(act: number) {
318
- var ind = oMenu.selectedIndex;
319
- if (ind < 0) {
320
- ind = oMenu.length - 1;
321
- }
322
- if (act == 1) {
323
- DomUtils.setValue('#menutitle', 'New Item');
324
- DomUtils.setValue('#menulink', '');
325
- }
326
- if (DomUtils.getValue('#menutitle').trim() == '') {
327
- alert('Please input menu text.');
328
- return;
329
- }
330
- var acc = DomUtils.getValue('#menuaccess');
331
- var nav = DomUtils.getValue('#menutarget');
332
- if (!nav || nav == '' || !acc || acc == '') {
333
- alert('Please select Target and Access Level.');
334
- return;
335
- }
336
- oMenu.options[oMenu.length] = new Option('', '');
337
- for (var i = oMenu.length - 1; ind >= 0 && i > ind; i--) {
338
- oMenu.options[i].text = oMenu.options[i - 1].text;
339
- oMenu.options[i].value = oMenu.options[i - 1].value;
340
- }
341
- doReplace(ind + 1);
342
- oMenu.options[ind + 1].selected = true;
343
- }
344
-
345
- function doDel() {
346
- var ind = getSel(true);
347
- if (ind < 0) return;
348
- if (!confirm('Delete the selected item and all the subs?')) return;
349
- var lev = getLevel(ind);
350
- var ind0 = -1;
351
- for (var i = ind; i < oMenu.length; i++) {
352
- var levx = getLevel(i);
353
- if (levx <= lev && i != ind) {
354
- break;
355
- }
356
- ind0 = i;
357
- }
358
- for (var i = ind0; i >= ind; i--) {
359
- oMenu.options[i].remove();
360
- }
361
-
362
- if (ind >= oMenu.length) ind = oMenu.length - 1;
363
- if (ind >= 0) oMenu.options[ind].selected = true;
364
- }
365
-
366
- function doMoveUp(ind: number) {
367
- if (ind < 1) return -1;
368
- var ind0 = -1;
369
- var lev = getLevel(ind);
370
- for (var i = ind - 1; i >= 0; i--) {
371
- var levx = getLevel(i);
372
- if (levx < lev) {
373
- break;
374
- }
375
- if (levx == lev) {
376
- ind0 = i;
377
- break;
378
- }
379
- }
380
- if (ind0 < 0) return -1;
381
- oMenu.options[ind0].selected = true;
382
- var inds = ind0;
383
-
384
- for (var i = ind; i < oMenu.length; i++) {
385
- var levx = getLevel(i);
386
- if (levx <= lev && i != ind) break;
387
-
388
- for (var j = i; j > ind0; j--) {
389
- var text = oMenu.options[j].text;
390
- var value = oMenu.options[j].value;
391
- oMenu.options[j].text = oMenu.options[j - 1].text;
392
- oMenu.options[j].value = oMenu.options[j - 1].value;
393
- oMenu.options[j - 1].text = text;
394
- oMenu.options[j - 1].value = value;
395
- }
396
- ind0++;
397
- }
398
- return ind0 - inds;
399
- }
400
- function doUp() {
401
- var ind = getSel(true);
402
- doMoveUp(ind);
403
- }
404
- function doDown() {
405
- var ind = getSel(true);
406
- if (ind < 0) return;
407
-
408
- if (ind >= oMenu.length - 1) return;
409
- var ind0 = -1;
410
- var lev = getLevel(ind);
411
- for (var i = ind + 1; i < oMenu.length; i++) {
412
- var levx = getLevel(i);
413
- if (levx < lev) {
414
- break;
415
- }
416
- if (levx == lev) {
417
- ind0 = i;
418
- break;
419
- }
420
- }
421
- if (ind0 < 0) return;
422
- var ind2 = doMoveUp(ind0);
423
- oMenu.options[ind + ind2].selected = true;
424
- }
425
- function doLeft() {
426
- var ind = getSel(true);
427
- if (ind < 0) return;
428
-
429
- var lev = getLevel(ind);
430
- if (lev <= 0) return;
431
- for (var i = ind; i < oMenu.length; i++) {
432
- var t = oMenu.options[i].value.split('\t');
433
- let newlev = Number.parseInt(t[0]);
434
- if (newlev <= lev && i != ind) break;
435
-
436
- newlev--;
437
- t[0] = '' + newlev;
438
- var pre = new Array(newlev * 4 + 1).join('-');
439
- oMenu.options[i].value = t.join(' ');
440
- oMenu.options[i].text = pre + t[4];
441
- }
442
- }
443
- function doRight() {
444
- var ind = getSel(true);
445
- if (ind < 1) return;
446
-
447
- var lev0 = getLevel(ind - 1);
448
- var lev = getLevel(ind);
449
- if (lev0 < lev) return;
450
- for (var i = ind; i < oMenu.length; i++) {
451
- var t = oMenu.options[i].value.split('\t');
452
- let newlev = Number.parseInt(t[0]);
453
- if (newlev <= lev && i != ind) break;
454
-
455
- newlev++;
456
- t[0] = '' + newlev;
457
- var pre = new Array(newlev * 4 + 1).join('-');
458
- oMenu.options[i].value = t.join(' ');
459
- oMenu.options[i].text = pre + t[4];
460
- }
461
- }
462
-
463
- const css: CssProps = {
464
- height: '100%',
465
- display: 'flex',
466
- flexDirection: 'column',
467
- '.list-top': {
468
- flex: '1',
469
- display: 'flex',
470
- flexDirection: 'column',
471
- },
472
- '.list-body': {
473
- flex: '1',
474
- display: 'flex',
475
- },
476
- '#menulist': {
477
- width: '200px',
478
- },
479
- '.edit': {
480
- alignSelf: 'normal',
481
- },
482
- '.action-box': {
483
- width: '100px',
484
- alignSelf: 'normal',
485
- button: {
486
- marginBottom: '0.3rem',
487
- },
488
- },
489
- };
490
- return (
491
- <div css={css} ref={ref}>
492
- <div class='admin-sub-title pt-s pl-s'>Edit Menu: {menuId}</div>
493
- <div class='list-top p-2'>
494
- <div class='row-box mb-s'>
495
- <button onClick={onClick} class='button-base'>
496
- Open
497
- </button>
498
- <button onClick={onSave} class='button-base'>
499
- Save
500
- </button>
501
- <button onClick={onSaveAs} class='button-base'>
502
- Save As
503
- </button>
504
- <button onClick={doNew} class='button-base'>
505
- Clear all items
506
- </button>
507
- <button onClick={doDelete} class='button-base red ml-m'>
508
- Delete from DB
509
- </button>
510
- </div>
511
- {/* <div class='row-box mt1'>
512
- <div class='w6'>Menu Id:</div>
513
- <input type='text' ref={refInput} class='input-base' placeholder='Menu Id' />
514
- </div>
515
- <div class='row-box mt1'>
516
- <div class='w6'>Title:</div>
517
- <input type='text' ref={refInput} class='input-base' placeholder='Menu Title' />
518
- </div>
519
- <div class='row-box mt1 mb1'>
520
- <div class='w6'>Remark:</div>
521
- <input type='text' ref={refInput} class='input-base w20' placeholder='Menu Remark' />
522
- </div> */}
523
- <div class='list-body row-box mt-1'>
524
- <div class='row-box h-100p'>
525
- <div class='list-box h-100p'>
526
- <select class='input-base w-20 h-100p' id='menulist' size={3} onChange={doListChg}>
527
- <option value='0 0 0 help.php?st_m0=help Help Home'>Home</option>
528
- <option value='1 0 0 help.php?st_p2=hlp_begin for Beginners'>----Sub Menu</option>
529
- </select>
530
- </div>
531
- <div class='action-box'>
532
- <button
533
- onClick={() => {
534
- doReplace();
535
- }}
536
- class='button-base button-s w-6'
537
- >
538
- Update
539
- </button>
540
- <button
541
- onClick={() => {
542
- doAppend(1);
543
- }}
544
- class='button-base button-s w-6'
545
- >
546
- Add New
547
- </button>
548
- <button
549
- onClick={() => {
550
- doAppend(2);
551
- }}
552
- class='button-base button-s w-6'
553
- >
554
- Add Copy
555
- </button>
556
- <button onClick={doDel} class='button-base button-s mb-m w-6'>
557
- Delete
558
- </button>
559
- <button onClick={doUp} class='button-base button-s mt3 w-4'>
560
- Up
561
- </button>
562
- <button onClick={doDown} class='button-base button-s w-4'>
563
- Down
564
- </button>
565
- <button onClick={doRight} class='button-base button-s w-4'>
566
- Right
567
- </button>
568
- <button onClick={doLeft} class='button-base button-s w-4'>
569
- Left
570
- </button>
571
- </div>
572
- </div>
573
- <div class='edit flex-1'>
574
- <div class='row-box' id='img_p0'>
575
- <div class='w-6'>Type</div>
576
- <input type='radio' id='itemtype1' name='itemtype' checked={true} />
577
- <label for='itemtype1'>Text</label>
578
- <input type='radio' id='itemtype2' name='itemtype' />
579
- <label for='itemtype2'>Image</label>
580
- </div>
581
-
582
- <div class='row-box mt-m'>
583
- <div class='w-6'>Title</div>
584
- <input type='text' id='menutitle' class='input-base w-20' />
585
- </div>
586
- <div class='row-box mt-m'>
587
- <div class='w-6'>Link</div>
588
- <input type='text' id='menulink' class='input-base w-20' />
589
- </div>
590
- <div class='row-box mt-m'>
591
- <div class='w-6'>Target</div>
592
- <select id='menutarget' class='input-base w20' size={1}>
593
- <option value='0'>Parent Window</option>
594
- <option value='1'>New Window</option>
595
- </select>
596
- </div>
597
-
598
- <div class='row-box mt-m' id='img_panel'>
599
- <div class='w-6'>Show Panel</div>
600
- <div>
601
- <input type='text' id='menupanel' class='input-base w-20' />
602
- <br />
603
- (This is ignored if it has a sub menu)
604
- </div>
605
- </div>
606
-
607
- <div class='row-box mt-m' id='img_p1'>
608
- <div class='w-6'>Image (Default)</div>
609
- <div>
610
- <input type='text' id='menuimageout' class='input-base w-20' /> <br />
611
- (Image for default)
612
- </div>
613
- </div>
614
- <div class='row-box mt-m' id='img_p2'>
615
- <div class='w-6'>Image (On)</div>
616
- <div>
617
- <input type='text' id='menuimageon' class='input-base w-20' /> <br />
618
- (Image when mouse is on)
619
- </div>
620
- </div>
621
-
622
- <div class='row-box mt-m'>
623
- <div class='w-6'>Access Level</div>
624
- <select id='menuaccess' class='input-base w-20' size={1}>
625
- <option value='0'>Public (All)</option>
626
- <option value='1'>Not logged in</option>
627
- <option value='2'>Logged in</option>
628
- <option value='3'>Admin</option>
629
- <option value='9'>Full Rights</option>
630
- </select>
631
- </div>
632
- </div>
633
- </div>
634
- </div>
635
- </div>
636
- );
637
- };
1
+ import { CssProps, getRenderPageProps, RefProps, DomUtils, ModalWindow, NotificationMessage } from 'lupine.components';
2
+
3
+ const fetchTableList = async () => {
4
+ const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/db/tables');
5
+ return data.json;
6
+ };
7
+ const fetchTableDrop = async (tableName: string) => {
8
+ const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/db/table-drop', {
9
+ table: tableName,
10
+ });
11
+ return data.json;
12
+ };
13
+ const fetchTableTruncate = async (tableName: string) => {
14
+ const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/db/table-truncate', {
15
+ table: tableName,
16
+ });
17
+ return data.json;
18
+ };
19
+
20
+ export const SaveMenu = (props: {
21
+ menuIdReadonly?: boolean;
22
+ menuId: string;
23
+ title: string;
24
+ note: string;
25
+ package: string;
26
+ }) => {
27
+ return (
28
+ <div class='save-menu'>
29
+ <div class='row-box mb-s'>
30
+ <div class='w-7'>Menu Id:</div>
31
+ <input type='text' id='s_menuId' value={props.menuId} class='input-base w-20' readonly={props.menuIdReadonly} />
32
+ </div>
33
+ <div class='row-box mb-s'>
34
+ <div class='w-7'>Menu Title:</div>
35
+ <input type='text' id='s_menuTitle' value={props.title} class='input-base w-20' />
36
+ </div>
37
+ <div class='row-box mb-s'>
38
+ <div class='w-7'>Menu Description:</div>
39
+ <input type='text' id='s_menuNote' value={props.note} class='input-base w-20' />
40
+ </div>
41
+ <div class='row-box mb-s'>
42
+ <div class='w-7'>Package id:</div>
43
+ <input type='text' id='s_menuPackage' value={props.package} class='input-base w-20' />
44
+ </div>
45
+ </div>
46
+ );
47
+ };
48
+
49
+ export const AdminMenuEditPage = (menuId: string) => {
50
+ let savedMenuId = '';
51
+ let savedMenuTitle = '';
52
+ let savedMenuNote = '';
53
+ let savedPackage = '';
54
+ const onDelete = async (tableName: string) => {
55
+ if (!confirm(`Are you really Deleting ${tableName}?`)) {
56
+ return;
57
+ }
58
+ const json = await fetchTableDrop(tableName);
59
+ console.log('====fetchTableDelete', json);
60
+ NotificationMessage.sendMessage('Deleted: ' + tableName);
61
+ onClick();
62
+ };
63
+
64
+ // const onDownload = async (tableName: string) => {
65
+ // DomUtils.download('/api/admin/db/table-download?table=' + tableName);
66
+ // };
67
+
68
+ const onClick = async () => {
69
+ const json = await fetchTableList();
70
+ console.log('====fetchTableList', json);
71
+ };
72
+
73
+ const doLoad = (results: any) => {
74
+ oMenu.length = 0;
75
+ savedMenuId = results.menuid;
76
+ savedMenuTitle = results.title;
77
+ savedMenuNote = results.note;
78
+ savedPackage = results.package;
79
+ for (const i in results.items) {
80
+ const item = results.items[i];
81
+ const lev = Number.parseInt(item[0]);
82
+ var pre = new Array(lev * 4 + 1).join('-');
83
+ oMenu.options[oMenu.length] = new Option(pre + item[4], item.join('\t'));
84
+ }
85
+ oMenu.selectedIndex = 0;
86
+ doListChg();
87
+ };
88
+ const onSave = () => {
89
+ doSave(false);
90
+ };
91
+ const onSaveAs = () => {
92
+ doSave(true);
93
+ };
94
+ const doSave = async (isSaveAs = false) => {
95
+ const handleClicked = async (index: number) => {
96
+ if (index === 0) {
97
+ // Save
98
+ const id = DomUtils.getValue('#s_menuId');
99
+ const title = DomUtils.getValue('#s_menuTitle');
100
+ const note = DomUtils.getValue('#s_menuNote');
101
+ const pkg = DomUtils.getValue('#s_menuPackage');
102
+ let regex = /^[a-zA-Z0-9]+$/;
103
+ if (!id || !regex.test(id)) {
104
+ alert('menuId is not valid!');
105
+ return;
106
+ }
107
+ const menuIdReadonly = !isSaveAs && !!savedMenuId;
108
+ const items = getAllItems();
109
+ const post: any = {
110
+ id,
111
+ title,
112
+ note,
113
+ items,
114
+ idReadonly: menuIdReadonly,
115
+ package: pkg,
116
+ };
117
+
118
+ const updateIds = () => {
119
+ savedMenuId = id;
120
+ savedMenuTitle = title;
121
+ savedMenuNote = note;
122
+ savedPackage = pkg;
123
+ ref.$('.admin-sub-title').innerHTML = `Edit Menu: ${savedMenuId}`;
124
+ };
125
+ const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/menu/save', post);
126
+ if (data.json && data.json.status !== 'ok') {
127
+ if (!post.idReadonly && data.json.status === 'ID_EXISTS') {
128
+ if (!confirm(`${data.json.message}\r\n\r\nDo you want to override the same menu id?`)) {
129
+ return;
130
+ }
131
+ post.idReadonly = true;
132
+ const data2 = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/menu/save', post);
133
+ if (data2.json && data2.json.status !== 'ok') {
134
+ alert(`Error happened: ${data2.json.message}`);
135
+ } else {
136
+ updateIds();
137
+ NotificationMessage.sendMessage('Menu is saved.');
138
+ }
139
+ } else {
140
+ alert(`Error happened: ${data.json.message}`);
141
+ return;
142
+ }
143
+ } else {
144
+ updateIds();
145
+ NotificationMessage.sendMessage('Menu is saved.');
146
+ }
147
+ }
148
+
149
+ modalClose();
150
+ };
151
+ const modalClose = await ModalWindow.show({
152
+ title: 'Save Menu',
153
+ buttons: ['Save', 'Cancel'],
154
+ // contentMaxHeight: '400px',
155
+ handleClicked,
156
+ children: (
157
+ <SaveMenu
158
+ menuIdReadonly={!!savedMenuId && !isSaveAs}
159
+ menuId={savedMenuId}
160
+ title={savedMenuTitle}
161
+ note={savedMenuNote}
162
+ package={savedPackage}
163
+ ></SaveMenu>
164
+ ),
165
+ });
166
+ };
167
+
168
+ let oMenu: HTMLSelectElement;
169
+ const ref: RefProps = {
170
+ onLoad: async () => {
171
+ oMenu = document.querySelector('#menulist')!;
172
+ if (menuId) {
173
+ const response = await getRenderPageProps().renderPageFunctions.fetchData(`/api/admin/menu/get/${menuId}`);
174
+ doLoad(response.json.result);
175
+ }
176
+ },
177
+ };
178
+ function getSel(ismsg = true) {
179
+ if (oMenu.selectedIndex < 0 && ismsg) {
180
+ if (oMenu.length == 0) {
181
+ NotificationMessage.sendMessage('No item in menu item list.');
182
+ } else {
183
+ NotificationMessage.sendMessage('Please select one item.');
184
+ }
185
+ }
186
+ return oMenu.selectedIndex;
187
+ }
188
+ function getLevel(ind: number) {
189
+ var t = oMenu.options[ind].value.split('\t');
190
+ return Number.parseInt(t[0]);
191
+ }
192
+ function getNav(ind: number) {
193
+ var t = oMenu.options[ind].value.split('\t');
194
+ return t[1];
195
+ }
196
+ function getAcc(ind: number) {
197
+ var t = oMenu.options[ind].value.split('\t');
198
+ return t[2];
199
+ }
200
+ function getLnk(ind: number) {
201
+ var t = oMenu.options[ind].value.split('\t');
202
+ return t[3];
203
+ }
204
+ function getTxt(ind: number) {
205
+ var t = oMenu.options[ind].value.split('\t');
206
+ return t[4];
207
+ }
208
+
209
+ function getAllItems() {
210
+ const ret = [];
211
+ for (var i = 0; i < oMenu.length; i++) {
212
+ // ret.push(oMenu.options[i].value);
213
+ ret.push([getLevel(i), getNav(i), getAcc(i), getLnk(i), getTxt(i)]);
214
+ }
215
+ return ret;
216
+ }
217
+ async function doDelete() {
218
+ if (!savedMenuId) {
219
+ alert('Current menu is not on DB yet.');
220
+ return;
221
+ }
222
+ if (!confirm('Do you delete this menu from the system?')) return;
223
+ await getRenderPageProps().renderPageFunctions.fetchData(`/api/admin/menu/delete/${savedMenuId}`);
224
+ doNew();
225
+ NotificationMessage.sendMessage('Menu is deleted.');
226
+ }
227
+ function doNew() {
228
+ savedMenuId = '';
229
+ for (var i = oMenu.length - 1; i >= 0; i--) {
230
+ oMenu.options[i].remove();
231
+ }
232
+ }
233
+ function byId(id: string) {
234
+ return document.getElementById(id)! as HTMLElement;
235
+ }
236
+ function doListChg() {
237
+ var ind = getSel(false);
238
+ var tt = getTxt(ind);
239
+
240
+ var ty = '0';
241
+ DomUtils.setValue('#menuimageout', '');
242
+ DomUtils.setValue('#menuimageon', '');
243
+ DomUtils.setValue('#menupanel', '');
244
+ if (tt.substring(0, 4) == '[::]') {
245
+ var t = tt.split('[::]');
246
+ if (t.length == 6) {
247
+ DomUtils.setValue('#menuimg1', t[3]);
248
+ DomUtils.setValue('#menuimg2', t[4]);
249
+ ty = t[1];
250
+ tt = t[2];
251
+ DomUtils.setValue('#menupanel', t[5]);
252
+ }
253
+ }
254
+
255
+ var lev = getLevel(ind);
256
+ if (lev > 0) {
257
+ byId('img_p0').style.display = 'none';
258
+ byId('img_p1').style.display = 'none';
259
+ byId('img_p2').style.display = 'none';
260
+ byId('img_panel').style.display = 'none';
261
+ } else {
262
+ byId('img_p0').style.display = '';
263
+ byId('img_p1').style.display = '';
264
+ byId('img_p2').style.display = '';
265
+ byId('img_panel').style.display = '';
266
+ }
267
+
268
+ DomUtils.setChecked('#itemtype1', ty == '' || ty == '0');
269
+ DomUtils.setChecked('#itemtype2', ty == '1');
270
+ DomUtils.setValue('#menutitle', tt);
271
+ DomUtils.setValue('#menulink', getLnk(ind));
272
+ DomUtils.setValue('#menutarget', getNav(ind));
273
+ DomUtils.setValue('#menuaccess', getAcc(ind));
274
+ }
275
+
276
+ function doReplace(ind2?: number) {
277
+ var ind = typeof ind2 === 'number' && ind2 >= 0 ? ind2 : getSel(true);
278
+ if (ind < 0) return;
279
+ var menutxt = DomUtils.getValue('#menutitle').trim();
280
+ if (menutxt == '') {
281
+ alert('Please input menu text.');
282
+ return;
283
+ }
284
+ if (menutxt.indexOf('[::]') >= 0) {
285
+ alert('Cannot include "[::]" in menu text.');
286
+ return;
287
+ }
288
+
289
+ var lev = getLevel(ind);
290
+ var acc = DomUtils.getValue('#menuaccess');
291
+ var nav = DomUtils.getValue('#menutarget');
292
+ if (!nav || nav == '' || !acc || acc == '') {
293
+ alert('Please select browsernav and access.');
294
+ return;
295
+ }
296
+
297
+ var itemty = '0';
298
+ if (DomUtils.getChecked('#itemtype2')) {
299
+ itemty = '1';
300
+ }
301
+ var img1 = DomUtils.getValue('#menuimageout').trim();
302
+ var img2 = DomUtils.getValue('#menuimageon').trim();
303
+ var panel = DomUtils.getValue('#menupanel').trim();
304
+ if (itemty == '1' && img1 == '') {
305
+ alert('For selected Image, need input image path.');
306
+ return;
307
+ }
308
+
309
+ if (img1 != '' || panel != '') {
310
+ menutxt = '[::]' + itemty + '[::]' + menutxt + '[::]' + img1 + '[::]' + img2 + '[::]' + panel;
311
+ }
312
+
313
+ var pre = new Array(lev * 4 + 1).join('-');
314
+ oMenu.options[ind].value = lev + ' ' + nav + ' ' + acc + ' XX ' + DomUtils.getValue('#menulink').trim() + ' ' + menutxt;
315
+ oMenu.options[ind].text = pre + DomUtils.getValue('#menutitle').trim();
316
+ }
317
+ function doAppend(act: number) {
318
+ var ind = oMenu.selectedIndex;
319
+ if (ind < 0) {
320
+ ind = oMenu.length - 1;
321
+ }
322
+ if (act == 1) {
323
+ DomUtils.setValue('#menutitle', 'New Item');
324
+ DomUtils.setValue('#menulink', '');
325
+ }
326
+ if (DomUtils.getValue('#menutitle').trim() == '') {
327
+ alert('Please input menu text.');
328
+ return;
329
+ }
330
+ var acc = DomUtils.getValue('#menuaccess');
331
+ var nav = DomUtils.getValue('#menutarget');
332
+ if (!nav || nav == '' || !acc || acc == '') {
333
+ alert('Please select Target and Access Level.');
334
+ return;
335
+ }
336
+ oMenu.options[oMenu.length] = new Option('', '');
337
+ for (var i = oMenu.length - 1; ind >= 0 && i > ind; i--) {
338
+ oMenu.options[i].text = oMenu.options[i - 1].text;
339
+ oMenu.options[i].value = oMenu.options[i - 1].value;
340
+ }
341
+ doReplace(ind + 1);
342
+ oMenu.options[ind + 1].selected = true;
343
+ }
344
+
345
+ function doDel() {
346
+ var ind = getSel(true);
347
+ if (ind < 0) return;
348
+ if (!confirm('Delete the selected item and all the subs?')) return;
349
+ var lev = getLevel(ind);
350
+ var ind0 = -1;
351
+ for (var i = ind; i < oMenu.length; i++) {
352
+ var levx = getLevel(i);
353
+ if (levx <= lev && i != ind) {
354
+ break;
355
+ }
356
+ ind0 = i;
357
+ }
358
+ for (var i = ind0; i >= ind; i--) {
359
+ oMenu.options[i].remove();
360
+ }
361
+
362
+ if (ind >= oMenu.length) ind = oMenu.length - 1;
363
+ if (ind >= 0) oMenu.options[ind].selected = true;
364
+ }
365
+
366
+ function doMoveUp(ind: number) {
367
+ if (ind < 1) return -1;
368
+ var ind0 = -1;
369
+ var lev = getLevel(ind);
370
+ for (var i = ind - 1; i >= 0; i--) {
371
+ var levx = getLevel(i);
372
+ if (levx < lev) {
373
+ break;
374
+ }
375
+ if (levx == lev) {
376
+ ind0 = i;
377
+ break;
378
+ }
379
+ }
380
+ if (ind0 < 0) return -1;
381
+ oMenu.options[ind0].selected = true;
382
+ var inds = ind0;
383
+
384
+ for (var i = ind; i < oMenu.length; i++) {
385
+ var levx = getLevel(i);
386
+ if (levx <= lev && i != ind) break;
387
+
388
+ for (var j = i; j > ind0; j--) {
389
+ var text = oMenu.options[j].text;
390
+ var value = oMenu.options[j].value;
391
+ oMenu.options[j].text = oMenu.options[j - 1].text;
392
+ oMenu.options[j].value = oMenu.options[j - 1].value;
393
+ oMenu.options[j - 1].text = text;
394
+ oMenu.options[j - 1].value = value;
395
+ }
396
+ ind0++;
397
+ }
398
+ return ind0 - inds;
399
+ }
400
+ function doUp() {
401
+ var ind = getSel(true);
402
+ doMoveUp(ind);
403
+ }
404
+ function doDown() {
405
+ var ind = getSel(true);
406
+ if (ind < 0) return;
407
+
408
+ if (ind >= oMenu.length - 1) return;
409
+ var ind0 = -1;
410
+ var lev = getLevel(ind);
411
+ for (var i = ind + 1; i < oMenu.length; i++) {
412
+ var levx = getLevel(i);
413
+ if (levx < lev) {
414
+ break;
415
+ }
416
+ if (levx == lev) {
417
+ ind0 = i;
418
+ break;
419
+ }
420
+ }
421
+ if (ind0 < 0) return;
422
+ var ind2 = doMoveUp(ind0);
423
+ oMenu.options[ind + ind2].selected = true;
424
+ }
425
+ function doLeft() {
426
+ var ind = getSel(true);
427
+ if (ind < 0) return;
428
+
429
+ var lev = getLevel(ind);
430
+ if (lev <= 0) return;
431
+ for (var i = ind; i < oMenu.length; i++) {
432
+ var t = oMenu.options[i].value.split('\t');
433
+ let newlev = Number.parseInt(t[0]);
434
+ if (newlev <= lev && i != ind) break;
435
+
436
+ newlev--;
437
+ t[0] = '' + newlev;
438
+ var pre = new Array(newlev * 4 + 1).join('-');
439
+ oMenu.options[i].value = t.join(' ');
440
+ oMenu.options[i].text = pre + t[4];
441
+ }
442
+ }
443
+ function doRight() {
444
+ var ind = getSel(true);
445
+ if (ind < 1) return;
446
+
447
+ var lev0 = getLevel(ind - 1);
448
+ var lev = getLevel(ind);
449
+ if (lev0 < lev) return;
450
+ for (var i = ind; i < oMenu.length; i++) {
451
+ var t = oMenu.options[i].value.split('\t');
452
+ let newlev = Number.parseInt(t[0]);
453
+ if (newlev <= lev && i != ind) break;
454
+
455
+ newlev++;
456
+ t[0] = '' + newlev;
457
+ var pre = new Array(newlev * 4 + 1).join('-');
458
+ oMenu.options[i].value = t.join(' ');
459
+ oMenu.options[i].text = pre + t[4];
460
+ }
461
+ }
462
+
463
+ const css: CssProps = {
464
+ height: '100%',
465
+ display: 'flex',
466
+ flexDirection: 'column',
467
+ '.list-top': {
468
+ flex: '1',
469
+ display: 'flex',
470
+ flexDirection: 'column',
471
+ },
472
+ '.list-body': {
473
+ flex: '1',
474
+ display: 'flex',
475
+ },
476
+ '#menulist': {
477
+ width: '200px',
478
+ },
479
+ '.edit': {
480
+ alignSelf: 'normal',
481
+ },
482
+ '.action-box': {
483
+ width: '100px',
484
+ alignSelf: 'normal',
485
+ button: {
486
+ marginBottom: '0.3rem',
487
+ },
488
+ },
489
+ };
490
+ return (
491
+ <div css={css} ref={ref}>
492
+ <div class='admin-sub-title pt-s pl-s'>Edit Menu: {menuId}</div>
493
+ <div class='list-top p-2'>
494
+ <div class='row-box mb-s'>
495
+ <button onClick={onClick} class='button-base'>
496
+ Open
497
+ </button>
498
+ <button onClick={onSave} class='button-base'>
499
+ Save
500
+ </button>
501
+ <button onClick={onSaveAs} class='button-base'>
502
+ Save As
503
+ </button>
504
+ <button onClick={doNew} class='button-base'>
505
+ Clear all items
506
+ </button>
507
+ <button onClick={doDelete} class='button-base red ml-m'>
508
+ Delete from DB
509
+ </button>
510
+ </div>
511
+ {/* <div class='row-box mt1'>
512
+ <div class='w6'>Menu Id:</div>
513
+ <input type='text' ref={refInput} class='input-base' placeholder='Menu Id' />
514
+ </div>
515
+ <div class='row-box mt1'>
516
+ <div class='w6'>Title:</div>
517
+ <input type='text' ref={refInput} class='input-base' placeholder='Menu Title' />
518
+ </div>
519
+ <div class='row-box mt1 mb1'>
520
+ <div class='w6'>Remark:</div>
521
+ <input type='text' ref={refInput} class='input-base w20' placeholder='Menu Remark' />
522
+ </div> */}
523
+ <div class='list-body row-box mt-1'>
524
+ <div class='row-box h-100p'>
525
+ <div class='list-box h-100p'>
526
+ <select class='input-base w-20 h-100p' id='menulist' size={3} onChange={doListChg}>
527
+ <option value='0 0 0 help.php?st_m0=help Help Home'>Home</option>
528
+ <option value='1 0 0 help.php?st_p2=hlp_begin for Beginners'>----Sub Menu</option>
529
+ </select>
530
+ </div>
531
+ <div class='action-box'>
532
+ <button
533
+ onClick={() => {
534
+ doReplace();
535
+ }}
536
+ class='button-base button-s w-6'
537
+ >
538
+ Update
539
+ </button>
540
+ <button
541
+ onClick={() => {
542
+ doAppend(1);
543
+ }}
544
+ class='button-base button-s w-6'
545
+ >
546
+ Add New
547
+ </button>
548
+ <button
549
+ onClick={() => {
550
+ doAppend(2);
551
+ }}
552
+ class='button-base button-s w-6'
553
+ >
554
+ Add Copy
555
+ </button>
556
+ <button onClick={doDel} class='button-base button-s mb-m w-6'>
557
+ Delete
558
+ </button>
559
+ <button onClick={doUp} class='button-base button-s mt3 w-4'>
560
+ Up
561
+ </button>
562
+ <button onClick={doDown} class='button-base button-s w-4'>
563
+ Down
564
+ </button>
565
+ <button onClick={doRight} class='button-base button-s w-4'>
566
+ Right
567
+ </button>
568
+ <button onClick={doLeft} class='button-base button-s w-4'>
569
+ Left
570
+ </button>
571
+ </div>
572
+ </div>
573
+ <div class='edit flex-1'>
574
+ <div class='row-box' id='img_p0'>
575
+ <div class='w-6'>Type</div>
576
+ <input type='radio' id='itemtype1' name='itemtype' checked={true} />
577
+ <label for='itemtype1'>Text</label>
578
+ <input type='radio' id='itemtype2' name='itemtype' />
579
+ <label for='itemtype2'>Image</label>
580
+ </div>
581
+
582
+ <div class='row-box mt-m'>
583
+ <div class='w-6'>Title</div>
584
+ <input type='text' id='menutitle' class='input-base w-20' />
585
+ </div>
586
+ <div class='row-box mt-m'>
587
+ <div class='w-6'>Link</div>
588
+ <input type='text' id='menulink' class='input-base w-20' />
589
+ </div>
590
+ <div class='row-box mt-m'>
591
+ <div class='w-6'>Target</div>
592
+ <select id='menutarget' class='input-base w20' size={1}>
593
+ <option value='0'>Parent Window</option>
594
+ <option value='1'>New Window</option>
595
+ </select>
596
+ </div>
597
+
598
+ <div class='row-box mt-m' id='img_panel'>
599
+ <div class='w-6'>Show Panel</div>
600
+ <div>
601
+ <input type='text' id='menupanel' class='input-base w-20' />
602
+ <br />
603
+ (This is ignored if it has a sub menu)
604
+ </div>
605
+ </div>
606
+
607
+ <div class='row-box mt-m' id='img_p1'>
608
+ <div class='w-6'>Image (Default)</div>
609
+ <div>
610
+ <input type='text' id='menuimageout' class='input-base w-20' /> <br />
611
+ (Image for default)
612
+ </div>
613
+ </div>
614
+ <div class='row-box mt-m' id='img_p2'>
615
+ <div class='w-6'>Image (On)</div>
616
+ <div>
617
+ <input type='text' id='menuimageon' class='input-base w-20' /> <br />
618
+ (Image when mouse is on)
619
+ </div>
620
+ </div>
621
+
622
+ <div class='row-box mt-m'>
623
+ <div class='w-6'>Access Level</div>
624
+ <select id='menuaccess' class='input-base w-20' size={1}>
625
+ <option value='0'>Public (All)</option>
626
+ <option value='1'>Not logged in</option>
627
+ <option value='2'>Logged in</option>
628
+ <option value='3'>Admin</option>
629
+ <option value='9'>Full Rights</option>
630
+ </select>
631
+ </div>
632
+ </div>
633
+ </div>
634
+ </div>
635
+ </div>
636
+ );
637
+ };