dsh-manage-session 0.3.3 → 0.4.8
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/CHANGELOG.ja.md +19 -0
- package/CHANGELOG.ko.md +18 -0
- package/CHANGELOG.md +40 -0
- package/dsh.plugin.json +2 -2
- package/lib/client.js +167 -33
- package/lib/index.d.ts +123 -8
- package/lib/index.js +1147 -815
- package/package.json +125 -122
- package/src/client/card.tsx +150 -153
- package/src/client/health-panel.tsx +51 -0
- package/src/client/host-api.ts +14 -1
- package/src/client/index.ts +337 -234
- package/src/client/locales.ts +15 -0
- package/src/host/health/gates.ts +4 -1
- package/src/host/health/source-kind.ts +350 -0
- package/src/host/history/archive.ts +4 -1
- package/src/host/history/purge.ts +51 -4
- package/src/index.ts +56 -48
package/package.json
CHANGED
|
@@ -1,122 +1,125 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-manage-session",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"publishConfig": {
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"@deepseek-ai/dsh-client-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"lib/
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"README.md",
|
|
66
|
-
"README.
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"INSTALL.md",
|
|
70
|
-
"INSTALL.
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"CHANGELOG.md",
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"@deepseek-ai/
|
|
85
|
-
"@deepseek-ai/dsh-client-
|
|
86
|
-
"@deepseek-ai/dsh-client-ui-
|
|
87
|
-
"@deepseek-ai/
|
|
88
|
-
"
|
|
89
|
-
"@deepseek-ai/
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
"@deepseek-ai/
|
|
110
|
-
"@
|
|
111
|
-
"@
|
|
112
|
-
"@types/
|
|
113
|
-
"
|
|
114
|
-
"react": "^18.
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
|
|
122
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-manage-session",
|
|
3
|
+
"version": "0.4.8",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"tag": "dsh-0.1.7"
|
|
6
|
+
},
|
|
7
|
+
"description": "DSH Web 插件(DSH 0.1.5 专线):会话管家 —— 会话历史文件(归档浏览与清理)与会话健康检查(体检 → 处方 → 出院),不碰会话日志、只做可逆处置",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"deepseek-harness",
|
|
10
|
+
"dsh",
|
|
11
|
+
"dsh-plugin",
|
|
12
|
+
"session",
|
|
13
|
+
"archive",
|
|
14
|
+
"health",
|
|
15
|
+
"doctor"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/drscrewdriver/dsh-manage-session.git"
|
|
20
|
+
},
|
|
21
|
+
"type": "module",
|
|
22
|
+
"main": "lib/index.js",
|
|
23
|
+
"types": "lib/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./lib/index.d.ts",
|
|
27
|
+
"default": "./lib/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./client": {
|
|
30
|
+
"default": "./lib/client.js"
|
|
31
|
+
},
|
|
32
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"dsh": {
|
|
36
|
+
"bundle": {
|
|
37
|
+
"patch": "./cordis.patch.yml"
|
|
38
|
+
},
|
|
39
|
+
"client": {
|
|
40
|
+
"platform": "web",
|
|
41
|
+
"inject": [
|
|
42
|
+
"@deepseek-ai/dsh-client-locale",
|
|
43
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
44
|
+
"@deepseek-ai/dsh-client-ui-settings-general"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "node -e \"require('fs').rmSync('lib',{recursive:true,force:true})\" && tsc -b && tsdown",
|
|
50
|
+
"prepublishOnly": "npm run build",
|
|
51
|
+
"typecheck": "tsc -b --pretty false",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"release:015": "npm publish --tag dsh-0.1.5"
|
|
54
|
+
},
|
|
55
|
+
"files": [
|
|
56
|
+
"lib/index.js",
|
|
57
|
+
"lib/index.d.ts",
|
|
58
|
+
"lib/client.js",
|
|
59
|
+
"src",
|
|
60
|
+
"cordis.patch.yml",
|
|
61
|
+
"dsh.plugin.json",
|
|
62
|
+
"screenshots.json",
|
|
63
|
+
"README.md",
|
|
64
|
+
"README.en.md",
|
|
65
|
+
"README.ja.md",
|
|
66
|
+
"README.ko.md",
|
|
67
|
+
"INSTALL.md",
|
|
68
|
+
"INSTALL.zh.md",
|
|
69
|
+
"INSTALL.ja.md",
|
|
70
|
+
"INSTALL.ko.md",
|
|
71
|
+
"CHANGELOG.md",
|
|
72
|
+
"CHANGELOG.ja.md",
|
|
73
|
+
"CHANGELOG.ko.md",
|
|
74
|
+
"LICENSE"
|
|
75
|
+
],
|
|
76
|
+
"engines": {
|
|
77
|
+
"node": ">=20",
|
|
78
|
+
"dsh": ">=0.1.7-rc.1 <0.1.8-0"
|
|
79
|
+
},
|
|
80
|
+
"license": "MIT",
|
|
81
|
+
"peerDependencies": {
|
|
82
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
83
|
+
"@deepseek-ai/dsh-client-locale": ">=0.1.7-rc.1 <0.1.8-0",
|
|
84
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.1 <0.1.8-0",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-settings-general": ">=0.1.7-rc.1 <0.1.8-0",
|
|
86
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-rc.1 <0.1.8-0",
|
|
87
|
+
"@deepseek-ai/schemastery": "^3.18.4",
|
|
88
|
+
"react": "^18.2.0",
|
|
89
|
+
"@deepseek-ai/dsh-session": ">=0.1.7-rc.1 <0.1.8-0"
|
|
90
|
+
},
|
|
91
|
+
"peerDependenciesMeta": {
|
|
92
|
+
"@deepseek-ai/dsh-client-locale": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"@deepseek-ai/dsh-client-ui-settings": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"@deepseek-ai/dsh-client-ui-settings-general": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"@deepseek-ai/dsh-client-ui-slots": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
104
|
+
"@deepseek-ai/dsh-session": {
|
|
105
|
+
"optional": true
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"devDependencies": {
|
|
109
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
110
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.7-rc.1",
|
|
111
|
+
"@deepseek-ai/schemastery": "^3.18.4",
|
|
112
|
+
"@types/node": "^24.0.0",
|
|
113
|
+
"@types/react": "~18.3.1",
|
|
114
|
+
"@types/react-dom": "^18.3.7",
|
|
115
|
+
"cordis": "^4.0.0-rc.7",
|
|
116
|
+
"react": "^18.2.0",
|
|
117
|
+
"react-dom": "^18.2.0",
|
|
118
|
+
"tsdown": "^0.22.2",
|
|
119
|
+
"tsx": "^4.23.12",
|
|
120
|
+
"typescript": "^5.6.0",
|
|
121
|
+
"vite-tsconfig-paths": "^6.1.1",
|
|
122
|
+
"vitest": "^4.1.1",
|
|
123
|
+
"@deepseek-ai/dsh-session": "^0.1.7-rc.1"
|
|
124
|
+
}
|
|
125
|
+
}
|
package/src/client/card.tsx
CHANGED
|
@@ -1,153 +1,150 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 设置卡(插件配置行):一个可折叠抽屉 —— 会话历史文件 / 健康检查。
|
|
3
|
-
*
|
|
4
|
-
* **chrome
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
'
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
'
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
open && createElement('div', { key: 'body', className: 'dss_setBody' }, rows),
|
|
152
|
-
])
|
|
153
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 设置卡(插件配置行):一个可折叠抽屉 —— 会话历史文件 / 健康检查。
|
|
3
|
+
*
|
|
4
|
+
* **chrome 必须自己渲染**:宿主不为贡献卡提供任何外壳,标题、说明、
|
|
5
|
+
* 展开/收起全归插件自己所有。早期版本只渲染裸行,与同分区其它插件
|
|
6
|
+
* 的抽屉形态不一致,还让 `card.title` / `card.desc` 成为死文案。
|
|
7
|
+
*
|
|
8
|
+
* 读写走 configForms(`configForms.get(STEWARD_ENTRY_ID)`,以本插件 entry 为键;
|
|
9
|
+
* 旧宿主回退 settingsScope 绑定)的显式 `set`。0.1.7 起本卡挂在插件族共用
|
|
10
|
+
* 设置节(`dsh-family.tab`,dsh-thinking-levels 顶级「起子插件设置」节声明)里,
|
|
11
|
+
* 与同节其它抽屉一样默认展开。
|
|
12
|
+
*/
|
|
13
|
+
import { createElement, useState, useSyncExternalStore, type JSX } from 'react'
|
|
14
|
+
import { DEFAULT_CONFIG, type StewardConfig } from '../config.ts'
|
|
15
|
+
import { translate, type LocaleKey } from './locales.ts'
|
|
16
|
+
|
|
17
|
+
/** 卡片字典面。 */
|
|
18
|
+
export type CardTranslate = (key: LocaleKey, params?: Record<string, unknown>) => string
|
|
19
|
+
|
|
20
|
+
/** 设置 scope 面(结构化镜像,与 toggle 的 SwitchCardScope 同形状)。 */
|
|
21
|
+
export interface StewardCardScope {
|
|
22
|
+
getSnapshot(): {
|
|
23
|
+
status: 'ready' | 'loading' | 'unavailable'
|
|
24
|
+
value: StewardConfig | undefined
|
|
25
|
+
revision?: number
|
|
26
|
+
writable: boolean
|
|
27
|
+
}
|
|
28
|
+
subscribe(listener: () => void): () => void
|
|
29
|
+
set(field: string, value: unknown): Promise<void>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** 卡片入参。 */
|
|
33
|
+
export interface StewardCardProps {
|
|
34
|
+
t?: CardTranslate
|
|
35
|
+
scope: StewardCardScope
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 一行设置项。 */
|
|
39
|
+
function Row(props: { title: string; desc?: string; control: JSX.Element }): JSX.Element {
|
|
40
|
+
return createElement('div', { className: 'dss_setRow' }, [
|
|
41
|
+
createElement('div', { key: 'text', className: 'dss_setText' }, [
|
|
42
|
+
createElement('span', { key: 't', className: 'dss_setTitle' }, props.title),
|
|
43
|
+
props.desc !== undefined && createElement('span', { key: 'd', className: 'dss_setDesc' }, props.desc),
|
|
44
|
+
]),
|
|
45
|
+
createElement('div', { key: 'ctl' }, props.control),
|
|
46
|
+
])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** 一个布尔开关(原生 checkbox 语义,样式由本插件 CSS 提供)。 */
|
|
50
|
+
function Toggle(props: { checked: boolean; disabled?: boolean; onChange: (checked: boolean) => void }): JSX.Element {
|
|
51
|
+
return createElement('label', { className: `dss_toggle${props.checked ? ' dss_toggleOn' : ''}` }, [
|
|
52
|
+
createElement('input', {
|
|
53
|
+
key: 'i',
|
|
54
|
+
type: 'checkbox',
|
|
55
|
+
checked: props.checked,
|
|
56
|
+
disabled: props.disabled === true,
|
|
57
|
+
onChange: (event: { target: { checked: boolean } }) => { props.onChange(event.target.checked) },
|
|
58
|
+
}),
|
|
59
|
+
createElement('span', { key: 's', className: 'dss_toggleTrack' }, createElement('span', { className: 'dss_toggleKnob' })),
|
|
60
|
+
])
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** 抽屉头:标题 + 说明 + chevron,整块可点。 */
|
|
64
|
+
function Header(props: { t?: CardTranslate; open: boolean; onToggle: () => void }): JSX.Element {
|
|
65
|
+
return createElement('button', {
|
|
66
|
+
key: 'head',
|
|
67
|
+
type: 'button',
|
|
68
|
+
className: 'dss_setHead',
|
|
69
|
+
'aria-expanded': props.open,
|
|
70
|
+
onClick: props.onToggle,
|
|
71
|
+
}, [
|
|
72
|
+
createElement('span', { key: 'text', className: 'dss_setHeadText' }, [
|
|
73
|
+
createElement('span', { key: 't', className: 'dss_setCardTitle' }, translate(props.t, 'card.title')),
|
|
74
|
+
createElement('span', { key: 'd', className: 'dss_setCardDesc' }, translate(props.t, 'card.desc')),
|
|
75
|
+
]),
|
|
76
|
+
createElement('svg', {
|
|
77
|
+
key: 'chev',
|
|
78
|
+
className: 'dss_setChev',
|
|
79
|
+
width: 16,
|
|
80
|
+
height: 16,
|
|
81
|
+
viewBox: '0 0 16 16',
|
|
82
|
+
'aria-hidden': true,
|
|
83
|
+
}, createElement('path', {
|
|
84
|
+
d: 'M4 6l4 4 4-4',
|
|
85
|
+
fill: 'none',
|
|
86
|
+
stroke: 'currentColor',
|
|
87
|
+
strokeWidth: 1.5,
|
|
88
|
+
strokeLinecap: 'round',
|
|
89
|
+
strokeLinejoin: 'round',
|
|
90
|
+
})),
|
|
91
|
+
])
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** 插件设置卡主体(抽屉)。默认展开,family 设置节内直接呈现完整面板。 */
|
|
95
|
+
export function StewardSettingsCard({ t, scope }: StewardCardProps): JSX.Element {
|
|
96
|
+
const snapshot = useSyncExternalStore(
|
|
97
|
+
(listener) => scope.subscribe(listener),
|
|
98
|
+
() => scope.getSnapshot(),
|
|
99
|
+
)
|
|
100
|
+
const [open, setOpen] = useState(true)
|
|
101
|
+
const value: Partial<StewardConfig> = snapshot.value ?? {}
|
|
102
|
+
const writable = snapshot.writable
|
|
103
|
+
|
|
104
|
+
const rows: JSX.Element[] = []
|
|
105
|
+
if (snapshot.status === 'unavailable') {
|
|
106
|
+
// 拿不到设置服务:抽屉仍要在(否则这个插件在分区里彻底消失),只是里面说明原因。
|
|
107
|
+
rows.push(createElement('div', { key: 'unavailable', className: 'dss_setDesc' }, translate(t, 'card.unavailable')))
|
|
108
|
+
} else {
|
|
109
|
+
rows.push(
|
|
110
|
+
createElement(Row, {
|
|
111
|
+
key: 'enabled',
|
|
112
|
+
title: translate(t, 'card.enabled'),
|
|
113
|
+
desc: translate(t, 'card.enabled.desc'),
|
|
114
|
+
control: createElement(Toggle, {
|
|
115
|
+
checked: value.enabled ?? DEFAULT_CONFIG.enabled,
|
|
116
|
+
disabled: !writable,
|
|
117
|
+
onChange: (checked) => { void scope.set('enabled', checked) },
|
|
118
|
+
}),
|
|
119
|
+
}),
|
|
120
|
+
createElement(Row, {
|
|
121
|
+
key: 'history',
|
|
122
|
+
title: translate(t, 'card.history'),
|
|
123
|
+
desc: translate(t, 'card.history.desc'),
|
|
124
|
+
control: createElement(Toggle, {
|
|
125
|
+
checked: value.historyFiles ?? DEFAULT_CONFIG.historyFiles,
|
|
126
|
+
disabled: !writable,
|
|
127
|
+
onChange: (checked) => { void scope.set('historyFiles', checked) },
|
|
128
|
+
}),
|
|
129
|
+
}),
|
|
130
|
+
createElement(Row, {
|
|
131
|
+
key: 'health',
|
|
132
|
+
title: translate(t, 'card.health'),
|
|
133
|
+
desc: translate(t, 'card.health.desc'),
|
|
134
|
+
control: createElement(Toggle, {
|
|
135
|
+
checked: value.healthCheck ?? DEFAULT_CONFIG.healthCheck,
|
|
136
|
+
disabled: !writable,
|
|
137
|
+
onChange: (checked) => { void scope.set('healthCheck', checked) },
|
|
138
|
+
}),
|
|
139
|
+
}),
|
|
140
|
+
)
|
|
141
|
+
if (!writable) rows.push(createElement('div', { key: 'ro', className: 'dss_setDesc' }, translate(t, 'card.readonly')))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return createElement('div', {
|
|
145
|
+
className: `dss_setCard${open ? ' dss_setCardOpen' : ''}`,
|
|
146
|
+
}, [
|
|
147
|
+
createElement(Header, { key: 'head', t, open, onToggle: () => { setOpen(current => !current) } }),
|
|
148
|
+
open && createElement('div', { key: 'body', className: 'dss_setBody' }, rows),
|
|
149
|
+
])
|
|
150
|
+
}
|