mirror of
https://github.com/Joxit/docker-registry-ui.git
synced 2026-02-17 21:19:51 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ddfb1b5ae | ||
|
|
3a385fc08d | ||
|
|
f958365336 | ||
|
|
29c17b1baa | ||
|
|
b323dc6c04 | ||
|
|
992328eae9 | ||
|
|
dd26bf66a2 | ||
|
|
8fcae3cda4 | ||
|
|
f4455703ca | ||
|
|
22e3f2254e | ||
|
|
4075e0005c | ||
|
|
7c00b85183 | ||
|
|
21e3ad51af | ||
|
|
73613a3b96 | ||
|
|
6da744a9c5 | ||
|
|
db6b74a5f0 |
18
.github/workflows/release.yml
vendored
18
.github/workflows/release.yml
vendored
@@ -15,9 +15,15 @@ jobs:
|
||||
run: npm install
|
||||
- name: Build the interface
|
||||
run: npm run build
|
||||
- name: Current tag
|
||||
id: current-tag
|
||||
- name: Major tag
|
||||
id: major-tag
|
||||
run: echo "::set-output name=tag::$(git describe --tags | grep -o '^[0-9]*')"
|
||||
- name: Minor tag
|
||||
id: minor-tag
|
||||
run: echo "::set-output name=tag::$(git describe --tags | grep -o '^[0-9]*\.[0-9]*')"
|
||||
- name: Patch tag
|
||||
id: patch-tag
|
||||
run: echo "::set-output name=tag::$(git describe --tags | grep -o '^[0-9]*\.[0-9]*\.[0-9]*')"
|
||||
- name: Download kokai
|
||||
run: curl -sSL https://github.com/Joxit/kokai/releases/download/$(curl -sSL https://api.github.com/repos/Joxit/kokai/releases/latest | jq -r ".tag_name")/kokai-linux-x86_64 > kokai
|
||||
- name: Create Release Note
|
||||
@@ -51,7 +57,9 @@ jobs:
|
||||
push: true
|
||||
tags: |
|
||||
joxit/docker-registry-ui:latest
|
||||
joxit/docker-registry-ui:${{steps.current-tag.outputs.tag}}
|
||||
joxit/docker-registry-ui:${{steps.major-tag.outputs.tag}}
|
||||
joxit/docker-registry-ui:${{steps.minor-tag.outputs.tag}}
|
||||
joxit/docker-registry-ui:${{steps.patch-tag.outputs.tag}}
|
||||
- name: Build and push Latest Debian Version
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
@@ -61,4 +69,6 @@ jobs:
|
||||
push: true
|
||||
tags: |
|
||||
joxit/docker-registry-ui:debian
|
||||
joxit/docker-registry-ui:${{steps.current-tag.outputs.tag}}-debian
|
||||
joxit/docker-registry-ui:${{steps.major-tag.outputs.tag}}-debian
|
||||
joxit/docker-registry-ui:${{steps.minor-tag.outputs.tag}}-debian
|
||||
joxit/docker-registry-ui:${{steps.patch-tag.outputs.tag}}-debian
|
||||
18
README.md
18
README.md
@@ -41,9 +41,13 @@ This web user interface uses [Riot](https://github.com/Riot/riot) the react-like
|
||||
- Add Title when using `REGISTRY_TITLE` (see [#28](https://github.com/Joxit/docker-registry-ui/issues/28)).
|
||||
- Customise docker pull command on static registry UI (see [#71](https://github.com/Joxit/docker-registry-ui/issues/71)).
|
||||
- Add custom header via environment variable and file via `NGINX_PROXY_HEADER_*` (see [#89](https://github.com/Joxit/docker-registry-ui/pull/89))
|
||||
- Show/Hide content digest in taglist via `SHOW_CONTENT_DIGEST` (values are: [`true`, `false`], default: `true`) (see [#126](https://github.com/Joxit/docker-registry-ui/issues/126)).
|
||||
- Show/Hide content digest in taglist via `SHOW_CONTENT_DIGEST` (values are: [`true`, `false`], default: `false`) (see [#126](https://github.com/Joxit/docker-registry-ui/issues/126)).
|
||||
- Limit the number of elements in the image list via `CATALOG_ELEMENTS_LIMIT` (see [#127](https://github.com/Joxit/docker-registry-ui/pull/127)).
|
||||
- Multi arch support in history page (see [#130](https://github.com/Joxit/docker-registry-ui/issues/130) and [#134](https://github.com/Joxit/docker-registry-ui/pull/134))
|
||||
- Set a list of default registries with `DEFAULT_REGISTRIES` (see [#219](https://github.com/Joxit/docker-registry-ui/pull/219)).
|
||||
- Desactivate add and remove regisitries with `READ_ONLY_REGISTRIES` (see [#219](https://github.com/Joxit/docker-registry-ui/pull/219)).
|
||||
- Filter images and tags with a search bar. You can select the search bar with the shortcut `CRTL` + `F` or `F3`. When the search bar is already focused, the shortcut will fallback to the default behavior (see [#213](https://github.com/Joxit/docker-registry-ui/issues/213)).
|
||||
- **Forward** custom header to your backend registry via environment variable and file via `NGINX_PROXY_PASS_HEADER_*` (see [#206](https://github.com/Joxit/docker-registry-ui/pull/206)).
|
||||
|
||||
## FAQ
|
||||
|
||||
@@ -64,7 +68,7 @@ This web user interface uses [Riot](https://github.com/Riot/riot) the react-like
|
||||
- Why the default nginx `Host` is set to `$http_host` ?
|
||||
- This fixes the issue [#88](https://github.com/Joxit/docker-registry-ui/issues/88). More about this in [#113](https://github.com/Joxit/docker-registry-ui/issues/113).
|
||||
- Why DELETE fails with 401 status code (using Basic Auth) ?
|
||||
- This is caused by a bug in docker registry, I suggest to have your UI on the same domain than your registry e.g. registry.example.com/ui/. (see [#104](https://github.com/Joxit/docker-registry-ui/issues/104)).
|
||||
- This is caused by a bug in docker registry, I suggest to have your UI on the same domain than your registry and use `NGINX_PROXY_PASS_URL` e.g. registry.example.com/ui/. (see [#104](https://github.com/Joxit/docker-registry-ui/issues/104), [#204](https://github.com/Joxit/docker-registry-ui/issues/204), [#207](https://github.com/Joxit/docker-registry-ui/issues/207), [#214](https://github.com/Joxit/docker-registry-ui/issues/214)).
|
||||
- Can I use the docker registry ui as a standalone application (with Electron) ?
|
||||
- Yes, check out the example [here](https://github.com/Joxit/docker-registry-ui/tree/main/examples/electron). (see [#129](https://github.com/Joxit/docker-registry-ui/pull/129))
|
||||
- I deleted images through the UI, but they are still present on the server. How can I delete them?
|
||||
@@ -83,11 +87,14 @@ Some env options are available for use this interface for **only one server**.
|
||||
- `REGISTRY_TITLE`: Set a custom title for your user interface. (default: value derived from `REGISTRY_URL`).
|
||||
- `PULL_URL`: Set a custom url when you copy the `docker pull` command. (default: value derived from `REGISTRY_URL`).
|
||||
- `DELETE_IMAGES`: Set if we can delete images from the UI. (default: `false`)
|
||||
- `SHOW_CONTENT_DIGEST`: Show content digest in docker tag list. (default: `true`)
|
||||
- `SHOW_CONTENT_DIGEST`: Show content digest in docker tag list. (default: `false`)
|
||||
- `CATALOG_ELEMENTS_LIMIT`: Limit the number of elements in the catalog page. (default: `100000`).
|
||||
- `SINGLE_REGISTRY`: Remove the menu that show the dialogs to add, remove and change the endpoint of your docker registry. (default `false`)
|
||||
- `SINGLE_REGISTRY`: Remove the menu that show the dialogs to add, remove and change the endpoint of your docker registry. (default: `false`).
|
||||
- `NGINX_PROXY_PASS_URL`: Update the default Nginx configuration and set the **proxy_pass** to your backend docker registry (this avoid CORS configuration). This is usually the name of your registry container in the form `http://registry:5000`.
|
||||
- `NGINX_PROXY_HEADER_*`: Update the default Nginx configuration and set **custom headers** for your backend docker registry. Only when `NGINX_PROXY_PASS_URL` is used.
|
||||
- `NGINX_PROXY_HEADER_*`: Update the default Nginx configuration and **set custom headers** for your backend docker registry. Only when `NGINX_PROXY_PASS_URL` is used.
|
||||
- `NGINX_PROXY_HEADER_*`: Update the default Nginx configuration and **forward custom headers** to your backend docker registry. Only when `NGINX_PROXY_PASS_URL` is used.
|
||||
- `DEFAULT_REGISTRIES`: List of comma separated registry URLs (e.g `http://registry.example.com,http://registry:5000`), available only when `SINGLE_REGISTRY=false`. (default: ` `).
|
||||
- `READ_ONLY_REGISTRIES`: Desactivate dialog for remove and add new registries, available only when `SINGLE_REGISTRY=false`. (default: `false`).
|
||||
|
||||
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/).
|
||||
|
||||
@@ -182,3 +189,4 @@ check out the [Electron](examples/electron/README.md) standalone application.
|
||||
- [UI showing same sha256 content digest for all tags + Delete is not working](https://github.com/Joxit/docker-registry-ui/tree/main/examples/issue-116) ([#116](https://github.com/Joxit/docker-registry-ui/issues/116))
|
||||
- [Electron-based Standalone Application](https://github.com/Joxit/docker-registry-ui/tree/main/examples/electron) ([#129](https://github.com/Joxit/docker-registry-ui/pull/129))
|
||||
- [Use docker-registry-ui as proxy with read-only right](https://github.com/Joxit/docker-registry-ui/tree/main/examples/read-only-auth) ([#47](https://github.com/Joxit/docker-registry-ui/issues/47))
|
||||
- [Use DEFAULT_REGISTRIES and READ_ONLY_REGISTRIES](https://github.com/Joxit/docker-registry-ui/tree/main/examples/pr-219) ([#219](https://github.com/Joxit/docker-registry-ui/issues/219))
|
||||
|
||||
@@ -12,4 +12,6 @@ defaults:
|
||||
- scope:
|
||||
path: ""
|
||||
values:
|
||||
image: /screenshot.png
|
||||
image: /screenshot.png
|
||||
plugins:
|
||||
- jekyll-seo-tag
|
||||
@@ -1,11 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
sed -i "s,\${REGISTRY_URL},${REGISTRY_URL}," index.html
|
||||
sed -i "s,\${REGISTRY_TITLE},${REGISTRY_TITLE}," index.html
|
||||
sed -i "s,\${PULL_URL},${PULL_URL}," index.html
|
||||
sed -i "s,\${SINGLE_REGISTRY},${SINGLE_REGISTRY}," index.html
|
||||
sed -i "s/\${CATALOG_ELEMENTS_LIMIT}/${CATALOG_ELEMENTS_LIMIT}/" index.html
|
||||
sed -i "s/\${SHOW_CONTENT_DIGEST}/${SHOW_CONTENT_DIGEST}/" index.html
|
||||
sed -i "s~\${REGISTRY_URL}~${REGISTRY_URL}~" index.html
|
||||
sed -i "s~\${REGISTRY_TITLE}~${REGISTRY_TITLE}~" index.html
|
||||
sed -i "s~\${PULL_URL}~${PULL_URL}~" index.html
|
||||
sed -i "s~\${SINGLE_REGISTRY}~${SINGLE_REGISTRY}~" index.html
|
||||
sed -i "s~\${CATALOG_ELEMENTS_LIMIT}~${CATALOG_ELEMENTS_LIMIT}~" index.html
|
||||
sed -i "s~\${SHOW_CONTENT_DIGEST}~${SHOW_CONTENT_DIGEST}~" index.html
|
||||
sed -i "s~\${DEFAULT_REGISTRIES}~${DEFAULT_REGISTRIES}~" index.html
|
||||
sed -i "s~\${READ_ONLY_REGISTRIES}~${READ_ONLY_REGISTRIES}~" index.html
|
||||
|
||||
if [ -z "${DELETE_IMAGES}" ] || [ "${DELETE_IMAGES}" = false ] ; then
|
||||
sed -i "s/\${DELETE_IMAGES}/false/" index.html
|
||||
@@ -30,8 +32,25 @@ get_nginx_proxy_headers() {
|
||||
done
|
||||
}
|
||||
|
||||
get_nginx_proxy_pass_headers() {
|
||||
(
|
||||
env &&
|
||||
if [ -f "/etc/nginx/.env" ]; then
|
||||
cat /etc/nginx/.env
|
||||
# Force new line
|
||||
echo ""
|
||||
fi
|
||||
) | while read e; do
|
||||
if [ -n "$(echo $e | grep -o '^NGINX_PROXY_PASS_HEADER_')" ]; then
|
||||
key=$(echo ${e%%=*} | sed 's/^NGINX_PROXY_PASS_HEADER_//' | sed 's/_/-/g')
|
||||
echo -n "proxy_pass_header \"${key}\"; "
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
if [ -n "${NGINX_PROXY_PASS_URL}" ] ; then
|
||||
sed -i "s,\${NGINX_PROXY_PASS_URL},${NGINX_PROXY_PASS_URL}," /etc/nginx/conf.d/default.conf
|
||||
sed -i "s^\${NGINX_PROXY_HEADERS}^$(get_nginx_proxy_headers)^" /etc/nginx/conf.d/default.conf
|
||||
sed -i "s^\${NGINX_PROXY_PASS_HEADERS}^$(get_nginx_proxy_pass_headers)^" /etc/nginx/conf.d/default.conf
|
||||
sed -i "s,#!,," /etc/nginx/conf.d/default.conf
|
||||
fi
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<body>
|
||||
<docker-registry-ui registry-url="" name="Demo Docker Registry UI" pull-url="" show-content-digest="true"
|
||||
is-image-remove-activated="true" catalog-elements-limit="1000" single-registry="false">
|
||||
is-image-remove-activated="true" catalog-elements-limit="1000" single-registry="false" default-registries="https://joxit.dev/docker-registry-demo">
|
||||
<script>
|
||||
if (localStorage.getItem('registryServer')) {
|
||||
localStorage.setItem('registryServer',
|
||||
@@ -46,10 +46,6 @@
|
||||
'https://joxit.dev/docker-registry-demo'
|
||||
)
|
||||
)
|
||||
} else {
|
||||
localStorage.setItem('registryServer', JSON.stringify([
|
||||
'https://joxit.dev/docker-registry-demo'
|
||||
]))
|
||||
}
|
||||
</script>
|
||||
<script src="../dist/docker-registry-ui.js"></script>
|
||||
|
||||
4
dist/docker-registry-ui.js
vendored
4
dist/docker-registry-ui.js
vendored
File diff suppressed because one or more lines are too long
3
dist/index.html
vendored
3
dist/index.html
vendored
@@ -15,4 +15,5 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--><!DOCTYPE html><html><head><meta charset="UTF-8"><link href="docker-registry-ui.css" rel="stylesheet" type="text/css"><meta name="viewport" content="width=device-width, initial-scale=1"><meta property="og:site_name" content="Docker Registry UI" /><meta name="twitter:card" content="summary" /><meta name="twitter:site" content="@Joxit" /><meta name="twitter:creator" content="@Jones Magloire" /><title>Docker Registry UI</title></head><body><docker-registry-ui registry-url="${REGISTRY_URL}" name="${REGISTRY_TITLE}" pull-url="${PULL_URL}"
|
||||
show-content-digest="${SHOW_CONTENT_DIGEST}" is-image-remove-activated="${DELETE_IMAGES}"
|
||||
catalog-elements-limit="${CATALOG_ELEMENTS_LIMIT}" single-registry="${SINGLE_REGISTRY}"></docker-registry-ui><script src="docker-registry-ui.js"></script></body></html>
|
||||
catalog-elements-limit="${CATALOG_ELEMENTS_LIMIT}" single-registry="${SINGLE_REGISTRY}"
|
||||
default-registries="${DEFAULT_REGISTRIES}" read-only-registries="${READ_ONLY_REGISTRIES}"></docker-registry-ui><script src="docker-registry-ui.js"></script></body></html>
|
||||
@@ -10,4 +10,5 @@
|
||||
- [Add custom headers bases on environment variable and/or file when the ui is used as proxy](https://github.com/Joxit/docker-registry-ui/tree/main/examples/proxy-headers) ([#89](https://github.com/Joxit/docker-registry-ui/pull/89))
|
||||
- [UI showing same sha256 content digest for all tags + Delete is not working](https://github.com/Joxit/docker-registry-ui/tree/main/examples/issue-116) ([#116](https://github.com/Joxit/docker-registry-ui/issues/116))
|
||||
- [Electron-based Standalone Application](https://github.com/Joxit/docker-registry-ui/tree/main/examples/electron) ([#129](https://github.com/Joxit/docker-registry-ui/pull/129))
|
||||
- [Use docker-registry-ui as proxy with read-only right](https://github.com/Joxit/docker-registry-ui/tree/main/examples/read-only-auth) ([#47](https://github.com/Joxit/docker-registry-ui/issues/47))
|
||||
- [Use docker-registry-ui as proxy with read-only right](https://github.com/Joxit/docker-registry-ui/tree/main/examples/read-only-auth) ([#47](https://github.com/Joxit/docker-registry-ui/issues/47))
|
||||
- [Use DEFAULT_REGISTRIES and READ_ONLY_REGISTRIES](https://github.com/Joxit/docker-registry-ui/tree/main/examples/pr-219) ([#219](https://github.com/Joxit/docker-registry-ui/issues/219))
|
||||
@@ -16,10 +16,14 @@ computer.
|
||||
* After building the web application, navigate to the ```electron``` directory
|
||||
and execute following commands to build the executable:
|
||||
```bash
|
||||
cd electron
|
||||
cd examples/electron
|
||||
npm install
|
||||
npm run dist
|
||||
```
|
||||
* Run the application:
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
If you encounter any issues, please check the troubleshooting below.
|
||||
|
||||
|
||||
|
||||
14
examples/pr-219/README.md
Normal file
14
examples/pr-219/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Example for pull request #219
|
||||
|
||||
Basic usage for `DEFAULT_REGISTRIES` and `READ_ONLY_REGISTRIES`.
|
||||
|
||||
Behaviors:
|
||||
- `DEFAULT_REGISTRIES`:
|
||||
- will set the list of registries in the localstorage when the localstorage is empty.
|
||||
- will overwrite the list of registries every time when `READ_ONLY_REGISTRIES=true`
|
||||
- `READ_ONLY_REGISTRIES`:
|
||||
- will remove dialog for Add and Remove registries
|
||||
|
||||
These options works only when `SINGLE_REGISTRY=false`
|
||||
|
||||
See [#219](https://github.com/Joxit/docker-registry-ui/pull/219)
|
||||
39
examples/pr-219/docker-compose.yml
Normal file
39
examples/pr-219/docker-compose.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
registry_1:
|
||||
image: registry:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 5000:5000
|
||||
container_name: registry_1
|
||||
environment:
|
||||
REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: "['*']"
|
||||
REGISTRY_STORAGE_DELETE_ENABLED: 'true'
|
||||
volumes:
|
||||
- ./data:/var/lib/registry
|
||||
|
||||
registry_2:
|
||||
image: registry:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 5001:5000
|
||||
container_name: registry_2
|
||||
environment:
|
||||
REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: "['*']"
|
||||
REGISTRY_STORAGE_DELETE_ENABLED: 'true'
|
||||
volumes:
|
||||
- ./data:/var/lib/registry
|
||||
|
||||
ui:
|
||||
image: joxit/docker-registry-ui:latest
|
||||
restart: always
|
||||
container_name: registry-ui
|
||||
environment:
|
||||
- REGISTRY_TITLE=Private Docker Registry
|
||||
- DEFAULT_REGISTRIES=http://localhost:5000,http://localhost:5001
|
||||
- DELETE_IMAGES=true
|
||||
- READ_ONLY_REGISTRIES=true
|
||||
- SINGLE_REGISTRY=false
|
||||
ports:
|
||||
- 80:80
|
||||
@@ -27,6 +27,7 @@ server {
|
||||
#! return 404;
|
||||
#! }
|
||||
#! ${NGINX_PROXY_HEADERS}
|
||||
#! ${NGINX_PROXY_PASS_HEADERS}
|
||||
#! proxy_pass ${NGINX_PROXY_PASS_URL};
|
||||
#! }
|
||||
|
||||
|
||||
26
package.json
26
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docker-registry-ui",
|
||||
"version": "2.0.7",
|
||||
"version": "2.1.0",
|
||||
"scripts": {
|
||||
"start": "ROLLUP_SERVE=true rollup -c -w",
|
||||
"build": "rollup -c",
|
||||
@@ -14,21 +14,21 @@
|
||||
"license": "AGPL-3.0",
|
||||
"description": "A web UI for private docker registry",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.9",
|
||||
"@babel/preset-env": "^7.12.7",
|
||||
"@riotjs/compiler": "^5.3.1",
|
||||
"@riotjs/observable": "^4.0.4",
|
||||
"@riotjs/route": "^7.0.0",
|
||||
"@babel/core": "^7.16.0",
|
||||
"@babel/preset-env": "^7.16.0",
|
||||
"@riotjs/compiler": "^5.4.2",
|
||||
"@riotjs/observable": "^4.1.1",
|
||||
"@riotjs/route": "^7.1.2",
|
||||
"@rollup/plugin-babel": "^5.2.2",
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-html": "^0.2.3",
|
||||
"@rollup/plugin-html": "^0.2.4",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^11.0.0",
|
||||
"core-js": "^3.9.1",
|
||||
"js-beautify": "^1.13.0",
|
||||
"riot": "^5.3.1",
|
||||
"riot-mui": "joxit/riot-5-mui#4d68d7f",
|
||||
"rollup": "^2.34.2",
|
||||
"@rollup/plugin-node-resolve": "^11.2.1",
|
||||
"core-js": "^3.19.1",
|
||||
"js-beautify": "^1.14.0",
|
||||
"riot": "^5.4.5",
|
||||
"riot-mui": "github:joxit/riot-5-mui#4d68d7f",
|
||||
"rollup": "^2.59.0",
|
||||
"rollup-plugin-app-utils": "^1.0.6",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
|
||||
@@ -26,12 +26,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div if="{ !state.loadend }" class="spinner-wrapper">
|
||||
<material-spinner></material-spinner>
|
||||
</div>
|
||||
<catalog-element each="{ item in state.repositories }" item="{ item }" filter-results="{ props.filterResults }"/>
|
||||
<catalog-element each="{ item in state.repositories }" item="{ item }" filter-results="{ props.filterResults }" />
|
||||
<script>
|
||||
import CatalogElement from './catalog-element.riot'
|
||||
import {
|
||||
Http
|
||||
} from '../../scripts/http';
|
||||
import {
|
||||
getRegistryServers
|
||||
} from '../../scripts/utils';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -41,18 +44,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
registryName: '',
|
||||
length: 0,
|
||||
loadend: false,
|
||||
repositories: []
|
||||
repositories: [],
|
||||
registryUrl: ''
|
||||
},
|
||||
|
||||
onBeforeMount(props) {
|
||||
this.state.registryName = props.registryName;
|
||||
this.state.catalogElementsLimit = props.catalogElementsLimit;
|
||||
},
|
||||
onMounted(props) {
|
||||
this.display(props, this.state)
|
||||
onMounted(props, state) {
|
||||
this.display(props, state)
|
||||
},
|
||||
onUpdated(props, state) {
|
||||
this.display(props, state);
|
||||
},
|
||||
|
||||
display(props, state) {
|
||||
if (props.registryUrl === state.registryUrl) {
|
||||
return;
|
||||
}
|
||||
state.registryUrl = props.registryUrl;
|
||||
let repositories = [];
|
||||
const self = this;
|
||||
const oReq = new Http({
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</material-popup>
|
||||
<script>
|
||||
import {
|
||||
getRegistryServers
|
||||
addRegistryServers
|
||||
} from '../../scripts/utils';
|
||||
import router from '../../scripts/router';
|
||||
|
||||
@@ -51,9 +51,7 @@
|
||||
if (!input.value.startsWith('http')) {
|
||||
return this.props.onNotify('The input field should start with http:// or https://.', true);
|
||||
}
|
||||
const url = input.value.trim().replace(/\/*$/, '');
|
||||
const registryServer = getRegistryServers().filter(e => e !== url);
|
||||
localStorage.setItem('registryServer', JSON.stringify([url].concat(registryServer)));
|
||||
const url = addRegistryServers(input.value);
|
||||
router.home()
|
||||
this.props.onServerChange(url);
|
||||
this.props.onClose()
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
</material-popup>
|
||||
<script>
|
||||
import {
|
||||
addRegistryServers,
|
||||
getRegistryServers
|
||||
} from '../../scripts/utils';
|
||||
import router from '../../scripts/router';
|
||||
@@ -45,9 +46,7 @@
|
||||
if (!select.value.startsWith('http')) {
|
||||
return this.props.onNotify('The select field should start with http:// or https://.', true);
|
||||
}
|
||||
const url = select.value.trim().replace(/\/*$/, '');
|
||||
const registryServer = getRegistryServers().filter(e => e !== url);
|
||||
localStorage.setItem('registryServer', JSON.stringify([url].concat(registryServer)));
|
||||
const url = addRegistryServers(select.value);
|
||||
router.home()
|
||||
this.props.onServerChange(url);
|
||||
this.props.onClose()
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<dialogs-menu>
|
||||
<add-registry-url opened="{ state['add-registry-url'] }" on-close="{ onClose('add-registry-url') }"
|
||||
<add-registry-url if="{ !props.readOnlyRegistries }" opened="{ state['add-registry-url'] }" on-close="{ onClose('add-registry-url') }"
|
||||
on-notify="{ props.onNotify }" on-server-change="{ props.onServerChange }"></add-registry-url>
|
||||
<change-registry-url opened="{ state['change-registry-url'] }" on-close="{ onClose('change-registry-url') }"
|
||||
on-notify="{ props.onNotify }" on-server-change="{ props.onServerChange }"></change-registry-url>
|
||||
<remove-registry-url opened="{ state['remove-registry-url'] }" on-close="{ onClose('remove-registry-url') }"
|
||||
<remove-registry-url if="{ !props.readOnlyRegistries }" opened="{ state['remove-registry-url'] }" on-close="{ onClose('remove-registry-url') }"
|
||||
on-notify="{ props.onNotify }" on-server-change="{ props.onServerChange }"></remove-registry-url>
|
||||
<div class="container">
|
||||
<material-button onClick="{ onClick }" waves-center="true" rounded="true" waves-opacity="0.6" waves-duration="600">
|
||||
<i class="material-icons">more_vert</i>
|
||||
</material-button>
|
||||
<material-dropdown-list items="{ dropdownItems }" onSelect="{ onDropdownSelect }"
|
||||
<material-dropdown-list items="{ dropdownItems.filter(item => item.ro || !props.readOnlyRegistries) }" onSelect="{ onDropdownSelect }"
|
||||
opened="{ state.isDropdownOpened }" />
|
||||
</div>
|
||||
<div class="overlay" onclick="{ onClick }" if="{ state.isDropdownOpened }"></div>
|
||||
@@ -42,13 +42,16 @@
|
||||
},
|
||||
dropdownItems: [{
|
||||
title: 'Add URL',
|
||||
name: 'add-registry-url'
|
||||
name: 'add-registry-url',
|
||||
ro: false
|
||||
}, {
|
||||
title: 'Change URL',
|
||||
name: 'change-registry-url'
|
||||
name: 'change-registry-url',
|
||||
ro: true
|
||||
}, {
|
||||
title: 'Remove URL',
|
||||
name: 'remove-registry-url'
|
||||
name: 'remove-registry-url',
|
||||
ro: false
|
||||
}],
|
||||
onDropdownSelect(key, item) {
|
||||
this.update({
|
||||
|
||||
@@ -38,13 +38,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
</material-popup>
|
||||
<script>
|
||||
import {
|
||||
getRegistryServers
|
||||
getRegistryServers,
|
||||
removeRegistryServers
|
||||
} from '../../scripts/utils';
|
||||
export default {
|
||||
remove(event) {
|
||||
const url = event.currentTarget.attributes.url && event.currentTarget.attributes.url.value;
|
||||
const registryServer = getRegistryServers().filter(e => e !== url);
|
||||
localStorage.setItem('registryServer', JSON.stringify(registryServer));
|
||||
removeRegistryServers(url);
|
||||
setTimeout(() => this.update(), 100);
|
||||
},
|
||||
getRegistryServers
|
||||
|
||||
@@ -20,7 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
<div class="logo">Docker Registry UI</div>
|
||||
<search-bar on-search="{ onSearch }"></search-bar>
|
||||
<dialogs-menu if="{props.singleRegistry !== 'true'}" on-notify="{ notifySnackbar }"
|
||||
on-server-change="{ onServerChange }"></dialogs-menu>
|
||||
on-server-change="{ onServerChange }" default-registries="{ props.defaultRegistries }"
|
||||
read-only-registries="{ truthy(props.readOnlyRegistries) }"></dialogs-menu>
|
||||
</material-navbar>
|
||||
</header>
|
||||
<main>
|
||||
@@ -77,6 +78,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import {
|
||||
stripHttps,
|
||||
getRegistryServers,
|
||||
setRegistryServers,
|
||||
truthy
|
||||
} from '../scripts/utils';
|
||||
import router from '../scripts/router';
|
||||
@@ -96,6 +98,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
state.snackbarMessage = undefined;
|
||||
},
|
||||
onBeforeMount(props) {
|
||||
if ((props.defaultRegistries && props.defaultRegistries.length > 0 && getRegistryServers().length === 0) ||
|
||||
truthy(props.readOnlyRegistries)) {
|
||||
setRegistryServers(props.defaultRegistries);
|
||||
}
|
||||
|
||||
// props.singleRegistry === 'true' means old static version
|
||||
const registryUrl = props.registryUrl ||
|
||||
(props.singleRegistry === 'true' ? undefined : (router.getUrlQueryParam() || getRegistryServers(0))) ||
|
||||
|
||||
@@ -20,6 +20,18 @@
|
||||
input.value = '';
|
||||
notify();
|
||||
})
|
||||
window.addEventListener('keydown', e => {
|
||||
// F3 or CTRL + F
|
||||
if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)) {
|
||||
// already focused, fallback to default behavior
|
||||
if (document.activeElement === input) {
|
||||
return true;
|
||||
} else {
|
||||
e.preventDefault();
|
||||
input.focus();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
<!-- build:keep production -->
|
||||
<docker-registry-ui registry-url="${REGISTRY_URL}" name="${REGISTRY_TITLE}" pull-url="${PULL_URL}"
|
||||
show-content-digest="${SHOW_CONTENT_DIGEST}" is-image-remove-activated="${DELETE_IMAGES}"
|
||||
catalog-elements-limit="${CATALOG_ELEMENTS_LIMIT}" single-registry="${SINGLE_REGISTRY}">
|
||||
catalog-elements-limit="${CATALOG_ELEMENTS_LIMIT}" single-registry="${SINGLE_REGISTRY}"
|
||||
default-registries="${DEFAULT_REGISTRIES}" read-only-registries="${READ_ONLY_REGISTRIES}">
|
||||
</docker-registry-ui>
|
||||
<!-- endbuild -->
|
||||
<!-- build:keep developement -->
|
||||
|
||||
@@ -64,7 +64,7 @@ export class DockerImage {
|
||||
return this.fillInfo();
|
||||
});
|
||||
this.on('get-sha256', function () {
|
||||
if (this.size !== undefined) {
|
||||
if (this.sha256 !== undefined) {
|
||||
return this.trigger('sha256', this.sha256);
|
||||
}
|
||||
return this.fillInfo();
|
||||
|
||||
@@ -53,7 +53,8 @@ export class Http {
|
||||
case 'loadend': {
|
||||
self.oReq.addEventListener('loadend', function () {
|
||||
if (this.status == 401 && !this.withCredentials) {
|
||||
const tokenAuth = parseAuthenticateHeader(this.getResponseHeader('www-authenticate'));
|
||||
const tokenAuth =
|
||||
this.hasHeader('www-authenticate') && parseAuthenticateHeader(this.getResponseHeader('www-authenticate'));
|
||||
self.onAuthentication(tokenAuth, (bearer) => {
|
||||
const req = new XMLHttpRequest();
|
||||
req._url = self._url;
|
||||
@@ -65,7 +66,7 @@ export class Http {
|
||||
req.setRequestHeader(key, self._headers[key]);
|
||||
}
|
||||
if (bearer && bearer.token) {
|
||||
req.setRequestHeader('Authorization', `Bearer ${bearer.token}`)
|
||||
req.setRequestHeader('Authorization', `Bearer ${bearer.token}`);
|
||||
} else {
|
||||
req.withCredentials = true;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
const LOCAL_STORAGE_KEY = 'registryServer';
|
||||
|
||||
export function bytesToSize(bytes) {
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
if (bytes == undefined || isNaN(bytes)) {
|
||||
@@ -152,7 +154,7 @@ export const ERROR_CAN_NOT_READ_CONTENT_DIGEST = {
|
||||
|
||||
export function getRegistryServers(i) {
|
||||
try {
|
||||
const res = JSON.parse(localStorage.getItem('registryServer'));
|
||||
const res = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY));
|
||||
if (res instanceof Array) {
|
||||
return !isNaN(i) ? res[i] : res.map((url) => url.trim().replace(/\/*$/, ''));
|
||||
}
|
||||
@@ -160,6 +162,28 @@ export function getRegistryServers(i) {
|
||||
return !isNaN(i) ? '' : [];
|
||||
}
|
||||
|
||||
export function setRegistryServers(registries) {
|
||||
if (typeof registries === 'string') {
|
||||
registries = registries.split(',');
|
||||
} else if (!Array.isArray(registries)) {
|
||||
throw new Error('setRegistries must be called with string or array parameter');
|
||||
}
|
||||
registries = registries.map((registry) => registry.replace(/\/*$/, ''));
|
||||
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(registries));
|
||||
}
|
||||
|
||||
export function addRegistryServers(registry) {
|
||||
const url = registry.trim().replace(/\/*$/, '');
|
||||
const registryServer = getRegistryServers().filter((e) => e !== url);
|
||||
setRegistryServers([url].concat(registryServer));
|
||||
return url;
|
||||
}
|
||||
|
||||
export function removeRegistryServers(registry) {
|
||||
const registryServers = getRegistryServers().filter((e) => e !== registry);
|
||||
setRegistryServers(registryServers);
|
||||
}
|
||||
|
||||
export function encodeURI(url) {
|
||||
if (!url) {
|
||||
return;
|
||||
@@ -175,5 +199,5 @@ export function decodeURI(url) {
|
||||
}
|
||||
|
||||
export function truthy(value) {
|
||||
return value === true || value === "true";
|
||||
}
|
||||
return value === true || value === 'true';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user