chore: merge release-v0.6.1 into main

This commit is contained in:
Jack Wills
2024-02-14 14:39:44 +00:00
16 changed files with 533 additions and 262 deletions
+13 -11
View File
@@ -1,23 +1,25 @@
### 2024-01-18
### 2024-02-14
### Chores
+ dependencies updated, [53b4bafbe53312fe41608ddf33e865d474222aaa], [58ef151600e362048a607c8ae61a5edfe80ab1dd], [b6fd35022a99ec0e982ddb154b0450d49c4840e9], [0438c108bdd9815d7eae1b89c47c4e6438f358d6]
+ files formatted, [1806165c3e266876b2d1806f7b662d09705f3aad]
+ create_release.sh check for unused lint, [d0b27211928f93f8455e1ee5a6a6485c6a21d382]
+ create_release v0.5.5, [616338b7107036e968f51c3ff80739f9ffb40fbd]
+ update dependencies, [10180d2e0817c00a198e27f7d71080c502639a6b]
+ update to ratatui v0.26.0, [d33dce3eec4c19cc3c3668dab77f7d25d6970c3c]
+ GitHub workflow dependency bump, [0314eac9df6cf9fea1943dcd06bd6a0b27131c16]
### Docs
= Readme updated, screenshot added, [7561a93415c1e1f596b15edba95e7b32a939cd90], [4069e5572f81cb689dbb9f735db919e4636cdccc]
### Features
+ Ports section added, closes #21, [65a1afcb0605604ede350a5630c775f94ebb74ee], [7a096a65c40924021fe643fe0aa1067095832df9]
+ screenshot updated, [fe5ec4f5dd25f11817be37f3f1867a6a2b0afc42]
### Fixes
+ sort arrow now on left of header, [40ddcb727d2c1758d6dd26a58507b85b219f51e2]
+ ports all listed in white, [d3b23585b38045eb3bc827367eca90eb7f7a7dd5]
+ use long container name in delete popup, [6202b7bbfdfb04a94959b5143dac3f1aa59cd336]
+ memory display, closes #33, [a182d40a7463164ef5dcac379d1a1768d77209d2]
### Refactors
+ rename string_wrapper > unit_struct, [27cf53e41f8b379f606c1c27620ee08e79bac57e]
+ use &[T] instead of &Vec<T>, [76cd08ab2f98687a866a6bbb4fa93bbdedaa7699], [1f62bb50210f2d66bb7215e42e8b21a3c1a6ec06]
+ draw_block constraints into consts, [0436ff1b7356c80532048c7d497c66d331092b01]
### Tests
+ Finally have tests, currently for layout and associated methods, at the moment running the tests will not interfere with any running Docker containers, [4bcf77db776a36e0a8151ecfbda722a66c4ba46c]
+ update port test with new colour, [f74ae3f5c34d74b78822078291fed401427c4cba]
+ color match tests updated, [5b287416315942b19c62f8c66348ce28462d894c]
see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details
Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 57 KiB

@@ -56,7 +56,7 @@ jobs:
# Upload output for release page
- name: Upload Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ${{ matrix.target }}
@@ -75,7 +75,7 @@ jobs:
uses: actions/checkout@v4
- name: Setup | Artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
- name: Update Release
uses: ncipollo/release-action@v1
+25
View File
@@ -1,3 +1,28 @@
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.6.1'>v0.6.1</a>
### 2024-02-14
### Chores
+ create_release v0.5.5, [616338b7](https://github.com/mrjackwills/oxker/commit/616338b7107036e968f51c3ff80739f9ffb40fbd)
+ update dependencies, [10180d2e](https://github.com/mrjackwills/oxker/commit/10180d2e0817c00a198e27f7d71080c502639a6b)
+ update to ratatui v0.26.0, [d33dce3e](https://github.com/mrjackwills/oxker/commit/d33dce3eec4c19cc3c3668dab77f7d25d6970c3c)
+ GitHub workflow dependency bump, [0314eac9](https://github.com/mrjackwills/oxker/commit/0314eac9df6cf9fea1943dcd06bd6a0b27131c16)
### Docs
+ screenshot updated, [fe5ec4f5](https://github.com/mrjackwills/oxker/commit/fe5ec4f5dd25f11817be37f3f1867a6a2b0afc42)
### Fixes
+ ports all listed in white, [d3b23585](https://github.com/mrjackwills/oxker/commit/d3b23585b38045eb3bc827367eca90eb7f7a7dd5)
+ use long container name in delete popup, [6202b7bb](https://github.com/mrjackwills/oxker/commit/6202b7bbfdfb04a94959b5143dac3f1aa59cd336)
+ memory display, closes [#33](https://github.com/mrjackwills/oxker/issues/33), [a182d40a](https://github.com/mrjackwills/oxker/commit/a182d40a7463164ef5dcac379d1a1768d77209d2)
### Refactors
+ use &[T] instead of &Vec<T>, [76cd08ab](https://github.com/mrjackwills/oxker/commit/76cd08ab2f98687a866a6bbb4fa93bbdedaa7699), [1f62bb50](https://github.com/mrjackwills/oxker/commit/1f62bb50210f2d66bb7215e42e8b21a3c1a6ec06)
+ draw_block constraints into consts, [0436ff1b](https://github.com/mrjackwills/oxker/commit/0436ff1b7356c80532048c7d497c66d331092b01)
### Tests
+ update port test with new colour, [f74ae3f5](https://github.com/mrjackwills/oxker/commit/f74ae3f5c34d74b78822078291fed401427c4cba)
+ color match tests updated, [5b287416](https://github.com/mrjackwills/oxker/commit/5b287416315942b19c62f8c66348ce28462d894c)
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.6.0'>v0.6.0</a>
### 2024-01-18
Generated
+126 -88
View File
@@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.8.7"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff"
dependencies = [
"cfg-if",
"once_cell",
@@ -66,9 +66,9 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.4"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
name = "anstyle-parse"
@@ -207,6 +207,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "castaway"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc"
dependencies = [
"rustversion",
]
[[package]]
name = "cc"
version = "1.0.83"
@@ -224,22 +233,22 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.31"
version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"serde",
"windows-targets 0.48.5",
"windows-targets 0.52.0",
]
[[package]]
name = "clap"
version = "4.4.18"
version = "4.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f"
dependencies = [
"clap_builder",
"clap_derive",
@@ -247,9 +256,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.4.18"
version = "4.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99"
dependencies = [
"anstream",
"anstyle",
@@ -261,9 +270,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.4.7"
version = "4.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
dependencies = [
"heck",
"proc-macro2",
@@ -273,9 +282,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.6.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "colorchoice"
@@ -283,6 +292,19 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "compact_str"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"ryu",
"static_assertions",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
@@ -347,9 +369,9 @@ dependencies = [
[[package]]
name = "either"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
[[package]]
name = "equivalent"
@@ -453,7 +475,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http",
"indexmap 2.1.0",
"indexmap 2.2.3",
"slab",
"tokio",
"tokio-util",
@@ -484,9 +506,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.3.4"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
[[package]]
name = "hex"
@@ -567,9 +589,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.59"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -611,9 +633,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.1.0"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
@@ -628,9 +650,9 @@ checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8"
[[package]]
name = "itertools"
version = "0.12.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
@@ -643,9 +665,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "js-sys"
version = "0.3.67"
version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
dependencies = [
"wasm-bindgen",
]
@@ -658,9 +680,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.152"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libredox"
@@ -691,9 +713,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "lru"
version = "0.12.1"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2994eeba8ed550fd9b47a0b38f0242bc3344e496483c6180b69139cc2fa5d1d7"
checksum = "db2c024b41519440580066ba82aab04092b333e09066a5eb86c7c4890df31f22"
dependencies = [
"hashbrown 0.14.3",
]
@@ -706,9 +728,9 @@ checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "miniz_oxide"
version = "0.7.1"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
@@ -736,10 +758,16 @@ dependencies = [
]
[[package]]
name = "num-traits"
version = "0.2.17"
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-traits"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
@@ -783,7 +811,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "oxker"
version = "0.6.0"
version = "0.6.1"
dependencies = [
"anyhow",
"bollard",
@@ -837,18 +865,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.3"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.3"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
dependencies = [
"proc-macro2",
"quote",
@@ -881,9 +909,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.76"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@@ -929,12 +957,13 @@ dependencies = [
[[package]]
name = "ratatui"
version = "0.25.0"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5659e52e4ba6e07b2dad9f1158f578ef84a73762625ddb51536019f34d180eb"
checksum = "bcb12f8fbf6c62614b0d56eb352af54f6a22410c3b079eb53ee93c7b97dd31d8"
dependencies = [
"bitflags 2.4.2",
"cassowary",
"compact_str",
"crossterm",
"indoc",
"itertools",
@@ -992,18 +1021,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.195"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.195"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
@@ -1012,9 +1041,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.111"
version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"itoa",
"ryu",
@@ -1046,16 +1075,17 @@ dependencies = [
[[package]]
name = "serde_with"
version = "3.4.0"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270"
dependencies = [
"base64",
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.1.0",
"indexmap 2.2.3",
"serde",
"serde_derive",
"serde_json",
"time",
]
@@ -1110,9 +1140,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.13.0"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b187f0231d56fe41bfb12034819dd2bf336422a5866de41bc3fec4b2e3883e8"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]]
name = "socket2"
@@ -1135,25 +1165,31 @@ dependencies = [
]
[[package]]
name = "strsim"
version = "0.10.0"
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]]
name = "strum"
version = "0.25.0"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.25.3"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18"
dependencies = [
"heck",
"proc-macro2",
@@ -1186,18 +1222,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.56"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.56"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
@@ -1216,12 +1252,13 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.31"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
@@ -1236,10 +1273,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
dependencies = [
"num-conv",
"time-core",
]
@@ -1260,9 +1298,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.35.1"
version = "1.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
dependencies = [
"backtrace",
"bytes",
@@ -1403,9 +1441,9 @@ dependencies = [
[[package]]
name = "unicode-segmentation"
version = "1.10.1"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "unicode-width"
@@ -1432,9 +1470,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.6.1"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
dependencies = [
"getrandom",
"rand",
@@ -1469,9 +1507,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.90"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -1479,9 +1517,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.90"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
dependencies = [
"bumpalo",
"log",
@@ -1494,9 +1532,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.90"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1504,9 +1542,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.90"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
dependencies = [
"proc-macro2",
"quote",
@@ -1517,9 +1555,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.90"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
[[package]]
name = "winapi"
+6 -6
View File
@@ -1,6 +1,6 @@
[package]
name = "oxker"
version = "0.6.0"
version = "0.6.1"
edition = "2021"
authors = ["Jack Wills <email@mrjackwills.com>"]
description = "A simple tui to view & control docker containers"
@@ -29,16 +29,16 @@ similar_names = "allow"
anyhow = "1.0"
bollard = "0.15"
cansi = "2.2"
clap = { version = "4.4", features = ["color", "derive", "unicode"] }
clap = { version = "4.5", features = ["color", "derive", "unicode"] }
crossterm = "0.27"
directories = "5.0"
futures-util = "0.3"
parking_lot = { version = "0.12" }
tokio = { version = "1.35", features = ["full"] }
ratatui = "0.26"
tokio = { version = "1.36", features = ["full"] }
tracing = "0.1"
tracing-subscriber = "0.3"
ratatui = "0.25"
uuid = { version = "1.6", features = ["fast-rng", "v4"] }
directories = "5.0"
uuid = { version = "1.7", features = ["fast-rng", "v4"] }
[dev-dependencies]
+112 -32
View File
@@ -1,7 +1,6 @@
#!/bin/bash
# rust create_release
# v0.4.1
# rust create_release v0.5.5
STAR_LINE='****************************************'
CWD=$(pwd)
@@ -18,6 +17,11 @@ error_close() {
exit 1
}
# Check that dialog is installed
if ! [ -x "$(command -v dialog)" ]; then
error_close "dialog is not installed"
fi
# $1 string - question to ask
ask_yn() {
printf "%b%s? [y/N]:%b " "${GREEN}" "$1" "${RESET}"
@@ -29,21 +33,34 @@ user_input() {
echo "$data"
}
# ask continue, or quit
ask_continue() {
ask_yn "continue"
if [[ ! "$(user_input)" =~ ^y$ ]]; then
exit
fi
}
# semver major update
update_major() {
local bumped_major
bumped_major=$((MAJOR + 1))
echo "${bumped_major}.0.0"
}
# semver minor update
update_minor() {
local bumped_minor
bumped_minor=$((MINOR + 1))
MINOR=bumped_minor
echo "${MAJOR}.${bumped_minor}.0"
}
# semver patch update
update_patch() {
local bumped_patch
bumped_patch=$((PATCH + 1))
PATCH=bumped_patch
echo "${MAJOR}.${MINOR}.${bumped_patch}"
}
@@ -153,14 +170,6 @@ check_tag() {
done
}
# ask continue, or quit
ask_continue() {
ask_yn "continue"
if [[ ! "$(user_input)" =~ ^y$ ]]; then
exit
fi
}
# run all tests
cargo_test() {
cargo test -- --test-threads=1
@@ -169,31 +178,55 @@ cargo_test() {
# Simulate publishing to crates.io
cargo_publish() {
echo -e "${PURPLE}cargo publish --dry-run${RESET}"
cargo publish --dry-run
ask_continue
}
# Build all releases that GitHub workflow would
# This will download GB's of docker images
cargo_build() {
cargo install cross
cargo_clean
# Check to see if cross is installed - if not then install
check_cross() {
if ! [ -x "$(command -v cross)" ]; then
echo -e "${GREEN}cargo install cross${RESET}"
cargo install cross
fi
}
cargo_build_x86_linux() {
check_cross
echo -e "${YELLOW}cross build --target x86_64-unknown-linux-musl --release${RESET}"
cross build --target x86_64-unknown-linux-musl --release
ask_continue
cargo_clean
}
cargo_build_aarch64_linux() {
check_cross
echo -e "${YELLOW}cross build --target aarch64-unknown-linux-musl --release${RESET}"
cross build --target aarch64-unknown-linux-musl --release
ask_continue
cargo_clean
}
cargo_build_armv6_linux() {
check_cross
echo -e "${YELLOW}cross build --target arm-unknown-linux-musleabihf --release${RESET}"
cross build --target arm-unknown-linux-musleabihf --release
ask_continue
cargo_clean
}
cargo_build_x86_windows() {
check_cross
echo -e "${YELLOW}cross build --target x86_64-pc-windows-gnu --release${RESET}"
cross build --target x86_64-pc-windows-gnu --release
}
# Build all releases that GitHub workflow would
# This will download GB's of docker images
cargo_build_all() {
cargo clean
cargo_build_armv6_linux
ask_continue
cargo_build_aarch64_linux
ask_continue
cargo_build_x86_linux
ask_continue
cargo_build_x86_windows
ask_continue
cargo_clean
}
# $1 text to colourise
@@ -202,11 +235,6 @@ release_continue() {
ask_continue
}
# Clean/remove builds, due to issue with cross-rs
cargo_clean() {
echo -e "${YELLOW}cargo clean${RESET}"
cargo clean
}
# Check repository for typos
check_typos() {
echo -e "\n${PURPLE}check typos${RESET}"
@@ -214,14 +242,16 @@ check_typos() {
ask_continue
}
# Make sure the unused lint isn't used
# Make sure the unused lint isn't used
check_allow_unused() {
matches_any=$(find . -type d \( -name .git -o -name target \) -prune -o -type f -exec grep -lE '^#!\[allow\(unused\)\]$' {} +)
matches_cargo=$(grep "^unused = \"allow\"" ./Cargo.toml)
if [ -n "$matches_any" ]; then
error_close "\"#[allow(unused)]\" in ${matches_any}"
echo "\"#[allow(unused)]\" in ${matches_any}"
ask_continue
elif [ -n "$matches_cargo" ]; then
error_close "\"unused = \"allow\"\" in Cargo.toml"
echo "\"unused = \"allow\"\" in Cargo.toml"
ask_continue
fi
}
@@ -234,7 +264,7 @@ release_flow() {
get_git_remote_url
cargo_test
cargo_build
cargo_build_all
cargo_publish
cd "${CWD}" || error_close "Can't find ${CWD}"
@@ -255,6 +285,7 @@ release_flow() {
echo -e "\ncargo fmt"
cargo fmt
echo -e "\n${PURPLE}cargo check${RESET}\n"
cargo check
@@ -267,8 +298,12 @@ release_flow() {
release_continue "git checkout main"
git checkout main
echo -e "${PURPLE}git pull origin main${RESET}"
git pull origin main
echo -e "${PURPLE}git merge --no-ff \"${RELEASE_BRANCH}\" -m \"chore: merge ${RELEASE_BRANCH} into main\"${RESET}"
git merge --no-ff "$RELEASE_BRANCH" -m "chore: merge ${RELEASE_BRANCH} into main"
echo -e "\n${PURPLE}cargo check${RESET}\n"
cargo check
@@ -291,6 +326,51 @@ release_flow() {
git branch -d "$RELEASE_BRANCH"
}
build_choice() {
cmd=(dialog --backtitle "Choose option" --radiolist "choose" 14 80 16)
options=(
1 "x86 musl linux" off
2 "aarch64 musl linux" off
3 "armv6 musl linux" off
4 "x86 windows" off
5 "all" off
)
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
exitStatus=$?
clear
if [ $exitStatus -ne 0 ]; then
exit
fi
for choice in $choices; do
case $choice in
0)
exit
;;
1)
cargo_build_x86_linux
exit
;;
2)
cargo_build_aarch64_linux
exit
;;
3)
cargo_build_armv6_linux
exit
;;
4)
cargo_build_x86_windows
exit
;;
5)
cargo_build_all
exit
;;
esac
done
}
main() {
cmd=(dialog --backtitle "Choose option" --radiolist "choose" 14 80 16)
options=(
@@ -319,7 +399,7 @@ main() {
break
;;
3)
cargo_build
build_choice
main
break
;;
-2
View File
@@ -11,8 +11,6 @@ services:
ipc: private
restart: always
shm_size: 256MB
ports:
- "127.0.0.1:4040:4040"
networks:
- oxker-example-net
deploy:
+2 -4
View File
@@ -48,7 +48,6 @@ impl PartialOrd for ContainerId {
}
}
/// TODO - use string_wrapper for ContainerId?
/// ContainerName and ContainerImage are simple structs, used so can implement custom fmt functions to them
macro_rules! unit_struct {
($name:ident) => {
@@ -537,7 +536,6 @@ pub struct ContainerItem {
pub mem_limit: ByteStats,
pub mem_stats: VecDeque<ByteStats>,
pub name: ContainerName,
// todo remove option, can be empty vec
pub ports: Vec<ContainerPorts>,
pub rx: ByteStats,
pub state: State,
@@ -691,7 +689,7 @@ mod tests {
use super::{ByteStats, ContainerName, CpuStats, LogsTz};
#[test]
// Display CpuStats as a string
/// Display CpuStats as a string
fn test_container_state_cpustats_to_string() {
let test = |f: f64, s: &str| {
assert_eq!(CpuStats::new(f).to_string(), s);
@@ -704,7 +702,7 @@ mod tests {
}
#[test]
// Display bytestats as a string, convert into correct data unit (Kb, MB, GB)
/// Display bytestats as a string, convert into correct data unit (Kb, MB, GB)
fn test_container_state_bytestats_to_string() {
let test = |u: u64, s: &str| {
assert_eq!(ByteStats::new(u).to_string(), s);
+11 -10
View File
@@ -212,7 +212,7 @@ impl AppData {
}
/// Get all the ContainerItems
pub const fn get_container_items(&self) -> &Vec<ContainerItem> {
pub fn get_container_items(&self) -> &[ContainerItem] {
&self.containers.items
}
@@ -383,6 +383,7 @@ impl AppData {
}
/// Get mutable Option of the currently selected container DockerControls items
/// TODO command or control, need a uniform name across the application
pub fn get_control_items(&mut self) -> Option<&mut Vec<DockerControls>> {
self.get_mut_selected_container()
.map(|i| &mut i.docker_controls.items)
@@ -1229,7 +1230,7 @@ mod tests {
}
#[test]
// Get the currently selected container
/// Get the currently selected container
fn test_app_data_get_selected_container() {
let (_ids, mut containers) = gen_containers();
let mut app_data = gen_appdata(&containers);
@@ -1249,7 +1250,7 @@ mod tests {
}
#[test]
// Get mut container by id
/// Get mut container by id
fn test_app_data_get_container_by_id() {
let (_ids, mut containers) = gen_containers();
let mut app_data = gen_appdata(&containers);
@@ -1259,7 +1260,7 @@ mod tests {
}
#[test]
// Get just the containers name by id
/// Get just the containers name by id
fn test_app_data_get_container_name_by_id() {
let (_ids, containers) = gen_containers();
let mut app_data = gen_appdata(&containers);
@@ -1269,7 +1270,7 @@ mod tests {
}
#[test]
// Get the id of the currently selected container
/// Get the id of the currently selected container
fn test_app_data_get_selected_container_id() {
let (_ids, containers) = gen_containers();
let mut app_data = gen_appdata(&containers);
@@ -1383,7 +1384,7 @@ mod tests {
"Up 1 hour".to_owned(),
)
};
let mut app_data = gen_appdata(&vec![gen_item_state(state)]);
let mut app_data = gen_appdata(&[gen_item_state(state)]);
app_data.containers_start();
app_data.docker_controls_start();
@@ -1832,15 +1833,15 @@ mod tests {
fn test_app_data_update_containers() {
let (_ids, containers) = gen_containers();
let mut app_data = gen_appdata(&containers);
let result_pre = app_data.get_container_items().clone();
let mut input = vec![
let result_pre = app_data.get_container_items().to_owned();
let mut input = [
gen_container_summary(1, "paused"),
gen_container_summary(2, "dead"),
];
app_data.update_containers(&mut input);
let result_post = app_data.get_container_items();
assert_ne!(&result_pre, result_post);
let result_post = app_data.get_container_items().to_owned();
assert_ne!(result_pre, result_post);
assert_eq!(result_post[0].state, State::Paused);
assert_eq!(result_post[1].state, State::Dead);
}
+15 -4
View File
@@ -1,7 +1,7 @@
use bollard::{
container::{
ListContainersOptions, LogsOptions, RemoveContainerOptions, StartContainerOptions, Stats,
StatsOptions,
ListContainersOptions, LogsOptions, MemoryStatsStats, RemoveContainerOptions,
StartContainerOptions, Stats, StatsOptions,
},
service::ContainerSummary,
Docker,
@@ -71,7 +71,7 @@ pub struct DockerData {
impl DockerData {
/// Use docker stats to calculate current cpu usage
#[allow(clippy::cast_precision_loss)]
// FIX: this can overflow
// TODO FIX: this can overflow
fn calculate_usage(stats: &Stats) -> f64 {
let mut cpu_percentage = 0.0;
let previous_cpu = stats.precpu_stats.cpu_usage.total_usage;
@@ -121,8 +121,19 @@ impl DockerData {
.take(1);
while let Some(Ok(stats)) = stream.next().await {
// Memory stats are only collected if the container is alive - is this the behaviour we want?
let mem_stat = if state.is_alive() {
Some(stats.memory_stats.usage.unwrap_or_default())
let mem_cache = stats.memory_stats.stats.map_or(0, |i| match i {
MemoryStatsStats::V1(x) => x.inactive_file,
MemoryStatsStats::V2(x) => x.inactive_file,
});
Some(
stats
.memory_stats
.usage
.unwrap_or_default()
.saturating_sub(mem_cache),
)
} else {
None
};
-1
View File
@@ -150,7 +150,6 @@ async fn main() {
let containers = app_data
.lock()
.get_container_items()
.clone()
.iter()
.map(|i| format!("{i}"))
.collect::<Vec<_>>();
+5 -2
View File
@@ -98,12 +98,13 @@ mod tests {
}]
.to_vec(),
alignment: None,
style: Style::default(),
}];
assert_eq!(result, expected);
}
#[test]
// Use the escape codes to colorize the text
/// Use the escape codes to colorize the text
fn color_match_colorize() {
let result = log_sanitizer::colorize_logs(INPUT);
let expected = vec![Line {
@@ -130,12 +131,13 @@ mod tests {
},
],
alignment: None,
style: Style::default(),
}];
assert_eq!(result, expected);
}
#[test]
// Remove all escape ansi codes from given input
/// Remove all escape ansi codes from given input
fn color_match_remove_ansi() {
let result = log_sanitizer::remove_ansi(INPUT);
let expected = vec![Line {
@@ -143,6 +145,7 @@ mod tests {
content: std::borrow::Cow::Borrowed("oxker"),
style: Style::default(),
}],
style: Style::default(),
alignment: None,
}];
assert_eq!(result, expected);
+206 -91
View File
@@ -44,6 +44,24 @@ const MARGIN: &str = " ";
const RIGHT_ARROW: &str = "";
const CIRCLE: &str = "";
const CONSTRAINT_50_50: [Constraint; 2] = [Constraint::Percentage(50), Constraint::Percentage(50)];
const CONSTRAINT_100: [Constraint; 1] = [Constraint::Percentage(100)];
const CONSTRAINT_POPUP: [Constraint; 5] = [
Constraint::Min(2),
Constraint::Max(1),
Constraint::Max(1),
Constraint::Max(3),
Constraint::Min(1),
];
const CONSTRAINT_BUTTONS: [Constraint; 5] = [
Constraint::Percentage(10),
Constraint::Percentage(35),
Constraint::Percentage(10),
Constraint::Percentage(35),
Constraint::Percentage(10),
];
/// From a given &str, return the maximum number of chars on a single line
fn max_line_width(text: &str) -> usize {
text.lines()
@@ -94,8 +112,7 @@ pub fn commands(
fd: &FrameData,
gui_state: &Arc<Mutex<GuiState>>,
) {
let block = || generate_block(app_data, area, fd, gui_state, SelectablePanel::Commands);
// let block = block();
let block = generate_block(app_data, area, fd, gui_state, SelectablePanel::Commands);
let items = app_data.lock().get_control_items().map_or(vec![], |i| {
i.iter()
.map(|c| {
@@ -108,18 +125,14 @@ pub fn commands(
.collect::<Vec<_>>()
});
let items = List::new(items)
.block(block())
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
.highlight_symbol(RIGHT_ARROW);
if let Some(i) = app_data.lock().get_control_state() {
let items = List::new(items)
.block(block)
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
.highlight_symbol(RIGHT_ARROW);
f.render_stateful_widget(items, area, i);
} else {
let block = || generate_block(app_data, area, fd, gui_state, SelectablePanel::Commands);
let paragraph = Paragraph::new("")
.block(block())
.alignment(Alignment::Center);
let paragraph = Paragraph::new("").block(block).alignment(Alignment::Center);
f.render_widget(paragraph, area);
}
}
@@ -241,11 +254,11 @@ pub fn logs(
fd: &FrameData,
gui_state: &Arc<Mutex<GuiState>>,
) {
let block = || generate_block(app_data, area, fd, gui_state, SelectablePanel::Logs);
let block = generate_block(app_data, area, fd, gui_state, SelectablePanel::Logs);
if fd.init {
let paragraph = Paragraph::new(format!("parsing logs {}", fd.loading_icon))
.style(Style::default())
.block(block())
.block(block)
.alignment(Alignment::Center);
f.render_widget(paragraph, area);
} else {
@@ -253,12 +266,12 @@ pub fn logs(
if logs.is_empty() {
let paragraph = Paragraph::new("no logs found")
.block(block())
.block(block)
.alignment(Alignment::Center);
f.render_widget(paragraph, area);
} else {
let items = List::new(logs)
.block(block())
.block(block)
.highlight_symbol(RIGHT_ARROW)
.highlight_style(Style::default().add_modifier(Modifier::BOLD));
// This should always return Some, as logs is not empty
@@ -307,12 +320,8 @@ pub fn ports(
))
.fg(Color::Yellow),
)];
for (index, item) in ports.0.iter().enumerate() {
let fg = if index % 2 == 0 {
Color::White
} else {
Color::Magenta
};
for item in &ports.0 {
let fg = Color::White;
let strings = item.print();
let line = vec![
@@ -333,7 +342,7 @@ pub fn chart(f: &mut Frame, area: Rect, app_data: &Arc<Mutex<AppData>>) {
if let Some((cpu, mem)) = app_data.lock().get_chart_data() {
let area = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
.constraints(CONSTRAINT_50_50)
.split(area);
let cpu_dataset = vec![Dataset::default()
@@ -423,7 +432,7 @@ pub fn heading_bar(
let mut color = Color::Black;
let mut prefix = "";
let mut prefix_margin = 0;
if let Some((a, b)) = data.sorted_by.as_ref() {
if let Some((a, b)) = &data.sorted_by {
if x == a {
match b {
SortedOrder::Asc => prefix = "",
@@ -505,12 +514,12 @@ pub fn heading_bar(
let column_width = if column_width > 0 { column_width } else { 1 };
let splits = if data.has_containers {
vec![
Constraint::Min(2),
Constraint::Max(2),
Constraint::Min(column_width.try_into().unwrap_or_default()),
Constraint::Min(info_width.try_into().unwrap_or_default()),
Constraint::Max(info_width.try_into().unwrap_or_default()),
]
} else {
vec![Constraint::Percentage(100)]
CONSTRAINT_100.to_vec()
};
let split_bar = Layout::default()
@@ -756,15 +765,12 @@ pub fn help_box(f: &mut Frame) {
let split_popup = Layout::default()
.direction(Direction::Vertical)
.constraints(
[
Constraint::Max(name_info.height.try_into().unwrap_or_default()),
Constraint::Max(description_info.height.try_into().unwrap_or_default()),
Constraint::Max(button_info.height.try_into().unwrap_or_default()),
Constraint::Max(final_info.height.try_into().unwrap_or_default()),
]
.as_ref(),
)
.constraints([
Constraint::Max(name_info.height.try_into().unwrap_or_default()),
Constraint::Max(description_info.height.try_into().unwrap_or_default()),
Constraint::Max(button_info.height.try_into().unwrap_or_default()),
Constraint::Min(final_info.height.try_into().unwrap_or_default()),
])
.split(area);
let name_paragraph = Paragraph::new(name_info.lines)
@@ -815,7 +821,7 @@ pub fn delete_confirm(f: &mut Frame, gui_state: &Arc<Mutex<GuiState>>, name: &Co
let confirm = Line::from(vec![
Span::from("Are you sure you want to delete container: "),
Span::styled(
name.to_string(),
name.get(),
Style::default()
.fg(Color::Red)
.bg(Color::White)
@@ -843,16 +849,10 @@ pub fn delete_confirm(f: &mut Frame, gui_state: &Arc<Mutex<GuiState>>, name: &Co
.alignment(Alignment::Center)
.block(button_block());
// Need to add some padding for the borders
let _yes_chars = u16::try_from(yes_text.chars().count() + 2).unwrap_or(9);
let no_para = Paragraph::new(no_text)
.alignment(Alignment::Center)
.block(button_block());
// Need to add some padding for the borders
// let no_chars = u16::try_from(no_text.chars().count() + 2).unwrap_or(8);
let area = popup(
lines,
max_line_width.into(),
@@ -862,30 +862,12 @@ pub fn delete_confirm(f: &mut Frame, gui_state: &Arc<Mutex<GuiState>>, name: &Co
let split_popup = Layout::default()
.direction(Direction::Vertical)
.constraints(
[
Constraint::Min(2),
Constraint::Max(1),
Constraint::Max(1),
Constraint::Max(3),
Constraint::Min(1),
]
.as_ref(),
)
.constraints(CONSTRAINT_POPUP)
.split(area);
let split_buttons = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[
Constraint::Percentage(10),
Constraint::Percentage(35),
Constraint::Percentage(10),
Constraint::Percentage(35),
Constraint::Percentage(10),
]
.as_ref(),
)
.constraints(CONSTRAINT_BUTTONS)
.split(split_popup[3]);
let no_area = split_buttons[1];
@@ -951,6 +933,7 @@ pub fn error(f: &mut Frame, error: AppError, seconds: Option<u8>) {
}
/// Draw info box in one of the 9 BoxLocations
// TODO is this broken?
pub fn info(f: &mut Frame, text: &str, instant: Instant, gui_state: &Arc<Mutex<GuiState>>) {
let block = Block::default()
.title("")
@@ -1085,7 +1068,7 @@ mod tests {
// ******************** //
#[test]
// Test that when DockerCommands are available, they are drawn correctly, dependant on container state
/// Test that when DockerCommands are available, they are drawn correctly, dependant on container state
fn test_draw_blocks_commands_none() {
let (w, h) = (12, 6);
let mut setup = test_setup(w, h, false, false);
@@ -1236,7 +1219,7 @@ mod tests {
}
#[test]
// When control panel is selected, the border is blue, if not then white, selected text is highlighted
/// When control panel is selected, the border is blue, if not then white, selected text is highlighted
fn test_draw_blocks_commands_panel_selected_color() {
let (w, h) = (12, 6);
let mut setup = test_setup(w, h, true, true);
@@ -1326,7 +1309,7 @@ mod tests {
}
#[test]
// No containers, panel unselected, then selected, border color changes correctly
/// No containers, panel unselected, then selected, border color changes correctly
fn test_draw_blocks_containers_none() {
let (w, h) = (25, 6);
let mut setup = test_setup(w, h, true, true);
@@ -1387,7 +1370,7 @@ mod tests {
}
#[test]
// Containers panel drawn, selected line is bold, border is blue
/// Containers panel drawn, selected line is bold, border is blue
fn test_draw_blocks_containers_some() {
let (w, h) = (130, 6);
let mut setup = test_setup(w, h, true, true);
@@ -1746,7 +1729,7 @@ mod tests {
// ********** //
#[test]
// No logs, panel unselected, then selected, border color changes correctly
/// No logs, panel unselected, then selected, border color changes correctly
fn test_draw_blocks_logs_none() {
let (w, h) = (25, 6);
let mut setup = test_setup(w, h, true, true);
@@ -1808,7 +1791,7 @@ mod tests {
}
#[test]
// Parsing logs, spinner visible, and then animates by one frame
/// Parsing logs, spinner visible, and then animates by one frame
fn test_draw_blocks_logs_parsing() {
let (w, h) = (25, 6);
let mut setup = test_setup(w, h, true, true);
@@ -1874,7 +1857,7 @@ mod tests {
}
#[test]
// Logs correct displayed, changing log state also draws correctly
/// Logs correct displayed, changing log state also draws correctly
fn test_draw_blocks_logs_some() {
let (w, h) = (25, 6);
let mut setup = test_setup(w, h, true, true);
@@ -1943,7 +1926,7 @@ mod tests {
}
#[test]
// Full (long) name displayed in logs border
/// Full (long) name displayed in logs border
fn test_draw_blocks_logs_long_name() {
let (w, h) = (80, 6);
let mut setup = test_setup(w, h, true, true);
@@ -2032,7 +2015,7 @@ mod tests {
}
}
#[test]
// When status is Running, but not data, charts drawn without dots etc
/// When status is Running, but not data, charts drawn without dots etc
fn test_draw_blocks_charts_running_none() {
let (w, h) = (80, 10);
let mut setup = test_setup(w, h, true, true);
@@ -2087,7 +2070,7 @@ mod tests {
}
#[test]
// When status is Running, charts correctly drawn
/// When status is Running, charts correctly drawn
fn test_draw_blocks_charts_running_some() {
let (w, h) = (80, 10);
let mut setup = test_setup(w, h, true, true);
@@ -2140,7 +2123,7 @@ mod tests {
}
#[test]
// Whens status paused, some text is now Yellow
/// Whens status paused, some text is now Yellow
fn test_draw_blocks_charts_paused() {
let (w, h) = (80, 10);
let mut setup = test_setup(w, h, true, true);
@@ -2188,7 +2171,7 @@ mod tests {
}
#[test]
// When dead, text is read
/// When dead, text is read
fn test_draw_blocks_charts_dead() {
let (w, h) = (80, 10);
let mut setup = test_setup(w, h, true, true);
@@ -2335,7 +2318,6 @@ mod tests {
let result = &setup.terminal.backend().buffer().content;
for (index, expected_char) in expected.chars().enumerate() {
let result_cell = &result[index];
assert_eq!(result_cell.symbol(), expected_char.to_string());
assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!(
@@ -2383,8 +2365,8 @@ mod tests {
test(" name state status cpu memory/limit id image ▼ ↓ rx ↑ tx ( h ) show help ", 99..=108, (Header::Rx, SortedOrder::Desc));
// tx
test(" name state status cpu memory/limit id image ↓ rx ▲ ↑ tx ( h ) show help ", 109..=122, (Header::Tx, SortedOrder::Asc));
test(" name state status cpu memory/limit id image ↓ rx ▼ ↑ tx ( h ) show help ", 109..=122, (Header::Tx, SortedOrder::Desc));
test(" name state status cpu memory/limit id image ↓ rx ▲ ↑ tx ( h ) show help ", 109..=118, (Header::Tx, SortedOrder::Asc));
test(" name state status cpu memory/limit id image ↓ rx ▼ ↑ tx ( h ) show help ", 109..=118, (Header::Tx, SortedOrder::Desc));
}
#[test]
@@ -2425,7 +2407,7 @@ mod tests {
// Help popup //
// ********** //
#[test]
// This will cause issues once the version has more than the current 5 chars (0.5.0)
/// This will cause issues once the version has more than the current 5 chars (0.5.0)
// Help popup is drawn correctly
fn test_draw_blocks_help() {
let (w, h) = (87, 30);
@@ -2525,7 +2507,7 @@ mod tests {
// ************ //
#[test]
// Delete container popup is drawn correctly
/// Delete container popup is drawn correctly
fn test_draw_blocks_delete() {
let (w, h) = (82, 10);
let mut setup = test_setup(w, h, true, true);
@@ -2587,6 +2569,70 @@ mod tests {
}
}
#[test]
/// Delete container popup is drawn correctly
fn test_draw_blocks_delete_long_name() {
let (w, h) = (106, 10);
let mut setup = test_setup(w, h, true, true);
let name = ContainerName::from("container_1_container_1_container_1");
setup.app_data.lock().containers.items[0].name = name.clone();
let expected = [
" ",
" ╭──────────────────────────────────── Confirm Delete ────────────────────────────────────╮ ",
" │ │ ",
" │ Are you sure you want to delete container: container_1_container_1_container_1 │ ",
" │ │ ",
" │ ╭──────────────────────────────╮ ╭─────────────────────────────╮ │ ",
" │ │ (N)o │ │ (Y)es │ │ ",
" │ ╰──────────────────────────────╯ ╰─────────────────────────────╯ │ ",
" ╰────────────────────────────────────────────────────────────────────────────────────────╯ ",
" ",
];
setup
.terminal
.draw(|f| {
super::delete_confirm(f, &setup.gui_state, &name);
})
.unwrap();
let result = &setup.terminal.backend().buffer().content;
for (row_index, row) in expected.iter().enumerate() {
for (char_index, expected_char) in row.chars().enumerate() {
let index = row_index * usize::from(w) + char_index;
let result_cell = &result[index];
assert_eq!(result_cell.symbol(), expected_char.to_string());
if row_index == 0
|| row_index == usize::from(h - 1)
|| char_index < 8
|| char_index > usize::from(w - 9)
{
assert_eq!(result_cell.fg, Color::Reset);
assert_eq!(result_cell.bg, Color::Reset);
} else {
assert_eq!(result_cell.bg, Color::White);
}
// Borders are black
if BORDER_CHARS.contains(&result_cell.symbol()) {
assert_eq!(result_cell.fg, Color::Black);
// Container name is red
} else if row_index == 3 && (57..=82).contains(&char_index) {
assert_eq!(result_cell.fg, Color::Red);
// All other text is black
} else if !row_index == 0
&& !row_index == usize::from(h - 1)
&& !char_index < 8
&& !char_index > usize::from(w - 9)
{
assert_eq!(result_cell.fg, Color::Black);
}
}
}
}
// ***** //
// popup //
// ***** //
@@ -2617,13 +2663,13 @@ mod tests {
.unwrap();
let result = &setup.terminal.backend().buffer().content;
for (row_index, row) in expected.iter().enumerate() {
for (char_index, expected_char) in row.chars().enumerate() {
let index = row_index * usize::from(w) + char_index;
let result_cell = &result[index];
assert_eq!(expected_char.to_string(), result_cell.symbol());
let (fg, bg) = if row_index >= 6 && char_index >= 32 {
(Color::White, Color::Blue)
} else {
@@ -2641,7 +2687,7 @@ mod tests {
// *********** //
#[test]
// Test that the error popup is centered, red background, white border, white text, and displays the correct text
/// Test that the error popup is centered, red background, white border, white text, and displays the correct text
fn test_draw_blocks_docker_connect_error() {
let (w, h) = (46, 9);
let mut setup = test_setup(w, h, true, true);
@@ -2692,7 +2738,7 @@ mod tests {
}
#[test]
// Test that the clearable error popup is centered, red background, white border, white text, and displays the correct text
/// Test that the clearable error popup is centered, red background, white border, white text, and displays the correct text
fn test_draw_blocks_clearable_error() {
let (w, h) = (39, 10);
let mut setup = test_setup(w, h, true, true);
@@ -2744,7 +2790,7 @@ mod tests {
}
#[test]
// Port section when container has no ports
/// Port section when container has no ports
fn test_draw_blocks_ports_no_ports() {
let (w, h) = (30, 8);
let mut setup = test_setup(w, h, true, true);
@@ -2824,7 +2870,7 @@ mod tests {
}
#[test]
// Port section when container has multiple ports
/// Port section when container has multiple ports
fn test_draw_blocks_ports_multiple_ports() {
let (w, h) = (32, 8);
let mut setup = test_setup(w, h, true, true);
@@ -2883,12 +2929,9 @@ mod tests {
if row_index == 1 && result_cell_as_char {
assert_eq!(result_cell.fg, Color::Yellow);
}
if row_index == 2 && result_cell_as_char {
if (2..=3).contains(&row_index) && result_cell_as_char {
assert_eq!(result_cell.fg, Color::White);
}
if row_index == 3 && result_cell_as_char {
assert_eq!(result_cell.fg, Color::Magenta);
}
if row_index == 4 && result_cell_as_char {
assert_eq!(result_cell.fg, Color::White);
}
@@ -2897,7 +2940,7 @@ mod tests {
}
#[test]
// Port section title color correct dependant on state
/// Port section title color correct dependant on state
fn test_draw_blocks_ports_container_state() {
let (w, h) = (32, 8);
let mut setup = test_setup(w, h, true, true);
@@ -2951,6 +2994,7 @@ mod tests {
})
.unwrap();
// This is wrong - why?
let expected = [
"╭─────────── ports ────────────╮",
"│ ip private public │",
@@ -2988,7 +3032,7 @@ mod tests {
// The whole layout //
// **************** //
#[test]
// Check that the whole layout is drawn correctly
/// Check that the whole layout is drawn correctly
fn test_draw_blocks_whole_layout() {
let (w, h) = (160, 30);
let mut setup = test_setup(w, h, true, true);
@@ -3028,7 +3072,7 @@ mod tests {
"│ │",
"│ │",
"╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
"╭───────────────────────── cpu 03.00% ──────────────────────────╮╭─────────────────────── memory 30.00 kB ───────────────────────╮╭────────── ports ───────────╮",
"╭───────────────────────── cpu 03.00% ──────────────────────────╮╭─────────────────────── memory 30.00 kB ───────────────────────╮╭────────── ports ───────────╮",
"│10.00%│ •••• ││100.00 kB│ ••• ││ ip private public│",
"│ │ ••• • ││ │ ••• • ││ 8001 │",
"│ │•• ••• ││ │•• ••• ││127.0.0.1 8003 8003│",
@@ -3052,4 +3096,75 @@ mod tests {
}
}
}
#[test]
/// Check that the whole layout is drawn correctly when have long container name and long image name
fn test_draw_blocks_whole_layout_long_name() {
let (w, h) = (190, 30);
let mut setup = test_setup(w, h, true, true);
insert_chart_data(&setup);
insert_logs(&setup);
setup.app_data.lock().containers.items[0]
.ports
.push(ContainerPorts {
ip: Some("127.0.0.1".to_owned()),
private: 8003,
public: Some(8003),
});
setup.app_data.lock().containers.items[0].name =
ContainerName::from("a_long_container_name_for_the_purposes_of_this_test");
setup.app_data.lock().containers.items[0].image =
ContainerImage::from("a_long_image_name_for_the_purposes_of_this_test");
let expected = [
" name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
"╭ Containers 1/3 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮╭─────────────────╮",
"│⚪ a_long_container_name_for_the… ✓ running Up 1 hour 03.00% 30.00 kB / 30.00 kB 1 a_long_image_name_for_the_pur… 0.00 kB 0.00 kB ││▶ pause │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB ││ restart │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB ││ stop │",
"│ ││ delete │",
"│ ││ │",
"│ ││ │",
"╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯╰─────────────────╯",
"╭ Logs 3/3 - a_long_container_name_for_the_purposes_of_this_test ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│ line 1 │",
"│ line 2 │",
"│▶ line 3 │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
"╭───────────────────────────────── cpu 03.00% ─────────────────────────────────╮╭────────────────────────────── memory 30.00 kB ───────────────────────────────╮╭────────── ports ───────────╮",
"│10.00%│ •••• ││100.00 kB│ ••••• ││ ip private public│",
"│ │ •••• • ││ │ ••• • ││ 8001 │",
"│ │••• •••• ││ │••• ••• ││127.0.0.1 8003 8003│",
"│ │ ││ │ ││ │",
"╰──────────────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
];
setup
.terminal
.draw(|f| {
draw_frame(f, &setup.app_data, &setup.gui_state);
})
.unwrap();
let result = &setup.terminal.backend().buffer().content;
for (row_index, row) in expected.iter().enumerate() {
for (char_index, expected_char) in row.chars().enumerate() {
let index = row_index * usize::from(w) + char_index;
let result_cell = &result[index];
assert_eq!(result_cell.symbol(), expected_char.to_string(),);
}
}
}
}
+6 -6
View File
@@ -109,19 +109,19 @@ impl BoxLocation {
) -> [Constraint; 3] {
match self {
Self::TopLeft | Self::MiddleLeft | Self::BottomLeft => [
Constraint::Max(text_width),
Constraint::Min(text_width),
Constraint::Max(blank_horizontal),
Constraint::Max(blank_horizontal),
],
Self::TopCentre | Self::MiddleCentre | Self::BottomCentre => [
Constraint::Max(blank_horizontal),
Constraint::Max(text_width),
Constraint::Min(text_width),
Constraint::Max(blank_horizontal),
],
Self::TopRight | Self::MiddleRight | Self::BottomRight => [
Constraint::Max(blank_horizontal),
Constraint::Max(blank_horizontal),
Constraint::Max(text_width),
Constraint::Min(text_width),
],
}
}
@@ -133,19 +133,19 @@ impl BoxLocation {
) -> [Constraint; 3] {
match self {
Self::TopLeft | Self::TopCentre | Self::TopRight => [
Constraint::Max(number_lines),
Constraint::Min(number_lines),
Constraint::Max(blank_vertical),
Constraint::Max(blank_vertical),
],
Self::MiddleLeft | Self::MiddleCentre | Self::MiddleRight => [
Constraint::Max(blank_vertical),
Constraint::Max(number_lines),
Constraint::Min(number_lines),
Constraint::Max(blank_vertical),
],
Self::BottomLeft | Self::BottomCentre | Self::BottomRight => [
Constraint::Max(blank_vertical),
Constraint::Max(blank_vertical),
Constraint::Max(number_lines),
Constraint::Min(number_lines),
],
}
}
+4 -3
View File
@@ -265,13 +265,14 @@ fn draw_frame(f: &mut Frame, app_data: &Arc<Mutex<AppData>>, gui_state: &Arc<Mut
let whole_layout = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(1), Constraint::Min(100)].as_ref())
.constraints([Constraint::Max(1), Constraint::Min(1)].as_ref())
.split(f.size());
// Split into 3, containers+controls, logs, then graphs
// This one is the issue!
let upper_main = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Max(fd.height), Constraint::Percentage(50)].as_ref())
.constraints([Constraint::Max(fd.height), Constraint::Min(1)].as_ref())
.split(whole_layout[1]);
let top_split = if fd.has_containers {
@@ -286,7 +287,7 @@ fn draw_frame(f: &mut Frame, app_data: &Arc<Mutex<AppData>>, gui_state: &Arc<Mut
.split(upper_main[0]);
let lower_split = if fd.has_containers {
vec![Constraint::Percentage(70), Constraint::Percentage(20)]
vec![Constraint::Percentage(70), Constraint::Percentage(30)]
} else {
vec![Constraint::Percentage(100)]
};