dockly 3.23.0 → 3.23.2
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/package.json +1 -1
- package/src/enum.js +11 -0
- package/src/screen.js +7 -5
- package/src/widgetsTemplates/list.widget.template.js +2 -2
- package/widgets/actionsMenu.widget.js +6 -2
- package/widgets/containers/containerList.widget.js +34 -22
- package/widgets/containers/containerSortList.widget.js +103 -0
- package/widgets/images/imageList.widget.js +2 -2
- package/widgets/toolbar.widget.js +4 -0
package/package.json
CHANGED
package/src/enum.js
ADDED
package/src/screen.js
CHANGED
|
@@ -11,16 +11,17 @@ const MODES = require('../lib/modes')
|
|
|
11
11
|
// from the user (index.js)
|
|
12
12
|
const CONTAINERS_GRID_LAYOUT = {
|
|
13
13
|
'actionsMenu': [4, 4, 4, 4],
|
|
14
|
-
'
|
|
15
|
-
'actionStatus': [6, 0, 1, 10],
|
|
14
|
+
'help': [4, 4, 4, 4],
|
|
16
15
|
'containerInfo': [2, 2, 8, 8],
|
|
16
|
+
'containerSortList': [4, 5, 3, 2],
|
|
17
17
|
'containerList': [0, 0, 6, 10],
|
|
18
|
-
'
|
|
18
|
+
'actionStatus': [6, 0, 1, 10],
|
|
19
19
|
'containerStatus': [0, 10, 2, 2],
|
|
20
20
|
'containerUtilization': [2, 10, 3, 2],
|
|
21
21
|
'containerVsImages': [5, 10, 2, 2],
|
|
22
|
-
'
|
|
23
|
-
'toolbar': [11, 0, 1, 12]
|
|
22
|
+
'containerLogs': [7, 0, 4, 12],
|
|
23
|
+
'toolbar': [11, 0, 1, 12],
|
|
24
|
+
'searchInput': [11, 0, 1, 12]
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
const SERVICES_GRID_LAYOUT = {
|
|
@@ -208,6 +209,7 @@ class screen {
|
|
|
208
209
|
this.clearWidgets()
|
|
209
210
|
this.toggleMode()
|
|
210
211
|
this.screen.destroy()
|
|
212
|
+
// TODO refactor this so that all of the assets aren't reloaded on screen switch
|
|
211
213
|
this.init()
|
|
212
214
|
})
|
|
213
215
|
}
|
|
@@ -45,9 +45,9 @@ class myWidget extends baseWidget(EventEmitter) {
|
|
|
45
45
|
this.toggleWidgetListColor = !this.toggleWidgetListColor
|
|
46
46
|
|
|
47
47
|
if (this.toggleWidgetListColor) {
|
|
48
|
-
str = chalk.cyan(chunk.toString('
|
|
48
|
+
str = chalk.cyan(chunk.toString('utf8').trim())
|
|
49
49
|
} else {
|
|
50
|
-
str = chalk.green(chunk.toString('
|
|
50
|
+
str = chalk.green(chunk.toString('utf8').trim())
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
this.updateItemLogs(str)
|
|
@@ -119,7 +119,7 @@ class myWidget extends baseWidget() {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
getWidget () {
|
|
122
|
-
return this.
|
|
122
|
+
return this.blessed.list({
|
|
123
123
|
label: this.label,
|
|
124
124
|
scrollable: true,
|
|
125
125
|
alwaysScroll: true,
|
|
@@ -137,7 +137,11 @@ class myWidget extends baseWidget() {
|
|
|
137
137
|
ch: '|'
|
|
138
138
|
},
|
|
139
139
|
vi: true,
|
|
140
|
-
align: 'center'
|
|
140
|
+
align: 'center',
|
|
141
|
+
left: 'center',
|
|
142
|
+
top: 'center',
|
|
143
|
+
width: '33%',
|
|
144
|
+
height: '33%'
|
|
141
145
|
})
|
|
142
146
|
}
|
|
143
147
|
|
|
@@ -5,11 +5,14 @@ const figures = require('figures')
|
|
|
5
5
|
|
|
6
6
|
const ListWidget = require('../../src/widgetsTemplates/list.widget.template')
|
|
7
7
|
|
|
8
|
+
const ContainerState = require('../../src/enum.js').ContainerState
|
|
9
|
+
|
|
8
10
|
class myWidget extends ListWidget {
|
|
9
11
|
constructor ({ blessed = {}, contrib = {}, screen = {}, grid = {} }) {
|
|
10
12
|
super({ blessed, contrib, screen, grid })
|
|
11
13
|
this.containersList = {}
|
|
12
14
|
this.containersListData = []
|
|
15
|
+
this.sortBy = ContainerState.running
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
getLabel () {
|
|
@@ -17,15 +20,21 @@ class myWidget extends ListWidget {
|
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
getItemLogs (containerId, cb) {
|
|
20
|
-
|
|
23
|
+
if (this.widgetsRepo.has('containerLogs')) {
|
|
24
|
+
return this.utilsRepo.get('docker').getContainerLogs(containerId, cb)
|
|
25
|
+
}
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
updateItemLogs (str) {
|
|
24
|
-
|
|
29
|
+
if (this.widgetsRepo.has('containerLogs')) {
|
|
30
|
+
return this.widgetsRepo.get('containerLogs').update(str)
|
|
31
|
+
}
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
clearItemLogs () {
|
|
28
|
-
|
|
35
|
+
if (this.widgetsRepo.has('containerLogs')) {
|
|
36
|
+
return this.widgetsRepo.get('containerLogs').clear()
|
|
37
|
+
}
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
getListItems (cb) {
|
|
@@ -56,6 +65,12 @@ class myWidget extends ListWidget {
|
|
|
56
65
|
}
|
|
57
66
|
}
|
|
58
67
|
|
|
68
|
+
sortContainersByState (state) {
|
|
69
|
+
this.sortBy = state
|
|
70
|
+
this.refreshList()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// TODO refactor this
|
|
59
74
|
formatList (containers) {
|
|
60
75
|
const containerList = {}
|
|
61
76
|
if (containers) {
|
|
@@ -82,12 +97,19 @@ class myWidget extends ListWidget {
|
|
|
82
97
|
let container = []
|
|
83
98
|
|
|
84
99
|
container = containerList[key]
|
|
100
|
+
const status = container[4]
|
|
85
101
|
container[4] = this.formatContainerState(container[4])
|
|
86
102
|
container[5] = this.formatContainerStatus(container[5])
|
|
103
|
+
container[7] = status
|
|
87
104
|
|
|
88
105
|
return container
|
|
89
106
|
})
|
|
90
107
|
|
|
108
|
+
list.sort(this.sortContainers(this.sortBy))
|
|
109
|
+
list = list.map(a => {
|
|
110
|
+
a.pop()
|
|
111
|
+
return a
|
|
112
|
+
})
|
|
91
113
|
list.unshift(['Id', 'Name', 'Image', 'Command', 'State', 'Status', 'Ports'])
|
|
92
114
|
this.containersListData = list
|
|
93
115
|
this.containersList = containerList
|
|
@@ -141,27 +163,17 @@ class myWidget extends ListWidget {
|
|
|
141
163
|
return this.widget.getItem(this.widget.selected).getContent().toString().trim().split(' ').shift()
|
|
142
164
|
}
|
|
143
165
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
* @returns {number} for position
|
|
150
|
-
*/
|
|
151
|
-
sortContainers (a, b) {
|
|
152
|
-
if (a[4] === 'running' && b[4] !== 'running') {
|
|
153
|
-
return -1
|
|
154
|
-
}
|
|
166
|
+
sortContainers (state) {
|
|
167
|
+
return (a, b) => {
|
|
168
|
+
if (a[7] === state && b[7] !== state) {
|
|
169
|
+
return -1
|
|
170
|
+
}
|
|
155
171
|
|
|
156
|
-
|
|
157
|
-
|
|
172
|
+
if (b[7] === state && a[7] !== state) {
|
|
173
|
+
return 1
|
|
174
|
+
}
|
|
175
|
+
return 0
|
|
158
176
|
}
|
|
159
|
-
|
|
160
|
-
if (a[4] === 'exited' && b[4] !== 'exited') {
|
|
161
|
-
return 1
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return 0
|
|
165
177
|
}
|
|
166
178
|
}
|
|
167
179
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const baseWidget = require('../../src/baseWidget')
|
|
2
|
+
const { ContainerState } = require('../../src/enum')
|
|
3
|
+
|
|
4
|
+
class ContainerSortListWidget extends baseWidget() {
|
|
5
|
+
constructor ({ blessed = {}, contrib = {}, screen = {}, grid = {} }) {
|
|
6
|
+
super()
|
|
7
|
+
this.blessed = blessed
|
|
8
|
+
this.contrib = contrib
|
|
9
|
+
this.screen = screen
|
|
10
|
+
this.grid = grid
|
|
11
|
+
this.label = 'Sort By:'
|
|
12
|
+
this.isVisible = false
|
|
13
|
+
const sortedStates = Object.keys(ContainerState)
|
|
14
|
+
sortedStates.sort((a, b) => a.length - b.length)
|
|
15
|
+
this.items = sortedStates
|
|
16
|
+
.map(state =>
|
|
17
|
+
({
|
|
18
|
+
[`By ${state.charAt(0).toUpperCase()}${state.slice(1)}`]:
|
|
19
|
+
{
|
|
20
|
+
handler: () => this.sortContainerList(state)
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
).reduce((accum, obj) => ({ ...accum, ...obj }), {})
|
|
24
|
+
|
|
25
|
+
this.widget = this.getWidget()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
init () {
|
|
29
|
+
if (!this.widgetsRepo.has('toolbar')) {
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this.registerEscapeKey()
|
|
34
|
+
this.registerSortHandler()
|
|
35
|
+
this.registerToolbarKey()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
sortContainerList (state) {
|
|
39
|
+
const containerList = this.widgetsRepo.get('containerList')
|
|
40
|
+
if (!containerList) {
|
|
41
|
+
// TODO throw error!
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
containerList.sortContainersByState(state)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
registerSortHandler () {
|
|
48
|
+
this.widget.on('select', (el) => {
|
|
49
|
+
this.items[el.getText()].handler()
|
|
50
|
+
this.toggleVisibility()
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
registerToolbarKey () {
|
|
55
|
+
const toolbar = this.widgetsRepo.get('toolbar')
|
|
56
|
+
toolbar.on('key', (keyString) => {
|
|
57
|
+
if (keyString === 'o') {
|
|
58
|
+
this.toggleVisibility()
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
registerEscapeKey () {
|
|
64
|
+
this.widget.on('keypress', (ch, key) => {
|
|
65
|
+
if (key.name === 'escape' || key.name === 'return') {
|
|
66
|
+
this.toggleVisibility()
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
toggleVisibility () {
|
|
72
|
+
if (this.isVisible) {
|
|
73
|
+
this.screen.remove(this.widget)
|
|
74
|
+
} else {
|
|
75
|
+
this.screen.append(this.widget)
|
|
76
|
+
this.screen.render()
|
|
77
|
+
this.widget.focus()
|
|
78
|
+
}
|
|
79
|
+
this.isVisible = !this.isVisible
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getWidget () {
|
|
83
|
+
return this.blessed.list({
|
|
84
|
+
label: this.label,
|
|
85
|
+
keys: true,
|
|
86
|
+
align: 'center',
|
|
87
|
+
border: {
|
|
88
|
+
type: 'line'
|
|
89
|
+
},
|
|
90
|
+
left: 'center',
|
|
91
|
+
top: 'center',
|
|
92
|
+
width: '16%',
|
|
93
|
+
height: '25%',
|
|
94
|
+
style: this.getWidgetStyle(),
|
|
95
|
+
items: Object.keys(this.items)
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
renderWidget () {
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = ContainerSortListWidget
|
|
@@ -45,11 +45,11 @@ class myWidget extends ListWidget {
|
|
|
45
45
|
|
|
46
46
|
if (images) {
|
|
47
47
|
images.forEach((image) => {
|
|
48
|
-
const getTag = (tag, part) => tag ? tag[0].split(':')[part] : 'none'
|
|
48
|
+
const getTag = (tag, part) => (tag && tag.length) ? tag[0].split(':')[part] : 'none'
|
|
49
49
|
|
|
50
50
|
imageList.push([
|
|
51
51
|
image.Id.substring(7, 12),
|
|
52
|
-
image.RepoDigests ? image.RepoDigests[0].split('@')[0] : getTag(image[2], 0),
|
|
52
|
+
(image.RepoDigests && image.RepoDigests.length) ? image.RepoDigests[0].split('@')[0] : getTag(image[2], 0),
|
|
53
53
|
getTag(image.RepoTags, 1),
|
|
54
54
|
this.timeDifference(image.Created),
|
|
55
55
|
this.formatBytes(image.Size)
|