dockly 3.24.3 → 3.24.5

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.md CHANGED
@@ -139,3 +139,21 @@ See [Awesome Docker list](https://github.com/veggiemonk/awesome-docker/blob/mast
139
139
 
140
140
  # Author
141
141
  Liran Tal <liran.tal@gmail.com>
142
+
143
+ <hr/>
144
+
145
+ <div align="center">
146
+ <p>
147
+ <a href="https://nodejs-security.com">
148
+ <img alt="Node.js Security" align="center" src="https://img.shields.io/badge/%F0%9F%A6%84-Learn%20Node.js%20Security%E2%86%92-gray.svg?colorA=5734F5&colorB=5734F5&style=flat" />
149
+ </a>
150
+ </p>
151
+
152
+ ![Screenshot 2024-09-12 at 20 08 07](https://github.com/user-attachments/assets/970a97fd-16bd-4b3c-b535-ae7445b52d4c)
153
+
154
+ <p>
155
+ Learn Node.js Secure Coding techniques and best practices from <a href="https://www.lirantal.com">Liran Tal</a>
156
+ </p>
157
+ </div>
158
+
159
+ <br/>
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "dockly",
3
- "version": "3.24.3",
3
+ "version": "3.24.5",
4
4
  "description": "Immersive terminal interface for managing docker containers and services",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "yarn run lint",
8
- "lint": "standard && yarn run lint:lockfile",
7
+ "test": "npm run lint",
8
+ "lint": "standard && npm run lint:lockfile",
9
9
  "lint:fix": "standard --fix",
10
- "lint:lockfile": "lockfile-lint --path yarn.lock --type yarn --validate-https --allowed-hosts npm yarn",
10
+ "lint:lockfile": "lockfile-lint --path package-lock.json --type npm --validate-https --allowed-hosts npm",
11
11
  "debug": "node --inspect=0.0.0.0:9222 ./index.js "
12
12
  },
13
13
  "files": [
@@ -76,7 +76,7 @@
76
76
  "figures": "^2.0.0",
77
77
  "glob": "^7.2.3",
78
78
  "lockfile-lint": "^3.0.9",
79
- "semver": "7.6.0"
79
+ "semver": "7.6.3"
80
80
  },
81
81
  "devDependencies": {
82
82
  "standard": "^12.0.1"
@@ -0,0 +1,43 @@
1
+ const CONTAINERS_GRID_LAYOUT = {
2
+ 'actionsMenu': [4, 4, 4, 4],
3
+ 'help': [4, 4, 4, 4],
4
+ 'containerInfo': [2, 2, 8, 8],
5
+ 'containerSortList': [4, 5, 3, 2],
6
+ 'containerList': [0, 0, 6, 10],
7
+ 'actionStatus': [6, 0, 1.5, 10],
8
+ 'containerStatus': [0, 10, 2, 2],
9
+ 'containerUtilization': [2, 10, 3, 2],
10
+ 'containerVsImages': [5, 10, 2, 2],
11
+ 'containerLogs': [7.5, 0, 4, 12],
12
+ 'toolbar': [11.5, 0, 1, 12],
13
+ 'searchInput': [11, 0, 1, 12]
14
+ }
15
+
16
+ const SERVICES_GRID_LAYOUT = {
17
+ 'actionsMenu': [4, 4, 4, 4],
18
+ 'actionStatus': [6, 0, 1.5, 10],
19
+ 'searchInput': [11, 0, 1, 12],
20
+ 'help': [4, 4, 4, 4],
21
+ 'servicesInfo': [2, 2, 8, 8],
22
+ 'servicesList': [0, 0, 6, 10],
23
+ 'servicesLogs': [7.5, 0, 4, 12],
24
+ 'servicesStatus': [0, 10, 2, 2],
25
+ 'servicesVsImages': [2, 10, 2, 2],
26
+ 'toolbar': [11, 0, 1, 12]
27
+ }
28
+
29
+ const IMAGES_GRID_LAYOUT = {
30
+ 'imageInfo': [2, 2, 8, 8],
31
+ 'imageList': [0, 0, 6, 10],
32
+ 'searchInput': [11, 0, 1, 12],
33
+ 'actionStatus': [6, 0, 1.5, 10],
34
+ 'help': [4, 4, 4, 4],
35
+ 'toolbar': [11, 0, 1, 12],
36
+ 'imageUtilization': [0, 10, 2, 2]
37
+ }
38
+
39
+ module.exports = {
40
+ CONTAINERS_GRID_LAYOUT,
41
+ SERVICES_GRID_LAYOUT,
42
+ IMAGES_GRID_LAYOUT
43
+ }
package/src/screen.js CHANGED
@@ -4,48 +4,11 @@ const path = require('path')
4
4
  const blessed = require('blessed')
5
5
  const contrib = require('blessed-contrib')
6
6
  const assetsLoader = require(path.join(__dirname, '/assetsLoader'))
7
-
7
+ const { CONTAINERS_GRID_LAYOUT, SERVICES_GRID_LAYOUT, IMAGES_GRID_LAYOUT } = require('./grid.config')
8
8
  const MODES = require('../lib/modes')
9
9
 
10
10
  // @TODO should be moved outside and used as a config
11
11
  // from the user (index.js)
12
- const CONTAINERS_GRID_LAYOUT = {
13
- 'actionsMenu': [4, 4, 4, 4],
14
- 'help': [4, 4, 4, 4],
15
- 'containerInfo': [2, 2, 8, 8],
16
- 'containerSortList': [4, 5, 3, 2],
17
- 'containerList': [0, 0, 6, 10],
18
- 'actionStatus': [6, 0, 1, 10],
19
- 'containerStatus': [0, 10, 2, 2],
20
- 'containerUtilization': [2, 10, 3, 2],
21
- 'containerVsImages': [5, 10, 2, 2],
22
- 'containerLogs': [7, 0, 4, 12],
23
- 'toolbar': [11, 0, 1, 12],
24
- 'searchInput': [11, 0, 1, 12]
25
- }
26
-
27
- const SERVICES_GRID_LAYOUT = {
28
- 'actionsMenu': [4, 4, 4, 4],
29
- 'actionStatus': [6, 0, 1, 10],
30
- 'searchInput': [11, 0, 1, 12],
31
- 'help': [4, 4, 4, 4],
32
- 'servicesInfo': [2, 2, 8, 8],
33
- 'servicesList': [0, 0, 6, 10],
34
- 'servicesLogs': [7, 0, 4, 12],
35
- 'servicesStatus': [0, 10, 2, 2],
36
- 'servicesVsImages': [2, 10, 2, 2],
37
- 'toolbar': [11, 0, 1, 12]
38
- }
39
-
40
- const IMAGES_GRID_LAYOUT = {
41
- 'imageInfo': [2, 2, 8, 8],
42
- 'imageList': [0, 0, 6, 10],
43
- 'searchInput': [11, 0, 1, 12],
44
- 'actionStatus': [6, 0, 1, 10],
45
- 'help': [4, 4, 4, 4],
46
- 'toolbar': [11, 0, 1, 12],
47
- 'imageUtilization': [0, 10, 2, 2]
48
- }
49
12
 
50
13
  const GRID_LAYOUT = {}
51
14
  GRID_LAYOUT[MODES.container] = CONTAINERS_GRID_LAYOUT
@@ -34,7 +34,6 @@ class myWidget extends baseWidget(EventEmitter) {
34
34
  if (err) {
35
35
  return null
36
36
  }
37
-
38
37
  // clear log box of previous logs
39
38
  this.clearItemLogs()
40
39
 
@@ -75,6 +74,12 @@ class myWidget extends baseWidget(EventEmitter) {
75
74
  })
76
75
 
77
76
  searchInput.on('exitSearch', () => {
77
+ this.update(
78
+ this.containersListData ||
79
+ this.imagesListData ||
80
+ this.servicesListData ||
81
+ [])
82
+ this.screen.render()
78
83
  this.focus()
79
84
  })
80
85
  }
@@ -45,7 +45,7 @@ class myWidget extends ListWidget {
45
45
  let filteredContainersList = this.containersListData[0]
46
46
  let containersList = this.containersListData.slice(1)
47
47
  let filteredContainers = []
48
-
48
+ const headerRow = this.containersListData[0]
49
49
  if (data) {
50
50
  filteredContainers = containersList.filter((container, index, containerItems) => {
51
51
  const containerName = container[1]
@@ -56,12 +56,19 @@ class myWidget extends ListWidget {
56
56
  }
57
57
  })
58
58
  }
59
-
59
+ // Render filtered services if available; otherwise, it means either the user hasn't provided input or no matches were found.
60
60
  if (filteredContainers.length > 0) {
61
61
  filteredContainers.unshift(filteredContainersList)
62
62
  this.update(filteredContainers)
63
63
  } else {
64
- this.update(this.containersListData)
64
+ if (data.length > 0) {
65
+ this.update([
66
+ headerRow,
67
+ ['', 'No containers found matching: ' + data, '', '', '', '', '']
68
+ ])
69
+ } else {
70
+ this.update(this.containersListData)
71
+ }
65
72
  }
66
73
  }
67
74
 
@@ -20,6 +20,7 @@ class myWidget extends ListWidget {
20
20
  let imageTitleList = this.imagesListData[0]
21
21
  let imageList = this.imagesListData.slice(1)
22
22
  let filteredimages = []
23
+ const headerRow = this.imagesListData[0]
23
24
 
24
25
  if (data) {
25
26
  filteredimages = imageList.filter((container, index, containerItems) => {
@@ -31,12 +32,19 @@ class myWidget extends ListWidget {
31
32
  }
32
33
  })
33
34
  }
34
-
35
+ // Render filtered services if available; otherwise, it means either the user hasn't provided input or no matches were found.
35
36
  if (filteredimages.length > 0) {
36
37
  filteredimages.unshift(imageTitleList)
37
38
  this.update(filteredimages)
38
39
  } else {
39
- this.update(this.imagesListData)
40
+ if (data.length > 0) {
41
+ this.update([
42
+ headerRow,
43
+ ['', 'No Images found matching: ' + data, '', '', '', '', '']
44
+ ])
45
+ } else {
46
+ this.update(this.imagesListData)
47
+ }
40
48
  }
41
49
  }
42
50
 
@@ -64,8 +64,13 @@ class myWidget extends baseWidget(EventEmitter) {
64
64
  this.inputValue = []
65
65
  this.widget.destroy()
66
66
  this.emit('exitSearch')
67
+ this.screen.remove(this.widget)
68
+ this.screen.render()
67
69
  } else {
68
- this.emit('keypress', this.captureText(key))
70
+ const searchText = this.captureText(key)
71
+ this.widget.setValue(searchText)
72
+ this.emit('keypress', searchText)
73
+ this.screen.render()
69
74
  }
70
75
  })
71
76
 
@@ -86,12 +91,11 @@ class myWidget extends baseWidget(EventEmitter) {
86
91
  // by default, remove this widget from the screen
87
92
  this.screen.remove(this.widget)
88
93
  }
89
-
90
94
  getWidget () {
91
95
  return this.grid.gridObj.set(...this.grid.gridLayout, this.blessed.textbox, {
92
- focused: false,
96
+ focused: true,
93
97
  border: 'line',
94
- style: this.getWidgetStyle({ bg: 'yellow', fg: 'black' }),
98
+ style: this.getWidgetStyle(),
95
99
  align: 'left',
96
100
  inputOnFocus: true,
97
101
  vi: true,
@@ -32,23 +32,30 @@ class myWidget extends ListWidget {
32
32
  let filteredContainersList = this.servicesListData[0]
33
33
  let serviceList = this.servicesListData.slice(1)
34
34
  let filteredServices = []
35
+ const headerRow = this.servicesListData[0]
35
36
 
36
37
  if (data) {
37
38
  filteredServices = serviceList.filter((service) => {
38
39
  const serviceName = service[1]
39
40
  const serviceImageName = service[2]
40
-
41
41
  if ((serviceName.indexOf(data) !== -1) || (serviceImageName.indexOf(data) !== -1)) {
42
42
  return true
43
43
  }
44
44
  })
45
45
  }
46
-
46
+ // Render filtered services if available; otherwise, it means either the user hasn't provided input or no matches were found.
47
47
  if (filteredServices.length > 0) {
48
48
  filteredServices.unshift(filteredContainersList)
49
49
  this.update(filteredServices)
50
50
  } else {
51
- this.update(this.servicesListData)
51
+ if (data.length > 0) {
52
+ this.update([
53
+ headerRow,
54
+ ['', 'No Services found matching: ' + data, '', '', '', '', '']
55
+ ])
56
+ } else {
57
+ this.update(this.servicesListData)
58
+ }
52
59
  }
53
60
  }
54
61