From 03157d841e4b1fe13dd430342ef3225008aba1e1 Mon Sep 17 00:00:00 2001 From: Joxit Date: Thu, 25 May 2023 07:01:50 +0200 Subject: [PATCH 1/4] test(branching): start new configurable branching repository system --- src/scripts/repositories.js | 27 +++++++++++++++++++++++++++ test/repositories.test.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/scripts/repositories.js create mode 100644 test/repositories.test.js diff --git a/src/scripts/repositories.js b/src/scripts/repositories.js new file mode 100644 index 0000000..caf9d1d --- /dev/null +++ b/src/scripts/repositories.js @@ -0,0 +1,27 @@ +const getRepositoryName = (split, max) => { + let repositoryName = ''; + for (let i = 0; i < max; i++) { + repositoryName += `${split[i]}/`; + } + return repositoryName; +}; + +export const getBranching = + (min = 1, max = 1) => + (repositories) => + repositories.sort().reduce(function (acc, image) { + const split = image.split('/'); + if (split.length > min && min > 0) { + const repoName = getRepositoryName(split, max); + if (acc.length === 0 || acc[acc.length - 1].repo != repoName) { + acc.push({ + repo: repoName, + images: [], + }); + } + acc[acc.length - 1].images.push(image); + return acc; + } + acc.push(image); + return acc; + }, []); diff --git a/test/repositories.test.js b/test/repositories.test.js new file mode 100644 index 0000000..d8bc125 --- /dev/null +++ b/test/repositories.test.js @@ -0,0 +1,31 @@ +import { getBranching } from '../src/scripts/repositories.js'; +import assert from 'assert'; + +describe('repositories', () => { + describe('getBranching', () => { + it('should not branch for no levels', () => { + const branching = getBranching(0, 0); + assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']); + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [ + 'alpine', + 'joxit/docker-registry-ui', + 'nginx', + ]); + }); + + it('should branch for one level', () => { + const branching = getBranching(1, 1); + assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']); + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [ + 'alpine', + { images: ['joxit/docker-registry-ui'], repo: 'joxit/' }, + 'nginx', + ]); + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'joxit/kokai', 'nginx']), [ + 'alpine', + { images: ['joxit/docker-registry-ui', 'joxit/kokai'], repo: 'joxit/' }, + 'nginx', + ]); + }); + }); +}); From 398fa65fa17189407ffa4f2e879f3de3f3e52e8a Mon Sep 17 00:00:00 2001 From: Joxit Date: Mon, 29 May 2023 15:38:38 +0200 Subject: [PATCH 2/4] test(branching): add new test for custom branching --- src/scripts/repositories.js | 48 +++++++++++++++---- test/repositories.test.js | 96 +++++++++++++++++++++++++++++++++++-- 2 files changed, 133 insertions(+), 11 deletions(-) diff --git a/src/scripts/repositories.js b/src/scripts/repositories.js index caf9d1d..1eac2ca 100644 --- a/src/scripts/repositories.js +++ b/src/scripts/repositories.js @@ -1,27 +1,59 @@ +import { DockerRegistryUIError } from './error.js'; + const getRepositoryName = (split, max) => { let repositoryName = ''; - for (let i = 0; i < max; i++) { + for (let i = 0; i < Math.min(max, split.length - 1); i++) { repositoryName += `${split[i]}/`; } return repositoryName; }; -export const getBranching = - (min = 1, max = 1) => - (repositories) => +const getLatestRepository = (repo, repoName) => { + if (!repo.images) { + return; + } + if (repo.repo === repoName) { + return repo; + } + for (let i = 0; i < repo.images.length; i++) { + const res = getLatestRepository(repo.images[i], repoName); + if (res) { + return res; + } + } + + if (repoName.startsWith(repo.repo)) { + const newRepo = { repo: repoName, images: [] }; + repo.images.push(newRepo); + return newRepo; + } +}; + +export const getBranching = (min = 1, max = 1) => { + if (min > max) { + throw new DockerRegistryUIError(`min must be inferior to max (min: ${min} <= max: ${max})`); + } else if (max < 0 || min < 0) { + throw new DockerRegistryUIError( + `min and max must be greater than equals to 0 (min: ${min} >= 0 and max: ${max} >= 0)` + ); + } + return (repositories) => repositories.sort().reduce(function (acc, image) { const split = image.split('/'); if (split.length > min && min > 0) { const repoName = getRepositoryName(split, max); - if (acc.length === 0 || acc[acc.length - 1].repo != repoName) { - acc.push({ + let repo = acc.length > 0 && getLatestRepository(acc[acc.length - 1], repoName); + if (!repo) { + repo = { repo: repoName, images: [], - }); + }; + acc.push(repo); } - acc[acc.length - 1].images.push(image); + repo.images.push(image); return acc; } acc.push(image); return acc; }, []); +}; diff --git a/test/repositories.test.js b/test/repositories.test.js index d8bc125..4e96e5c 100644 --- a/test/repositories.test.js +++ b/test/repositories.test.js @@ -1,4 +1,5 @@ import { getBranching } from '../src/scripts/repositories.js'; +import { DockerRegistryUIError } from '../src/scripts/error.js'; import assert from 'assert'; describe('repositories', () => { @@ -6,9 +7,10 @@ describe('repositories', () => { it('should not branch for no levels', () => { const branching = getBranching(0, 0); assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']); - assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [ + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'joxit/docker-registry-ui/amd64', 'nginx']), [ 'alpine', 'joxit/docker-registry-ui', + 'joxit/docker-registry-ui/amd64', 'nginx', ]); }); @@ -21,11 +23,99 @@ describe('repositories', () => { { images: ['joxit/docker-registry-ui'], repo: 'joxit/' }, 'nginx', ]); - assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'joxit/kokai', 'nginx']), [ + assert.deepEqual( + branching(['alpine', 'joxit/docker-registry-ui', 'joxit/kokai', 'joxit/docker-registry-ui/amd64', 'nginx']), + [ + 'alpine', + { images: ['joxit/docker-registry-ui', 'joxit/docker-registry-ui/amd64', 'joxit/kokai'], repo: 'joxit/' }, + 'nginx', + ] + ); + }); + + it('should branch for two level', () => { + const branching = getBranching(2, 2); + assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']); + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [ + 'alpine', + 'joxit/docker-registry-ui', + 'nginx', + ]); + assert.deepEqual( + branching([ + 'alpine', + 'joxit/docker-registry-ui', + 'joxit/kokai', + 'joxit/docker-registry-ui/amd64', + 'joxit/docker-registry-ui/amd64/latest', + 'joxit/docker-registry-ui/armv7', + 'joxit/docker-registry-ui/armv7/latest', + 'nginx', + ]), + [ + 'alpine', + 'joxit/docker-registry-ui', + { + images: [ + 'joxit/docker-registry-ui/amd64', + 'joxit/docker-registry-ui/amd64/latest', + 'joxit/docker-registry-ui/armv7', + 'joxit/docker-registry-ui/armv7/latest', + ], + repo: 'joxit/docker-registry-ui/', + }, + 'joxit/kokai', + 'nginx', + ] + ); + }); + + it('should branch from one to two level', () => { + const branching = getBranching(1, 2); + assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']); + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [ 'alpine', - { images: ['joxit/docker-registry-ui', 'joxit/kokai'], repo: 'joxit/' }, + { images: ['joxit/docker-registry-ui'], repo: 'joxit/' }, 'nginx', ]); + assert.deepEqual( + branching([ + 'alpine', + 'joxit/docker-registry-ui', + 'joxit/kokai', + 'joxit/docker-registry-ui/amd64', + 'joxit/docker-registry-ui/amd64/latest', + 'joxit/docker-registry-ui/armv7', + 'joxit/docker-registry-ui/armv7/latest', + 'nginx', + ]), + [ + 'alpine', + { + images: [ + 'joxit/docker-registry-ui', + { + images: [ + 'joxit/docker-registry-ui/amd64', + 'joxit/docker-registry-ui/amd64/latest', + 'joxit/docker-registry-ui/armv7', + 'joxit/docker-registry-ui/armv7/latest', + ], + repo: 'joxit/docker-registry-ui/', + }, + 'joxit/kokai', + ], + repo: 'joxit/', + }, + 'nginx', + ] + ); }); }); + + it('should branch from one to two level', () => { + assert.throws(() => getBranching(2, 1), DockerRegistryUIError, `Did not throw on min > max`); + assert.throws(() => getBranching(-2, 1), DockerRegistryUIError, `Did not throw on min < 0`); + assert.throws(() => getBranching(2, -1), DockerRegistryUIError, `Did not throw on max < 0`); + }); }); From 1031034bc4fc44c66ce4a4c87a87d29fb19bbf20 Mon Sep 17 00:00:00 2001 From: Joxit Date: Tue, 30 May 2023 07:49:18 +0200 Subject: [PATCH 3/4] feat(branching): add configuration for catalog arborescence --- bin/90-docker-registry-ui.sh | 2 ++ src/components/catalog/catalog-element.riot | 7 ++++ src/components/catalog/catalog.riot | 39 ++++++++++++--------- src/components/docker-registry-ui.riot | 32 +++++++++-------- src/components/error-page.riot | 4 +++ src/components/tag-history/tag-history.riot | 1 - src/index.html | 4 +++ src/scripts/error.js | 3 +- src/scripts/repositories.js | 17 +++++++-- src/style.scss | 13 +++---- test/repositories.test.js | 1 + 11 files changed, 80 insertions(+), 43 deletions(-) diff --git a/bin/90-docker-registry-ui.sh b/bin/90-docker-registry-ui.sh index c9c732f..94fd0ab 100755 --- a/bin/90-docker-registry-ui.sh +++ b/bin/90-docker-registry-ui.sh @@ -13,6 +13,8 @@ sed -i "s~\${HISTORY_CUSTOM_LABELS}~${HISTORY_CUSTOM_LABELS}~" index.html sed -i "s~\${USE_CONTROL_CACHE_HEADER}~${USE_CONTROL_CACHE_HEADER}~" index.html sed -i "s~\${TAGLIST_ORDER}~${TAGLIST_ORDER}~" index.html sed -i "s~\${CATALOG_DEFAULT_EXPANDED}~${CATALOG_DEFAULT_EXPANDED}~" index.html +sed -i "s~\${CATALOG_MIN_BRANCHES}~${CATALOG_MIN_BRANCHES}~" index.html +sed -i "s~\${CATALOG_MAX_BRANCHES}~${CATALOG_MAX_BRANCHES}~" index.html grep -o 'THEME[A-Z_]*' index.html | while read e; do sed -i "s~\${$e}~$(printenv $e)~" index.html diff --git a/src/components/catalog/catalog-element.riot b/src/components/catalog/catalog-element.riot index 788ae9b..b235056 100644 --- a/src/components/catalog/catalog-element.riot +++ b/src/components/catalog/catalog-element.riot @@ -52,6 +52,7 @@ along with this program. If not, see . show-catalog-nb-tags="{ props.showCatalogNbTags }" class="animated {!state.expanded && !props.filterResults ? 'hide' : ''} {state.expanding ? 'expanding' : ''}" each="{item in state.images}" + z-index="{ props.zIndex - 1 }" item="{ item }" > @@ -76,6 +77,12 @@ along with this program. If not, see . this.getNbTags(props, state); } }, + onMounted(props, state) { + const materialCard = this.$('material-card'); + if (materialCard) { + materialCard.style['z-index'] = props.zIndex; + } + }, onBeforeUpdate(props, state) { if (props.filterResults && state.images) { state.nImages = state.images.filter((image) => matchSearch(props.filterResults, image)).length; diff --git a/src/components/catalog/catalog.riot b/src/components/catalog/catalog.riot index 91aea31..3365a2f 100644 --- a/src/components/catalog/catalog.riot +++ b/src/components/catalog/catalog.riot @@ -35,10 +35,12 @@ along with this program. If not, see . on-authentication="{ props.onAuthentication }" show-catalog-nb-tags="{ props.showCatalogNbTags }" catalog-default-expanded="{ props.catalogDefaultExpanded || state.nRepositories === 1 }" + z-index="{ props.catalogMaxBranches - props.catalogMinBranches + 2 }" > + diff --git a/src/components/docker-registry-ui.riot b/src/components/docker-registry-ui.riot index 5f39d37..1ea7032 100644 --- a/src/components/docker-registry-ui.riot +++ b/src/components/docker-registry-ui.riot @@ -31,6 +31,21 @@ along with this program. If not, see .
+ + . on-authentication="{ onAuthentication }" show-catalog-nb-tags="{ truthy(props.showCatalogNbTags) }" catalog-default-expanded="{ truthy(props.catalogDefaultExpanded) }" + catalog-min-branches="{ props.catalogMinBranches }" + catalog-max-branches="{ props.catalogMaxBranches }" > @@ -82,21 +99,6 @@ along with this program. If not, see . on-authenticated="{ state.onAuthenticated }" opened="{ state.authenticationDialogOpened }" > - -