Skip to content

Commit d2222be

Browse files
authored
feat(taglist-order): add new option TAGLIST_ORDER (#307)
Create new option named `TAGLIST_ORDER` that will order tags using user defined configuration. Available values are: | value | description | | --- | --- | | `num-asc;alpha-asc` | Numbers come first in **ascending** order then alphabet in **ascending** order | | `num-desc;alpha-asc` | Numbers come first in **descending** order then alphabet in **ascending** order | | `num-asc;alpha-desc` | Numbers come first in **ascending** order then alphabet in **descending** order | | `num-desc;alpha-desc` | Numbers come first in **descending** order then alphabet in **descending** order | | `alpha-asc;num-asc` | Alphabet come first in **ascending** order then numbers in **ascending** order | | `alpha-asc;num-desc` (default) | Alphabet come first in **ascending** order then numbers in **descending** order | | `alpha-desc;num-asc` | Alphabet come first in **descending** order then numbers in **ascending** order | | `alpha-desc;num-desc` | Alphabet come first in **descending** order then numbers in **descending** order | Some examples in [test/taglist-order.test.js](https://github.com/Joxit/docker-registry-ui/blob/8bbfc5c390c334e66741d5a639d4b17c8fe6fcea/test/taglist-order.test.js) closes #294
2 parents bc80050 + c6dee14 commit d2222be

File tree

10 files changed

+277
-31
lines changed

10 files changed

+277
-31
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ Some env options are available for use this interface for **only one server** (w
9696
- `USE_CONTROL_CACHE_HEADER`: Use `Control-Cache` header and set to `no-store, no-cache`. This will avoid some issues on multi-arch images (see [#260](https://github.com/Joxit/docker-registry-ui/issues/260) and [#265](https://github.com/Joxit/docker-registry-ui/pull/265)). This option requires registry configuration: `Access-Control-Allow-Headers` with `Cache-Control`. (default: `false`). Since 2.3.0
9797
- `THEME`: Chose your default theme, could be `dark`, `light` or `auto` (see [#283](https://github.com/Joxit/docker-registry-ui/pull/283)). When auto is selected, you will have a switch to manually change from light to dark and vice-versa (see [#291](https://github.com/Joxit/docker-registry-ui/pull/291)). (default: `auto`). Since 2.4.0
9898
- `THEME_*`: See table in [Theme options](#theme-options) section (see [#283](https://github.com/Joxit/docker-registry-ui/pull/283)). Since 2.4.0
99+
- `TAGLIST_ORDER`: Set the default order for the taglist page, could be `num-asc;alpha-asc`, `num-desc;alpha-asc`, `num-asc;alpha-desc`, `num-desc;alpha-desc`, `alpha-asc;num-asc`, `alpha-asc;num-desc`, `alpha-desc;num-asc` or `alpha-desc;num-desc` (see [#307](https://github.com/Joxit/docker-registry-ui/pull/307)). (default: `alpha-asc;num-desc`) Since 2.5.0
99100

100101
There are some examples with [docker-compose](https://docs.docker.com/compose/) and docker-registry-ui as proxy [here](https://github.com/Joxit/docker-registry-ui/tree/main/examples/ui-as-proxy/) or docker-registry-ui as standalone [here](https://github.com/Joxit/docker-registry-ui/tree/main/examples/ui-as-standalone/).
101102

bin/90-docker-registry-ui.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ sed -i "s~\${READ_ONLY_REGISTRIES}~${READ_ONLY_REGISTRIES}~" index.html
1111
sed -i "s~\${SHOW_CATALOG_NB_TAGS}~${SHOW_CATALOG_NB_TAGS}~" index.html
1212
sed -i "s~\${HISTORY_CUSTOM_LABELS}~${HISTORY_CUSTOM_LABELS}~" index.html
1313
sed -i "s~\${USE_CONTROL_CACHE_HEADER}~${USE_CONTROL_CACHE_HEADER}~" index.html
14+
sed -i "s~\${TAGLIST_ORDER}~${TAGLIST_ORDER}~" index.html
1415

1516
grep -o 'THEME[A-Z_]*' index.html | while read e; do
1617
sed -i "s~\${$e}~$(printenv $e)~" index.html

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"format-riot": "find src rollup rollup.config.js -name '*.riot' -exec prettier --config .prettierrc -w --parser html {} \\;",
1010
"start": "rollup -c -w --environment ROLLUP_SERVE:true",
1111
"build": "rollup -c",
12-
"build:electron": "npm run build && cd examples/electron && npm install && npm run dist"
12+
"build:electron": "npm run build && cd examples/electron && npm install && npm run dist",
13+
"test": "mocha"
1314
},
1415
"repository": {
1516
"type": "git",
@@ -31,6 +32,7 @@
3132
"@rollup/plugin-node-resolve": "^15.0.1",
3233
"@rollup/plugin-terser": "^0.2.1",
3334
"core-js": "^3.27.1",
35+
"mocha": "^10.2.0",
3436
"node-sass": "^8.0.0",
3537
"prettier": "^2.8.1",
3638
"riot": "^7.1.0",

src/components/docker-registry-ui.riot

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
5555
filter-results="{ state.filter }"
5656
on-authentication="{ onAuthentication }"
5757
use-control-cache-header="{ truthy(props.useControlCacheHeader) }"
58+
taglist-order="{ props.taglistOrder }"
5859
></tag-list>
5960
</route>
6061
<route path="{baseRoute}taghistory/(.*)">

src/components/tag-list/tag-list.riot

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
6161

6262
<script>
6363
import { Http } from '../../scripts/http';
64-
import { DockerImage, compare } from '../../scripts/docker-image';
64+
import { DockerImage } from '../../scripts/docker-image';
6565
import { getNumPages, getPageLabels } from '../../scripts/utils';
6666
import Pagination from './pagination.riot';
6767
import TagTable from './tag-table.riot';
6868
import router from '../../scripts/router';
69+
import { getTagComparator, taglistOrderParser } from '../../scripts/taglist-order';
70+
6971
export default {
7072
components: {
7173
Pagination,
@@ -79,13 +81,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
7981
asc: true,
8082
page: router.getPageQueryParam() || 1,
8183
};
84+
try {
85+
this.state.taglistOrder = taglistOrderParser(props.taglistOrder)
86+
} catch(e) {
87+
props.onNotify(e);
88+
}
8289
},
8390
onMounted(props, state) {
8491
this.display(props, state);
8592
window.addEventListener('resize', this.onResize);
8693
// this may be run before the final document size is available, so schedule
8794
// a correction once everything is set up.
8895
window.requestAnimationFrame(this.onResize);
96+
this.tagComparator = getTagComparator(props.taglistOrder);
8997
},
9098
display(props, state) {
9199
state.tags = [];
@@ -106,7 +114,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
106114
useControlCacheHeader: props.useControlCacheHeader,
107115
})
108116
)
109-
.sort(compare);
117+
.sort(self.tagComparator);
110118
window.requestAnimationFrame(self.onResize);
111119
self.update({
112120
page: Math.min(state.page, getNumPages(tags)),
@@ -168,7 +176,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
168176
this.state.tags.reverse();
169177
this.state.asc = false;
170178
} else {
171-
this.state.tags.sort(compare);
179+
this.state.tags.sort(this.tagComparator);
172180
this.state.asc = true;
173181
}
174182
this.update();

src/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
show-catalog-nb-tags="${SHOW_CATALOG_NB_TAGS}"
4848
history-custom-labels="${HISTORY_CUSTOM_LABELS}"
4949
use-control-cache-header="${USE_CONTROL_CACHE_HEADER}"
50+
taglist-order="${TAGLIST_ORDER}"
5051
theme="${THEME}"
5152
theme-primary-text="${THEME_PRIMARY_TEXT}"
5253
theme-neutral-text="${THEME_NEUTRAL_TEXT}"
@@ -73,6 +74,7 @@
7374
show-catalog-nb-tags="true"
7475
history-custom-labels="first_custom_labels,second_custom_labels"
7576
use-control-cache-header="false"
77+
taglist-order=""
7678
theme="auto"
7779
theme-primary-text=""
7880
theme-neutral-text=""

src/scripts/docker-image.js

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,6 @@ import { Http } from './http';
1818
import { isDigit, eventTransfer, ERROR_CAN_NOT_READ_CONTENT_DIGEST } from './utils';
1919
import observable from '@riotjs/observable';
2020

21-
const tagReduce = (acc, e) => {
22-
if (acc.length > 0 && isDigit(acc[acc.length - 1].charAt(0)) == isDigit(e)) {
23-
acc[acc.length - 1] += e;
24-
} else {
25-
acc.push(e);
26-
}
27-
return acc;
28-
};
29-
30-
export function compare(e1, e2) {
31-
const tag1 = e1.tag.match(/./g).reduce(tagReduce, []);
32-
const tag2 = e2.tag.match(/./g).reduce(tagReduce, []);
33-
34-
for (var i = 0; i < tag1.length && i < tag2.length; i++) {
35-
const compare = tag1[i].localeCompare(tag2[i]);
36-
if (isDigit(tag1[i].charAt(0)) && isDigit(tag2[i].charAt(0))) {
37-
const diff = tag1[i] - tag2[i];
38-
if (diff != 0) {
39-
return diff;
40-
}
41-
} else if (compare != 0) {
42-
return compare;
43-
}
44-
}
45-
return e1.tag.length - e2.tag.length;
46-
}
47-
4821
export class DockerImage {
4922
constructor(name, tag, { list, registryUrl, onNotify, onAuthentication, useControlCacheHeader }) {
5023
this.name = name;

src/scripts/error.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export class DockerRegistryUIError extends Error {
2+
constructor(msg) {
3+
super(msg);
4+
this.isError = true;
5+
}
6+
}

src/scripts/taglist-order.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { DockerRegistryUIError } from './error.js';
2+
import { isDigit } from './utils.js';
3+
4+
const TAGLIST_ORDER_REGEX = /(alpha-(asc|desc);num-(asc|desc))|(num-(asc|desc);alpha-(asc|desc))/;
5+
6+
export const taglistOrderVariants = (taglistOrder) => {
7+
switch (taglistOrder) {
8+
case 'desc':
9+
return 'alpha-desc;num-desc';
10+
case 'asc':
11+
return 'num-asc;alpha-asc';
12+
case 'alpha-desc':
13+
case 'alpha-asc':
14+
case 'num-desc':
15+
case 'num-asc':
16+
return `${taglistOrder};${taglistOrder.startsWith('num') ? 'alpha' : 'num'}-asc`;
17+
default:
18+
if (!taglistOrder) {
19+
return 'alpha-asc;num-desc';
20+
} else if (TAGLIST_ORDER_REGEX.test(taglistOrder)) {
21+
return taglistOrder;
22+
}
23+
throw new DockerRegistryUIError(`The taglist order \`${taglistOrder}\` is not recognized.`);
24+
}
25+
};
26+
27+
export const taglistOrderParser = (taglistOrder) => {
28+
const orders = taglistOrderVariants(taglistOrder)
29+
.split(';')
30+
.filter((e) => e)
31+
.map((e) => e.split('-').filter((e) => e))
32+
.reduce((acc, e, idx) => {
33+
if (e.length > 1) {
34+
acc[e[0] + 'Asc'] = e[1] === 'asc';
35+
}
36+
if (idx === 0) {
37+
acc.numFirst = e[0] === 'num';
38+
}
39+
return acc;
40+
}, {});
41+
42+
return orders;
43+
};
44+
45+
export const tagReduce = (acc, e) => {
46+
if (acc.length > 0 && isDigit(acc[acc.length - 1].charAt(0)) == isDigit(e)) {
47+
acc[acc.length - 1] += e;
48+
} else {
49+
acc.push(e);
50+
}
51+
return acc;
52+
};
53+
54+
export const splitTagToArray = (tag) =>
55+
tag
56+
.split('')
57+
.reduce(tagReduce, [])
58+
.map((e) => (isDigit(e.charAt(0)) ? parseInt(e) : e));
59+
60+
const applyOrder = (order, e1, e2) => {
61+
if (e1 === e2) {
62+
return 0;
63+
}
64+
const numFirst = order.numFirst ? 1 : -1;
65+
if (typeof e1 === 'number') {
66+
const factor = order.numAsc ? 1 : -1;
67+
return typeof e2 === 'number' ? (e1 - e2) * factor : -1 * numFirst;
68+
} else if (typeof e2 === 'number') {
69+
return 1 * numFirst;
70+
} else {
71+
const factor = order.alphaAsc ? 1 : -1;
72+
return e1.localeCompare(e2) * factor;
73+
}
74+
};
75+
76+
export const getTagComparator = (order) => {
77+
return (e1, e2) => {
78+
const tag1 = splitTagToArray(e1.tag || e1);
79+
const tag2 = splitTagToArray(e2.tag || e2);
80+
81+
for (var i = 0; i < tag1.length && i < tag2.length; i++) {
82+
const compare = applyOrder(order, tag1[i], tag2[i]);
83+
if (compare != 0) {
84+
return compare;
85+
}
86+
}
87+
return (e1.tag || e1).length - (e2.tag || e2).length;
88+
};
89+
};

0 commit comments

Comments
 (0)