cmdbox 0.5.1.1__py3-none-any.whl → 0.5.2__py3-none-any.whl

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.

Potentially problematic release.


This version of cmdbox might be problematic. Click here for more details.

Files changed (118) hide show
  1. cmdbox/app/app.py +4 -2
  2. cmdbox/app/auth/signin.py +633 -631
  3. cmdbox/app/client.py +10 -10
  4. cmdbox/app/common.py +50 -6
  5. cmdbox/app/commons/convert.py +9 -0
  6. cmdbox/app/commons/module.py +113 -113
  7. cmdbox/app/commons/redis_client.py +40 -29
  8. cmdbox/app/edge.py +4 -4
  9. cmdbox/app/features/cli/audit_base.py +135 -0
  10. cmdbox/app/features/cli/cmdbox_audit_createdb.py +224 -0
  11. cmdbox/app/features/cli/cmdbox_audit_delete.py +299 -0
  12. cmdbox/app/features/cli/cmdbox_audit_search.py +350 -0
  13. cmdbox/app/features/cli/cmdbox_audit_write.py +240 -0
  14. cmdbox/app/features/cli/cmdbox_client_file_copy.py +207 -207
  15. cmdbox/app/features/cli/cmdbox_client_file_download.py +207 -207
  16. cmdbox/app/features/cli/cmdbox_client_file_list.py +193 -193
  17. cmdbox/app/features/cli/cmdbox_client_file_mkdir.py +191 -191
  18. cmdbox/app/features/cli/cmdbox_client_file_move.py +199 -199
  19. cmdbox/app/features/cli/cmdbox_client_file_remove.py +190 -190
  20. cmdbox/app/features/cli/cmdbox_client_file_rmdir.py +190 -190
  21. cmdbox/app/features/cli/cmdbox_client_file_upload.py +212 -212
  22. cmdbox/app/features/cli/cmdbox_client_server_info.py +166 -166
  23. cmdbox/app/features/cli/cmdbox_server_list.py +88 -88
  24. cmdbox/app/features/cli/cmdbox_server_stop.py +138 -138
  25. cmdbox/app/features/web/cmdbox_web_del_cmd.py +2 -0
  26. cmdbox/app/features/web/cmdbox_web_del_pipe.py +1 -0
  27. cmdbox/app/features/web/cmdbox_web_do_signin.py +12 -2
  28. cmdbox/app/features/web/cmdbox_web_do_signout.py +1 -0
  29. cmdbox/app/features/web/cmdbox_web_exec_cmd.py +25 -1
  30. cmdbox/app/features/web/cmdbox_web_exec_pipe.py +1 -0
  31. cmdbox/app/features/web/cmdbox_web_filer download.py +43 -42
  32. cmdbox/app/features/web/cmdbox_web_filer.py +1 -0
  33. cmdbox/app/features/web/cmdbox_web_filer_upload.py +65 -64
  34. cmdbox/app/features/web/cmdbox_web_gui.py +166 -165
  35. cmdbox/app/features/web/cmdbox_web_load_pin.py +43 -43
  36. cmdbox/app/features/web/cmdbox_web_raw_pipe.py +87 -87
  37. cmdbox/app/features/web/cmdbox_web_save_cmd.py +1 -0
  38. cmdbox/app/features/web/cmdbox_web_save_pin.py +42 -42
  39. cmdbox/app/features/web/cmdbox_web_save_pipe.py +1 -0
  40. cmdbox/app/features/web/cmdbox_web_users.py +12 -0
  41. cmdbox/app/options.py +767 -601
  42. cmdbox/extensions/features.yml +20 -0
  43. cmdbox/extensions/sample_project/sample/app/features/cli/sample_client_time.py +82 -82
  44. cmdbox/extensions/sample_project/sample/app/features/cli/sample_server_time.py +145 -145
  45. cmdbox/licenses/{LICENSE.Sphinx.8.1.3(BSD License).txt → LICENSE.Sphinx.8.2.3(UNKNOWN).txt} +1 -1
  46. cmdbox/licenses/{LICENSE.babel.2.16.0(BSD License).txt → LICENSE.babel.2.17.0(BSD License).txt } +1 -1
  47. cmdbox/licenses/{LICENSE.pkginfo.1.10.0(MIT License).txt → LICENSE.charset-normalizer.3.4.1(MIT License).txt } +1 -1
  48. cmdbox/licenses/LICENSE.gunicorn.23.0.0(MIT License).txt +23 -0
  49. cmdbox/licenses/LICENSE.importlib_metadata.8.6.1(Apache Software License).txt +202 -0
  50. cmdbox/licenses/LICENSE.nh3.0.2.21(MIT).txt +21 -0
  51. cmdbox/licenses/{LICENSE.pillow.11.0.0(CMU License (MIT-CMU)).txt → LICENSE.pillow.11.1.0(CMU License (MIT-CMU)).txt } +27 -40
  52. cmdbox/licenses/LICENSE.plyer.2.1.0(MIT License).txt +19 -0
  53. cmdbox/licenses/LICENSE.prompt_toolkit.3.0.50(BSD License).txt +27 -0
  54. cmdbox/licenses/LICENSE.psycopg-binary.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt +165 -0
  55. cmdbox/licenses/LICENSE.psycopg-pool.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt +165 -0
  56. cmdbox/licenses/LICENSE.psycopg.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt +165 -0
  57. cmdbox/licenses/LICENSE.pycryptodome.3.22.0(BSD License; Public Domain).txt +61 -0
  58. cmdbox/licenses/LICENSE.pystray.0.19.5(GNU Lesser General Public License v3 (LGPLv3)).txt +674 -0
  59. cmdbox/licenses/LICENSE.questionary.2.1.0(MIT License).txt +19 -0
  60. cmdbox/licenses/LICENSE.roman-numerals-py.3.1.0(CC0 1.0 Universal (CC0 1.0) Public Domain Dedication; Zero-Clause BSD (0BSD)).txt +146 -0
  61. cmdbox/licenses/{LICENSE.six.1.16.0(MIT License).txt → LICENSE.six.1.17.0(MIT License).txt } +1 -1
  62. cmdbox/licenses/{LICENSE.charset-normalizer.3.4.0(MIT License).txt → LICENSE.typing-inspection.0.4.0(MIT License).txt } +2 -2
  63. cmdbox/licenses/LICENSE.tzdata.2025.2(Apache Software License).txt +15 -0
  64. cmdbox/licenses/files.txt +48 -36
  65. cmdbox/logconf_audit.yml +30 -0
  66. cmdbox/logconf_cmdbox.yml +30 -0
  67. cmdbox/version.py +2 -2
  68. cmdbox/web/assets/cmdbox/color_mode.css +516 -0
  69. cmdbox/web/assets/cmdbox/common.js +19 -0
  70. cmdbox/web/assets/cmdbox/list_cmd.js +89 -43
  71. cmdbox/web/assets/cmdbox/list_pipe.js +2 -1
  72. cmdbox/web/assets/cmdbox/main.js +2 -2
  73. cmdbox/web/assets/cmdbox/result.js +2 -2
  74. cmdbox/web/assets/cmdbox/signin.js +2 -2
  75. cmdbox/web/assets/cmdbox/users.js +2 -3
  76. cmdbox/web/assets/cmdbox/view_result.js +1 -1
  77. cmdbox/web/assets/filer/main.js +2 -2
  78. cmdbox/web/filer.html +16 -2
  79. cmdbox/web/gui.html +21 -2
  80. cmdbox/web/result.html +15 -1
  81. cmdbox/web/signin.html +35 -14
  82. cmdbox/web/users.html +15 -1
  83. {cmdbox-0.5.1.1.dist-info → cmdbox-0.5.2.dist-info}/METADATA +25 -5
  84. {cmdbox-0.5.1.1.dist-info → cmdbox-0.5.2.dist-info}/RECORD +117 -97
  85. {cmdbox-0.5.1.1.dist-info → cmdbox-0.5.2.dist-info}/entry_points.txt +0 -1
  86. cmdbox/licenses/LICENSE.nh3.0.2.18(MIT).txt +0 -1
  87. /cmdbox/licenses/{LICENSE.Jinja2.3.1.4(BSD License).txt → LICENSE.Jinja2.3.1.6(BSD License).txt} +0 -0
  88. /cmdbox/licenses/{LICENSE.Pygments.2.18.0(BSD License).txt → LICENSE.Pygments.2.19.1(BSD License).txt} +0 -0
  89. /cmdbox/licenses/{LICENSE.anyio.4.6.2.post1(MIT License).txt → LICENSE.anyio.4.9.0(MIT License).txt} +0 -0
  90. /cmdbox/licenses/{LICENSE.argcomplete.3.5.1(Apache Software License).txt → LICENSE.argcomplete.3.6.1(Apache Software License).txt} +0 -0
  91. /cmdbox/licenses/{LICENSE.certifi.2024.8.30(Mozilla Public License 2.0 (MPL 2.0)).txt → LICENSE.certifi.2025.1.31(Mozilla Public License 2.0 (MPL 2.0)).txt} +0 -0
  92. /cmdbox/licenses/{LICENSE.click.8.1.7(BSD License).txt → LICENSE.click.8.1.8(BSD License).txt} +0 -0
  93. /cmdbox/licenses/{LICENSE.cryptography.43.0.3(Apache Software License; BSD License).txt → LICENSE.cryptography.44.0.2(Apache Software License; BSD License).txt} +0 -0
  94. /cmdbox/licenses/{LICENSE.fastapi.0.115.5(MIT License).txt → LICENSE.fastapi.0.115.12(MIT License).txt} +0 -0
  95. /cmdbox/licenses/{LICENSE.importlib_metadata.8.5.0(Apache Software License).txt → LICENSE.id.1.5.0(Apache Software License).txt} +0 -0
  96. /cmdbox/licenses/{LICENSE.keyring.25.5.0(MIT License).txt → LICENSE.keyring.25.6.0(MIT License).txt} +0 -0
  97. /cmdbox/licenses/{LICENSE.more-itertools.10.5.0(MIT License).txt → LICENSE.more-itertools.10.6.0(MIT License).txt} +0 -0
  98. /cmdbox/licenses/{LICENSE.numpy.2.1.3(BSD License).txt → LICENSE.numpy.2.2.4(BSD License).txt} +0 -0
  99. /cmdbox/licenses/{LICENSE.prettytable.3.12.0(BSD License).txt → LICENSE.prettytable.3.16.0(UNKNOWN).txt} +0 -0
  100. /cmdbox/licenses/{LICENSE.pydantic.2.10.2(MIT License).txt → LICENSE.pydantic.2.11.1(MIT License).txt} +0 -0
  101. /cmdbox/licenses/{LICENSE.pydantic_core.2.27.1(MIT License).txt → LICENSE.pydantic_core.2.33.0(MIT License).txt} +0 -0
  102. /cmdbox/licenses/{LICENSE.python-dotenv.1.0.1(BSD License).txt → LICENSE.python-dotenv.1.1.0(BSD License).txt} +0 -0
  103. /cmdbox/licenses/{LICENSE.python-multipart.0.0.17(Apache Software License).txt → LICENSE.python-multipart.0.0.20(Apache Software License).txt} +0 -0
  104. /cmdbox/licenses/{LICENSE.redis.5.2.0(MIT License).txt → LICENSE.redis.5.2.1(MIT License).txt} +0 -0
  105. /cmdbox/licenses/{LICENSE.rich.13.9.4(MIT License).txt → LICENSE.rich.14.0.0(MIT License).txt} +0 -0
  106. /cmdbox/licenses/{LICENSE.sphinx-intl.2.3.0(BSD License).txt → LICENSE.sphinx-intl.2.3.1(BSD License).txt} +0 -0
  107. /cmdbox/licenses/{LICENSE.starlette.0.41.3(BSD License).txt → LICENSE.starlette.0.46.1(BSD License).txt} +0 -0
  108. /cmdbox/licenses/{LICENSE.tomli.2.1.0(MIT License).txt → LICENSE.tomli.2.2.1(MIT License).txt} +0 -0
  109. /cmdbox/licenses/{LICENSE.twine.5.1.1(Apache Software License).txt → LICENSE.twine.6.1.0(Apache Software License).txt} +0 -0
  110. /cmdbox/licenses/{LICENSE.typing_extensions.4.12.2(Python Software Foundation License).txt → LICENSE.typing_extensions.4.13.0(UNKNOWN).txt} +0 -0
  111. /cmdbox/licenses/{LICENSE.urllib3.2.2.3(MIT License).txt → LICENSE.urllib3.2.3.0(MIT License).txt} +0 -0
  112. /cmdbox/licenses/{LICENSE.uvicorn.0.32.1(BSD License).txt → LICENSE.uvicorn.0.34.0(BSD License).txt} +0 -0
  113. /cmdbox/licenses/{LICENSE.watchfiles.1.0.0(MIT License).txt → LICENSE.watchfiles.1.0.4(MIT License).txt} +0 -0
  114. /cmdbox/licenses/{LICENSE.websockets.14.1(BSD License).txt → LICENSE.websockets.15.0.1(BSD License).txt} +0 -0
  115. /cmdbox/licenses/{LICENSE.zope.interface.7.1.1(Zope Public License).txt → LICENSE.zope.interface.7.2(Zope Public License).txt} +0 -0
  116. {cmdbox-0.5.1.1.dist-info → cmdbox-0.5.2.dist-info}/LICENSE +0 -0
  117. {cmdbox-0.5.1.1.dist-info → cmdbox-0.5.2.dist-info}/WHEEL +0 -0
  118. {cmdbox-0.5.1.1.dist-info → cmdbox-0.5.2.dist-info}/top_level.txt +0 -0
@@ -15,7 +15,14 @@ const list_cmd_func = async () => {
15
15
  }
16
16
  elem.find('.cmd_title').text(row.title);
17
17
  elem.find('.cmd_mode').text(row.mode);
18
- elem.find('.cmd_cmd').text(row.cmd)
18
+ elem.find('.cmd_cmd').text(row.cmd);
19
+ const tags_elem = elem.find('.cmd_tags');
20
+ if (row.tag && Array.isArray(row.tag)) {
21
+ row.tag.forEach(tag => {
22
+ if (tag=='') return;
23
+ tags_elem.append(`<span class="badge text-bg-secondary me-1"><svg class="bi bi-svg_tag" width="16" height="16" fill="currentColor"><use href="#svg_tag"></use></svg>${tag}</span>`);
24
+ });
25
+ }
19
26
  if (row.tag && Array.isArray(row.tag)) {
20
27
  const tags = new Set([...row.tag]);
21
28
  elem.find('.cmd_card').attr('data-tags', Array.from(tags).join(','));
@@ -24,49 +31,90 @@ const list_cmd_func = async () => {
24
31
  };
25
32
  py_list_cmd.forEach(row => {card_func(row, true)});
26
33
  py_list_cmd.forEach(row => {card_func(row, false)});
27
- $('#cmd_item_tags').html('');
34
+ const cmd_item_tags = $('#cmd_item_tags').html('');
35
+ const tag_bot_click = (e) => {
36
+ const ct = $(e.currentTarget);
37
+ const cmd_items = $('#cmd_items').find('.cmd_card:not(.cmd_add)');
38
+ const andor_sw = ct.hasClass('andor_switch');
39
+ const and_val = $('#andor_switch').prop('checked');
40
+ // 選択中のボタンの場合は解除中にする
41
+ if (!andor_sw && ct.hasClass('btn-secondary')) {
42
+ ct.removeClass('btn-secondary');
43
+ ct.addClass('btn-outline-secondary');
44
+ }
45
+ // 解除中のボタンの場合は選択中にする
46
+ else if (!andor_sw && ct.hasClass('btn-outline-secondary')) {
47
+ ct.removeClass('btn-outline-secondary');
48
+ ct.addClass('btn-secondary');
49
+ }
50
+ // 選択中のタグを取得
51
+ const tags = new Set();
52
+ cmd_item_tags.find('.btn-tag').each((i, elem) => {
53
+ if ($(elem).hasClass('btn-secondary')) tags.add($(elem).attr('data-tag'));
54
+ });
55
+ // タグ無しボタンが選択された場合
56
+ if (ct.hasClass('btn_notag') && ct.hasClass('btn-secondary')) {
57
+ cmd_item_tags.find('.btn-tag').removeClass('btn-secondary').addClass('btn-outline-secondary');
58
+ cmd_items.parent().hide();
59
+ cmd_items.each((i, elem) => {
60
+ const el = $(elem);
61
+ const itags = el.attr('data-tags');
62
+ if (itags) return;
63
+ el.parent().show();
64
+ });
65
+ return;
66
+ }
67
+ // notagボタンの選択を解除
68
+ if (!andor_sw) $('#btn_notag').removeClass('btn-secondary').addClass('btn-outline-secondary');
69
+ // タグがない場合は全て表示
70
+ if (tags.size == 0) {
71
+ cmd_items.parent().show();
72
+ return;
73
+ }
74
+ // タグがある場合はタグに一致するものだけ表示
75
+ cmd_items.parent().hide();
76
+ cmd_items.each((i, elem) => {
77
+ const el = $(elem);
78
+ // andorチェックされている場合はすべてのタグを含むものを表示
79
+ if (and_val) {
80
+ const itags = el.attr('data-tags');
81
+ if (!itags) return;
82
+ const etags = itags.split(',');
83
+ if (etags.filter(tag => tags.has(tag)).length == tags.size) el.parent().show();
84
+ return;
85
+ }
86
+ // andorチェックされていない場合はいずれかのタグを含むものを表示
87
+ tags.forEach(tag => {
88
+ const itags = el.attr('data-tags');
89
+ if (!itags) return;
90
+ else if (itags.split(',').includes(tag)) el.parent().show();
91
+ });
92
+ });
93
+ };
94
+ // タグボタンを追加
28
95
  py_list_cmd.forEach(row => {
96
+ // タグボタンを追加
29
97
  if (!row.tag || !Array.isArray(row.tag)) return;
30
- const cmd_item_tags = $('#cmd_item_tags');
31
98
  row.tag.forEach(tag => {
32
99
  if (tag=='') return;
33
100
  if (cmd_item_tags.find(`[data-tag="${tag}"]`).length > 0) return;
34
- const elem = $(`<button type="button" class="btn btn-outline-secondary btn-sm btn-tag me-2">${tag}</button>`);
101
+ const elem = $(`<button type="button" class="btn btn-outline-secondary btn-sm btn-tag me-2">` +
102
+ `<svg class="bi svg-tag" width="16" height="16" fill="currentColor"><use href="#svg_tag"></use></svg>${tag}</button>`);
35
103
  elem.attr('data-tag', tag);
36
- elem.text(tag);
37
- elem.click((e) => {
38
- const ct = $(e.currentTarget);
39
- const cmd_items = $('#cmd_items').find('.cmd_card:not(.cmd_add)');
40
- if (ct.hasClass('btn-secondary')) {
41
- ct.removeClass('btn-secondary');
42
- ct.addClass('btn-outline-secondary');
43
- }
44
- else if (ct.hasClass('btn-outline-secondary')) {
45
- ct.removeClass('btn-outline-secondary');
46
- ct.addClass('btn-secondary');
47
- }
48
- const tags = new Set();
49
- cmd_item_tags.find('.btn-tag').each((i, elem) => {
50
- if ($(elem).hasClass('btn-secondary')) tags.add($(elem).attr('data-tag'));
51
- });
52
- if (tags.size == 0) {
53
- cmd_items.parent().show();
54
- return;
55
- }
56
- cmd_items.parent().hide();
57
- tags.forEach(tag => {
58
- cmd_items.each((i, elem) => {
59
- const el = $(elem);
60
- const itags = el.attr('data-tags');
61
- if (!itags) return;
62
- else if (itags.split(',').includes(tag)) el.parent().show();
63
- });
64
- });
65
- });
104
+ elem.click(tag_bot_click);
66
105
  cmd_item_tags.append(elem);
67
106
  });
68
-
69
107
  });
108
+ // タグ未選択ボタンを追加
109
+ const noselect_bot = $(`<button type="button" class="btn btn-outline-secondary btn-sm btn_notag me-2" id="btn_notag">no tag</button>`);
110
+ noselect_bot.click(tag_bot_click);
111
+ cmd_item_tags.append(noselect_bot);
112
+ // and/orスイッチを追加
113
+ const andor_bot = $(`<div class="form-check form-switch text-secondary d-inline-block"/>`);
114
+ andor_bot.append('<input class="form-check-input andor_switch" type="checkbox" id="andor_switch">');
115
+ andor_bot.append('<label class="form-check-label" for="andor_switch">or / and</label>');
116
+ andor_bot.find('#andor_switch').click(tag_bot_click);
117
+ cmd_item_tags.append(andor_bot);
70
118
  }
71
119
  // コマンドファイルの取得が出来た時の処理
72
120
  const list_cmd_func_then = () => {
@@ -129,6 +177,8 @@ const list_cmd_func_then = () => {
129
177
  if (next_elem) next_elem.after(elem);
130
178
  else row_content.append(elem);
131
179
  input_elem = elem.find('.row_content_template_input');
180
+ if(row.type=='date') input_elem.attr('type', 'date');
181
+ else if(row.type=='datetime') input_elem.attr('type', 'datetime-local');
132
182
  input_elem.removeClass('row_content_template_input');
133
183
  input_elem.val(row.default);
134
184
  }
@@ -218,9 +268,7 @@ const list_cmd_func_then = () => {
218
268
  // マルチの場合は追加ボタンを追加
219
269
  if(row.multi){
220
270
  const btn_a = $('<button class="btn btn-secondary add_buton" type="button"></button>');
221
- btn_a.append('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16">'
222
- +'<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>'
223
- +'</svg>');
271
+ btn_a.append('<svg class="bi bi-plus" width="16" height="16" fill="currentColor"><use href="#btn_plus"></use></svg>');
224
272
  input_elem.parent().append(btn_a);
225
273
  let mk_func = (row, next_elem) => {
226
274
  // row, next_elemの値を残すためにクロージャーにする
@@ -239,10 +287,8 @@ const list_cmd_func_then = () => {
239
287
  return () => del_elem.remove();
240
288
  }
241
289
  const btn_t = $('<button class="btn btn-secondary" type="button"></button>');
242
- btn_t.append('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">'
243
- +'<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>'
244
- +'<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>'
245
- +'</svg>');
290
+ btn_trash
291
+ btn_t.append('<svg class="bi bi-trash" width="16" height="16" fill="currentColor"><use href="#btn_trash"></use></svg>');
246
292
  input_elem.parent().append(btn_t);
247
293
  btn_t.click(mk_func(input_elem.parent().parent(), row));
248
294
  }
@@ -525,7 +571,7 @@ const get_param = (modal_elem) => {
525
571
  $(elem).addClass('is-valid');
526
572
  }
527
573
  } else if (data_type=='bool') {
528
- if(data_val!='true' && data_val!='false') $(elem).addClass('is-invalid');
574
+ if(data_val!='true' && data_val!='false' && !$(elem).prop('disabled')) $(elem).addClass('is-invalid');
529
575
  else {
530
576
  data_val = data_val=='true';
531
577
  $(elem).removeClass('is-invalid');
@@ -45,7 +45,8 @@ list_pipe_func_then = () => {
45
45
  const option = $('<option></option>');
46
46
  pipe_cmd_select.append(option);
47
47
  option.attr('value', cmd['title']);
48
- option.text(`${cmd['title']}(mode=${cmd['mode']}, cmd=${cmd['cmd']})`);
48
+ const tag = cmd['tag'] ? `, tag=${cmd['tag']}` : '';
49
+ option.text(`${cmd['title']}(mode=${cmd['mode']}, cmd=${cmd['cmd']}${tag})`);
49
50
  });
50
51
  cmd_select_template.find('.add_buton').click((e) => {
51
52
  cmd_select_template_func($(e.currentTarget), py_list_cmd);
@@ -1,6 +1,6 @@
1
1
  $(() => {
2
- // ダークモード対応
3
- cmdbox.change_dark_mode(window.matchMedia('(prefers-color-scheme: dark)').matches);
2
+ // カラーモード対応
3
+ cmdbox.change_color_mode();
4
4
  // コマンド一覧の取得と表示
5
5
  list_cmd_func().then(list_cmd_func_then);
6
6
  // コマンド一覧の検索
@@ -1,6 +1,6 @@
1
1
  $(() => {
2
- // ダークモード対応
3
- cmdbox.change_dark_mode(window.matchMedia('(prefers-color-scheme: dark)').matches);
2
+ // カラーモード対応
3
+ cmdbox.change_color_mode();
4
4
  // アイコンを表示
5
5
  cmdbox.set_logoicon('.navbar-brand');
6
6
  // copyright表示
@@ -1,6 +1,6 @@
1
1
  $(() => {
2
- // ダークモード対応
3
- cmdbox.change_dark_mode(window.matchMedia('(prefers-color-scheme: dark)').matches);
2
+ // カラーモード対応
3
+ cmdbox.change_color_mode();
4
4
 
5
5
  $('.theme-item').off('click').on('click', (event) => {
6
6
  $('.theme-item').removeClass('active');
@@ -552,9 +552,8 @@ users.passsetting_list = async () => {
552
552
  mk_card(passsetting_elem, 'Account Lockout', passsetting_root_data['lockout']);
553
553
  };
554
554
  $(() => {
555
- // ダークモード対応
556
- cmdbox.change_dark_mode(window.matchMedia('(prefers-color-scheme: dark)').matches);
557
-
555
+ // カラーモード対応
556
+ cmdbox.change_color_mode();
558
557
  // アイコンを表示
559
558
  cmdbox.set_logoicon('.navbar-brand');
560
559
  // copyright表示
@@ -24,7 +24,7 @@ const render_result_func = (target_elem, result, res_size) => {
24
24
  if (!result || Array.isArray(result) && result.length<=0) return;
25
25
  const mk_table_func = () => {
26
26
  const table = $('<table class="table table-bordered table-hover table-sm"></table>');
27
- const table_head = $('<thead class="table-dark bg-dark"></thead>');
27
+ const table_head = $('<thead></thead>');
28
28
  const table_body = $('<tbody></tbody>');
29
29
  table.append(table_head);
30
30
  table.append(table_body);
@@ -1,6 +1,6 @@
1
1
  $(() => {
2
- // ダークモード対応
3
- cmdbox.change_dark_mode(window.matchMedia('(prefers-color-scheme: dark)').matches);
2
+ // カラーモード対応
3
+ cmdbox.change_color_mode();
4
4
  // スプリッター初期化
5
5
  $('.split-pane').splitPane();
6
6
  // アイコンを表示
cmdbox/web/filer.html CHANGED
@@ -29,8 +29,21 @@
29
29
  <a class="nav-link dropdown-toggle" href="#" id="viewMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
30
30
  View
31
31
  </a>
32
- <ul class="dropdown-menu">
33
- <li><a class="dropdown-item" href="#" onclick="cmdbox.change_dark_mode();">Change Dark Mode</a></li>
32
+ <ul class="dropdown-menu viewmenu">
33
+ <li class="nav-item dropdown">
34
+ <span class="dropdown-item">
35
+ Change Dark Mode
36
+ <select class="d-inline-block change_color_mode" onchange="cmdbox.change_color_mode($(this).val());">
37
+ <option value="dark" selected>Dark</option>
38
+ <option value="midnight">midnight</option>
39
+ <option value="deepsea">deepsea</option>
40
+ <option value="verdant">verdant</option>
41
+ <option value="bumblebee">bumblebee</option>
42
+ <option value="crimson">crimson</option>
43
+ <option value="light">light</option>
44
+ </select>
45
+ </span>
46
+ </li>
34
47
  </ul>
35
48
  </li>
36
49
  <li class="nav-item dropdown">
@@ -201,6 +214,7 @@
201
214
  });
202
215
  </script>
203
216
  <link rel="stylesheet" href="assets/bootstrap/bootstrap.min.5.3.0.css">
217
+ <link rel="stylesheet" href="assets/cmdbox/color_mode.css">
204
218
  <link rel="stylesheet" href="assets/lightbox2/css/lightbox.min.css">
205
219
  <link rel="stylesheet" href="assets/tree-menu/css/tree-menu.css">
206
220
  <link rel="stylesheet" href="assets/split-pane/split-pane.css">
cmdbox/web/gui.html CHANGED
@@ -51,6 +51,10 @@
51
51
  <symbol id="svg_magic_btn" viewBox="0 0 16 16">
52
52
  <path d="M9.5 2.672a.5.5 0 1 0 1 0V.843a.5.5 0 0 0-1 0zm4.5.035A.5.5 0 0 0 13.293 2L12 3.293a.5.5 0 1 0 .707.707zM7.293 4A.5.5 0 1 0 8 3.293L6.707 2A.5.5 0 0 0 6 2.707zm-.621 2.5a.5.5 0 1 0 0-1H4.843a.5.5 0 1 0 0 1zm8.485 0a.5.5 0 1 0 0-1h-1.829a.5.5 0 0 0 0 1zM13.293 10A.5.5 0 1 0 14 9.293L12.707 8a.5.5 0 1 0-.707.707zM9.5 11.157a.5.5 0 0 0 1 0V9.328a.5.5 0 0 0-1 0zm1.854-5.097a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L8.646 5.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0l1.293-1.293Zm-3 3a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L.646 13.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0z"/>
53
53
  </symbol>
54
+ <symbol id="svg_tag" viewBox="0 0 16 16">
55
+ <path d="M6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m-1 0a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/>
56
+ <path d="M2 1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 1 6.586V2a1 1 0 0 1 1-1m0 5.586 7 7L13.586 9l-7-7H2z"/>
57
+ </symbol>
54
58
  </svg>
55
59
  <!-- ナビゲーションバー -->
56
60
  <nav class="navbar navbar-expand-sm fixed-top p-2">
@@ -81,7 +85,20 @@
81
85
  View
82
86
  </a>
83
87
  <ul class="dropdown-menu viewmenu">
84
- <li><a class="dropdown-item" href="#" onclick="cmdbox.change_dark_mode();">Change Dark Mode</a></li>
88
+ <li class="nav-item dropdown">
89
+ <span class="dropdown-item">
90
+ Change Dark Mode
91
+ <select class="d-inline-block change_color_mode" onchange="cmdbox.change_color_mode($(this).val());">
92
+ <option value="dark" selected>Dark</option>
93
+ <option value="midnight">midnight</option>
94
+ <option value="deepsea">deepsea</option>
95
+ <option value="verdant">verdant</option>
96
+ <option value="bumblebee">bumblebee</option>
97
+ <option value="crimson">crimson</option>
98
+ <option value="light">light</option>
99
+ </select>
100
+ </span>
101
+ </li>
85
102
  <li><a class="dropdown-item" href="#" onclick="$(`#console_modal`).modal(`show`);">Console log</a></li>
86
103
  </ul>
87
104
  </li>
@@ -133,7 +150,8 @@
133
150
  <div class="d-flex">
134
151
  <h5 class="cmd_title card-title d-inline-block">Card title</h5>
135
152
  </div>
136
- <h6 class="card-subtitle mb-2 text-muted">mode:<span class="cmd_mode"></span>, cmd:<span class="cmd_cmd"></span></h6>
153
+ <h6 class="card-subtitle mb-2">mode:<span class="cmd_mode"></span>, cmd:<span class="cmd_cmd"></span></h6>
154
+ <h6 class="card-subtitle text-end"><span class="cmd_tags text-secondary"></span></h6>
137
155
  </div>
138
156
  </div>
139
157
  </div>
@@ -490,6 +508,7 @@
490
508
  });
491
509
  </script>
492
510
  <link rel="stylesheet" href="assets/bootstrap/bootstrap.min.5.3.0.css">
511
+ <link rel="stylesheet" href="assets/cmdbox/color_mode.css">
493
512
  <link rel="stylesheet" href="assets/lightbox2/css/lightbox.min.css">
494
513
  <link rel="stylesheet" href="assets/tree-menu/css/tree-menu.css">
495
514
  <script type="text/javascript" src="assets/bootstrap/bootstrap.bundle.min.5.3.0.js"></script>
cmdbox/web/result.html CHANGED
@@ -66,7 +66,20 @@
66
66
  View
67
67
  </a>
68
68
  <ul class="dropdown-menu viewmenu">
69
- <li><a class="dropdown-item" href="#" onclick="cmdbox.change_dark_mode();">Change Dark Mode</a></li>
69
+ <li class="nav-item dropdown">
70
+ <span class="dropdown-item">
71
+ Change Dark Mode
72
+ <select class="d-inline-block change_color_mode" onchange="cmdbox.change_color_mode($(this).val());">
73
+ <option value="dark" selected>Dark</option>
74
+ <option value="midnight">midnight</option>
75
+ <option value="deepsea">deepsea</option>
76
+ <option value="verdant">verdant</option>
77
+ <option value="bumblebee">bumblebee</option>
78
+ <option value="crimson">crimson</option>
79
+ <option value="light">light</option>
80
+ </select>
81
+ </span>
82
+ </li>
70
83
  <li><a class="dropdown-item" href="#" onclick="$(`#console_modal`).modal(`show`);">Console log</a></li>
71
84
  </ul>
72
85
  </li>
@@ -183,6 +196,7 @@
183
196
  });
184
197
  </script>
185
198
  <link rel="stylesheet" href="assets/bootstrap/bootstrap.min.5.3.0.css">
199
+ <link rel="stylesheet" href="assets/cmdbox/color_mode.css">
186
200
  <link rel="stylesheet" href="assets/lightbox2/css/lightbox.min.css">
187
201
  <script type="text/javascript" src="assets/bootstrap/bootstrap.bundle.min.5.3.0.js"></script>
188
202
  <script type="text/javascript" src="assets/jquery/jquery.min.3.2.0.js"></script>
cmdbox/web/signin.html CHANGED
@@ -17,13 +17,6 @@
17
17
  <symbol id="circle-half" viewBox="0 0 16 16">
18
18
  <path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"></path>
19
19
  </symbol>
20
- <symbol id="moon-stars-fill" viewBox="0 0 16 16">
21
- <path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"></path>
22
- <path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z"></path>
23
- </symbol>
24
- <symbol id="sun-fill" viewBox="0 0 16 16">
25
- <path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"></path>
26
- </symbol>
27
20
  <symbol id="google" viewBox="0 0 16 16">
28
21
  <path d="M15.545 6.558a9.4 9.4 0 0 1 .139 1.626c0 2.434-.87 4.492-2.384 5.885h.002C11.978 15.292 10.158 16 8 16A8 8 0 1 1 8 0a7.7 7.7 0 0 1 5.352 2.082l-2.284 2.284A4.35 4.35 0 0 0 8 3.166c-2.087 0-3.86 1.408-4.492 3.304a4.8 4.8 0 0 0 0 3.063h.003c.635 1.893 2.405 3.301 4.492 3.301 1.078 0 2.004-.276 2.722-.764h-.003a3.7 3.7 0 0 0 1.599-2.431H8v-3.08z"/>
29
22
  </symbol>
@@ -50,22 +43,49 @@
50
43
  </button>
51
44
  <ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="bd-theme-text" style="">
52
45
  <li>
53
- <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="light" aria-pressed="false">
54
- <svg class="bi me-2 opacity-50 theme-icon" width="1em" height="1em"><use href="#sun-fill"></use></svg>
55
- Light
46
+ <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="dark" aria-pressed="false">
47
+ Dark
56
48
  <svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
57
49
  </button>
58
50
  </li>
59
51
  <li>
60
- <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="dark" aria-pressed="false">
61
- <svg class="bi me-2 opacity-50 theme-icon" width="1em" height="1em"><use href="#moon-stars-fill"></use></svg>
62
- Dark
52
+ <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="midnight" aria-pressed="false">
53
+ Midnight
54
+ <svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
55
+ </button>
56
+ </li>
57
+ <li>
58
+ <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="deepsea" aria-pressed="false">
59
+ Deepsea
60
+ <svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
61
+ </button>
62
+ </li>
63
+ <li>
64
+ <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="verdant" aria-pressed="false">
65
+ Verdant
66
+ <svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
67
+ </button>
68
+ </li>
69
+ <li>
70
+ <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="bumblebee" aria-pressed="false">
71
+ Bumblebee
72
+ <svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
73
+ </button>
74
+ </li>
75
+ <li>
76
+ <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="crimson" aria-pressed="false">
77
+ Crimson
78
+ <svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
79
+ </button>
80
+ </li>
81
+ <li>
82
+ <button type="button" class="dropdown-item d-flex align-items-center theme-item" data-bs-theme-value="light" aria-pressed="false">
83
+ Light
63
84
  <svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
64
85
  </button>
65
86
  </li>
66
87
  <li>
67
88
  <button type="button" class="dropdown-item d-flex align-items-center theme-item active" data-bs-theme-value="auto" aria-pressed="true">
68
- <svg class="bi me-2 opacity-50 theme-icon" width="1em" height="1em"><use href="#circle-half"></use></svg>
69
89
  Auto
70
90
  <svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
71
91
  </button>
@@ -124,6 +144,7 @@
124
144
  });
125
145
  </script>
126
146
  <link rel="stylesheet" href="../assets/bootstrap/bootstrap.min.5.3.0.css">
147
+ <link rel="stylesheet" href="../assets/cmdbox/color_mode.css">
127
148
  <script type="text/javascript" src="../assets/bootstrap/bootstrap.bundle.min.5.3.0.js"></script>
128
149
  <script type="text/javascript" src="../assets/jquery/jquery.min.3.2.0.js"></script>
129
150
  <script type="text/javascript" src="../assets/cmdbox/common.js"></script>
cmdbox/web/users.html CHANGED
@@ -65,7 +65,20 @@
65
65
  View
66
66
  </a>
67
67
  <ul class="dropdown-menu viewmenu">
68
- <li><a class="dropdown-item" href="#" onclick="cmdbox.change_dark_mode();">Change Dark Mode</a></li>
68
+ <li class="nav-item dropdown">
69
+ <span class="dropdown-item">
70
+ Change Dark Mode
71
+ <select class="d-inline-block change_color_mode" onchange="cmdbox.change_color_mode($(this).val());">
72
+ <option value="dark" selected>Dark</option>
73
+ <option value="midnight">midnight</option>
74
+ <option value="deepsea">deepsea</option>
75
+ <option value="verdant">verdant</option>
76
+ <option value="">bumblebee</option>
77
+ <option value="crimson">crimson</option>
78
+ <option value="light">light</option>
79
+ </select>
80
+ </span>
81
+ </li>
69
82
  <li><a class="dropdown-item" href="#" onclick="$(`#console_modal`).modal(`show`);">Console log</a></li>
70
83
  </ul>
71
84
  </li>
@@ -261,6 +274,7 @@
261
274
  });
262
275
  </script>
263
276
  <link rel="stylesheet" href="assets/bootstrap/bootstrap.min.5.3.0.css">
277
+ <link rel="stylesheet" href="assets/cmdbox/color_mode.css">
264
278
  <link rel="stylesheet" href="assets/lightbox2/css/lightbox.min.css">
265
279
  <link rel="stylesheet" href="assets/tree-menu/css/tree-menu.css">
266
280
  <script type="text/javascript" src="assets/bootstrap/bootstrap.bundle.min.5.3.0.js"></script>
@@ -1,16 +1,15 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cmdbox
3
- Version: 0.5.1.1
3
+ Version: 0.5.2
4
4
  Summary: cmdbox: It is a command line application with a plugin mechanism.
5
5
  Home-page: https://github.com/hamacom2004jp/cmdbox
6
+ Download-URL: https://github.com/hamacom2004jp/cmdbox
6
7
  Author: hamacom2004jp
7
8
  Author-email: hamacom2004jp@gmail.com
8
9
  Maintainer: hamacom2004jp
9
10
  Maintainer-email: hamacom2004jp@gmail.com
10
11
  License: MIT
11
- Download-URL: https://github.com/hamacom2004jp/cmdbox
12
12
  Keywords: cli restapi redis fastapi
13
- Platform: UNKNOWN
14
13
  Classifier: Development Status :: 4 - Beta
15
14
  Classifier: Intended Audience :: Developers
16
15
  Classifier: Intended Audience :: Information Technology
@@ -21,6 +20,7 @@ Classifier: Programming Language :: Python
21
20
  Classifier: Topic :: Utilities
22
21
  Requires-Python: >=3.8
23
22
  Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
24
  Requires-Dist: argcomplete
25
25
  Requires-Dist: cryptography
26
26
  Requires-Dist: fastapi
@@ -30,6 +30,7 @@ Requires-Dist: itsdangerous
30
30
  Requires-Dist: numpy
31
31
  Requires-Dist: Pillow
32
32
  Requires-Dist: plyer
33
+ Requires-Dist: psycopg[binary]
33
34
  Requires-Dist: pystray
34
35
  Requires-Dist: python-multipart
35
36
  Requires-Dist: pycryptodome
@@ -286,6 +287,27 @@ aliases: # Specify the alias for the specified co
286
287
  # e.g. /{1}_exec
287
288
  move: # Specify whether to move the regular expression group of the source to the target.
288
289
  # e.g. true
290
+ audit:
291
+ enabled: true # Specify whether to enable the audit function.
292
+ feature:
293
+ mode: audit # Specify the mode of the feature to be audited.
294
+ cmd: write # Specify the command to be audited.
295
+ options: # Specify the options for the audit function.
296
+ host: localhost # Specify the service host of the audit Redis server.
297
+ port: 6379 # Specify the service port of the audit Redis server.
298
+ password: password # Specify the access password of the audit Redis server.
299
+ svname: server # Specify the audit service name of the inference server.
300
+ retry_count: 3 # Specifies the number of reconnections to the audit Redis server.If less than 0 is specified, reconnection is forever.
301
+ retry_interval: 1 # Specifies the number of seconds before reconnecting to the audit Redis server.
302
+ timeout: 1 # Specify the maximum waiting time until the server responds.
303
+ pg_enabled: False # Specify True if using the postgresql database server.
304
+ pg_host: localhost # Specify the postgresql host.
305
+ pg_port: 5432 # Specify the postgresql port.
306
+ pg_user: postgres # Specify the postgresql user name.
307
+ pg_password: password # Specify the postgresql password.
308
+ pg_dbname: audit # Specify the postgresql database name.
309
+ retention_period_days: 365 # Specify the number of days to retain audit logs.
310
+
289
311
  ```
290
312
 
291
313
  - The following files should also be known when using commands on the web screen or RESTAPI.
@@ -422,5 +444,3 @@ oauth2: # OAuth2 settings.
422
444
  # Lisence
423
445
 
424
446
  This project is licensed under the MIT License, see the LICENSE file for details
425
-
426
-