dsh-ssh-manage 0.3.2 → 0.3.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.
package/README.en.md CHANGED
@@ -96,16 +96,16 @@ Creating a host requires alias, hostname and password. The password is not writt
96
96
 
97
97
  ### From npm (recommended)
98
98
 
99
- npm package: [`dsh-ssh-manage`](https://www.npmjs.com/package/dsh-ssh-manage) (current version `0.3.2`).
99
+ npm package: [`dsh-ssh-manage`](https://www.npmjs.com/package/dsh-ssh-manage) (current version `0.3.3`).
100
100
 
101
101
  ```text
102
- plugin_manager action=install_bundle target=dsh-ssh-manage@0.3.2
102
+ plugin_manager action=install_bundle target=dsh-ssh-manage@0.3.3
103
103
  ```
104
104
 
105
105
  Or with the DSH CLI:
106
106
 
107
107
  ```bash
108
- dsh plugin add dsh-ssh-manage@0.3.2
108
+ dsh plugin add dsh-ssh-manage@0.3.3
109
109
  ```
110
110
 
111
111
  After installation, refresh the Web page; the sidebar shows an "SSH Hosts" entry with id `dsh-ssh-manage`.
package/README.md CHANGED
@@ -98,16 +98,16 @@
98
98
 
99
99
  ### 从 npm 安装(推荐)
100
100
 
101
- npm 包:[`dsh-ssh-manage`](https://www.npmjs.com/package/dsh-ssh-manage)(当前版本 `0.3.2`)。
101
+ npm 包:[`dsh-ssh-manage`](https://www.npmjs.com/package/dsh-ssh-manage)(当前版本 `0.3.3`)。
102
102
 
103
103
  ```text
104
- plugin_manager action=install_bundle target=dsh-ssh-manage@0.3.2
104
+ plugin_manager action=install_bundle target=dsh-ssh-manage@0.3.3
105
105
  ```
106
106
 
107
107
  或使用 DSH CLI:
108
108
 
109
109
  ```bash
110
- dsh plugin add dsh-ssh-manage@0.3.2
110
+ dsh plugin add dsh-ssh-manage@0.3.3
111
111
  ```
112
112
 
113
113
  安装后刷新 Web 页面,左侧栏会出现「SSH 主机」入口,入口 id 为 `dsh-ssh-manage`。
package/client.js CHANGED
@@ -134,6 +134,9 @@ window.__ModuleLoader__.load({
134
134
  'editor.port': ['端口', 'Port'],
135
135
  'editor.group': ['分组', 'Group'],
136
136
  'editor.groupPlaceholder': ['例如 production', 'e.g. production'],
137
+ 'editor.groupChoose': ['选择已有分组', 'Choose an existing group'],
138
+ 'editor.groupNone': ['无分组', 'No group'],
139
+ 'editor.groupNoOptions': ['还没有已有分组,直接输入新名称即可。', 'No groups yet; type a new name.'],
137
140
  'editor.tags': ['标签', 'Tags'],
138
141
  'editor.tagsPlaceholder': ['web, critical(逗号分隔)', 'web, critical (comma separated)'],
139
142
  'editor.label': ['显示名称', 'Display name'],
@@ -4590,6 +4593,9 @@ window.__ModuleLoader__.load({
4590
4593
  const [password, setPassword] = React.useState('')
4591
4594
  const [passwordError, setPasswordError] = React.useState('')
4592
4595
  const [formError, setFormError] = React.useState('')
4596
+ const [groupMenuOpen, setGroupMenuOpen] = React.useState(false)
4597
+ const groupMenuRef = React.useRef(null)
4598
+ const groupOptions = (model.allGroups ?? []).filter((group) => group.key !== '').map((group) => group.key)
4593
4599
  const busy = isPending('editor')
4594
4600
  const passwordRequired = !original || original.passwordConfigured !== true
4595
4601
 
@@ -4619,6 +4625,27 @@ window.__ModuleLoader__.load({
4619
4625
  }
4620
4626
  })
4621
4627
 
4628
+ React.useEffect(() => {
4629
+ if (!groupMenuOpen) return undefined
4630
+ const close = (event) => {
4631
+ if (groupMenuRef.current && groupMenuRef.current.contains(event.target)) return
4632
+ setGroupMenuOpen(false)
4633
+ }
4634
+ const onKey = (event) => {
4635
+ if (event.key === 'Escape') {
4636
+ event.preventDefault()
4637
+ event.stopPropagation()
4638
+ setGroupMenuOpen(false)
4639
+ }
4640
+ }
4641
+ document.addEventListener('mousedown', close)
4642
+ document.addEventListener('keydown', onKey, true)
4643
+ return () => {
4644
+ document.removeEventListener('mousedown', close)
4645
+ document.removeEventListener('keydown', onKey, true)
4646
+ }
4647
+ }, [groupMenuOpen])
4648
+
4622
4649
  async function submit() {
4623
4650
  const alias = draft.host.trim()
4624
4651
  const hostname = draft.hostname.trim()
@@ -4745,11 +4772,59 @@ window.__ModuleLoader__.load({
4745
4772
  h(
4746
4773
  Field,
4747
4774
  { label: t('editor.group') },
4748
- h(TextInput, {
4749
- value: draft.group,
4750
- onChange: (value) => update('group', value),
4751
- placeholder: t('editor.groupPlaceholder'),
4752
- }),
4775
+ h(
4776
+ 'div',
4777
+ { className: 'ssh-groupCombo', ref: groupMenuRef },
4778
+ h(TextInput, {
4779
+ value: draft.group,
4780
+ onChange: (value) => update('group', value),
4781
+ placeholder: t('editor.groupPlaceholder'),
4782
+ }),
4783
+ h(
4784
+ 'button',
4785
+ {
4786
+ type: 'button',
4787
+ className: 'ssh-groupToggle',
4788
+ title: t('editor.groupChoose'),
4789
+ 'aria-label': t('editor.groupChoose'),
4790
+ 'aria-haspopup': 'listbox',
4791
+ 'aria-expanded': groupMenuOpen,
4792
+ onClick: () => setGroupMenuOpen((value) => !value),
4793
+ },
4794
+ h(IconChevronDown, { size: 13 }),
4795
+ ),
4796
+ groupMenuOpen
4797
+ ? h(
4798
+ 'div',
4799
+ { className: 'ssh-groupMenu', role: 'listbox' },
4800
+ h('button', {
4801
+ type: 'button',
4802
+ role: 'option',
4803
+ 'aria-selected': draft.group.trim() === '',
4804
+ className: cx('ssh-groupOption', draft.group.trim() === '' && 'active'),
4805
+ onClick: () => {
4806
+ update('group', '')
4807
+ setGroupMenuOpen(false)
4808
+ },
4809
+ }, t('editor.groupNone')),
4810
+ groupOptions.length === 0
4811
+ ? h('div', { className: 'ssh-groupEmpty' }, t('editor.groupNoOptions'))
4812
+ : groupOptions.map((option) =>
4813
+ h('button', {
4814
+ key: option,
4815
+ type: 'button',
4816
+ role: 'option',
4817
+ 'aria-selected': draft.group.trim() === option,
4818
+ className: cx('ssh-groupOption', draft.group.trim() === option && 'active'),
4819
+ onClick: () => {
4820
+ update('group', option)
4821
+ setGroupMenuOpen(false)
4822
+ },
4823
+ }, option),
4824
+ ),
4825
+ )
4826
+ : null,
4827
+ ),
4753
4828
  ),
4754
4829
  h(
4755
4830
  Field,
@@ -5298,7 +5373,7 @@ body.ssh-col-resizing,body.ssh-col-resizing *{cursor:col-resize!important;user-s
5298
5373
  .ssh-mainTop{flex:0 0 auto;display:flex;align-items:center;flex-wrap:wrap;gap:8px;row-gap:6px;padding:10px 14px;border-bottom:.5px solid var(--ssh-border);min-height:56px}
5299
5374
  .ssh-context{display:flex;align-items:baseline;gap:6px;min-width:0;max-width:180px;flex:0 0 auto}
5300
5375
  .ssh-contextName{font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
5301
- .ssh-contextCount{font-size:11px;color:var(--ssh-text-3);font-variant-numeric:tabular-nums}
5376
+ .ssh-contextCount{font-size:11px;color:var(--ssh-text-2);font-variant-numeric:tabular-nums}
5302
5377
  .ssh-search{position:relative;display:flex;align-items:center;flex:0 1 300px;min-width:120px}
5303
5378
  .ssh-search > svg{position:absolute;left:10px;color:var(--ssh-dim);pointer-events:none;z-index:1}
5304
5379
  .ssh-search .ssh-input{height:30px;padding-left:31px;border-radius:999px;background:var(--ssh-layer-1);font-size:12px}
@@ -5312,7 +5387,7 @@ body.ssh-col-resizing,body.ssh-col-resizing *{cursor:col-resize!important;user-s
5312
5387
  .ssh-table{flex:1;min-height:0;display:flex;flex-direction:column;min-width:0}
5313
5388
  .ssh-tableScroll{flex:1;min-height:0;overflow:auto;display:flex;flex-direction:column}
5314
5389
  .ssh-grid{display:grid;align-items:center;column-gap:8px;padding:0 12px;width:100%;min-width:0}
5315
- .ssh-head{flex:0 0 auto;height:38px;border-bottom:.5px solid var(--ssh-border);color:var(--ssh-text-3);font-size:11px;font-weight:500;background:var(--ssh-bg);position:sticky;top:0;z-index:3;min-width:640px}
5390
+ .ssh-head{flex:0 0 auto;height:38px;border-bottom:.5px solid var(--ssh-border);color:var(--ssh-text-2);font-size:11px;font-weight:500;background:var(--ssh-bg);position:sticky;top:0;z-index:3;min-width:640px}
5316
5391
  .ssh-cell{min-width:0;display:flex;align-items:center;gap:6px;overflow:hidden}
5317
5392
  .ssh-headBtn{appearance:none;display:inline-flex;align-items:center;gap:4px;padding:0;border:0;background:transparent;color:inherit;font:inherit;font-size:11px;font-weight:500;cursor:pointer;white-space:nowrap;min-width:0}
5318
5393
  .ssh-headBtn:hover{color:var(--ssh-text)}
@@ -5330,32 +5405,32 @@ body.ssh-col-resizing,body.ssh-col-resizing *{cursor:col-resize!important;user-s
5330
5405
  .ssh-colLatency{min-width:0}
5331
5406
  .ssh-colSystem{min-width:0}
5332
5407
  .ssh-osBadge{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:8px;background:var(--ssh-layer-3);color:var(--ssh-brand)}
5333
- .ssh-osBadge.muted{color:var(--ssh-dim)}
5408
+ .ssh-osBadge.muted{color:var(--ssh-text-2)}
5334
5409
  .ssh-osName{font-size:11.5px;color:var(--ssh-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
5335
- .ssh-osName.muted{color:var(--ssh-dim)}
5410
+ .ssh-osName.muted{color:var(--ssh-text-2)}
5336
5411
  .ssh-latency{appearance:none;display:inline-flex;align-items:center;gap:5px;height:24px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--ssh-text-2);font:inherit;font-size:11.5px;white-space:nowrap;cursor:pointer}
5337
- .ssh-latency.ok{color:var(--dsw-alias-state-success-label,var(--ssh-text-2))}
5338
- .ssh-latency.muted{color:var(--ssh-dim)}
5412
+ .ssh-latency.ok{color:var(--ssh-success)}
5413
+ .ssh-latency.muted{color:var(--ssh-text-2)}
5339
5414
  .ssh-latency:hover:not(:disabled){color:var(--ssh-text)}
5340
5415
  .ssh-latency:disabled{cursor:default}
5341
5416
  .ssh-latencyDot{width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.55}
5342
5417
  .ssh-latencyIcon{display:inline-flex;color:var(--dsw-alias-state-success-label,var(--ssh-success))}
5343
5418
  .ssh-colName{flex-direction:column;align-items:flex-start;gap:0}
5344
5419
  .ssh-nameMain{display:flex;align-items:center;gap:5px;max-width:100%;font-size:12.5px;font-weight:500;color:var(--ssh-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
5345
- .ssh-nameSub{max-width:100%;font-size:10.5px;color:var(--ssh-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
5420
+ .ssh-nameSub{max-width:100%;font-size:10.5px;color:var(--ssh-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
5346
5421
  .ssh-favMark{color:var(--ssh-warn);display:inline-flex;flex:0 0 auto}
5347
5422
  .ssh-colAddress{gap:3px;min-width:0}
5348
- .ssh-address{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;color:var(--ssh-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
5423
+ .ssh-address{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;color:var(--ssh-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
5349
5424
  .ssh-inlineActions{display:inline-flex;gap:1px;flex:0 0 auto;opacity:.45;transition:opacity .12s ease}
5350
5425
  .ssh-row:hover .ssh-inlineActions{opacity:1}
5351
5426
  .ssh-miniBtn{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--ssh-text-3);cursor:pointer}
5352
5427
  .ssh-miniBtn:hover{background:var(--ssh-hover);color:var(--ssh-text)}
5353
5428
  .ssh-colInfo{gap:4px;row-gap:3px;flex-wrap:wrap;align-content:center;overflow:visible}
5354
5429
  .ssh-chip{display:inline-flex;flex:0 0 auto;align-items:center;height:21px;max-width:100%;padding:0 7px;border-radius:6px;border:.5px solid var(--ssh-border);background:var(--ssh-layer-3);font-size:10.5px;color:var(--ssh-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
5355
- .ssh-mutedText{font-size:11.5px;color:var(--ssh-dim)}
5430
+ .ssh-mutedText{font-size:11.5px;color:var(--ssh-text-2)}
5356
5431
  .ssh-colNotes{min-width:0}
5357
5432
  .ssh-noteText{font-size:11.5px;color:var(--ssh-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
5358
- .ssh-noteText.muted{color:var(--ssh-dim)}
5433
+ .ssh-noteText.muted{color:var(--ssh-text-2)}
5359
5434
  .ssh-colActions{gap:4px;justify-content:flex-start;overflow:visible}
5360
5435
  .ssh-colGear{justify-content:flex-end}
5361
5436
  .ssh-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:56px 24px;text-align:center;color:var(--ssh-text-3);font-size:12px;min-height:0}
@@ -5391,6 +5466,14 @@ body.ssh-col-resizing,body.ssh-col-resizing *{cursor:col-resize!important;user-s
5391
5466
  .ssh-input.mono,.ssh-textarea.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px}
5392
5467
  .ssh-textarea{height:auto;padding:9px 11px;line-height:1.65;resize:vertical;min-height:74px}
5393
5468
  .ssh-field{display:flex;flex-direction:column;gap:5px;min-width:0}
5469
+ .ssh-groupCombo{position:relative;display:flex;align-items:center;gap:4px}
5470
+ .ssh-groupCombo .ssh-input{flex:1;min-width:0}
5471
+ .ssh-groupToggle{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:.5px solid var(--ssh-border-strong);border-radius:var(--ssh-radius-sm);background:var(--ssh-layer-2);color:var(--ssh-text-2);cursor:pointer;flex:0 0 auto}
5472
+ .ssh-groupToggle:hover{background:var(--ssh-hover);color:var(--ssh-text)}
5473
+ .ssh-groupMenu{position:absolute;z-index:12;top:calc(100% + 5px);left:0;right:0;max-height:190px;overflow:auto;padding:4px;border:.5px solid var(--ssh-border-strong);border-radius:var(--ssh-radius-md);background:var(--ssh-layer-1);box-shadow:var(--ssh-shadow)}
5474
+ .ssh-groupOption{appearance:none;display:block;width:100%;padding:6px 8px;border:0;border-radius:6px;background:transparent;color:var(--ssh-text);font:inherit;font-size:12px;text-align:left;cursor:pointer}
5475
+ .ssh-groupOption:hover,.ssh-groupOption.active{background:var(--ssh-hover)}
5476
+ .ssh-groupEmpty{padding:6px 8px;font-size:11.5px;color:var(--ssh-text-2)}
5394
5477
  .ssh-field.wide{grid-column:1/-1}
5395
5478
  .ssh-label{font-size:11.5px;font-weight:500;color:var(--ssh-text-2)}
5396
5479
  .ssh-hint{font-size:10.5px;color:var(--ssh-text-3);line-height:1.55}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-ssh-manage",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "A DSH sidebar plugin for managing SSH host profiles with a real interactive PTY terminal.",
5
5
  "license": "MIT",
6
6
  "private": false,