diff --git a/README.md b/README.md
index f3949f4..fff5c6f 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ This web user interface uses [Riot](https://github.com/Riot/riot) the react-like
- Use `joxit/docker-registry-ui:static` as reverse proxy to your docker registry (This will avoid CORS).
- Display image size (see #30)
- Add Title when using REGISTRY_URL (see #28)
-- Alpine and Debian based images with supports for arm32v7
+- Alpine and Debian based images with supports for arm32v7 and arm64v8
- Copy `docker pull` command to clipbloard
- Show sha256 for specific tag (hover image tag)
diff --git a/arm32v7-static.dockerfile b/arm32v7-static.dockerfile
index 4497d81..32a94a2 100644
--- a/arm32v7-static.dockerfile
+++ b/arm32v7-static.dockerfile
@@ -20,8 +20,7 @@ WORKDIR /usr/share/nginx/html/
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
-COPY dist/scripts/script-static.js /usr/share/nginx/html/scripts/script.js
-COPY dist/scripts/tags-static.js /usr/share/nginx/html/scripts/tags.js
+COPY dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js
COPY bin/entrypoint /bin
ENTRYPOINT entrypoint
diff --git a/arm64v8-static.dockerfile b/arm64v8-static.dockerfile
index ded0efc..f10881f 100644
--- a/arm64v8-static.dockerfile
+++ b/arm64v8-static.dockerfile
@@ -20,8 +20,7 @@ WORKDIR /usr/share/nginx/html/
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
-COPY dist/scripts/script-static.js /usr/share/nginx/html/scripts/script.js
-COPY dist/scripts/tags-static.js /usr/share/nginx/html/scripts/tags.js
+COPY dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js
COPY bin/entrypoint /bin
ENTRYPOINT entrypoint
diff --git a/bin/entrypoint b/bin/entrypoint
index ed78f90..c6be0ef 100755
--- a/bin/entrypoint
+++ b/bin/entrypoint
@@ -1,10 +1,10 @@
#!/bin/sh
$@
-sed -i "s,\${URL},${URL}," scripts/script.js
-sed -i "s,\${REGISTRY_TITLE},${REGISTRY_TITLE}," scripts/script.js
+sed -i "s,\${URL},${URL}," scripts/docker-registry-ui.js
+sed -i "s,\${REGISTRY_TITLE},${REGISTRY_TITLE}," scripts/docker-registry-ui.js
if [ -z "${DELETE_IMAGES}" ] || [ "${DELETE_IMAGES}" = false ] ; then
- sed -i "s/registryUI.isImageRemoveActivated *= *[^,;]*/registryUI.isImageRemoveActivated=false/" scripts/script.js
+ sed -i "s/registryUI.isImageRemoveActivated *= *[^,;]*/registryUI.isImageRemoveActivated=false/" scripts/docker-registry-ui.js
fi
if [ -n "${REGISTRY_URL}" ] ; then
diff --git a/debian-static.dockerfile b/debian-static.dockerfile
index bc65c44..3a6541f 100644
--- a/debian-static.dockerfile
+++ b/debian-static.dockerfile
@@ -20,8 +20,7 @@ WORKDIR /usr/share/nginx/html/
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
-COPY dist/scripts/script-static.js /usr/share/nginx/html/scripts/script.js
-COPY dist/scripts/tags-static.js /usr/share/nginx/html/scripts/tags.js
+COPY dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js
COPY bin/entrypoint /bin
ENTRYPOINT entrypoint
diff --git a/dist/index.html b/dist/index.html
index 72f68b3..5caf748 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -13,4 +13,4 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
--->
Docker Registry UI
\ No newline at end of file
+-->Docker Registry UI
\ No newline at end of file
diff --git a/dist/scripts/docker-registry-ui-static.js b/dist/scripts/docker-registry-ui-static.js
new file mode 100644
index 0000000..df0a324
--- /dev/null
+++ b/dist/scripts/docker-registry-ui-static.js
@@ -0,0 +1,18 @@
+/*!
+ * docker-registry-ui
+ * Copyright (C) 2016-2018 Jones Magloire @Joxit
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+function Http(){this.oReq=new XMLHttpRequest,this.oReq.hasHeader=Http.hasHeader,this.oReq.getErrorMessage=Http.getErrorMessage,this._events={},this._headers={}}Http.prototype.addEventListener=function(t,e){this._events[t]=e;var r=this;switch(t){case"loadend":r.oReq.addEventListener("loadend",function(){if(401==this.status){var t=new XMLHttpRequest;for(key in t.open(r._method,r._url),r._events)t.addEventListener(key,r._events[key]);for(key in r._headers)t.setRequestHeader(key,r._headers[key]);t.withCredentials=!0,t.hasHeader=Http.hasHeader,t.getErrorMessage=Http.getErrorMessage,t.send()}else e.bind(this)()});break;case"load":r.oReq.addEventListener("load",function(){401!==this.status&&e.bind(this)()});break;default:r.oReq.addEventListener(t,function(){e.bind(this)()})}},Http.prototype.setRequestHeader=function(t,e){this.oReq.setRequestHeader(t,e),this._headers[t]=e},Http.prototype.open=function(t,e){this._method=t,this._url=e,this.oReq.open(t,e)},Http.prototype.send=function(){this.oReq.send()},Http.hasHeader=function(t){return this.getAllResponseHeaders().split("\n").some(function(e){return new RegExp("^"+t+":","i").test(e)})},Http.getErrorMessage=function(){return registryUI.url()&®istryUI.url().match("^http://")&&"https:"===window.location.protocol?"Mixed Content: The page at `"+window.location.origin+"` was loaded over HTTPS, but requested an insecure server endpoint `"+registryUI.url()+"`. This request has been blocked; the content must be served over HTTPS.":registryUI.url()?this.withCredentials&&!this.hasHeader("Access-Control-Allow-Credentials")?"The `Access-Control-Allow-Credentials` header in the response is missing and must be set to `true` when the request's credentials mode is on. Origin `"+registryUI.url()+"` is therefore not allowed access.":"An error occured: Check your connection and your registry must have `Access-Control-Allow-Origin` header set to `"+window.location.origin+"`":"Incorrect server endpoint."};var registryUI={url:function(){return"${URL}"},name:function(){return"${REGISTRY_TITLE}"},isImageRemoveActivated:!0,catalog:{},taglist:{}};window.addEventListener("DOMContentLoaded",function(){riot.mount("*")}),riot.tag2("catalog",'
Repositories of {registryUI.name()}
send {item}
',"","",function(t){registryUI.catalog.instance=this,registryUI.catalog.display=function(){registryUI.catalog.repositories=[];var t=new Http;t.addEventListener("load",function(){registryUI.catalog.repositories=[],200==this.status?(registryUI.catalog.repositories=JSON.parse(this.responseText).repositories||[],registryUI.catalog.repositories.sort()):404==this.status?registryUI.snackbar("Server not found",!0):registryUI.snackbar(this.responseText)}),t.addEventListener("error",function(){registryUI.snackbar(this.getErrorMessage(),!0),registryUI.catalog.repositories=[]}),t.addEventListener("loadend",function(){registryUI.catalog.loadend=!0,registryUI.catalog.instance.update()}),t.open("GET",registryUI.url()+"/v2/_catalog?n=100000"),t.send()},registryUI.catalog.go=function(t){route("taglist/"+t)},registryUI.catalog.display()}),riot.tag2("app",'
Tags of {registryUI.name() + \'/\' + registryUI.taglist.name}
Repository
Size
Tag
{image.name}
',"","",function(t){registryUI.taglist.instance=this,registryUI.taglist.display=function(){if(registryUI.taglist.tags=[],"taglist"==route.routeName){var t=new Http;registryUI.taglist.instance.update(),t.addEventListener("load",function(){registryUI.taglist.tags=[],200==this.status?(registryUI.taglist.tags=JSON.parse(this.responseText).tags||[],registryUI.taglist.tags=registryUI.taglist.tags.map(function(t){return new registryUI.DockerImage(registryUI.taglist.name,t)}).sort(registryUI.DockerImage.compare)):404==this.status?registryUI.snackbar("Server not found",!0):registryUI.snackbar(this.responseText,!0)}),t.addEventListener("error",function(){registryUI.snackbar(this.getErrorMessage(),!0),registryUI.taglist.tags=[]}),t.addEventListener("loadend",function(){registryUI.taglist.loadend=!0,registryUI.taglist.instance.update()}),t.open("GET",registryUI.url()+"/v2/"+registryUI.taglist.name+"/tags/list"),t.send(),registryUI.taglist.asc=!0}},registryUI.taglist.display(),registryUI.taglist.instance.update(),registryUI.taglist.reverse=function(){registryUI.taglist.asc?(registryUI.taglist.tags.reverse(),registryUI.taglist.asc=!1):(registryUI.taglist.tags.sort(registryUI.DockerImage.compare),registryUI.taglist.asc=!0),registryUI.taglist.instance.update()},registryUI.taglist.refresh=function(){route(registryUI.taglist.name)}}),riot.tag2("copy-to-clipboard",' content_copy',"","",function(t){this.dockerCmd="docker pull "+registryUI.cleanName()+"/"+t.image.name+":"+t.image.tag,this.copy=function(){var t=this.refs.input;t.style.display="block",t.select(),document.execCommand("copy"),t.style.display="none",registryUI.snackbar("`"+this.dockerCmd+"` has been copied to clipboard.")}}),riot.tag2("remove-image",'delete',"","",function(t){registryUI.removeImage=registryUI.removeImage||{},registryUI.removeImage.remove=function(t,e){var r=new Http;r.addEventListener("loadend",function(){if(registryUI.taglist.refresh(),200==this.status){if(!this.hasHeader("Docker-Content-Digest"))return void registryUI.errorSnackbar("You need to add Access-Control-Expose-Headers: ['Docker-Content-Digest'] in your server configuration.");var r=this.getResponseHeader("Docker-Content-Digest"),i=new Http;i.addEventListener("loadend",function(){200==this.status||202==this.status?(registryUI.taglist.refresh(),registryUI.snackbar("Deleting "+t+":"+e+" image. Run `registry garbage-collect config.yml` on your registry")):404==this.status?registryUI.errorSnackbar("Digest not found"):registryUI.snackbar(this.responseText)}),i.open("DELETE",registryUI.url()+"/v2/"+t+"/manifests/"+r),i.setRequestHeader("Accept","application/vnd.docker.distribution.manifest.v2+json"),i.addEventListener("error",function(){registryUI.errorSnackbar("An error occurred when deleting image. Check if your server accept DELETE methods Access-Control-Allow-Methods: ['DELETE'].")}),i.send()}else 404==this.status?registryUI.errorSnackbar("Manifest for "+t+":"+e+" not found"):registryUI.snackbar(this.responseText)}),r.open("HEAD",registryUI.url()+"/v2/"+t+"/manifests/"+e),r.setRequestHeader("Accept","application/vnd.docker.distribution.manifest.v2+json"),r.send()}}),riot.tag2("image-size",'
',"","",function(t){var e=this;t.image.on("sha256",function(t){e.sha256=t.substring(0,19),e.update()}),t.image.trigger("get-sha256")});
\ No newline at end of file
diff --git a/dist/scripts/docker-registry-ui.js b/dist/scripts/docker-registry-ui.js
new file mode 100644
index 0000000..0ec118d
--- /dev/null
+++ b/dist/scripts/docker-registry-ui.js
@@ -0,0 +1,18 @@
+/*!
+ * docker-registry-ui
+ * Copyright (C) 2016-2018 Jones Magloire @Joxit
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+function Http(){this.oReq=new XMLHttpRequest,this.oReq.hasHeader=Http.hasHeader,this.oReq.getErrorMessage=Http.getErrorMessage,this._events={},this._headers={}}Http.prototype.addEventListener=function(e,t){this._events[e]=t;var r=this;switch(e){case"loadend":r.oReq.addEventListener("loadend",function(){if(401==this.status){var e=new XMLHttpRequest;for(key in e.open(r._method,r._url),r._events)e.addEventListener(key,r._events[key]);for(key in r._headers)e.setRequestHeader(key,r._headers[key]);e.withCredentials=!0,e.hasHeader=Http.hasHeader,e.getErrorMessage=Http.getErrorMessage,e.send()}else t.bind(this)()});break;case"load":r.oReq.addEventListener("load",function(){401!==this.status&&t.bind(this)()});break;default:r.oReq.addEventListener(e,function(){t.bind(this)()})}},Http.prototype.setRequestHeader=function(e,t){this.oReq.setRequestHeader(e,t),this._headers[e]=t},Http.prototype.open=function(e,t){this._method=e,this._url=t,this.oReq.open(e,t)},Http.prototype.send=function(){this.oReq.send()},Http.hasHeader=function(e){return this.getAllResponseHeaders().split("\n").some(function(t){return new RegExp("^"+e+":","i").test(t)})},Http.getErrorMessage=function(){return registryUI.url()&®istryUI.url().match("^http://")&&"https:"===window.location.protocol?"Mixed Content: The page at `"+window.location.origin+"` was loaded over HTTPS, but requested an insecure server endpoint `"+registryUI.url()+"`. This request has been blocked; the content must be served over HTTPS.":registryUI.url()?this.withCredentials&&!this.hasHeader("Access-Control-Allow-Credentials")?"The `Access-Control-Allow-Credentials` header in the response is missing and must be set to `true` when the request's credentials mode is on. Origin `"+registryUI.url()+"` is therefore not allowed access.":"An error occured: Check your connection and your registry must have `Access-Control-Allow-Origin` header set to `"+window.location.origin+"`":"Incorrect server endpoint."};var registryUI={URL_QUERY_PARAM_REGEX:/[&?]url=/,URL_PARAM_REGEX:/^url=/};registryUI.name=registryUI.url=function(e){if(!registryUI._url){var t=registryUI.getUrlQueryParam();if(t)try{return registryUI._url=registryUI.decodeURI(t),registryUI._url}catch(e){console.log(e)}registryUI._url=registryUI.getRegistryServer(0)}return registryUI._url},registryUI.getRegistryServer=function(e){try{var t=JSON.parse(localStorage.getItem("registryServer"));if(t instanceof Array)return isNaN(e)?t.map(function(e){return e.trim().replace(/\/*$/,"")}):t[e]}catch(e){}return isNaN(e)?[]:""},registryUI.addServer=function(e){var t=registryUI.getRegistryServer();e=e.trim().replace(/\/*$/,""),-1==t.indexOf(e)&&(t.push(e),registryUI._url||registryUI.updateHistory(e),localStorage.setItem("registryServer",JSON.stringify(t)))},registryUI.changeServer=function(e){var t=registryUI.getRegistryServer();e=e.trim().replace(/\/*$/,"");var r=t.indexOf(e);-1!=r&&(t.splice(r,1),t=[e].concat(t),registryUI.updateHistory(e),localStorage.setItem("registryServer",JSON.stringify(t)))},registryUI.removeServer=function(e){var t=registryUI.getRegistryServer();e=e.trim().replace(/\/*$/,"");var r=t.indexOf(e);-1!=r&&(t.splice(r,1),localStorage.setItem("registryServer",JSON.stringify(t)),e==registryUI.url()&&(registryUI.updateHistory(registryUI.getRegistryServer(0)),route("")))},registryUI.updateHistory=function(e){history.pushState(null,"",(e?"?url="+registryUI.encodeURI(e):"?")+window.location.hash),registryUI._url=e},registryUI.getUrlQueryParam=function(){var e=window.location.search;if(registryUI.URL_QUERY_PARAM_REGEX.test(e)){var t=e.split(/^\?|&/).find(function(e){return e&®istryUI.URL_PARAM_REGEX.test(e)});return t?t.replace(registryUI.URL_PARAM_REGEX,""):t}},registryUI.encodeURI=function(e){return e.indexOf("&")<0?window.encodeURIComponent(e):btoa(e)},registryUI.decodeURI=function(e){return e.startsWith("http")?window.decodeURIComponent(e):atob(e)},registryUI.isImageRemoveActivated=!0,registryUI.catalog={},registryUI.taglist={},window.addEventListener("DOMContentLoaded",function(){riot.mount("*")}),riot.tag2("add",'
',"","",function(e){registryUI.catalog.instance=this,registryUI.catalog.display=function(){registryUI.catalog.repositories=[];var e=new Http;e.addEventListener("load",function(){registryUI.catalog.repositories=[],200==this.status?(registryUI.catalog.repositories=JSON.parse(this.responseText).repositories||[],registryUI.catalog.repositories.sort()):404==this.status?registryUI.snackbar("Server not found",!0):registryUI.snackbar(this.responseText)}),e.addEventListener("error",function(){registryUI.snackbar(this.getErrorMessage(),!0),registryUI.catalog.repositories=[]}),e.addEventListener("loadend",function(){registryUI.catalog.loadend=!0,registryUI.catalog.instance.update()}),e.open("GET",registryUI.url()+"/v2/_catalog?n=100000"),e.send()},registryUI.catalog.go=function(e){route("taglist/"+e)},registryUI.catalog.display()}),riot.tag2("change",'
Change your Server ?
ChangeCancel
',"","",function(e){registryUI.changeTag=registryUI.changeTag||{},this.one("mount",function(){registryUI.changeTag.dialog=this.tags["material-popup"],registryUI.changeTag.dialog.getServerUrl=function(){return this.refs["server-list"]?this.refs["server-list"].value:""},registryUI.changeTag.dialog.on("updated",function(){this.refs["server-list"]&&(this.refs["server-list"].value=registryUI.url())})}),registryUI.changeTag.show=function(){registryUI.changeTag.dialog.open()},registryUI.changeTag.change=function(){registryUI.changeTag.dialog.getServerUrl().length>0&®istryUI.changeServer(registryUI.changeTag.dialog.getServerUrl()),registryUI.home(),registryUI.changeTag.dialog.close()},registryUI.changeTag.close=function(){registryUI.changeTag.dialog.close()}}),riot.tag2("copy-to-clipboard",' content_copy',"","",function(e){this.dockerCmd="docker pull "+registryUI.cleanName()+"/"+e.image.name+":"+e.image.tag,this.copy=function(){var e=this.refs.input;e.style.display="block",e.select(),document.execCommand("copy"),e.style.display="none",registryUI.snackbar("`"+this.dockerCmd+"` has been copied to clipboard.")}}),riot.tag2("image-size",'
',"","",function(e){registryUI.menuTag=registryUI.menuTag||{},registryUI.menuTag.update=this.update,this.one("mount",function(e){var t=this;registryUI.menuTag.close=function(){t.tags["material-dropdown"].close(),t.update()},registryUI.menuTag.isOpen=function(){return t.tags["material-dropdown"].opened},registryUI.menuTag.toggle=function(){t.tags["material-dropdown"].opened?t.tags["material-dropdown"].close():t.tags["material-dropdown"].open(),t.update()}})}),riot.tag2("remove-image",'delete',"","",function(e){registryUI.removeImage=registryUI.removeImage||{},registryUI.removeImage.remove=function(e,t){var r=new Http;r.addEventListener("loadend",function(){if(registryUI.taglist.refresh(),200==this.status){if(!this.hasHeader("Docker-Content-Digest"))return void registryUI.errorSnackbar("You need to add Access-Control-Expose-Headers: ['Docker-Content-Digest'] in your server configuration.");var r=this.getResponseHeader("Docker-Content-Digest"),i=new Http;i.addEventListener("loadend",function(){200==this.status||202==this.status?(registryUI.taglist.refresh(),registryUI.snackbar("Deleting "+e+":"+t+" image. Run `registry garbage-collect config.yml` on your registry")):404==this.status?registryUI.errorSnackbar("Digest not found"):registryUI.snackbar(this.responseText)}),i.open("DELETE",registryUI.url()+"/v2/"+e+"/manifests/"+r),i.setRequestHeader("Accept","application/vnd.docker.distribution.manifest.v2+json"),i.addEventListener("error",function(){registryUI.errorSnackbar("An error occurred when deleting image. Check if your server accept DELETE methods Access-Control-Allow-Methods: ['DELETE'].")}),i.send()}else 404==this.status?registryUI.errorSnackbar("Manifest for "+e+":"+t+" not found"):registryUI.snackbar(this.responseText)}),r.open("HEAD",registryUI.url()+"/v2/"+e+"/manifests/"+t),r.setRequestHeader("Accept","application/vnd.docker.distribution.manifest.v2+json"),r.send()}}),riot.tag2("remove",'
Tags of {registryUI.name() + \'/\' + registryUI.taglist.name}
Repository
Size
Tag
{image.name}
',"","",function(e){registryUI.taglist.instance=this,registryUI.taglist.display=function(){if(registryUI.taglist.tags=[],"taglist"==route.routeName){var e=new Http;registryUI.taglist.instance.update(),e.addEventListener("load",function(){registryUI.taglist.tags=[],200==this.status?(registryUI.taglist.tags=JSON.parse(this.responseText).tags||[],registryUI.taglist.tags=registryUI.taglist.tags.map(function(e){return new registryUI.DockerImage(registryUI.taglist.name,e)}).sort(registryUI.DockerImage.compare)):404==this.status?registryUI.snackbar("Server not found",!0):registryUI.snackbar(this.responseText,!0)}),e.addEventListener("error",function(){registryUI.snackbar(this.getErrorMessage(),!0),registryUI.taglist.tags=[]}),e.addEventListener("loadend",function(){registryUI.taglist.loadend=!0,registryUI.taglist.instance.update()}),e.open("GET",registryUI.url()+"/v2/"+registryUI.taglist.name+"/tags/list"),e.send(),registryUI.taglist.asc=!0}},registryUI.taglist.display(),registryUI.taglist.instance.update(),registryUI.taglist.reverse=function(){registryUI.taglist.asc?(registryUI.taglist.tags.reverse(),registryUI.taglist.asc=!1):(registryUI.taglist.tags.sort(registryUI.DockerImage.compare),registryUI.taglist.asc=!0),registryUI.taglist.instance.update()},registryUI.taglist.refresh=function(){route(registryUI.taglist.name)}});
\ No newline at end of file
diff --git a/dist/scripts/script-static.js b/dist/scripts/script-static.js
deleted file mode 100644
index 9169771..0000000
--- a/dist/scripts/script-static.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * docker-registry-ui
- * Copyright (C) 2016-2018 Jones Magloire @Joxit
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-function Http(){this.oReq=new XMLHttpRequest,this.oReq.hasHeader=Http.hasHeader,this.oReq.getErrorMessage=Http.getErrorMessage,this._events={},this._headers={}}Http.prototype.addEventListener=function(e,t){this._events[e]=t;var r=this;switch(e){case"loadend":r.oReq.addEventListener("loadend",function(){if(401==this.status){var e=new XMLHttpRequest;e.open(r._method,r._url);for(key in r._events)e.addEventListener(key,r._events[key]);for(key in r._headers)e.setRequestHeader(key,r._headers[key]);e.withCredentials=!0,e.hasHeader=Http.hasHeader,e.getErrorMessage=Http.getErrorMessage,e.send()}else t.bind(this)()});break;case"load":r.oReq.addEventListener("load",function(){401!==this.status&&t.bind(this)()});break;default:r.oReq.addEventListener(e,function(){t.bind(this)()})}},Http.prototype.setRequestHeader=function(e,t){this.oReq.setRequestHeader(e,t),this._headers[e]=t},Http.prototype.open=function(e,t){this._method=e,this._url=t,this.oReq.open(e,t)},Http.prototype.send=function(){this.oReq.send()},Http.hasHeader=function(e){return this.getAllResponseHeaders().split("\n").some(function(t){return new RegExp("^"+e+":","i").test(t)})},Http.getErrorMessage=function(){return registryUI.url()&®istryUI.url().match("^http://")&&"https:"===window.location.protocol?"Mixed Content: The page at `"+window.location.origin+"` was loaded over HTTPS, but requested an insecure server endpoint `"+registryUI.url()+"`. This request has been blocked; the content must be served over HTTPS.":registryUI.url()?this.withCredentials&&!this.hasHeader("Access-Control-Allow-Credentials")?"The `Access-Control-Allow-Credentials` header in the response is missing and must be set to `true` when the request's credentials mode is on. Origin `"+registryUI.url()+"` is therefore not allowed access.":"An error occured: Check your connection and your registry must have `Access-Control-Allow-Origin` header set to `"+window.location.origin+"`":"Incorrect server endpoint."};var registryUI={};registryUI.url=function(){return"${URL}"},registryUI.name=function(){return"${REGISTRY_TITLE}"},registryUI.isImageRemoveActivated=!0,registryUI.catalog={},registryUI.taglist={},riot.mount("catalog"),riot.mount("taglist"),riot.mount("app");
\ No newline at end of file
diff --git a/dist/scripts/script.js b/dist/scripts/script.js
deleted file mode 100644
index 9d13e01..0000000
--- a/dist/scripts/script.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * docker-registry-ui
- * Copyright (C) 2016-2018 Jones Magloire @Joxit
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-function Http(){this.oReq=new XMLHttpRequest,this.oReq.hasHeader=Http.hasHeader,this.oReq.getErrorMessage=Http.getErrorMessage,this._events={},this._headers={}}Http.prototype.addEventListener=function(e,r){this._events[e]=r;var t=this;switch(e){case"loadend":t.oReq.addEventListener("loadend",function(){if(401==this.status){var e=new XMLHttpRequest;e.open(t._method,t._url);for(key in t._events)e.addEventListener(key,t._events[key]);for(key in t._headers)e.setRequestHeader(key,t._headers[key]);e.withCredentials=!0,e.hasHeader=Http.hasHeader,e.getErrorMessage=Http.getErrorMessage,e.send()}else r.bind(this)()});break;case"load":t.oReq.addEventListener("load",function(){401!==this.status&&r.bind(this)()});break;default:t.oReq.addEventListener(e,function(){r.bind(this)()})}},Http.prototype.setRequestHeader=function(e,r){this.oReq.setRequestHeader(e,r),this._headers[e]=r},Http.prototype.open=function(e,r){this._method=e,this._url=r,this.oReq.open(e,r)},Http.prototype.send=function(){this.oReq.send()},Http.hasHeader=function(e){return this.getAllResponseHeaders().split("\n").some(function(r){return new RegExp("^"+e+":","i").test(r)})},Http.getErrorMessage=function(){return registryUI.url()&®istryUI.url().match("^http://")&&"https:"===window.location.protocol?"Mixed Content: The page at `"+window.location.origin+"` was loaded over HTTPS, but requested an insecure server endpoint `"+registryUI.url()+"`. This request has been blocked; the content must be served over HTTPS.":registryUI.url()?this.withCredentials&&!this.hasHeader("Access-Control-Allow-Credentials")?"The `Access-Control-Allow-Credentials` header in the response is missing and must be set to `true` when the request's credentials mode is on. Origin `"+registryUI.url()+"` is therefore not allowed access.":"An error occured: Check your connection and your registry must have `Access-Control-Allow-Origin` header set to `"+window.location.origin+"`":"Incorrect server endpoint."};var registryUI={};registryUI.URL_QUERY_PARAM_REGEX=/[&?]url=/,registryUI.URL_PARAM_REGEX=/^url=/,registryUI.name=registryUI.url=function(e){if(!registryUI._url){var r=registryUI.getUrlQueryParam();if(r)try{return registryUI._url=registryUI.decodeURI(r),registryUI._url}catch(e){console.log(e)}registryUI._url=registryUI.getRegistryServer(0)}return registryUI._url},registryUI.getRegistryServer=function(e){try{var r=JSON.parse(localStorage.getItem("registryServer"));if(r instanceof Array)return isNaN(e)?r.map(function(e){return e.trim().replace(/\/*$/,"")}):r[e]}catch(e){}return isNaN(e)?[]:""},registryUI.addServer=function(e){var r=registryUI.getRegistryServer();e=e.trim().replace(/\/*$/,"");var t=r.indexOf(e);t==-1&&(r.push(e),registryUI._url||registryUI.updateHistory(e),localStorage.setItem("registryServer",JSON.stringify(r)))},registryUI.changeServer=function(e){var r=registryUI.getRegistryServer();e=e.trim().replace(/\/*$/,"");var t=r.indexOf(e);t!=-1&&(r.splice(t,1),r=[e].concat(r),registryUI.updateHistory(e),localStorage.setItem("registryServer",JSON.stringify(r)))},registryUI.removeServer=function(e){var r=registryUI.getRegistryServer();e=e.trim().replace(/\/*$/,"");var t=r.indexOf(e);t!=-1&&(r.splice(t,1),localStorage.setItem("registryServer",JSON.stringify(r)),e==registryUI.url()&&(registryUI.updateHistory(registryUI.getRegistryServer(0)),route("")))},registryUI.updateHistory=function(e){history.pushState(null,"",(e?"?url="+registryUI.encodeURI(e):"?")+window.location.hash),registryUI._url=e},registryUI.getUrlQueryParam=function(){var e=window.location.search;if(registryUI.URL_QUERY_PARAM_REGEX.test(e)){var r=e.split(/^\?|&/).find(function(e){return e&®istryUI.URL_PARAM_REGEX.test(e)});return r?r.replace(registryUI.URL_PARAM_REGEX,""):r}},registryUI.encodeURI=function(e){return e.indexOf("&")<0?window.encodeURIComponent(e):btoa(e)},registryUI.decodeURI=function(e){return e.startsWith("http")?window.decodeURIComponent(e):atob(e)},registryUI.isImageRemoveActivated=!0,registryUI.catalog={},registryUI.taglist={},riot.mount("*");
\ No newline at end of file
diff --git a/dist/scripts/tags-static.js b/dist/scripts/tags-static.js
deleted file mode 100644
index 3fe68ac..0000000
--- a/dist/scripts/tags-static.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * docker-registry-ui
- * Copyright (C) 2016-2018 Jones Magloire @Joxit
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-riot.tag2("catalog",'
Repositories of {registryUI.name()}
send {item}
',"","",function(t){registryUI.catalog.instance=this,registryUI.catalog.display=function(){registryUI.catalog.repositories=[];var t=new Http;t.addEventListener("load",function(){registryUI.catalog.repositories=[],200==this.status?(registryUI.catalog.repositories=JSON.parse(this.responseText).repositories||[],registryUI.catalog.repositories.sort()):404==this.status?registryUI.snackbar("Server not found",!0):registryUI.snackbar(this.responseText)}),t.addEventListener("error",function(){registryUI.snackbar(this.getErrorMessage(),!0),registryUI.catalog.repositories=[]}),t.addEventListener("loadend",function(){registryUI.catalog.loadend=!0,registryUI.catalog.instance.update()}),t.open("GET",registryUI.url()+"/v2/_catalog?n=100000"),t.send()},registryUI.catalog.go=function(t){route("taglist/"+t)},registryUI.catalog.display()}),riot.tag2("app",'
Tags of {registryUI.name() + \'/\' + registryUI.taglist.name}
Repository
Size
Tag
{image.name}
',"","",function(t){registryUI.taglist.instance=this,registryUI.taglist.display=function(){if(registryUI.taglist.tags=[],"taglist"==route.routeName){var t=new Http;registryUI.taglist.instance.update(),t.addEventListener("load",function(){registryUI.taglist.tags=[],200==this.status?(registryUI.taglist.tags=JSON.parse(this.responseText).tags||[],registryUI.taglist.tags=registryUI.taglist.tags.map(function(t){return new registryUI.DockerImage(registryUI.taglist.name,t)}).sort(registryUI.DockerImage.compare)):404==this.status?registryUI.snackbar("Server not found",!0):registryUI.snackbar(this.responseText,!0)}),t.addEventListener("error",function(){registryUI.snackbar(this.getErrorMessage(),!0),registryUI.taglist.tags=[]}),t.addEventListener("loadend",function(){registryUI.taglist.loadend=!0,registryUI.taglist.instance.update()}),t.open("GET",registryUI.url()+"/v2/"+registryUI.taglist.name+"/tags/list"),t.send(),registryUI.taglist.asc=!0}},registryUI.taglist.display(),registryUI.taglist.instance.update(),registryUI.taglist.reverse=function(){registryUI.taglist.asc?(registryUI.taglist.tags.reverse(),registryUI.taglist.asc=!1):(registryUI.taglist.tags.sort(registryUI.DockerImage.compare),registryUI.taglist.asc=!0),registryUI.taglist.instance.update()},registryUI.taglist.refresh=function(){route(registryUI.taglist.name)}}),riot.tag2("copy-to-clipboard",' content_copy',"","",function(t){this.dockerCmd="docker pull "+registryUI.cleanName()+"/"+t.image.name+":"+t.image.tag,this.copy=function(){var t=this.refs.input;t.style.display="block",t.select(),document.execCommand("copy"),t.style.display="none",registryUI.snackbar("`"+this.dockerCmd+"` has been copied to clipboard.")}}),riot.tag2("remove-image",'delete',"","",function(t){registryUI.removeImage=registryUI.removeImage||{},registryUI.removeImage.remove=function(t,e){var r=new Http;r.addEventListener("loadend",function(){if(registryUI.taglist.refresh(),200==this.status){if(!this.hasHeader("Docker-Content-Digest"))return void registryUI.errorSnackbar("You need to add Access-Control-Expose-Headers: ['Docker-Content-Digest'] in your server configuration.");var r=this.getResponseHeader("Docker-Content-Digest"),i=new Http;i.addEventListener("loadend",function(){200==this.status||202==this.status?(registryUI.taglist.refresh(),registryUI.snackbar("Deleting "+t+":"+e+" image. Run `registry garbage-collect config.yml` on your registry")):404==this.status?registryUI.errorSnackbar("Digest not found"):registryUI.snackbar(this.responseText)}),i.open("DELETE",registryUI.url()+"/v2/"+t+"/manifests/"+r),i.setRequestHeader("Accept","application/vnd.docker.distribution.manifest.v2+json"),i.addEventListener("error",function(){registryUI.errorSnackbar("An error occurred when deleting image. Check if your server accept DELETE methods Access-Control-Allow-Methods: ['DELETE'].")}),i.send()}else 404==this.status?registryUI.errorSnackbar("Manifest for "+t+":"+e+" not found"):registryUI.snackbar(this.responseText)}),r.open("HEAD",registryUI.url()+"/v2/"+t+"/manifests/"+e),r.setRequestHeader("Accept","application/vnd.docker.distribution.manifest.v2+json"),r.send()}}),riot.tag2("image-size",'
',"","",function(t){var e=this;t.image.on("sha256",function(t){e.sha256=t.substring(0,19),e.update()}),t.image.trigger("get-sha256")});
\ No newline at end of file
diff --git a/dist/scripts/tags.js b/dist/scripts/tags.js
deleted file mode 100644
index 5850e58..0000000
--- a/dist/scripts/tags.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * docker-registry-ui
- * Copyright (C) 2016-2018 Jones Magloire @Joxit
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-riot.tag2("add",'
',"","",function(e){registryUI.catalog.instance=this,registryUI.catalog.display=function(){registryUI.catalog.repositories=[];var e=new Http;e.addEventListener("load",function(){registryUI.catalog.repositories=[],200==this.status?(registryUI.catalog.repositories=JSON.parse(this.responseText).repositories||[],registryUI.catalog.repositories.sort()):404==this.status?registryUI.snackbar("Server not found",!0):registryUI.snackbar(this.responseText)}),e.addEventListener("error",function(){registryUI.snackbar(this.getErrorMessage(),!0),registryUI.catalog.repositories=[]}),e.addEventListener("loadend",function(){registryUI.catalog.loadend=!0,registryUI.catalog.instance.update()}),e.open("GET",registryUI.url()+"/v2/_catalog?n=100000"),e.send()},registryUI.catalog.go=function(e){route("taglist/"+e)},registryUI.catalog.display()}),riot.tag2("change",'
Change your Server ?
ChangeCancel
',"","",function(e){registryUI.changeTag=registryUI.changeTag||{},this.one("mount",function(){registryUI.changeTag.dialog=this.tags["material-popup"],registryUI.changeTag.dialog.getServerUrl=function(){return this.refs["server-list"]?this.refs["server-list"].value:""},registryUI.changeTag.dialog.on("updated",function(){this.refs["server-list"]&&(this.refs["server-list"].value=registryUI.url())})}),registryUI.changeTag.show=function(){registryUI.changeTag.dialog.open()},registryUI.changeTag.change=function(){registryUI.changeTag.dialog.getServerUrl().length>0&®istryUI.changeServer(registryUI.changeTag.dialog.getServerUrl()),registryUI.home(),registryUI.changeTag.dialog.close()},registryUI.changeTag.close=function(){registryUI.changeTag.dialog.close()}}),riot.tag2("copy-to-clipboard",' content_copy',"","",function(e){this.dockerCmd="docker pull "+registryUI.cleanName()+"/"+e.image.name+":"+e.image.tag,this.copy=function(){var e=this.refs.input;e.style.display="block",e.select(),document.execCommand("copy"),e.style.display="none",registryUI.snackbar("`"+this.dockerCmd+"` has been copied to clipboard.")}}),riot.tag2("image-size",'
',"","",function(e){registryUI.menuTag=registryUI.menuTag||{},registryUI.menuTag.update=this.update,this.one("mount",function(e){var t=this;registryUI.menuTag.close=function(){t.tags["material-dropdown"].close(),t.update()},registryUI.menuTag.isOpen=function(){return t.tags["material-dropdown"].opened},registryUI.menuTag.toggle=function(){t.tags["material-dropdown"].opened?t.tags["material-dropdown"].close():t.tags["material-dropdown"].open(),t.update()}})}),riot.tag2("remove-image",'delete',"","",function(e){registryUI.removeImage=registryUI.removeImage||{},registryUI.removeImage.remove=function(e,t){var r=new Http;r.addEventListener("loadend",function(){if(registryUI.taglist.refresh(),200==this.status){if(!this.hasHeader("Docker-Content-Digest"))return void registryUI.errorSnackbar("You need to add Access-Control-Expose-Headers: ['Docker-Content-Digest'] in your server configuration.");var r=this.getResponseHeader("Docker-Content-Digest"),a=new Http;a.addEventListener("loadend",function(){200==this.status||202==this.status?(registryUI.taglist.refresh(),registryUI.snackbar("Deleting "+e+":"+t+" image. Run `registry garbage-collect config.yml` on your registry")):404==this.status?registryUI.errorSnackbar("Digest not found"):registryUI.snackbar(this.responseText)}),a.open("DELETE",registryUI.url()+"/v2/"+e+"/manifests/"+r),a.setRequestHeader("Accept","application/vnd.docker.distribution.manifest.v2+json"),a.addEventListener("error",function(){registryUI.errorSnackbar("An error occurred when deleting image. Check if your server accept DELETE methods Access-Control-Allow-Methods: ['DELETE'].")}),a.send()}else 404==this.status?registryUI.errorSnackbar("Manifest for "+e+":"+t+" not found"):registryUI.snackbar(this.responseText)}),r.open("HEAD",registryUI.url()+"/v2/"+e+"/manifests/"+t),r.setRequestHeader("Accept","application/vnd.docker.distribution.manifest.v2+json"),r.send()}}),riot.tag2("remove",'
',"","",function(opts){var _this=this;this.items=[],this.title=null;var lastValue=this.value,valueChanged=function(){_this.value!==lastValue&&(lastValue=_this.value,_this.root.dispatchEvent(new CustomEvent("change",{value:_this.value})))};if(this.getOptions=function(){Array.prototype.forEach.call(_this.refs.options.children,function(t,e){if("option"==t.tagName.toLowerCase()){var i={title:t.innerHTML,value:t.getAttribute("value")};_this.items.push(i),null!=t.getAttribute("isSelected")&&(_this.refs.dropdown.update({selected:e}),_this.update({value:i.value||i.title}),valueChanged(),_this.title=i.title)}}),_this.refs.dropdown.update({items:_this.items}),_this.refs.dropdown.selected&&_this.update({hValue:_this.refs.dropdown.items[_this.refs.dropdown.selected].value||_this.refs.dropdown.items[_this.refs.dropdown.selected].title}),_this.update({isParsed:!0}),valueChanged()},opts.items)try{this.items=eval(opts.items)||[],this.items.length&&this.refs.dropdown.update({items:this.items})}catch(t){console.error("Something wrong with your items. For details look at it - "+t)}this.on("mount",function(){_this.getOptions(),_this.refs.dropdown.on("selectChanged",function(t){_this.update({value:_this.refs.dropdown.items[t].value||_this.refs.dropdown.items[t].title}),valueChanged(),_this.refs.input.update({value:_this.refs.dropdown.items[t].title}),setTimeout(function(){_this.refs.dropdown.update({items:_this.items})},200)}),_this.refs.input.on("valueChanged",function(t){_this.refs.dropdown.update({items:_this.filter("items",{title:t})})}),_this.refs.input.on("focusChanged",function(t){_this.refs.input.value==(opts.defaulttext||"Choose item")&&t&&_this.refs.input.update({value:""}),""!=_this.refs.input.value||t||_this.refs.input.update({value:opts.defaulttext||"Choose item"}),t&&_this.refs.dropdown.open()}),_this.refs.dropdown.root.style.top=_this.refs.input.root.getBoundingClientRect().height+"px",_this.refs.input.update({value:_this.title||opts.defaulttext||"Choose item"})}),this.mixin("collection")})},function(module,exports,__webpack_require__){"use strict";riot.tag2("material-dropdown-list",'
',"","",function(opts){var _this=this;if(this.opened=!1,opts.items){try{this.items=eval(opts.items)||[]}catch(t){console.error("Something wrong with your items. For details look at it - "+t)}this.update({items:this.items})}opts.selected&&this.update({selected:opts.selected}),this.select=function(t){return _this.update({selected:t.item.key}),_this.close(),_this.trigger("selectChanged",t.item.key,t.item.item),!0},this.open=function(){_this.update({opened:!0,opening:!0}),_this.opts.extraclose&&document.body.appendChild(_this.refs.overlay),setTimeout(function(){_this.update({opening:!1})},0)},this.close=function(){_this.update({opening:!0}),setTimeout(function(){_this.update({opened:!1})},200)}})},function(t,e,i){"use strict";riot.tag2("material-dropdown",'
',"","",function(t){var e=this;if(this.opts=t,this.required="",this.name=t.ref||"input",this.notSupportedTypes=["date","color","datetime","month","range","time"],-1!=this.notSupportedTypes.indexOf(t.type))throw new Error("Sorry but we do not support "+t.type+" type yet!");this.update({showIcon:!1}),this.on("mount",function(){e.update({value:t.value||"",disabled:t.disabled||!1,required:t.required||!1}),e.n=t.ref||"default-input",e.refs[e.n].addEventListener("focus",e.changeFocus),e.refs[e.n].addEventListener("blur",e.changeFocus)}),this.changeFocus=function(i){if(e.disabled)return!1;e.update({focused:e.refs[e.n]==document.activeElement}),e.trigger("focusChanged",e.focused,i),t.focuschanged&&"function"==typeof t.focuschanged&&t.focuschanged(e.focused)},this.changeValue=function(i){e.update({value:e.refs[e.n].value}),e.trigger("valueChanged",e.refs[e.n].value,i),t.valuechanged&&"function"==typeof t.valuechanged&&t.valuechanged(e.refs[e.n].value)},this.iconClickHandler=function(t){e.opts.iconclicked&&"function"==typeof e.opts.iconclicked&&e.opts.iconclicked.call(e,t),e.trigger("iconclicked",t)},this.on("update",function(t){t&&void 0!=t.value&&e.validationType&&e.isValid(e.validate(t.value))}),this.isValid=function(t){e.update({error:!t})},this.mixin("validate")})},function(t,e,i){"use strict";riot.tag2("material-navbar",'