diff --git a/package.json b/package.json index a011d17..2e82d09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "docker-registry-ui", "version": "2.3.3", + "type": "module", "scripts": { "format": "npm run format-html && npm run format-js && npm run format-riot", "format-html": "find src rollup rollup.config.js -name '*.html' -exec prettier --config .prettierrc -w --parser html {} \\;", @@ -18,28 +19,28 @@ "license": "AGPL-3.0", "description": "A web UI for private docker registry", "devDependencies": { - "@babel/core": "^7.17.9", - "@babel/preset-env": "^7.16.0", - "@riotjs/compiler": "^6.1.3", + "@babel/core": "^7.20.5", + "@babel/preset-env": "^7.20.2", + "@riotjs/compiler": "^6.4.2", "@riotjs/observable": "^4.1.1", - "@riotjs/route": "^8.0.1", - "@rollup/plugin-babel": "^5.2.2", - "@rollup/plugin-commonjs": "^21.1.0", - "@rollup/plugin-html": "^0.2.4", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^13.2.1", - "core-js": "^3.22.0", - "node-sass": "^7.0.1", - "prettier": "^2.6.2", - "riot": "^6.1.2", - "riot-mui": "github:joxit/riot-5-mui#4d68d7f", - "rollup": "^2.70.2", + "@riotjs/route": "^8.0.2", + "@rollup/plugin-babel": "^6.0.3", + "@rollup/plugin-commonjs": "^23.0.3", + "@rollup/plugin-html": "^1.0.1", + "@rollup/plugin-json": "^5.0.2", + "@rollup/plugin-node-resolve": "^15.0.1", + "core-js": "^3.26.1", + "node-sass": "^8.0.0", + "prettier": "^2.8.0", + "riot": "^7.1.0", + "riot-mui": "github:joxit/riot-5-mui#a9b0ce4", + "rollup": "^3.5.1", "rollup-plugin-app-utils": "^1.0.6", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-copy": "^3.4.0", "rollup-plugin-riot": "^6.0.0", - "rollup-plugin-scss": "^3.0.0", - "rollup-plugin-serve": "^1.1.0", + "rollup-plugin-scss": "^4.0.0", + "rollup-plugin-serve": "^2.0.2", "rollup-plugin-styles": "^4.0.0", "rollup-plugin-terser": "^7.0.2" } diff --git a/rollup.config.js b/rollup.config.js index e60bd2b..547eb50 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -7,12 +7,12 @@ import { babel } from '@rollup/plugin-babel'; import scss from 'rollup-plugin-scss'; import serve from 'rollup-plugin-serve'; import html from '@rollup/plugin-html'; -import htmlUseref from './rollup/html-useref'; +import htmlUseref from './rollup/html-useref.js'; import json from '@rollup/plugin-json'; import copy from 'rollup-plugin-copy'; -import copyTransform from './rollup/copy-transform'; -import license from './rollup/license'; -import checkOutput from './rollup/check-output'; +import copyTransform from './rollup/copy-transform.js'; +import license from './rollup/license.js'; +import checkOutput from './rollup/check-output.js'; const useServe = process.env.ROLLUP_SERVE === 'true'; const output = useServe ? '.serve' : 'dist'; @@ -22,7 +22,7 @@ const plugins = [ json(), nodeResolve(), commonjs(), - scss({ output: `./${output}/docker-registry-ui.css`, outputStyle: 'compressed' }), + scss({ fileName: `docker-registry-ui.css`, outputStyle: 'compressed' }), babel({ babelHelpers: 'bundled', presets: [['@babel/env', { useBuiltIns: 'usage', corejs: { version: '2' } }]] }), copy({ targets: [ diff --git a/src/components/catalog/catalog-element.riot b/src/components/catalog/catalog-element.riot index 01a1c0b..234385a 100644 --- a/src/components/catalog/catalog-element.riot +++ b/src/components/catalog/catalog-element.riot @@ -21,7 +21,10 @@ along with this program. If not, see . if="{!props.filterResults || state.nImages > 0 || matchSearch(props.filterResults, state.image)}" > - + + + + send { state.image || state.repo } @@ -76,9 +79,7 @@ along with this program. If not, see . }, onClick() { const state = this.state; - if (!state.repo) { - router.taglist(state.image); - } else { + if (state.repo) { this.update({ expanded: !this.state.expanded, expanding: true, @@ -112,6 +113,7 @@ along with this program. If not, see . oReq.send(); }, matchSearch, + router, }; diff --git a/src/components/dialogs/add-registry-url.riot b/src/components/dialogs/add-registry-url.riot index 41df728..5094cdf 100644 --- a/src/components/dialogs/add-registry-url.riot +++ b/src/components/dialogs/add-registry-url.riot @@ -16,16 +16,16 @@ --> -
Add your Server ?
-
- +
Add your Server ?
+
+ Write your URL without /v2
-
- +
+ Add - + Cancel
@@ -55,6 +55,9 @@ this.props.onClose(); setTimeout(() => router.updateUrlQueryParam(url), 100); }, + registryUrlValidator(input) { + return /^https?:\/\//.test(input) && !/\/v2\/?$/.test(input) + } }; diff --git a/src/components/dialogs/change-registry-url.riot b/src/components/dialogs/change-registry-url.riot index bae4937..3c1b770 100644 --- a/src/components/dialogs/change-registry-url.riot +++ b/src/components/dialogs/change-registry-url.riot @@ -15,18 +15,18 @@ along with this program. If not, see . --> - -
Change your Server ?
-
+ +
Change your Server ?
+
-
- +
+ Change - + Cancel
@@ -62,6 +62,7 @@ background: 0 0; border: none; font-weight: 400; + font-size: 1em; line-height: 24px; height: 24px; border-bottom: 1px solid #2f6975; diff --git a/src/components/dialogs/confirm-delete-image.riot b/src/components/dialogs/confirm-delete-image.riot index 8fdbc7b..fb5728d 100644 --- a/src/components/dialogs/confirm-delete-image.riot +++ b/src/components/dialogs/confirm-delete-image.riot @@ -16,17 +16,17 @@ --> -
These images will be deleted
-
+
These images will be deleted
+
  • { image.name }:{ image.tag }
-
- +
+ Delete - + Cancel
diff --git a/src/components/dialogs/dialogs-menu.riot b/src/components/dialogs/dialogs-menu.riot index c0ad257..067f318 100644 --- a/src/components/dialogs/dialogs-menu.riot +++ b/src/components/dialogs/dialogs-menu.riot @@ -35,15 +35,23 @@ on-notify="{ props.onNotify }" on-server-change="{ props.onServerChange }" > -
- +
+ more_vert - + >
diff --git a/src/components/search-bar.riot b/src/components/search-bar.riot index 77fffd1..06e546b 100644 --- a/src/components/search-bar.riot +++ b/src/components/search-bar.riot @@ -1,5 +1,5 @@ - + diff --git a/src/components/tag-list/remove-image.riot b/src/components/tag-list/remove-image.riot index f518ab5..b7a4f5c 100644 --- a/src/components/tag-list/remove-image.riot +++ b/src/components/tag-list/remove-image.riot @@ -16,13 +16,15 @@ along with this program. If not, see . --> delete @@ -56,8 +58,8 @@ along with this program. If not, see . deleteImage() { this.props.handleCheckboxChange(ACTION_DELETE_IMAGE, this.props.image); }, - handleCheckboxChange(checked) { - const action = checked ? ACTION_CHECK_TO_DELETE : ACTION_UNCHECK_TO_DELETE; + handleCheckboxChange(event) { + const action = event.target.checked ? ACTION_CHECK_TO_DELETE : ACTION_UNCHECK_TO_DELETE; this.props.handleCheckboxChange(action, this.props.image); }, }; diff --git a/src/components/tag-list/tag-history-button.riot b/src/components/tag-list/tag-history-button.riot index 8595f18..8a6692d 100644 --- a/src/components/tag-list/tag-history-button.riot +++ b/src/components/tag-list/tag-history-button.riot @@ -17,11 +17,13 @@ along with this program. If not, see . history @@ -40,7 +42,7 @@ along with this program. If not, see . }, routeToHistory() { if (!this.props.image.ociImage) { - router.history(this.props.image.name, this.props.image.tag); + return router.history(this.props.image.name, this.props.image.tag); } }, }; diff --git a/src/components/tag-list/tag-list.riot b/src/components/tag-list/tag-list.riot index 65ddf18..ec176eb 100644 --- a/src/components/tag-list/tag-list.riot +++ b/src/components/tag-list/tag-list.riot @@ -17,7 +17,14 @@ along with this program. If not, see .
- + arrow_back

diff --git a/src/components/tag-list/tag-table.riot b/src/components/tag-list/tag-table.riot index 795d3b9..7c60194 100644 --- a/src/components/tag-list/tag-table.riot +++ b/src/components/tag-list/tag-table.riot @@ -63,12 +63,14 @@ along with this program. If not, see . > delete @@ -78,31 +80,31 @@ along with this program. If not, see . - + - + - + + > - + + > - + . checked="{ state.toDelete.has(image) }" on-notify="{ props.onNotify }" on-authentication="{ props.onAuthentication }" - /> + > @@ -172,7 +174,7 @@ along with this program. If not, see . confirmDeleteImage: false, }); }, - onRemoveImageHeaderChange(checked, event) { + onRemoveImageHeaderChange(event) { if (event.altKey === true) { const tags = getPage(this.props.tags, this.props.page); tags @@ -184,7 +186,7 @@ along with this program. If not, see . }); } else { this.update({ - multiDelete: checked, + multiDelete: event.target.checked, }); } }, diff --git a/src/index.js b/src/index.js index 97b5af5..60ac3ac 100644 --- a/src/index.js +++ b/src/index.js @@ -10,7 +10,7 @@ import { MaterialCheckbox, MaterialTabs, MaterialSnackbar, - MaterialDropdownList, + MaterialDropdown, MaterialPopup, MaterialInput, } from 'riot-mui'; @@ -28,7 +28,7 @@ register('material-waves', MaterialWaves); register('material-checkbox', MaterialCheckbox); register('material-snackbar', MaterialSnackbar); register('material-tabs', MaterialTabs); -register('material-dropdown-list', MaterialDropdownList); +register('material-dropdown', MaterialDropdown); register('material-popup', MaterialPopup); register('material-input', MaterialInput); diff --git a/src/scripts/router.js b/src/scripts/router.js index e8fc42e..58c9bfb 100644 --- a/src/scripts/router.js +++ b/src/scripts/router.js @@ -14,7 +14,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import { router, getCurrentRoute } from '@riotjs/route'; +import { getCurrentRoute } from '@riotjs/route'; import { encodeURI, decodeURI } from './utils'; function getQueryParams() { @@ -59,16 +59,16 @@ function baseUrl(qs) { export default { home() { - router.push(baseUrl({ page: null })); + return baseUrl({ page: null }); }, taglist(image) { - router.push(`${baseUrl({ page: null })}#!/taglist/${image}`); + return `${baseUrl({ page: null })}#!/taglist/${image}`; }, getTagListImage() { return getCurrentRoute().replace(/^.*(#!)?\/?taglist\//, ''); }, history(image, tag) { - router.push(`${baseUrl({ page: null })}#!/taghistory/image/${image}/tag/${tag}`); + return `${baseUrl({ page: null })}#!/taghistory/image/${image}/tag/${tag}`; }, getTagHistoryImage() { return getCurrentRoute().replace(/^.*(#!)?\/?taghistory\/image\/(.*)\/tag\/(.*)\/?$/, '$2'); diff --git a/src/style.scss b/src/style.scss index d4463e7..a0b55e3 100644 --- a/src/style.scss +++ b/src/style.scss @@ -23,18 +23,20 @@ @import 'riot-mui/src/material-elements/material-checkbox/material-checkbox.scss'; @import 'riot-mui/src/material-elements/material-tabs/material-tabs.scss'; @import 'riot-mui/src/material-elements/material-snackbar/material-snackbar.scss'; -@import 'riot-mui/src/material-elements/material-dropdown-list/material-dropdown-list.scss'; +@import 'riot-mui/src/material-elements/material-dropdown/material-dropdown.scss'; @import 'riot-mui/src/material-elements/material-popup/material-popup.scss'; @import 'riot-mui/src/material-elements/material-input/material-input.scss'; @import './roboto.scss'; @import './material-icons.scss'; - + html > body { font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif !important; + font-size: 16px; } -html, body { +html, +body { margin: 0; height: 100%; } @@ -59,44 +61,35 @@ html, body { font-weight: inherit; } -material-card, material-tabs, pagination .conatianer { +material-card, +material-tabs, +pagination .container { max-width: 95%; margin: auto; margin-top: 20px; margin-bottom: 20px; } -pagination .conatianer { - display: flex; - display: -moz-flex; - display: -webkit-flex; - display: -ms-flexbox; -} - -pagination .conatianer .pagination-centered { - margin: auto; -} - /* 1515px * 0.95 = 1440px */ -@media screen and (min-width: 1515px){ - material-card, material-tabs, pagination .conatianer { +@media screen and (min-width: 1515px) { + material-card, + material-tabs, + pagination .container { max-width: 1440px; } } material-tabs { display: block; - -webkit-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16), 0 2px 10px 0 rgba(0,0,0,.12); - -ms-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12); - -moz-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12); - -o-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12); - box-shadow: 0 2px 5px 0 rgba(0,0,0,.16), 0 2px 10px 0 rgba(0,0,0,.12); + -webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + -ms-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + -moz-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + -o-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); } material-tabs material-button, material-tabs material-button .content .text { - background-color: #fff; - color: #aaa; text-transform: none; } @@ -117,20 +110,12 @@ material-spinner { flex-direction: column; } -material-navbar { - height: 64px; -} - -material-navbar nav-wrapper { - display: flex; -} - .logo { padding: 0 16px 0 72px; text-decoration: none; font-size: 20px; line-height: 1; - letter-spacing: .02em; + letter-spacing: 0.02em; font-weight: 400; } @@ -169,18 +154,22 @@ h2 { overflow: hidden; } +docker-registry-ui material-button > :first-child .content i.material-icons, +docker-registry-ui material-button > :first-child .content i.material-icons.material-icons { + font-size: 24px; +} + .list > span i.material-icons, .list > li i.material-icons { margin-right: 32px; height: 24px; width: 24px; - font-size: 24px; box-sizing: border-box; color: #757575; } .list > span .right i.material-icons.animated { - transition: all 350ms cubic-bezier(.4,0,.2,1); + transition: all 350ms cubic-bezier(0.4, 0, 0.2, 1); margin-right: 10px; } @@ -237,7 +226,7 @@ material-card table { width: 100%; border: none; position: relative; - border: 1px solid rgba(0, 0, 0, .12); + border: 1px solid rgba(0, 0, 0, 0.12); border-collapse: collapse; white-space: nowrap; font-size: 13px; @@ -250,7 +239,7 @@ material-card table th { vertical-align: bottom; line-height: 24px; height: 48px; - color: rgba(0, 0, 0, .54); + color: rgba(0, 0, 0, 0.54); box-sizing: border-box; padding: 0 18px 12px 18px; text-align: right; @@ -260,17 +249,16 @@ material-card table th { text-align: left; } -material-card material-button:hover, -material-card table tbody tr:hover, -pagination material-button:hover { - background-color: #eee; +material-button:hover > :first-child[inverted='true'], +material-card .material-card-title-action material-button:hover button, +material-card table tbody tr:hover { + background-color: #eee !important; } -material-card material-button, -material-card table tbody tr, -pagination material-button { - transition-duration: .28s; - transition-timing-function: cubic-bezier(.4, 0, .2, 1); +material-button > :first-child[inverted='true'], +material-card table tbody tr { + transition-duration: 0.28s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-property: background-color; } @@ -283,8 +271,8 @@ material-card table td { font-size: 16px; position: relative; height: 48px; - border-top: 1px solid rgba(0, 0, 0, .12); - border-bottom: 1px solid rgba(0, 0, 0, .12); + border-top: 1px solid rgba(0, 0, 0, 0.12); + border-bottom: 1px solid rgba(0, 0, 0, 0.12); padding: 12px 18px; box-sizing: border-box; vertical-align: middle; @@ -292,27 +280,30 @@ material-card table td { } tag-history-button button:hover, -material-card table th.material-card-th-sorted-ascending:hover, material-card table th.material-card-th-sorted-descending:hover { +material-card table th.material-card-th-sorted-ascending:hover, +material-card table th.material-card-th-sorted-descending:hover { cursor: pointer; } -material-card table th.material-card-th-sorted-ascending:hover:before, material-card table th.material-card-th-sorted-descending:hover:before { - color: rgba(0, 0, 0, .26); +material-card table th.material-card-th-sorted-ascending:hover:before, +material-card table th.material-card-th-sorted-descending:hover:before { + color: rgba(0, 0, 0, 0.26); } -material-card table th.material-card-th-sorted-ascending:before, material-card table th.material-card-th-sorted-descending:before { +material-card table th.material-card-th-sorted-ascending:before, +material-card table th.material-card-th-sorted-descending:before { font-family: 'Material Icons'; font-weight: 400; font-style: normal; line-height: 1; font-size: 16px; - content: "\e5d8"; + content: '\e5d8'; margin-right: 5px; vertical-align: sub; } material-card table th.material-card-th-sorted-descending:before { - content: "\e5db"; + content: '\e5db'; } material-button .content i.material-icons, @@ -329,19 +320,13 @@ material-snackbar .toast { height: auto; } -material-popup material-button, -pagination material-button { - background-color: #fff; - color: #000; -} - material-popup material-button:hover material-waves { - background-color: hsla(0, 0%, 75%, .2); + background-color: hsla(0, 0%, 75%, 0.2); } -material-popup .popup { +material-popup .popup > .content { + padding: 1em; max-width: 450px; - top: 2em; } footer { @@ -366,7 +351,8 @@ material-footer { /* 5 + 2 + 3 + 24 + 3 + 2 + 18 */ padding-right: 57px; } -image-tag, .copy-to-clipboard { +image-tag, +.copy-to-clipboard { display: inline-block; } image-content-digest { @@ -405,28 +391,11 @@ taglist .image-size { width: 7em; } -catalog material-card, -tag-history material-card { - min-height: auto; -} - -tag-history-button button { - background: none; - border: none; -} - -material-card material-button, -pagination material-button { - max-height: 30px; - max-width: 30px; -} - material-button:hover material-waves { background: none; } -material-card material-button, -pagination material-button { +material-card material-button { background-color: inherit; } @@ -436,7 +405,7 @@ catalog-element material-card { } catalog-element catalog-element material-card { - transition: all 350ms cubic-bezier(.4,0,.2,1); + transition: all 350ms cubic-bezier(0.4, 0, 0.2, 1); z-index: 1; position: relative; } @@ -451,7 +420,7 @@ catalog-element catalog-element > .content { margin-left: 3em; } -@media screen and (min-width: 1515px){ +@media screen and (min-width: 1515px) { catalog-element catalog-element > .content material-card { max-width: calc(1440px - 3em); } @@ -489,29 +458,3 @@ material-checkbox .checkbox { material-checkbox .checkbox.checked { background-color: #777; } - -pagination material-button { - padding: 0.2em 0.75em; -} - -pagination material-button .content { - display: flex; - align-content: center; - line-height: 1.9em; -} - -pagination material-button.current { - border: 1px solid rgba(0, 0, 0, .12); -} - -pagination material-button.current.space-left { - margin-left: 85px; -} - -pagination material-button.current.space-right { - margin-right: 85px; -} - -pagination material-button .content i.material-icons { - color: #000; -} \ No newline at end of file